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:
parent
1bc5c7ac5b
commit
af8329394b
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue