hv: vpci: handle the quirk part for pass through pci device cfg access in dm

There're some PCI devices need special handler for vendor-specical feature or
capability CFG access. The Intel GPU is one of them. In order to keep the ACRN-HV
clean, we want to throw the qurik part of PCI CFG asccess to DM to handle.

To achieve this, we implement per-device policy base on whether it needs quirk handler
for a VM: each device could configure as "quirk pass through device" or not. For a
"quirk pass through device", we will handle the general part in HV and the quirk part
in DM. For a non "quirk pass through device",  we will handle all the part in HV.

Tracked-On: #4371
Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
Li Fei1
2020-03-13 11:44:51 +08:00
committed by wenlingz
parent e5c7a96513
commit e99ddf28c3
7 changed files with 75 additions and 36 deletions

View File

@@ -123,6 +123,28 @@ read_config(struct pci_device *phys_dev, long reg, int width)
return temp;
}
static int
write_config(struct pci_device *phys_dev, long reg, int width, uint32_t data)
{
int temp = -1;
switch (width) {
case 1:
temp = pci_device_cfg_write_u8(phys_dev, data, reg);
break;
case 2:
temp = pci_device_cfg_write_u16(phys_dev, data, reg);
break;
case 4:
temp = pci_device_cfg_write_u32(phys_dev, data, reg);
break;
default:
warnx("%s: invalid reg width", __func__);
}
return temp;
}
static int
cfginit_cap(struct vmctx *ctx, struct passthru_dev *ptdev)
{
@@ -515,8 +537,10 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
/* initialize the EPT mapping for passthrough GPU opregion */
vm_map_ptdev_mmio(ctx, 0, 2, 0, GPU_OPREGION_GPA, GPU_OPREGION_SIZE, opregion_start_hpa);
pcidev.rsvd2[0] = GPU_GSM_GPA | (gsm_phys & ~PCIM_BDSM_GSM_MASK) ;
pcidev.rsvd2[1] = GPU_OPREGION_GPA | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK);
pci_set_cfgdata32(dev, PCIR_BDSM, GPU_GSM_GPA | (gsm_phys & ~PCIM_BDSM_GSM_MASK));
pci_set_cfgdata32(dev, PCIR_ASLS_CTL, GPU_OPREGION_GPA | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK));
pcidev.type = QUIRK_PTDEV;
}
pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func);
@@ -628,13 +652,27 @@ static int
passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
int coff, int bytes, uint32_t *rv)
{
return ~0;
struct passthru_dev *ptdev = dev->arg;
if ((PCI_BDF(dev->bus, dev->slot, dev->func) == PCI_BDF_GPU) &&
((coff == PCIR_BDSM) || (coff == PCIR_ASLS_CTL)))
*rv = pci_get_cfgdata32(dev, coff);
else
*rv = read_config(ptdev->phys_dev, coff, bytes);
return 0;
}
static int
passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
int coff, int bytes, uint32_t val)
{
struct passthru_dev *ptdev = dev->arg;
if (!((PCI_BDF(dev->bus, dev->slot, dev->func) == PCI_BDF_GPU) &&
((coff == PCIR_BDSM) || (coff == PCIR_ASLS_CTL))))
write_config(ptdev->phys_dev, coff, bytes, val);
return 0;
}

View File

@@ -154,8 +154,9 @@ struct vm_memmap {
*
*/
struct acrn_assign_pcidev {
/** reversed for externed compatibility */
uint32_t rsvd1;
#define QUIRK_PTDEV (1 << 0) /* We will only handle general part in HV, others in DM */
/** the type of the the pass-through PCI device */
uint32_t type;
/** virtual BDF# of the pass-through PCI device */
uint16_t virt_bdf;