pci: Implement pci_bar_enabled() for SR-IOV VFs

In a VF's configuration space, "memory space enable" is hard-wired to 0,
so the existing implementation always returns false.  We need to read
the SR-IOV control register from the PF device to get the value of the
MSE bit.

Fix pci_bar_enabled() to read this register instead for VFs.  I don't
see any way to access the PF's config space without a backpointer in the
pci device ivars, so I added one.

This fixes a regression where bhyve(8) fails to map the MSI-X table
after commit 7fa2335347 ("bhyve: Map the MSI-X table unconditionally
for passthrough") when a VF is passed through, since with that commit we
use PCIOCBARMMAP to map the table and that ioctl always fails for VFs
without this change.  As a bonus, pciconf(8) now correctly reports the
enablement of BARs for VFs.

Reported and tested by:	Raúl Muñoz <raul.munoz@custos.es>
Reviewed by:	rstone, jhb
Sponsored by:	The FreeBSD Foundation

(cherry picked from commit 1f960e646b)
This commit is contained in:
Mark Johnston 2021-11-09 13:07:57 -05:00
parent 5c2e6d9610
commit ab9866cc79
3 changed files with 12 additions and 0 deletions

View file

@ -3150,6 +3150,16 @@ pci_bar_enabled(device_t dev, struct pci_map *pm)
if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) &&
!(pm->pm_value & PCIM_BIOS_ENABLE))
return (0);
#ifdef PCI_IOV
if ((dinfo->cfg.flags & PCICFG_VF) != 0) {
struct pcicfg_iov *iov;
iov = dinfo->cfg.iov;
cmd = pci_read_config(iov->iov_pf,
iov->iov_pos + PCIR_SRIOV_CTL, 2);
return ((cmd & PCIM_SRIOV_VF_MSE) != 0);
}
#endif
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) || PCI_BAR_MEM(pm->pm_value))
return ((cmd & PCIM_CMD_MEMEN) != 0);

View file

@ -151,6 +151,7 @@ pci_iov_attach_method(device_t bus, device_t dev, nvlist_t *pf_schema,
error = EBUSY;
goto cleanup;
}
iov->iov_pf = dev;
iov->iov_pos = iov_pos;
schema = pci_iov_build_schema(&pf_schema, &vf_schema);

View file

@ -37,6 +37,7 @@ struct pci_iov_bar {
};
struct pcicfg_iov {
device_t iov_pf;
struct cdev *iov_cdev;
nvlist_t *iov_schema;