git: 1f960e646b72 - main - pci: Implement pci_bar_enabled() for SR-IOV VFs

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 09 Nov 2021 18:20:26 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=1f960e646b7280795766fdaa183e3b9bd4cea345

commit 1f960e646b7280795766fdaa183e3b9bd4cea345
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-11-09 18:07:57 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-09 18:13:36 +0000

    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 7fa233534736 ("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
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32839
---
 sys/dev/pci/pci.c             | 10 ++++++++++
 sys/dev/pci/pci_iov.c         |  1 +
 sys/dev/pci/pci_iov_private.h |  1 +
 3 files changed, 12 insertions(+)

diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 702f9fc3aa05..7493ae1727fb 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -3151,6 +3151,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);
diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c
index 6db2cf445843..f577640595a9 100644
--- a/sys/dev/pci/pci_iov.c
+++ b/sys/dev/pci/pci_iov.c
@@ -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);
diff --git a/sys/dev/pci/pci_iov_private.h b/sys/dev/pci/pci_iov_private.h
index 0d1dda871b44..be3456d4781f 100644
--- a/sys/dev/pci/pci_iov_private.h
+++ b/sys/dev/pci/pci_iov_private.h
@@ -37,6 +37,7 @@ struct pci_iov_bar {
 };
 
 struct pcicfg_iov {
+	device_t iov_pf;
 	struct cdev *iov_cdev;
 	nvlist_t *iov_schema;