svn commit: r279448 - head/sys/dev/pci
Ryan Stone
rstone at FreeBSD.org
Sun Mar 1 00:40:21 UTC 2015
Author: rstone
Date: Sun Mar 1 00:40:19 2015
New Revision: 279448
URL: https://svnweb.freebsd.org/changeset/base/279448
Log:
Emulate the Device ID and Vendor ID registers for VFs
The SR-IOV standard requires VFs to read all-ones when the VID
and DID registers are read. The VMM (hypervisor) is required to
emulate them instead. Make pci_read_config() do this emulation.
Change pci_user.c to use pci_read_config() to read config space
registers instead of going directly to the pcib so that the
emulated VID/DID registers work correctly on VFs. This is
required both for pciconf and bhyve PCI passthrough.
Differential Revision: https://reviews.freebsd.org/D77
Reviewed by: jhb
MFC after: 1 month
Sponsored by: Sandvine Inc.
Modified:
head/sys/dev/pci/pci.c
head/sys/dev/pci/pci_user.c
Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c Sun Mar 1 00:40:09 2015 (r279447)
+++ head/sys/dev/pci/pci.c Sun Mar 1 00:40:19 2015 (r279448)
@@ -4880,6 +4880,37 @@ pci_read_config_method(device_t dev, dev
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
+#ifdef PCI_IOV
+ /*
+ * SR-IOV VFs don't implement the VID or DID registers, so we have to
+ * emulate them here.
+ */
+ if (cfg->flags & PCICFG_VF) {
+ if (reg == PCIR_VENDOR) {
+ switch (width) {
+ case 4:
+ return (cfg->device << 16 | cfg->vendor);
+ case 2:
+ return (cfg->vendor);
+ case 1:
+ return (cfg->vendor & 0xff);
+ default:
+ return (0xffffffff);
+ }
+ } else if (reg == PCIR_DEVICE) {
+ switch (width) {
+ /* Note that an unaligned 4-byte read is an error. */
+ case 2:
+ return (cfg->device);
+ case 1:
+ return (cfg->device & 0xff);
+ default:
+ return (0xffffffff);
+ }
+ }
+ }
+#endif
+
return (PCIB_READ_CONFIG(device_get_parent(dev),
cfg->bus, cfg->slot, cfg->func, reg, width));
}
Modified: head/sys/dev/pci/pci_user.c
==============================================================================
--- head/sys/dev/pci/pci_user.c Sun Mar 1 00:40:09 2015 (r279447)
+++ head/sys/dev/pci/pci_user.c Sun Mar 1 00:40:19 2015 (r279448)
@@ -492,7 +492,7 @@ pci_list_vpd(device_t dev, struct pci_li
static int
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
- device_t pcidev, brdev;
+ device_t pcidev;
void *confdata;
const char *name;
struct devlist *devlist_head;
@@ -922,37 +922,25 @@ getconfexit:
io->pi_sel.pc_bus, io->pi_sel.pc_dev,
io->pi_sel.pc_func);
if (pcidev) {
- brdev = device_get_parent(
- device_get_parent(pcidev));
-
#ifdef PRE7_COMPAT
if (cmd == PCIOCWRITE || cmd == PCIOCWRITE_OLD)
#else
if (cmd == PCIOCWRITE)
#endif
- PCIB_WRITE_CONFIG(brdev,
- io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func,
+ pci_write_config(pcidev,
io->pi_reg,
io->pi_data,
io->pi_width);
#ifdef PRE7_COMPAT
else if (cmd == PCIOCREAD_OLD)
io_old->pi_data =
- PCIB_READ_CONFIG(brdev,
- io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func,
+ pci_read_config(pcidev,
io->pi_reg,
io->pi_width);
#endif
else
io->pi_data =
- PCIB_READ_CONFIG(brdev,
- io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func,
+ pci_read_config(pcidev,
io->pi_reg,
io->pi_width);
error = 0;
More information about the svn-src-all
mailing list