mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-20 10:20:57 +00:00
dm: implement ivshmem inter-vm communication for hv-land
This patch is used to create and destroy an ivshmem device which is emulated in hypervisor. Tracked-On: #4853 Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
1d084073d6
commit
91e2fcfecf
@ -62,12 +62,16 @@
|
||||
#define IVSHMEM_DOORBELL_REG 0x0c
|
||||
#define IVSHMEM_RESERVED_REG 0x0f
|
||||
|
||||
#define hv_land_prefix "hv:/"
|
||||
#define dm_land_prefix "sos:/"
|
||||
|
||||
struct pci_ivshmem_vdev {
|
||||
struct pci_vdev *dev;
|
||||
char *name;
|
||||
int fd;
|
||||
void *addr;
|
||||
uint32_t size;
|
||||
bool is_hv_land;
|
||||
};
|
||||
|
||||
static int
|
||||
@ -135,6 +139,28 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
create_ivshmem_from_hv(struct vmctx *ctx, struct pci_vdev *vdev,
|
||||
const char *shm_name, uint32_t shm_size)
|
||||
{
|
||||
struct acrn_emul_dev dev = {};
|
||||
uint64_t addr = 0;
|
||||
|
||||
dev.dev_id.fields.vendor_id = IVSHMEM_VENDOR_ID;
|
||||
dev.dev_id.fields.device_id = IVSHMEM_DEVICE_ID;
|
||||
dev.slot = PCI_BDF(vdev->bus, vdev->slot, vdev->func);
|
||||
dev.io_addr[IVSHMEM_MMIO_BAR] = pci_get_cfgdata32(vdev,
|
||||
PCIR_BAR(IVSHMEM_MMIO_BAR));
|
||||
addr = pci_get_cfgdata32(vdev, PCIR_BAR(IVSHMEM_MEM_BAR));
|
||||
addr |= 0x0c; /* 64bit, prefetchable */
|
||||
dev.io_addr[IVSHMEM_MEM_BAR] = addr;
|
||||
addr = pci_get_cfgdata32(vdev, PCIR_BAR(IVSHMEM_MEM_BAR + 1));
|
||||
dev.io_addr[IVSHMEM_MEM_BAR + 1] = addr;
|
||||
dev.io_size[IVSHMEM_MEM_BAR] = shm_size;
|
||||
strncpy((char*)dev.args, shm_name, 32);
|
||||
return vm_create_hv_vdev(ctx, &dev);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_ivshmem_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
||||
int baridx, uint64_t offset, int size, uint64_t value)
|
||||
@ -217,6 +243,8 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
uint32_t size;
|
||||
char *tmp, *name, *orig;
|
||||
struct pci_ivshmem_vdev *ivshmem_vdev = NULL;
|
||||
bool is_hv_land;
|
||||
int rc;
|
||||
|
||||
/* ivshmem device usage: "-s N,ivshmem,shm_name,shm_size" */
|
||||
tmp = orig = strdup(opts);
|
||||
@ -229,6 +257,17 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
pr_warn("the shared memory size is not set\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!strncmp(name, hv_land_prefix, strlen(hv_land_prefix))) {
|
||||
is_hv_land = true;
|
||||
} else if (!strncmp(name, dm_land_prefix, strlen(dm_land_prefix))) {
|
||||
is_hv_land = false;
|
||||
name += strlen(dm_land_prefix);
|
||||
} else {
|
||||
pr_warn("the ivshmem memory prefix name is incorrect\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dm_strtoui(tmp, &tmp, 10, &size) != 0) {
|
||||
pr_warn("the shared memory size is incorrect, %s\n", tmp);
|
||||
goto err;
|
||||
@ -247,6 +286,7 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
}
|
||||
|
||||
ivshmem_vdev->dev = dev;
|
||||
ivshmem_vdev->is_hv_land = is_hv_land;
|
||||
dev->arg = ivshmem_vdev;
|
||||
|
||||
/* initialize config space */
|
||||
@ -258,12 +298,17 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
pci_emul_alloc_bar(dev, IVSHMEM_MMIO_BAR, PCIBAR_MEM32, IVSHMEM_REG_SIZE);
|
||||
pci_emul_alloc_bar(dev, IVSHMEM_MEM_BAR, PCIBAR_MEM64, size);
|
||||
|
||||
/*
|
||||
* TODO: If UOS reprograms ivshmem BAR2, the shared memory will be
|
||||
* unavailable for UOS, so we need to remap GPA and HPA of shared
|
||||
* memory in this case.
|
||||
*/
|
||||
if (create_ivshmem_from_dm(ctx, dev, name, size) < 0)
|
||||
if (is_hv_land) {
|
||||
rc = create_ivshmem_from_hv(ctx, dev, name, size);
|
||||
} else {
|
||||
/*
|
||||
* TODO: If UOS reprograms ivshmem BAR2, the shared memory will be
|
||||
* unavailable for UOS, so we need to remap GPA and HPA of shared
|
||||
* memory in this case.
|
||||
*/
|
||||
rc = create_ivshmem_from_dm(ctx, dev, name, size);
|
||||
}
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
free(orig);
|
||||
@ -287,6 +332,18 @@ destroy_ivshmem_from_dm(struct pci_ivshmem_vdev *vdev)
|
||||
close(vdev->fd);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_ivshmem_from_hv(struct vmctx *ctx, struct pci_vdev *vdev)
|
||||
{
|
||||
|
||||
struct acrn_emul_dev emul_dev = {};
|
||||
|
||||
emul_dev.dev_id.fields.vendor_id = IVSHMEM_VENDOR_ID;
|
||||
emul_dev.dev_id.fields.device_id = IVSHMEM_DEVICE_ID;
|
||||
emul_dev.slot = PCI_BDF(vdev->bus, vdev->slot, vdev->func);
|
||||
vm_destroy_hv_vdev(ctx, &emul_dev);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_ivshmem_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
{
|
||||
@ -297,7 +354,11 @@ pci_ivshmem_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
pr_warn("%s, invalid ivshmem instance\n", __func__);
|
||||
return;
|
||||
}
|
||||
destroy_ivshmem_from_dm(vdev);
|
||||
if (vdev->is_hv_land)
|
||||
destroy_ivshmem_from_hv(ctx, dev);
|
||||
else
|
||||
destroy_ivshmem_from_dm(vdev);
|
||||
|
||||
if (vdev->name) {
|
||||
/*
|
||||
* shm_unlink will only remove the shared memory file object,
|
||||
@ -311,6 +372,7 @@ pci_ivshmem_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
*/
|
||||
free(vdev->name);
|
||||
}
|
||||
|
||||
free(vdev);
|
||||
dev->arg = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user