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 <fei1.li@intel.com>
Acked-by: Eddie Dong<eddie.dong@Intel.com>
This commit is contained in:
Li Fei1 2020-05-07 09:44:07 +08:00 committed by wenlingz
parent 1bc5c7ac5b
commit af8329394b
5 changed files with 36 additions and 11 deletions

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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,

View File

@ -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,

View File

@ -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 {