mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-21 10:51:35 +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_DOORBELL_REG 0x0c
|
||||||
#define IVSHMEM_RESERVED_REG 0x0f
|
#define IVSHMEM_RESERVED_REG 0x0f
|
||||||
|
|
||||||
|
#define hv_land_prefix "hv:/"
|
||||||
|
#define dm_land_prefix "sos:/"
|
||||||
|
|
||||||
struct pci_ivshmem_vdev {
|
struct pci_ivshmem_vdev {
|
||||||
struct pci_vdev *dev;
|
struct pci_vdev *dev;
|
||||||
char *name;
|
char *name;
|
||||||
int fd;
|
int fd;
|
||||||
void *addr;
|
void *addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
bool is_hv_land;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -135,6 +139,28 @@ err:
|
|||||||
return -1;
|
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
|
static void
|
||||||
pci_ivshmem_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
pci_ivshmem_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
||||||
int baridx, uint64_t offset, int size, uint64_t value)
|
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;
|
uint32_t size;
|
||||||
char *tmp, *name, *orig;
|
char *tmp, *name, *orig;
|
||||||
struct pci_ivshmem_vdev *ivshmem_vdev = NULL;
|
struct pci_ivshmem_vdev *ivshmem_vdev = NULL;
|
||||||
|
bool is_hv_land;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* ivshmem device usage: "-s N,ivshmem,shm_name,shm_size" */
|
/* ivshmem device usage: "-s N,ivshmem,shm_name,shm_size" */
|
||||||
tmp = orig = strdup(opts);
|
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");
|
pr_warn("the shared memory size is not set\n");
|
||||||
goto err;
|
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) {
|
if (dm_strtoui(tmp, &tmp, 10, &size) != 0) {
|
||||||
pr_warn("the shared memory size is incorrect, %s\n", tmp);
|
pr_warn("the shared memory size is incorrect, %s\n", tmp);
|
||||||
goto err;
|
goto err;
|
||||||
@ -247,6 +286,7 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ivshmem_vdev->dev = dev;
|
ivshmem_vdev->dev = dev;
|
||||||
|
ivshmem_vdev->is_hv_land = is_hv_land;
|
||||||
dev->arg = ivshmem_vdev;
|
dev->arg = ivshmem_vdev;
|
||||||
|
|
||||||
/* initialize config space */
|
/* 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_MMIO_BAR, PCIBAR_MEM32, IVSHMEM_REG_SIZE);
|
||||||
pci_emul_alloc_bar(dev, IVSHMEM_MEM_BAR, PCIBAR_MEM64, size);
|
pci_emul_alloc_bar(dev, IVSHMEM_MEM_BAR, PCIBAR_MEM64, size);
|
||||||
|
|
||||||
/*
|
if (is_hv_land) {
|
||||||
* TODO: If UOS reprograms ivshmem BAR2, the shared memory will be
|
rc = create_ivshmem_from_hv(ctx, dev, name, size);
|
||||||
* unavailable for UOS, so we need to remap GPA and HPA of shared
|
} else {
|
||||||
* memory in this case.
|
/*
|
||||||
*/
|
* TODO: If UOS reprograms ivshmem BAR2, the shared memory will be
|
||||||
if (create_ivshmem_from_dm(ctx, dev, name, size) < 0)
|
* 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;
|
goto err;
|
||||||
|
|
||||||
free(orig);
|
free(orig);
|
||||||
@ -287,6 +332,18 @@ destroy_ivshmem_from_dm(struct pci_ivshmem_vdev *vdev)
|
|||||||
close(vdev->fd);
|
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
|
static void
|
||||||
pci_ivshmem_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
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__);
|
pr_warn("%s, invalid ivshmem instance\n", __func__);
|
||||||
return;
|
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) {
|
if (vdev->name) {
|
||||||
/*
|
/*
|
||||||
* shm_unlink will only remove the shared memory file object,
|
* 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->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(vdev);
|
free(vdev);
|
||||||
dev->arg = NULL;
|
dev->arg = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user