From 696f6c7ba43d87919a583d78e72292235c0e8157 Mon Sep 17 00:00:00 2001 From: Yuan Liu Date: Mon, 9 Mar 2020 21:41:10 +0800 Subject: [PATCH] hv: the VM can only deinit its own devices VM needs to check if it owns this device before deiniting it. Tracked-On: #4433 Signed-off-by: Yuan Liu Signed-off-by: Yin Fengwei Acked-by: Eddie Dong --- hypervisor/dm/vpci/vpci.c | 12 ++++++++---- hypervisor/dm/vpci/vsriov.c | 6 ++++-- hypervisor/include/arch/x86/guest/vm.h | 25 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 48b1e9cfe..dfc6b9494 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -637,7 +637,10 @@ static void deinit_prelaunched_vm_vpci(struct acrn_vm *vm) for (i = 0U; i < vm->vpci.pci_vdev_cnt; i++) { vdev = (struct pci_vdev *) &(vm->vpci.pci_vdevs[i]); - vdev->vdev_ops->deinit_vdev(vdev); + /* Only deinit the VM's own devices */ + if (is_own_device(vm, vdev)) { + vdev->vdev_ops->deinit_vdev(vdev); + } } } @@ -669,7 +672,8 @@ static void deinit_postlaunched_vm_vpci(struct acrn_vm *vm) for (i = 0U; i < sos_vm->vpci.pci_vdev_cnt; i++) { vdev = (struct pci_vdev *)&(sos_vm->vpci.pci_vdevs[i]); - if (vdev->vpci->vm == vm) { + /* Only deinit the VM's own devices */ + if (is_own_device(vm, vdev)) { spinlock_obtain(&vm->vpci.lock); target_vdev = vdev->new_owner; ret = move_pt_device(vm->iommu, sos_vm->iommu, (uint8_t)target_vdev->pdev->bdf.bits.b, @@ -716,7 +720,7 @@ int32_t vpci_assign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pc * * For now, we don't support assignment of PF to a UOS. */ - if ((vdev_in_sos != NULL) && (vdev_in_sos->vpci->vm == sos_vm) && (vdev_in_sos->pdev != NULL) && (!has_sriov_cap(vdev_in_sos))) { + if ((vdev_in_sos != NULL) && is_own_device(sos_vm, vdev_in_sos) && (vdev_in_sos->pdev != NULL) && (!has_sriov_cap(vdev_in_sos))) { /* ToDo: Each PT device must support one type reset */ if (!vdev_in_sos->pdev->has_pm_reset && !vdev_in_sos->pdev->has_flr && !vdev_in_sos->pdev->has_af_flr) { @@ -781,7 +785,7 @@ int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev * sos_vm = get_sos_vm(); spinlock_obtain(&sos_vm->vpci.lock); vdev_in_sos = pci_find_vdev(&sos_vm->vpci, bdf); - if ((vdev_in_sos != NULL) && (vdev_in_sos->vpci->vm == tgt_vm) && (vdev_in_sos->pdev != NULL)) { + if ((vdev_in_sos != NULL) && is_own_device(tgt_vm, vdev_in_sos) && (vdev_in_sos->pdev != NULL)) { vdev = vdev_in_sos->new_owner; spinlock_obtain(&tgt_vm->vpci.lock); diff --git a/hypervisor/dm/vpci/vsriov.c b/hypervisor/dm/vpci/vsriov.c index b67c387dc..b8d9bcd04 100644 --- a/hypervisor/dm/vpci/vsriov.c +++ b/hypervisor/dm/vpci/vsriov.c @@ -207,8 +207,9 @@ static void enable_vfs(struct pci_vdev *pf_vdev) create_vf(pf_vdev, vf_bdf, idx); } else { /* Re-activate a zombie VF */ - if (vf_vdev->vpci == NULL) { + if (is_zombie_vf(vf_vdev)) { vf_vdev->vpci = pf_vdev->vpci; + vf_vdev->vdev_ops->init_vdev(vf_vdev); } } } @@ -250,8 +251,9 @@ static void disable_vfs(struct pci_vdev *pf_vdev) bdf.fields.bus = get_vf_bus(pf_vdev, first, stride, idx); bdf.fields.devfun = get_vf_devfun(pf_vdev, first, stride, idx); vf_vdev = pci_find_vdev(&pf_vdev->vpci->vm->vpci, bdf); - if (vf_vdev != NULL) { + if ((vf_vdev != NULL) && (!is_zombie_vf(vf_vdev))) { /* set disabled VF as zombie vdev instance */ + vf_vdev->vdev_ops->deinit_vdev(vf_vdev); vf_vdev->vpci = NULL; } } diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 1d38fb390..c9515066d 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -206,6 +206,31 @@ static inline uint16_t vmid_2_rel_vmid(uint16_t sos_vmid, uint16_t vmid) { return (vmid - sos_vmid); } +/** + * @brief Check if the vdev belongs to the vm + * + * @param vm Pointer to a vm instance + * @param vdev Pointer to a vdev instance + * + * @return If the vm owns the vdev device return true, otherwsie return false + */ +static inline bool is_own_device(const struct acrn_vm *vm, const struct pci_vdev *vdev) +{ + return (&vm->vpci == vdev->vpci); +} + +/** + * @brief Check if the specified vdev is a zombie VF instance + * + * @param vdev Pointer to vdev instance + * + * @return If the vdev is a zombie VF instance return true, otherwise return false + */ +static inline bool is_zombie_vf(const struct pci_vdev *vdev) +{ + return (vdev->vpci == NULL); +} + void make_shutdown_vm_request(uint16_t pcpu_id); bool need_shutdown_vm(uint16_t pcpu_id); int32_t shutdown_vm(struct acrn_vm *vm);