From af8329394bf63739ebc08e74c71712abb4058c30 Mon Sep 17 00:00:00 2001 From: Li Fei1 Date: Thu, 7 May 2020 09:44:07 +0800 Subject: [PATCH] hv: vpci: minor refine the vdev ownership data structure Add a new field 'parent_user' to record the parent user of the vdev. And refine 'new_owner' to 'user' to record who is the current user of the vdev. Like ----------------------------------------------------------------------------------------------- vdev in | HV | pre-VM | SOS | post-VM | | |vdev used by SOS|vdev used by post-VM| ----------------------------------------------------------------------------------------------- parent_user| NULL(HV) | NULL(HV) | NULL(HV) | NULL(HV) | vdev in SOS ----------------------------------------------------------------------------------------------- user | vdev in HV | vdev in pre-VM | vdev in SOS | vdev in post-VM | vdev in post-VM ----------------------------------------------------------------------------------------------- Tracked-On: #4550 Signed-off-by: Li Fei1 Acked-by: Eddie Dong --- hypervisor/dm/vpci/vhostbridge.c | 5 +++++ hypervisor/dm/vpci/vmsix.c | 2 +- hypervisor/dm/vpci/vpci.c | 23 +++++++++++++++-------- hypervisor/dm/vpci/vpci_bridge.c | 5 +++++ hypervisor/include/dm/vpci.h | 12 ++++++++++-- 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/hypervisor/dm/vpci/vhostbridge.c b/hypervisor/dm/vpci/vhostbridge.c index 42c1f7750..1a9a016ab 100644 --- a/hypervisor/dm/vpci/vhostbridge.c +++ b/hypervisor/dm/vpci/vhostbridge.c @@ -86,10 +86,15 @@ static void init_vhostbridge(struct pci_vdev *vdev) pci_vdev_write_vcfg(vdev, 0xf5U, 1U, 0xfU); pci_vdev_write_vcfg(vdev, 0xf6U, 1U, 0x1cU); pci_vdev_write_vcfg(vdev, 0xf7U, 1U, 0x1U); + + vdev->parent_user = NULL; + vdev->user = vdev; } static void deinit_vhostbridge(__unused struct pci_vdev *vdev) { + vdev->parent_user = NULL; + vdev->user = NULL; } diff --git a/hypervisor/dm/vpci/vmsix.c b/hypervisor/dm/vpci/vmsix.c index 7b676e249..554dde891 100644 --- a/hypervisor/dm/vpci/vmsix.c +++ b/hypervisor/dm/vpci/vmsix.c @@ -195,7 +195,7 @@ int32_t vmsix_handle_table_mmio_access(struct io_request *io_req, void *handler_ vdev = (struct pci_vdev *)handler_private_data; /* This device has not be assigned to other OS */ - if (vdev->new_owner == NULL) { + if (vdev->user == vdev) { offset = mmio->address - vdev->msix.mmio_gpa; if (msixtable_access(vdev, (uint32_t)offset)) { diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 8546cae8a..7ed114d76 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -360,12 +360,12 @@ static struct pci_vdev *find_available_vdev(struct acrn_vpci *vpci, union pci_bd { struct pci_vdev *vdev = pci_find_vdev(vpci, bdf); - if ((vdev != NULL) && (vdev->vpci != vpci)) { + if ((vdev != NULL) && (vdev->user != vdev)) { /* In the case a device is assigned to a UOS and is not in a zombie state */ - if ((vdev->new_owner != NULL) && (vdev->new_owner->vpci != NULL)) { + if ((vdev->user != NULL) && (vdev->user->vpci != NULL)) { /* the SOS is able to access, if and only if the SOS has higher severity than the UOS. */ if (get_vm_severity(vpci2vm(vpci)->vm_id) < - get_vm_severity(vpci2vm(vdev->new_owner->vpci)->vm_id)) { + get_vm_severity(vpci2vm(vdev->user->vpci)->vm_id)) { vdev = NULL; } } else { @@ -378,6 +378,9 @@ static struct pci_vdev *find_available_vdev(struct acrn_vpci *vpci, union pci_bd static void vpci_init_pt_dev(struct pci_vdev *vdev) { + vdev->parent_user = NULL; + vdev->user = vdev; + /* * Here init_vdev_pt() needs to be called after init_vmsix() for the following reason: * init_vdev_pt() will indirectly call has_msix_cap(), which @@ -397,6 +400,9 @@ static void vpci_deinit_pt_dev(struct pci_vdev *vdev) remove_vdev_pt_iommu_domain(vdev); deinit_vmsix(vdev); deinit_vmsi(vdev); + + vdev->user = NULL; + vdev->parent_user = NULL; } struct cfg_header_perm { @@ -704,7 +710,7 @@ static void deinit_postlaunched_vm_vpci(struct acrn_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; + target_vdev = vdev->user; ret = move_pt_device(vm->iommu, sos_vm->iommu, (uint8_t)target_vdev->pdev->bdf.bits.b, (uint8_t)(target_vdev->pdev->bdf.value & 0xFFU)); if (ret != 0) { @@ -717,7 +723,7 @@ static void deinit_postlaunched_vm_vpci(struct acrn_vm *vm) /* Move vdev pointers back to SOS*/ vdev->vpci = (struct acrn_vpci *) &sos_vm->vpci; - vdev->new_owner = NULL; + vdev->user = NULL; spinlock_release(&vm->vpci.lock); } } @@ -783,8 +789,9 @@ int32_t vpci_assign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pc vdev->flags |= pcidev->type; vdev->bdf.value = pcidev->virt_bdf; + vdev->parent_user = vdev_in_sos; spinlock_release(&tgt_vm->vpci.lock); - vdev_in_sos->new_owner = vdev; + vdev_in_sos->user = vdev; } } else { pr_fatal("%s, can't find PCI device %x:%x.%x for vm[%d] %x:%x.%x\n", __func__, @@ -816,7 +823,7 @@ int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev * spinlock_obtain(&sos_vm->vpci.lock); vdev_in_sos = pci_find_vdev(&sos_vm->vpci, bdf); if ((vdev_in_sos != NULL) && is_own_device(tgt_vm, vdev_in_sos) && (vdev_in_sos->pdev != NULL)) { - vdev = vdev_in_sos->new_owner; + vdev = vdev_in_sos->user; spinlock_obtain(&tgt_vm->vpci.lock); @@ -834,7 +841,7 @@ int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev * spinlock_release(&tgt_vm->vpci.lock); vdev_in_sos->vpci = &sos_vm->vpci; - vdev_in_sos->new_owner = NULL; + vdev_in_sos->user = NULL; } else { pr_fatal("%s, can't find PCI device %x:%x.%x for vm[%d] %x:%x.%x\n", __func__, pcidev->phys_bdf >> 8U, (pcidev->phys_bdf >> 3U) & 0x1fU, pcidev->phys_bdf & 0x7U, diff --git a/hypervisor/dm/vpci/vpci_bridge.c b/hypervisor/dm/vpci/vpci_bridge.c index 00a8965e3..278187861 100644 --- a/hypervisor/dm/vpci/vpci_bridge.c +++ b/hypervisor/dm/vpci/vpci_bridge.c @@ -70,10 +70,15 @@ static void init_vpci_bridge(struct pci_vdev *vdev) pci_vdev_write_vcfg(vdev, PCIR_HDRTYPE, 1U, (PCIM_HDRTYPE_BRIDGE | PCIM_MFDEV)); pci_vdev_write_vcfg(vdev, PCIR_CLASS, 1U, PCIC_BRIDGE); pci_vdev_write_vcfg(vdev, PCIR_SUBCLASS, 1U, PCIS_BRIDGE_PCI); + + vdev->parent_user = NULL; + vdev->user = vdev; } static void deinit_vpci_bridge(__unused struct pci_vdev *vdev) { + vdev->parent_user = NULL; + vdev->user = NULL; } static int32_t read_vpci_bridge_cfg(const struct pci_vdev *vdev, uint32_t offset, diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index e864a1dcb..52d501516 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -123,8 +123,16 @@ struct pci_vdev { /* Pointer to corressponding operations */ const struct pci_vdev_ops *vdev_ops; - /* For SOS, if the device is latterly assigned to a UOS, we use this field to track the new owner. */ - struct pci_vdev *new_owner; + /* + * vdev in | HV | pre-VM | SOS | post-VM + * | | |vdev used by SOS|vdev used by post-VM| + * ----------------------------------------------------------------------------------------------- + * parent_user| NULL(HV) | NULL(HV) | NULL(HV) | NULL(HV) | vdev in SOS + * ----------------------------------------------------------------------------------------------- + * user | vdev in HV | vdev in pre-VM | vdev in SOS | vdev in post-VM | vdev in post-VM + */ + struct pci_vdev *parent_user; + struct pci_vdev *user; }; union pci_cfg_addr_reg {