From 996e8f680c9d1056eb8d6f43e477ef32c34f62c9 Mon Sep 17 00:00:00 2001 From: Tao Yuhong Date: Fri, 23 Oct 2020 17:43:45 -0400 Subject: [PATCH] HV: pci-vuart support create vdev hcall Add cteate method for vmcs9900 vdev in hypercalls. The destroy method of ivshmem is also suitable for other emulated vdev, move it into hcall_destroy_vdev() for all emulated vdevs Tracked-On: #5394 Signed-off-by: Tao Yuhong Reviewed-by: Wang, Yu1 --- hypervisor/arch/x86/cpu.c | 1 + hypervisor/common/hypercall.c | 33 ++++++++++++++++++------- hypervisor/dm/vpci/ivshmem.c | 24 +++++-------------- hypervisor/dm/vpci/vmcs9900.c | 41 ++++++++++++++++++++++++++++++++ hypervisor/include/dm/ivshmem.h | 2 +- hypervisor/include/dm/vmcs9900.h | 2 ++ 6 files changed, 76 insertions(+), 27 deletions(-) diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 199f5ebb0..5fe3d839c 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #define CPU_UP_TIMEOUT 100U /* millisecond */ diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 5be2ef10e..e2bc08cb8 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -21,19 +21,21 @@ #include #include #include +#include #define DBG_LEVEL_HYCALL 6U -typedef int32_t (*emul_dev_op) (struct acrn_vm *vm, struct acrn_emul_dev *dev); +typedef int32_t (*emul_dev_create) (struct acrn_vm *vm, struct acrn_emul_dev *dev); +typedef int32_t (*emul_dev_destroy) (struct pci_vdev *vdev); struct emul_dev_ops { /* * The low 32 bits represent the vendor id and device id of PCI device, * and the high 32 bits represent the device number of the legacy device */ uint64_t dev_id; - emul_dev_op create; - emul_dev_op destroy; - + /* TODO: to re-use vdev_init/vdev_deinit directly in hypercall */ + emul_dev_create create; + emul_dev_destroy destroy; }; static struct emul_dev_ops emul_dev_ops_tbl[] = { @@ -42,6 +44,7 @@ static struct emul_dev_ops emul_dev_ops_tbl[] = { #else {(IVSHMEM_VENDOR_ID | (IVSHMEM_DEVICE_ID << 16U)), NULL, NULL}, #endif + {(MCS9900_VENDOR | (MCS9900_DEV << 16U)), create_vmcs9900_vdev, destroy_vmcs9900_vdev}, }; bool is_hypercall_from_ring0(void) @@ -1216,16 +1219,30 @@ int32_t hcall_destroy_vdev(struct acrn_vm *vm, struct acrn_vm *target_vm, __unus { int32_t ret = -EINVAL; struct acrn_emul_dev dev; + struct pci_vdev *vdev; struct emul_dev_ops *op; + union pci_bdf bdf; /* We should only destroy a device to a post-launched VM at creating or pausing time for safety, not runtime or other cases*/ if (is_created_vm(target_vm) || is_paused_vm(target_vm)) { if (copy_from_gpa(vm, &dev, param2, sizeof(dev)) == 0) { - op = find_emul_dev_ops(&dev); - if ((op != NULL) && (op->destroy != NULL)) { - ret = op->destroy(target_vm, &dev); + op = find_emul_dev_ops(&dev); + if (op != NULL) { + bdf.value = (uint16_t) dev.slot; + vdev = pci_find_vdev(&vm->vpci, bdf); + if (vdev != NULL) { + vdev->pci_dev_config->vbdf.value = UNASSIGNED_VBDF; + if (op->destroy != NULL) { + ret = op->destroy(vdev); + } else { + ret = 0; + } + } else { + pr_warn("%s, failed to destroy emulated device %x:%x.%x\n", + __func__, bdf.bits.b, bdf.bits.d, bdf.bits.f); + } + } } - } } else { pr_err("%s, vm[%d] is not a postlaunched VM, or not in CREATED/PAUSED status to destroy a vdev\n", __func__, target_vm->vm_id); } diff --git a/hypervisor/dm/vpci/ivshmem.c b/hypervisor/dm/vpci/ivshmem.c index 2206db421..19deee0b7 100644 --- a/hypervisor/dm/vpci/ivshmem.c +++ b/hypervisor/dm/vpci/ivshmem.c @@ -394,27 +394,15 @@ int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev) return ret; } -/** - * @pre vm != NULL - * @pre dev != NULL - */ -int32_t destroy_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev) +int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev) { - struct pci_vdev *vdev; - union pci_bdf bdf; - int32_t ret = 0; + uint32_t i; - bdf.value = (uint16_t) dev->slot; - vdev = pci_find_vdev(&vm->vpci, bdf); - if (vdev != NULL) { - vdev->pci_dev_config->vbdf.value = UNASSIGNED_VBDF; - (void)memset(vdev->pci_dev_config->vbar_base, 0U, sizeof(vdev->pci_dev_config->vbar_base)); - } else { - pr_warn("%s, failed to destroy ivshmem device %x:%x.%x\n", - __func__, bdf.bits.b, bdf.bits.d, bdf.bits.f); - ret = -EINVAL; + for (i = 0U; i < vdev->nr_bars; i++) { + vpci_update_one_vbar(vdev, i, 0U, NULL, ivshmem_vbar_unmap); } - return ret; + + return 0; } const struct pci_vdev_ops vpci_ivshmem_ops = { diff --git a/hypervisor/dm/vpci/vmcs9900.c b/hypervisor/dm/vpci/vmcs9900.c index bc1d02800..c159b76cb 100644 --- a/hypervisor/dm/vpci/vmcs9900.c +++ b/hypervisor/dm/vpci/vmcs9900.c @@ -10,6 +10,7 @@ #include #include #include "vpci_priv.h" +#include #define MCS9900_MMIO_BAR 0U #define MCS9900_MSIX_BAR 1U @@ -167,3 +168,43 @@ const struct pci_vdev_ops vmcs9900_ops = { .write_vdev_cfg = write_vmcs9900_cfg, .read_vdev_cfg = read_vmcs9900_cfg, }; + +int32_t create_vmcs9900_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev) +{ + uint32_t i; + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + struct acrn_vm_pci_dev_config *dev_config = NULL; + int32_t ret = -EINVAL; + uint16_t vuart_idx = *((uint16_t*)(dev->args)); + + for (i = 0U; i < vm_config->pci_dev_num; i++) { + dev_config = &vm_config->pci_devs[i]; + if (dev_config->vuart_idx == vuart_idx) { + dev_config->vbdf.value = (uint16_t) dev->slot; + dev_config->vbar_base[0] = (uint64_t) dev->io_addr[0]; + dev_config->vbar_base[1] = (uint64_t) dev->io_addr[1]; + (void) vpci_init_vdev(&vm->vpci, dev_config, NULL); + ret = 0; + break; + } + } + + if (ret != 0) { + pr_err("Unsupport: create VM%d vuart_idx=%d", vm->vm_id, vuart_idx); + } + + return ret; +} + +int32_t destroy_vmcs9900_vdev(struct pci_vdev *vdev) +{ + uint32_t i; + + for (i = 0U; i < vdev->nr_bars; i++) { + vpci_update_one_vbar(vdev, i, 0U, NULL, unmap_vmcs9900_vbar); + } + + deinit_pci_vuart(vdev); + + return 0; +} diff --git a/hypervisor/include/dm/ivshmem.h b/hypervisor/include/dm/ivshmem.h index fa7ea4c55..17ada7e53 100644 --- a/hypervisor/include/dm/ivshmem.h +++ b/hypervisor/include/dm/ivshmem.h @@ -38,7 +38,7 @@ extern const struct pci_vdev_ops vpci_ivshmem_ops; void init_ivshmem_shared_memory(void); int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev); -int32_t destroy_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev); +int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev); #endif /* CONFIG_IVSHMEM_ENABLED */ #endif /* IVSHMEM_H */ diff --git a/hypervisor/include/dm/vmcs9900.h b/hypervisor/include/dm/vmcs9900.h index 00bad8d17..1ee3118a2 100644 --- a/hypervisor/include/dm/vmcs9900.h +++ b/hypervisor/include/dm/vmcs9900.h @@ -12,5 +12,7 @@ extern const struct pci_vdev_ops vmcs9900_ops; void trigger_vmcs9900_msix(struct pci_vdev *vdev); +int32_t create_vmcs9900_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev); +int32_t destroy_vmcs9900_vdev(struct pci_vdev *vdev); #endif