Skip to content

Commit cc6711b

Browse files
mgurtovoyAlex Williamson
authored andcommitted
PCI / VFIO: Add 'override_only' support for VFIO PCI sub system
Expose an 'override_only' helper macro (i.e. PCI_DRIVER_OVERRIDE_DEVICE_VFIO) for VFIO PCI sub system and add the required code to prefix its matching entries with "vfio_" in modules.alias file. It allows VFIO device drivers to include match entries in the modules.alias file produced by kbuild that are not used for normal driver autoprobing and module autoloading. Drivers using these match entries can be connected to the PCI device manually, by userspace, using the existing driver_override sysfs. For example the resulting modules.alias may have: alias pci:v000015B3d00001021sv*sd*bc*sc*i* mlx5_core alias vfio_pci:v000015B3d00001021sv*sd*bc*sc*i* mlx5_vfio_pci alias vfio_pci:v*d*sv*sd*bc*sc*i* vfio_pci In this example mlx5_core and mlx5_vfio_pci match to the same PCI device. The kernel will autoload and autobind to mlx5_core but the kernel and udev mechanisms will ignore mlx5_vfio_pci. When userspace wants to change a device to the VFIO subsystem it can implement a generic algorithm: 1) Identify the sysfs path to the device: /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 2) Get the modalias string from the kernel: $ cat /sys/bus/pci/devices/0000:01:00.0/modalias pci:v000015B3d00001021sv000015B3sd00000001bc02sc00i00 3) Prefix it with vfio_: vfio_pci:v000015B3d00001021sv000015B3sd00000001bc02sc00i00 4) Search modules.alias for the above string and select the entry that has the fewest *'s: alias vfio_pci:v000015B3d00001021sv*sd*bc*sc*i* mlx5_vfio_pci 5) modprobe the matched module name: $ modprobe mlx5_vfio_pci 6) cat the matched module name to driver_override: echo mlx5_vfio_pci > /sys/bus/pci/devices/0000:01:00.0/driver_override 7) unbind device from original module echo 0000:01:00.0 > /sys/bus/pci/devices/0000:01:00.0/driver/unbind 8) probe PCI drivers (or explicitly bind to mlx5_vfio_pci) echo 0000:01:00.0 > /sys/bus/pci/drivers_probe The algorithm is independent of bus type. In future the other buses with VFIO device drivers, like platform and ACPI, can use this algorithm as well. This patch is the infrastructure to provide the information in the modules.alias to userspace. Convert the only VFIO pci_driver which results in one new line in the modules.alias: alias vfio_pci:v*d*sv*sd*bc*sc*i* vfio_pci Later series introduce additional HW specific VFIO PCI drivers, such as mlx5_vfio_pci. Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> # for pci.h Signed-off-by: Yishai Hadas <yishaih@nvidia.com> Link: https://lore.kernel.org/r/20210826103912.128972-11-yishaih@nvidia.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 343b725 commit cc6711b

5 files changed

Lines changed: 42 additions & 3 deletions

File tree

drivers/vfio/pci/vfio_pci.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,16 @@ static int vfio_pci_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
178178
return vfio_pci_core_sriov_configure(pdev, nr_virtfn);
179179
}
180180

181+
static const struct pci_device_id vfio_pci_table[] = {
182+
{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_ANY_ID, PCI_ANY_ID) }, /* match all by default */
183+
{}
184+
};
185+
186+
MODULE_DEVICE_TABLE(pci, vfio_pci_table);
187+
181188
static struct pci_driver vfio_pci_driver = {
182189
.name = "vfio-pci",
183-
.id_table = NULL, /* only dynamic ids */
190+
.id_table = vfio_pci_table,
184191
.probe = vfio_pci_probe,
185192
.remove = vfio_pci_remove,
186193
.sriov_configure = vfio_pci_sriov_configure,

include/linux/mod_devicetable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ typedef unsigned long kernel_ulong_t;
1616

1717
#define PCI_ANY_ID (~0)
1818

19+
enum {
20+
PCI_ID_F_VFIO_DRIVER_OVERRIDE = 1,
21+
};
22+
1923
/**
2024
* struct pci_device_id - PCI device ID structure
2125
* @vendor: Vendor ID to match (or PCI_ANY_ID)

include/linux/pci.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,20 @@ struct pci_driver {
916916
.vendor = (vend), .device = (dev), .subvendor = PCI_ANY_ID, \
917917
.subdevice = PCI_ANY_ID, .override_only = (driver_override)
918918

919+
/**
920+
* PCI_DRIVER_OVERRIDE_DEVICE_VFIO - macro used to describe a VFIO
921+
* "driver_override" PCI device.
922+
* @vend: the 16 bit PCI Vendor ID
923+
* @dev: the 16 bit PCI Device ID
924+
*
925+
* This macro is used to create a struct pci_device_id that matches a
926+
* specific device. The subvendor and subdevice fields will be set to
927+
* PCI_ANY_ID and the driver_override will be set to
928+
* PCI_ID_F_VFIO_DRIVER_OVERRIDE.
929+
*/
930+
#define PCI_DRIVER_OVERRIDE_DEVICE_VFIO(vend, dev) \
931+
PCI_DEVICE_DRIVER_OVERRIDE(vend, dev, PCI_ID_F_VFIO_DRIVER_OVERRIDE)
932+
919933
/**
920934
* PCI_DEVICE_SUB - macro used to describe a specific PCI device with subsystem
921935
* @vend: the 16 bit PCI Vendor ID

scripts/mod/devicetable-offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int main(void)
4242
DEVID_FIELD(pci_device_id, subdevice);
4343
DEVID_FIELD(pci_device_id, class);
4444
DEVID_FIELD(pci_device_id, class_mask);
45+
DEVID_FIELD(pci_device_id, override_only);
4546

4647
DEVID(ccw_device_id);
4748
DEVID_FIELD(ccw_device_id, match_flags);

scripts/mod/file2alias.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ static int do_ieee1394_entry(const char *filename,
426426
return 1;
427427
}
428428

429-
/* Looks like: pci:vNdNsvNsdNbcNscNiN. */
429+
/* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
430430
static int do_pci_entry(const char *filename,
431431
void *symval, char *alias)
432432
{
@@ -440,8 +440,21 @@ static int do_pci_entry(const char *filename,
440440
DEF_FIELD(symval, pci_device_id, subdevice);
441441
DEF_FIELD(symval, pci_device_id, class);
442442
DEF_FIELD(symval, pci_device_id, class_mask);
443+
DEF_FIELD(symval, pci_device_id, override_only);
444+
445+
switch (override_only) {
446+
case 0:
447+
strcpy(alias, "pci:");
448+
break;
449+
case PCI_ID_F_VFIO_DRIVER_OVERRIDE:
450+
strcpy(alias, "vfio_pci:");
451+
break;
452+
default:
453+
warn("Unknown PCI driver_override alias %08X\n",
454+
override_only);
455+
return 0;
456+
}
443457

444-
strcpy(alias, "pci:");
445458
ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
446459
ADD(alias, "d", device != PCI_ANY_ID, device);
447460
ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);

0 commit comments

Comments
 (0)