[PATCH v3 00/13] Support for VFIO variant drivers, Part 2

This is "V3 of Part 2". "V2 of Part 2": is here: https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/EVHMT... Part 1 (which simply made it possible to use virsh nodedev-detach to bind a device to a manually-specified variant driver, and at guest runtime allowed libvirt to ignore the fact that the driver found to the device was something other than exactly "vfio-pci") was here: https://listman.redhat.com/archives/libvir-list/2023-August/241338.html and pushed upstream as of commit v9.6.0-153-g24beaffec3 Part 2 adds two new pieces of functionality: 1) It is possible to manually specify a VFIO variant driver (or force the generic vfio-pci driver) for a device in the domain XML with, e.g.: <driver name='mlx5_vfio_pci'/> (for the former) or: <driver name='vfio-pci'/> (for the latter). 2) By default libvirt will now find the "best match" VFIO or VFIO variant driver by comparing the device's modalias file contents (in sysfs) with vfio drivers found in the running kernel's modules.alias file. This means that "virsh nodedev-detach" of a host device will bind it to its appropriate VFIO variant driver (if one is available), and also if a <hostdev> decice in a domain config has "managed='yes'", libvirt will bind it to a variant driver if possible (in order to force binding to the basic vfio-pci driver instead, you just need to add the <driver> element mentioned above). Differences from V2 to V3: * I attempted to simplify my explanation of the confusion with module name vs. driver name that I had in the commit log of patch 1. * I think I've addressed all of the minor issues pointed out by Peter in his reviews V2 (joining unnecessarily split lines, failing when a modalias file can't be found (rather than "kind of" ignoring it), and other minor fixes. * The main difference between V2 and V3 is that I've relented on the issue of re-using the existing <driver name='blah'/> attribute (due to potential backwrd compatibility problems we might encounter), and am instead adding a new attribute <driver model='blah'/>. This means that both the driver name and the new driver model attribute names don't make as much sense, but that's what fancy GUI frontends are for -hiding the borderline-confusing names! * One change suggested by Peter that I enthusiastically agree with, but haven't implemented in V3 is to cache the few relevant lines of modules.alias rather than rereading the entire file each time. I do agree with him, but have run out of steam (and time) to implement it now - I do promise a followup with this functionality "soon". Patches 2-9 and 11 were already ACKed by Peter in V2 (several of them conditionally based on some minor fixes that I have made). This leaves only patches 1, 10, 12, and 13 that require an ACK (V2 had 15 patches, but I removed two of them). Laine Stump (13): util: properly deal with VFIO module name vs. driver name schema: consolidate RNG for all hostdev <driver> elements conf: move/rename hostdev PCI driver type enum to device_conf.h conf: normalize hostdev <driver> parsing to simplify adding new attr conf: put hostdev PCI backend into a struct conf: use virDeviceHostdevPCIDriverInfo in network and networkport objects conf: split out hostdev <driver> parse/format to their own functions conf: use new common parser/formatter for hostdev driver in network XML conf: replace virHostdevIsVFIODevice with virHostdevIsPCIDevice xen: explicitly set hostdev driver.name at runtime, not in postparse tests: remove explicit <driver name='vfio'/> from hostdev test cases conf: support manually specifying VFIO variant driver in <hostdev> XML qemu: automatically bind to a vfio variant driver, if available docs/formatdomain.rst | 55 ++- docs/formatnetwork.rst | 22 +- docs/formatnetworkport.rst | 1 - docs/pci-addresses.rst | 1 - src/conf/device_conf.c | 59 +++ src/conf/device_conf.h | 27 ++ src/conf/domain_capabilities.c | 2 +- src/conf/domain_capabilities.h | 2 +- src/conf/domain_conf.c | 98 +---- src/conf/domain_conf.h | 18 +- src/conf/network_conf.c | 42 +- src/conf/network_conf.h | 17 +- src/conf/schemas/basictypes.rng | 20 + src/conf/schemas/domaincommon.rng | 173 ++++---- src/conf/schemas/network.rng | 10 +- src/conf/schemas/networkport.rng | 10 +- src/conf/virconftypes.h | 2 + src/conf/virnetworkportdef.c | 22 +- src/conf/virnetworkportdef.h | 4 +- src/hypervisor/virhostdev.c | 16 +- src/hypervisor/virhostdev.h | 2 - src/libvirt_private.syms | 8 +- src/libxl/libxl_capabilities.c | 3 +- src/libxl/libxl_domain.c | 73 +++- src/libxl/libxl_driver.c | 25 +- src/network/bridge_driver.c | 3 +- src/qemu/qemu_capabilities.c | 4 +- src/qemu/qemu_command.c | 16 +- src/qemu/qemu_domain.c | 28 +- src/qemu/qemu_hostdev.c | 2 +- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_validate.c | 6 +- src/security/security_apparmor.c | 2 +- src/security/security_dac.c | 4 +- src/security/security_selinux.c | 4 +- src/security/virt-aa-helper.c | 7 +- src/test/test_driver.c | 18 +- src/util/virpci.c | 410 ++++++++++++++++-- src/util/virpci.h | 2 + tests/domaincapstest.c | 4 +- tests/libxlxml2domconfigdata/moredevs-hvm.xml | 1 - tests/networkxml2xmlin/hostdev-pf-old.xml | 8 + tests/networkxml2xmlin/hostdev-pf.xml | 1 - tests/networkxml2xmlout/hostdev-pf-old.xml | 8 + tests/networkxml2xmlout/hostdev-pf.xml | 1 - tests/networkxml2xmltest.c | 6 + .../qemuhotplug-hostdev-pci.xml | 1 - .../qemumemlock-pc-hardlimit+hostdev.xml | 1 - ...emumemlock-pc-hardlimit+locked+hostdev.xml | 1 - .../qemumemlock-pc-hostdev-nvme.xml | 1 - .../qemumemlock-pc-hostdev.xml | 1 - .../qemumemlock-pc-locked+hostdev.xml | 1 - .../qemumemlock-pseries-hardlimit+hostdev.xml | 1 - ...mlock-pseries-hardlimit+locked+hostdev.xml | 1 - .../qemumemlock-pseries-hostdev.xml | 1 - .../qemumemlock-pseries-locked+hostdev.xml | 1 - tests/qemustatusxml2xmldata/modern-in.xml | 1 - .../hostdev-pci-address-unassigned.xml | 4 - .../hostdev-pci-multifunction.xml | 7 - .../hostdev-vfio-multidomain.xml | 1 - .../hostdev-vfio-zpci-autogenerate-fids.xml | 2 - .../hostdev-vfio-zpci-autogenerate-uids.xml | 2 - .../hostdev-vfio-zpci-autogenerate.xml | 1 - .../hostdev-vfio-zpci-boundaries.xml | 2 - .../hostdev-vfio-zpci-ccw-memballoon.xml | 1 - .../hostdev-vfio-zpci-duplicate.xml | 2 - ...ostdev-vfio-zpci-invalid-uid-valid-fid.xml | 1 - .../hostdev-vfio-zpci-multidomain-many.xml | 8 - .../hostdev-vfio-zpci-set-zero.xml | 1 - .../hostdev-vfio-zpci-uid-set-zero.xml | 1 - .../hostdev-vfio-zpci-wrong-arch.xml | 1 - tests/qemuxml2argvdata/hostdev-vfio-zpci.xml | 1 - .../hostdev-vfio.x86_64-latest.args | 5 +- tests/qemuxml2argvdata/hostdev-vfio.xml | 19 +- .../net-hostdev-vfio-multidomain.xml | 1 - tests/qemuxml2argvdata/net-hostdev-vfio.xml | 1 - tests/qemuxml2argvdata/pseries-hostdevs-1.xml | 3 - tests/qemuxml2argvdata/pseries-hostdevs-2.xml | 2 - tests/qemuxml2argvdata/pseries-hostdevs-3.xml | 2 - ...v-pci-address-unassigned.x86_64-latest.xml | 4 - ...ostdev-pci-multifunction.x86_64-latest.xml | 7 - ...dev-vfio-old-driver-name.x86_64-latest.xml | 46 ++ ...io-zpci-autogenerate-fids.s390x-latest.xml | 2 - ...io-zpci-autogenerate-uids.s390x-latest.xml | 2 - ...ev-vfio-zpci-autogenerate.s390x-latest.xml | 1 - ...tdev-vfio-zpci-boundaries.s390x-latest.xml | 2 - ...-vfio-zpci-ccw-memballoon.s390x-latest.xml | 1 - ...fio-zpci-multidomain-many.s390x-latest.xml | 8 - .../hostdev-vfio-zpci.s390x-latest.xml | 1 - .../hostdev-vfio.x86_64-latest.xml | 24 +- .../net-hostdev-vfio.x86_64-latest.xml | 1 - .../pseries-hostdevs-1.ppc64-latest.xml | 3 - .../pseries-hostdevs-2.ppc64-latest.xml | 2 - .../pseries-hostdevs-3.ppc64-latest.xml | 2 - tests/virhostdevtest.c | 2 +- .../plug-hostdev-pci-unmanaged.xml | 1 - .../plug-hostdev-pci.xml | 1 - tests/virpcimock.c | 9 + tests/xlconfigdata/test-fullvirt-pci.xml | 2 - tests/xmconfigdata/test-pci-dev-syntax.xml | 2 - tests/xmconfigdata/test-pci-devs.xml | 2 - tools/virsh-completer-nodedev.c | 4 +- 102 files changed, 927 insertions(+), 530 deletions(-) create mode 100644 tests/networkxml2xmlin/hostdev-pf-old.xml create mode 100644 tests/networkxml2xmlout/hostdev-pf-old.xml create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-old-driver-name.x86_64-latest.xml -- 2.43.0

Historically libvirt hasn't differentiated between the name of a loadable kernel module, and the name of the device driver that module implements, but these two names can be (and usually are) at least subtly different. For example, the loadable module called "vfio_pci" implements a PCI driver called "vfio-pci". We have always used the name "vfio-pci" both to load the module (with modprobe) and to check (in /sys/bus/pci/drivers) if the driver is available. (This has happened to work because modprobe "normalizes" all the names it is given by replacing "-" with "_", so "vfio-pci" works for both loading the module and checking for the driver.) When we recently gained the ability to manually specify the driver for "virsh nodedev-detach", the fragility of this system became apparent - if a user gave the "driver name" as "vfio_pci", then we would modprobe the module correctly, but then erroneously believe it hadn't been loaded because /sys/bus/pci/drivers/vfio_pci didn't exist. For manual specification of the driver name, we could deal with this by telling the user "always use the correct name for the driver, don't assume that it has the same name as the module", but it would still end up confusing people, especially since some drivers do use underscore in their name (e.g. the mlx5_vfio_pci driver/module). This will only get worse when an upcoming patch starts automatically determining the driver to use for VFIO-assigned devices - it will look in the kernel's modules.alias file to find "best" VFIO variant *module* for a device, and 3 out of 4 current examples of vfio-pci/variant drivers have a mismatch between module name and driver name, so the current code would end up properly loading the module, but then erroneously think that the driver wasn't available. This patch makes the code more forgiving by 1) checking for both $drivername and underscore($drivername) in /sys/bus/pci/drivers 2) when we determine a module needs to be loaded, look at the link in /sys/module/$modulename/driver/pci:$drivername to determine the name of the driver we need to bind to the device(rather than just assuming the driver has the same name as the module Signed-off-by: Laine Stump <laine@redhat.com> --- Change from V1: I tried to simplify the explanation in the commit log message src/util/virpci.c | 193 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 30 deletions(-) diff --git a/src/util/virpci.c b/src/util/virpci.c index afce7b52b7..f6bdf56057 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -222,6 +222,13 @@ virPCIDriverDir(const char *driver) } +static char * +virPCIModuleDir(const char *module) +{ + return g_strdup_printf("/sys/module/%s", module); +} + + static char * virPCIFile(const char *device, const char *file) { @@ -1154,44 +1161,166 @@ virPCIDeviceReset(virPCIDevice *dev, } +/** + * virPCINameDashToUnderscore: + * @path: the module/driver name or path - will be directly modified + * + * Replace all occurences of "-" with "_" in the name + * part of the path (everything after final "/" + * + * return true if any change was made, otherwise false. + */ static int -virPCIProbeDriver(const char *driverName) +virPCINameDashToUnderscore(char *path) { - g_autofree char *drvpath = NULL; + bool changed = false; + char *tmp = strrchr(path, '/'); + + if (!tmp) + tmp = path; + + while (*tmp) { + if (*tmp == '-') { + *tmp = '_'; + changed = true; + } + tmp++; + } + + return changed; +} + + +static int +virPCIProbeModule(const char *moduleName) +{ + g_autofree char *modulePath = NULL; g_autofree char *errbuf = NULL; - drvpath = virPCIDriverDir(driverName); + modulePath = virPCIModuleDir(moduleName); /* driver previously loaded, return */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0; - if ((errbuf = virKModLoad(driverName))) { - VIR_WARN("failed to load driver %s: %s", driverName, errbuf); - goto cleanup; + if ((errbuf = virKModLoad(moduleName))) { + /* If we know failure was because of admin config, let's report that; + * otherwise, report a more generic failure message + */ + if (virKModIsProhibited(moduleName)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI driver module %1$s: administratively prohibited"), + moduleName); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI driver module %1$s: %2$s"), + moduleName, errbuf); + } + return -1; } /* driver loaded after probing */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0; - cleanup: - /* If we know failure was because of admin config, let's report that; - * otherwise, report a more generic failure message + virReportError(VIR_ERR_INTERNAL_ERROR, + _("modprobe reported success loading module '%1$s', but module is missing from /sys/module"), + moduleName); + return -1; +} + +/** + * virPCIDeviceFindDriver: + * @dev: initialized virPCIDevice, including desired stubDriverName + * + * Checks if there is a driver named @dev->stubDriverName already + * loaded. If there is, we're done. If not, look for a driver with + * that same name, except with dashes replaced with underscores. + + * If neither of the above is found, then look for/load the module of + * the underscored version of the name, and follow the links from + * /sys/module/$name/drivers/pci:* to the PCI driver associated with that + * module, and update @dev->stubDriverName with that name. + * + * On a successful return, @dev->stubDriverName will be updated with + * the proper name for the driver, and that driver will be loaded. + * + * returns 0 on success, -1 on failure + */ +static int +virPCIDeviceFindDriver(virPCIDevice *dev) +{ + g_autofree char *driverPath = virPCIDriverDir(dev->stubDriverName); + g_autofree char *moduleName = NULL; + g_autofree char *moduleDriversDir = NULL; + g_autoptr(DIR) dir = NULL; + struct dirent *ent; + int direrr; + + /* unchanged stubDriverName */ + if (virFileExists(driverPath)) + return 0; + + /* try replacing "-" with "_" */ + if (virPCINameDashToUnderscore(driverPath) && virFileExists(driverPath)) { + + /* update original name in dev */ + virPCINameDashToUnderscore(dev->stubDriverName); + return 0; + } + + /* look for a module with this name (but always replacing + * "-" with "_", since that's what modprobe does) */ - if (virKModIsProhibited(driverName)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s: administratively prohibited"), - driverName); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s"), - driverName); + + moduleName = g_strdup(dev->stubDriverName); + virPCINameDashToUnderscore(moduleName); + + if (virPCIProbeModule(moduleName) < 0) + return -1; + + /* module was found/loaded. Now find the PCI driver it implements, + * linked to by /sys/module/$moduleName/drivers/pci:$driverName + */ + + moduleDriversDir = g_strdup_printf("/sys/module/%s/drivers", moduleName); + + if (virDirOpen(&dir, moduleDriversDir) < 0) + return -1; + + while ((direrr = virDirRead(dir, &ent, moduleDriversDir))) { + + if (STRPREFIX(ent->d_name, "pci:")) { + /* this is the link to the driver we want */ + + g_autofree char *drvName = NULL; + g_autofree char *drvPath = NULL; + + /* extract the driver name from the link name */ + drvName = g_strdup(ent->d_name + strlen("pci:")); + + /* make sure that driver is actually loaded */ + drvPath = virPCIDriverDir(drvName); + if (!virFileExists(drvPath)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("pci driver '%1$s' supposedly loaded by module '%2$s' not found in sysfs"), + drvName, moduleName); + return -1; + } + + g_free(dev->stubDriverName); + dev->stubDriverName = g_steal_pointer(&drvName); + return 0; + } } + virReportError(VIR_ERR_INTERNAL_ERROR, + _("module '%1$s' does not implement any pci driver"), + moduleName); return -1; } + int virPCIDeviceUnbind(virPCIDevice *dev) { @@ -1291,7 +1420,6 @@ virPCIDeviceUnbindFromStub(virPCIDevice *dev) static int virPCIDeviceBindToStub(virPCIDevice *dev) { - const char *stubDriverName = dev->stubDriverName; g_autofree char *stubDriverPath = NULL; g_autofree char *driverLink = NULL; @@ -1303,30 +1431,35 @@ virPCIDeviceBindToStub(virPCIDevice *dev) return -1; } - if (!stubDriverName - && !(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown stub driver configured for PCI device %1$s"), - dev->name); - return -1; + if (!dev->stubDriverName) { + + const char *stubDriverName = NULL; + + if (!(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown stub driver configured for PCI device %1$s"), + dev->name); + return -1; + } + dev->stubDriverName = g_strdup(stubDriverName); } - if (virPCIProbeDriver(stubDriverName) < 0) + if (virPCIDeviceFindDriver(dev) < 0) return -1; - stubDriverPath = virPCIDriverDir(stubDriverName); + stubDriverPath = virPCIDriverDir(dev->stubDriverName); driverLink = virPCIFile(dev->name, "driver"); if (virFileExists(driverLink)) { if (virFileLinkPointsTo(driverLink, stubDriverPath)) { /* The device is already bound to the correct driver */ VIR_DEBUG("Device %s is already bound to %s", - dev->name, stubDriverName); + dev->name, dev->stubDriverName); return 0; } } - if (virPCIDeviceBindWithDriverOverride(dev, stubDriverName) < 0) + if (virPCIDeviceBindWithDriverOverride(dev, dev->stubDriverName) < 0) return -1; dev->unbind_from_stub = true; -- 2.43.0

On Fri, Jan 05, 2024 at 03:20:04 -0500, Laine Stump wrote:
Historically libvirt hasn't differentiated between the name of a loadable kernel module, and the name of the device driver that module implements, but these two names can be (and usually are) at least subtly different.
For example, the loadable module called "vfio_pci" implements a PCI driver called "vfio-pci". We have always used the name "vfio-pci" both to load the module (with modprobe) and to check (in /sys/bus/pci/drivers) if the driver is available. (This has happened to work because modprobe "normalizes" all the names it is given by replacing "-" with "_", so "vfio-pci" works for both loading the module and checking for the driver.)
When we recently gained the ability to manually specify the driver for "virsh nodedev-detach", the fragility of this system became apparent - if a user gave the "driver name" as "vfio_pci", then we would modprobe the module correctly, but then erroneously believe it hadn't been loaded because /sys/bus/pci/drivers/vfio_pci didn't exist. For manual specification of the driver name, we could deal with this by telling the user "always use the correct name for the driver, don't assume that it has the same name as the module", but it would still end up confusing people, especially since some drivers do use underscore in their name (e.g. the mlx5_vfio_pci driver/module).
This will only get worse when an upcoming patch starts automatically determining the driver to use for VFIO-assigned devices - it will look in the kernel's modules.alias file to find "best" VFIO variant *module* for a device, and 3 out of 4 current examples of vfio-pci/variant drivers have a mismatch between module name and driver name, so the current code would end up properly loading the module, but then erroneously think that the driver wasn't available.
This patch makes the code more forgiving by
1) checking for both $drivername and underscore($drivername) in /sys/bus/pci/drivers
2) when we determine a module needs to be loaded, look at the link in /sys/module/$modulename/driver/pci:$drivername to determine the name of the driver we need to bind to the device(rather than just assuming the driver has the same name as the module
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V1: I tried to simplify the explanation in the commit log message
I don't think this addresses Jason's comment from V1, stating that we should only deal with driver names and let modprobe find the correct module. Same thing when you are looking for the best *driver* for the device. Yes you find a module name, but you can query the module itself for the driver and just use the driver. As Jason stated, we should not deal with modules at all. Without addressing this I will not give a R-b.

On 1/5/24 9:22 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:04 -0500, Laine Stump wrote:
Historically libvirt hasn't differentiated between the name of a loadable kernel module, and the name of the device driver that module implements, but these two names can be (and usually are) at least subtly different.
For example, the loadable module called "vfio_pci" implements a PCI driver called "vfio-pci". We have always used the name "vfio-pci" both to load the module (with modprobe) and to check (in /sys/bus/pci/drivers) if the driver is available. (This has happened to work because modprobe "normalizes" all the names it is given by replacing "-" with "_", so "vfio-pci" works for both loading the module and checking for the driver.)
When we recently gained the ability to manually specify the driver for "virsh nodedev-detach", the fragility of this system became apparent - if a user gave the "driver name" as "vfio_pci", then we would modprobe the module correctly, but then erroneously believe it hadn't been loaded because /sys/bus/pci/drivers/vfio_pci didn't exist. For manual specification of the driver name, we could deal with this by telling the user "always use the correct name for the driver, don't assume that it has the same name as the module", but it would still end up confusing people, especially since some drivers do use underscore in their name (e.g. the mlx5_vfio_pci driver/module).
This will only get worse when an upcoming patch starts automatically determining the driver to use for VFIO-assigned devices - it will look in the kernel's modules.alias file to find "best" VFIO variant *module* for a device, and 3 out of 4 current examples of vfio-pci/variant drivers have a mismatch between module name and driver name, so the current code would end up properly loading the module, but then erroneously think that the driver wasn't available.
This patch makes the code more forgiving by
1) checking for both $drivername and underscore($drivername) in /sys/bus/pci/drivers
2) when we determine a module needs to be loaded, look at the link in /sys/module/$modulename/driver/pci:$drivername to determine the name of the driver we need to bind to the device(rather than just assuming the driver has the same name as the module
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V1: I tried to simplify the explanation in the commit log message
I don't think this addresses Jason's comment from V1, stating that we should only deal with driver names and let modprobe find the correct module.
modprobe has no way of "finding" the proper module for a given driver - all it does is replace "-" with "_" in the name and hope for the best. The problem is that the way to get to module name from a driver name is to follow the links in the driver's directory in sysfs, but the driver's directory in sysfs doesn't exist until the module has been loaded, and if the module is already loaded then you don't need to know the name of the module any more.
Same thing when you are looking for the best *driver* for the device. Yes you find a module name, but you can query the module itself for the driver and just use the driver.
That is what we end up doing - when we find the module name for a variant, we load that module and then follow the link to get to the driver.
As Jason stated, we should not deal with modules at all.
I disagree. If the module for a driver isn't loaded, then (unless the modulename happens to be (underscore($drivername)) there is no way to figure out what module to load. (If the module had already been loaded, then we could follow the links in sysfs from driver to module, but of course if the module is already loaded then we don't need to know the module name!) In the end, though, with the currently existing VFIO/VFIO-variant drivers, the only point of contention is that my current code allows specifying <driver name='vfio_pci'/> in the XML, and you (and Jason) are saying that we shouldn't allow that, but should require <driver name='vfio-pci'/>. Since, at some point *internally* we do need to support starting with "vfio_pci" and end up with "vfio-pci", this all comes down to whether the extra flexibility is at a higher level (as in this patch) or if it's only done at a lower level (i.e. doing it during the virPCIDeviceFindBestVFIOVariant() in patch 13). I'll see if I can make something that does it at that level and resubmit (but will then forward any bug reports about failing with <driver name='vfio_pci'/> to you :-P)
Without addressing this I will not give a R-b.

On Fri, Jan 05, 2024 at 10:33:33 -0500, Laine Stump wrote:
On 1/5/24 9:22 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:04 -0500, Laine Stump wrote:
[...]
Change from V1: I tried to simplify the explanation in the commit log message
I don't think this addresses Jason's comment from V1, stating that we should only deal with driver names and let modprobe find the correct module.
modprobe has no way of "finding" the proper module for a given driver - all it does is replace "-" with "_" in the name and hope for the best. The problem is that the way to get to module name from a driver name is to follow the links in the driver's directory in sysfs, but the driver's directory in sysfs doesn't exist until the module has been loaded, and if the module is already loaded then you don't need to know the name of the module any more.
Same thing when you are looking for the best *driver* for the device. Yes you find a module name, but you can query the module itself for the driver and just use the driver.
That is what we end up doing - when we find the module name for a variant, we load that module and then follow the link to get to the driver.
As Jason stated, we should not deal with modules at all.
I disagree. If the module for a driver isn't loaded, then (unless the modulename happens to be (underscore($drivername)) there is no way to figure out what module to load.
(If the module had already been loaded, then we could follow the links in sysfs from driver to module, but of course if the module is already loaded then we don't need to know the module name!)
In the end, though, with the currently existing VFIO/VFIO-variant drivers, the only point of contention is that my current code allows specifying <driver name='vfio_pci'/> in the XML, and you (and Jason) are saying that we shouldn't allow that, but should require <driver name='vfio-pci'/>. Since, at some point *internally* we do need to support starting with "vfio_pci" and end up with "vfio-pci", this all comes down to whether the extra flexibility is at a higher level (as in this patch) or if it's only done at a lower level (i.e. doing it during the virPCIDeviceFindBestVFIOVariant() in patch 13). I'll see if I can make something that does it at that level and resubmit (but will then forward any bug reports about failing with <driver name='vfio_pci'/> to you :-P)
Fair enough, I think this explanation is sufficient for me. I've done a proper review in another subthread.

On Fri, Jan 05, 2024 at 03:20:04 -0500, Laine Stump wrote:
Historically libvirt hasn't differentiated between the name of a loadable kernel module, and the name of the device driver that module implements, but these two names can be (and usually are) at least subtly different.
For example, the loadable module called "vfio_pci" implements a PCI driver called "vfio-pci". We have always used the name "vfio-pci" both to load the module (with modprobe) and to check (in /sys/bus/pci/drivers) if the driver is available. (This has happened to work because modprobe "normalizes" all the names it is given by replacing "-" with "_", so "vfio-pci" works for both loading the module and checking for the driver.)
When we recently gained the ability to manually specify the driver for "virsh nodedev-detach", the fragility of this system became apparent - if a user gave the "driver name" as "vfio_pci", then we would modprobe the module correctly, but then erroneously believe it hadn't been loaded because /sys/bus/pci/drivers/vfio_pci didn't exist. For manual specification of the driver name, we could deal with this by telling the user "always use the correct name for the driver, don't assume that it has the same name as the module", but it would still end up confusing people, especially since some drivers do use underscore in their name (e.g. the mlx5_vfio_pci driver/module).
This will only get worse when an upcoming patch starts automatically determining the driver to use for VFIO-assigned devices - it will look in the kernel's modules.alias file to find "best" VFIO variant *module* for a device, and 3 out of 4 current examples of vfio-pci/variant drivers have a mismatch between module name and driver name, so the current code would end up properly loading the module, but then erroneously think that the driver wasn't available.
This patch makes the code more forgiving by
1) checking for both $drivername and underscore($drivername) in /sys/bus/pci/drivers
2) when we determine a module needs to be loaded, look at the link in /sys/module/$modulename/driver/pci:$drivername to determine the name of the driver we need to bind to the device(rather than just assuming the driver has the same name as the module
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V1: I tried to simplify the explanation in the commit log message
src/util/virpci.c | 193 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 30 deletions(-)
[...]
@@ -1154,44 +1161,166 @@ virPCIDeviceReset(virPCIDevice *dev, }
+/** + * virPCINameDashToUnderscore: + * @path: the module/driver name or path - will be directly modified + * + * Replace all occurences of "-" with "_" in the name + * part of the path (everything after final "/" + * + * return true if any change was made, otherwise false. + */ static int
'int'
-virPCIProbeDriver(const char *driverName) +virPCINameDashToUnderscore(char *path) { - g_autofree char *drvpath = NULL; + bool changed = false;
'bool'
+ char *tmp = strrchr(path, '/'); + + if (!tmp) + tmp = path; + + while (*tmp) { + if (*tmp == '-') { + *tmp = '_'; + changed = true; + } + tmp++; + } + + return changed;
bool returned as int.
+} + +
+static int +virPCIProbeModule(const char *moduleName) +{ + g_autofree char *modulePath = NULL; g_autofree char *errbuf = NULL;
- drvpath = virPCIDriverDir(driverName); + modulePath = virPCIModuleDir(moduleName);
/* driver previously loaded, return */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0;
- if ((errbuf = virKModLoad(driverName))) { - VIR_WARN("failed to load driver %s: %s", driverName, errbuf); - goto cleanup; + if ((errbuf = virKModLoad(moduleName))) { + /* If we know failure was because of admin config, let's report that; + * otherwise, report a more generic failure message + */ + if (virKModIsProhibited(moduleName)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI driver module %1$s: administratively prohibited"),
Based on this message it's definitely not an VIR_ERR_INTERNAL_ERROR
+ moduleName); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR,
and this too is not really internal
+ _("Failed to load PCI driver module %1$s: %2$s"), + moduleName, errbuf); + } + return -1; }
/* driver loaded after probing */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0;
- cleanup: - /* If we know failure was because of admin config, let's report that; - * otherwise, report a more generic failure message + virReportError(VIR_ERR_INTERNAL_ERROR,
and this too.
+ _("modprobe reported success loading module '%1$s', but module is missing from /sys/module"), + moduleName); + return -1; +} + +/** + * virPCIDeviceFindDriver: + * @dev: initialized virPCIDevice, including desired stubDriverName + * + * Checks if there is a driver named @dev->stubDriverName already + * loaded. If there is, we're done. If not, look for a driver with + * that same name, except with dashes replaced with underscores. + + * If neither of the above is found, then look for/load the module of + * the underscored version of the name, and follow the links from + * /sys/module/$name/drivers/pci:* to the PCI driver associated with that + * module, and update @dev->stubDriverName with that name. + * + * On a successful return, @dev->stubDriverName will be updated with + * the proper name for the driver, and that driver will be loaded. + * + * returns 0 on success, -1 on failure + */ +static int +virPCIDeviceFindDriver(virPCIDevice *dev) +{ + g_autofree char *driverPath = virPCIDriverDir(dev->stubDriverName); + g_autofree char *moduleName = NULL; + g_autofree char *moduleDriversDir = NULL; + g_autoptr(DIR) dir = NULL; + struct dirent *ent; + int direrr; + + /* unchanged stubDriverName */ + if (virFileExists(driverPath)) + return 0; + + /* try replacing "-" with "_" */ + if (virPCINameDashToUnderscore(driverPath) && virFileExists(driverPath)) { + + /* update original name in dev */ + virPCINameDashToUnderscore(dev->stubDriverName); + return 0; + } + + /* look for a module with this name (but always replacing + * "-" with "_", since that's what modprobe does) */ - if (virKModIsProhibited(driverName)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s: administratively prohibited"), - driverName); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s"), - driverName); + + moduleName = g_strdup(dev->stubDriverName); + virPCINameDashToUnderscore(moduleName); + + if (virPCIProbeModule(moduleName) < 0) + return -1; + + /* module was found/loaded. Now find the PCI driver it implements, + * linked to by /sys/module/$moduleName/drivers/pci:$driverName + */ + + moduleDriversDir = g_strdup_printf("/sys/module/%s/drivers", moduleName); + + if (virDirOpen(&dir, moduleDriversDir) < 0) + return -1; + + while ((direrr = virDirRead(dir, &ent, moduleDriversDir))) {
This is only assigned but not read. Also iteration must not continue if -1 is returned, which is usually what direrr is used for.
+ + if (STRPREFIX(ent->d_name, "pci:")) { + /* this is the link to the driver we want */ + + g_autofree char *drvName = NULL; + g_autofree char *drvPath = NULL; + + /* extract the driver name from the link name */ + drvName = g_strdup(ent->d_name + strlen("pci:")); + + /* make sure that driver is actually loaded */ + drvPath = virPCIDriverDir(drvName); + if (!virFileExists(drvPath)) { + virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("pci driver '%1$s' supposedly loaded by module '%2$s' not found in sysfs"), + drvName, moduleName); + return -1; + } + + g_free(dev->stubDriverName); + dev->stubDriverName = g_steal_pointer(&drvName); + return 0; + } }
+ virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("module '%1$s' does not implement any pci driver"), + moduleName); return -1; }
+ int virPCIDeviceUnbind(virPCIDevice *dev) { @@ -1291,7 +1420,6 @@ virPCIDeviceUnbindFromStub(virPCIDevice *dev) static int virPCIDeviceBindToStub(virPCIDevice *dev) { - const char *stubDriverName = dev->stubDriverName; g_autofree char *stubDriverPath = NULL; g_autofree char *driverLink = NULL;
@@ -1303,30 +1431,35 @@ virPCIDeviceBindToStub(virPCIDevice *dev) return -1; }
- if (!stubDriverName - && !(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown stub driver configured for PCI device %1$s"), - dev->name); - return -1; + if (!dev->stubDriverName) { + + const char *stubDriverName = NULL; + + if (!(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { + virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("Unknown stub driver configured for PCI device %1$s"), + dev->name); + return -1; + } + dev->stubDriverName = g_strdup(stubDriverName); }
- if (virPCIProbeDriver(stubDriverName) < 0) + if (virPCIDeviceFindDriver(dev) < 0) return -1;
- stubDriverPath = virPCIDriverDir(stubDriverName); + stubDriverPath = virPCIDriverDir(dev->stubDriverName); driverLink = virPCIFile(dev->name, "driver");
if (virFileExists(driverLink)) { if (virFileLinkPointsTo(driverLink, stubDriverPath)) { /* The device is already bound to the correct driver */ VIR_DEBUG("Device %s is already bound to %s", - dev->name, stubDriverName); + dev->name, dev->stubDriverName); return 0; } }
- if (virPCIDeviceBindWithDriverOverride(dev, stubDriverName) < 0) + if (virPCIDeviceBindWithDriverOverride(dev, dev->stubDriverName) < 0) return -1;
dev->unbind_from_stub = true;
With the stuff above addressed: Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On 1/5/24 3:03 PM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:04 -0500, Laine Stump wrote:
Historically libvirt hasn't differentiated between the name of a loadable kernel module, and the name of the device driver that module implements, but these two names can be (and usually are) at least subtly different.
For example, the loadable module called "vfio_pci" implements a PCI driver called "vfio-pci". We have always used the name "vfio-pci" both to load the module (with modprobe) and to check (in /sys/bus/pci/drivers) if the driver is available. (This has happened to work because modprobe "normalizes" all the names it is given by replacing "-" with "_", so "vfio-pci" works for both loading the module and checking for the driver.)
When we recently gained the ability to manually specify the driver for "virsh nodedev-detach", the fragility of this system became apparent - if a user gave the "driver name" as "vfio_pci", then we would modprobe the module correctly, but then erroneously believe it hadn't been loaded because /sys/bus/pci/drivers/vfio_pci didn't exist. For manual specification of the driver name, we could deal with this by telling the user "always use the correct name for the driver, don't assume that it has the same name as the module", but it would still end up confusing people, especially since some drivers do use underscore in their name (e.g. the mlx5_vfio_pci driver/module).
This will only get worse when an upcoming patch starts automatically determining the driver to use for VFIO-assigned devices - it will look in the kernel's modules.alias file to find "best" VFIO variant *module* for a device, and 3 out of 4 current examples of vfio-pci/variant drivers have a mismatch between module name and driver name, so the current code would end up properly loading the module, but then erroneously think that the driver wasn't available.
This patch makes the code more forgiving by
1) checking for both $drivername and underscore($drivername) in /sys/bus/pci/drivers
2) when we determine a module needs to be loaded, look at the link in /sys/module/$modulename/driver/pci:$drivername to determine the name of the driver we need to bind to the device(rather than just assuming the driver has the same name as the module
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V1: I tried to simplify the explanation in the commit log message
src/util/virpci.c | 193 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 30 deletions(-)
[...]
@@ -1154,44 +1161,166 @@ virPCIDeviceReset(virPCIDevice *dev, }
+/** + * virPCINameDashToUnderscore: + * @path: the module/driver name or path - will be directly modified + * + * Replace all occurences of "-" with "_" in the name + * part of the path (everything after final "/" + * + * return true if any change was made, otherwise false. + */ static int
'int'
-virPCIProbeDriver(const char *driverName) +virPCINameDashToUnderscore(char *path) { - g_autofree char *drvpath = NULL; + bool changed = false;
'bool'
+ char *tmp = strrchr(path, '/'); + + if (!tmp) + tmp = path; + + while (*tmp) { + if (*tmp == '-') { + *tmp = '_'; + changed = true; + } + tmp++; + } + + return changed;
bool returned as int.
Sigh. How am I still alive? (well, this is pretty innocuous, but still incorrect... Good thing I don't work on nuclear plant safety software or something) :-/
+} + +
+static int +virPCIProbeModule(const char *moduleName) +{ + g_autofree char *modulePath = NULL; g_autofree char *errbuf = NULL;
- drvpath = virPCIDriverDir(driverName); + modulePath = virPCIModuleDir(moduleName);
/* driver previously loaded, return */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0;
- if ((errbuf = virKModLoad(driverName))) { - VIR_WARN("failed to load driver %s: %s", driverName, errbuf); - goto cleanup; + if ((errbuf = virKModLoad(moduleName))) { + /* If we know failure was because of admin config, let's report that; + * otherwise, report a more generic failure message + */ + if (virKModIsProhibited(moduleName)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI driver module %1$s: administratively prohibited"),
Based on this message it's definitely not an VIR_ERR_INTERNAL_ERROR
I always hate trying to categorize errors. What's your opinion of the proper category for these?
+ moduleName); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR,
and this too is not really internal
+ _("Failed to load PCI driver module %1$s: %2$s"), + moduleName, errbuf); + } + return -1; }
/* driver loaded after probing */ - if (virFileExists(drvpath)) + if (virFileExists(modulePath)) return 0;
- cleanup: - /* If we know failure was because of admin config, let's report that; - * otherwise, report a more generic failure message + virReportError(VIR_ERR_INTERNAL_ERROR,
and this too.
+ _("modprobe reported success loading module '%1$s', but module is missing from /sys/module"), + moduleName); + return -1; +} + +/** + * virPCIDeviceFindDriver: + * @dev: initialized virPCIDevice, including desired stubDriverName + * + * Checks if there is a driver named @dev->stubDriverName already + * loaded. If there is, we're done. If not, look for a driver with + * that same name, except with dashes replaced with underscores. + + * If neither of the above is found, then look for/load the module of + * the underscored version of the name, and follow the links from + * /sys/module/$name/drivers/pci:* to the PCI driver associated with that + * module, and update @dev->stubDriverName with that name. + * + * On a successful return, @dev->stubDriverName will be updated with + * the proper name for the driver, and that driver will be loaded. + * + * returns 0 on success, -1 on failure + */ +static int +virPCIDeviceFindDriver(virPCIDevice *dev) +{ + g_autofree char *driverPath = virPCIDriverDir(dev->stubDriverName); + g_autofree char *moduleName = NULL; + g_autofree char *moduleDriversDir = NULL; + g_autoptr(DIR) dir = NULL; + struct dirent *ent; + int direrr; + + /* unchanged stubDriverName */ + if (virFileExists(driverPath)) + return 0; + + /* try replacing "-" with "_" */ + if (virPCINameDashToUnderscore(driverPath) && virFileExists(driverPath)) { + + /* update original name in dev */ + virPCINameDashToUnderscore(dev->stubDriverName); + return 0; + } + + /* look for a module with this name (but always replacing + * "-" with "_", since that's what modprobe does) */ - if (virKModIsProhibited(driverName)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s: administratively prohibited"), - driverName); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI driver module %1$s"), - driverName); + + moduleName = g_strdup(dev->stubDriverName); + virPCINameDashToUnderscore(moduleName); + + if (virPCIProbeModule(moduleName) < 0) + return -1; + + /* module was found/loaded. Now find the PCI driver it implements, + * linked to by /sys/module/$moduleName/drivers/pci:$driverName + */ + + moduleDriversDir = g_strdup_printf("/sys/module/%s/drivers", moduleName); + + if (virDirOpen(&dir, moduleDriversDir) < 0) + return -1; + + while ((direrr = virDirRead(dir, &ent, moduleDriversDir))) {
This is only assigned but not read. Also iteration must not continue if -1 is returned, which is usually what direrr is used for.
Again, how am I still alive? It's troublesome that I would write this, since every single example of virDirRead in the entire tree checks for > 0 return :-/.
+ + if (STRPREFIX(ent->d_name, "pci:")) { + /* this is the link to the driver we want */ + + g_autofree char *drvName = NULL; + g_autofree char *drvPath = NULL; + + /* extract the driver name from the link name */ + drvName = g_strdup(ent->d_name + strlen("pci:")); + + /* make sure that driver is actually loaded */ + drvPath = virPCIDriverDir(drvName); + if (!virFileExists(drvPath)) { + virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("pci driver '%1$s' supposedly loaded by module '%2$s' not found in sysfs"), + drvName, moduleName); + return -1; + } + + g_free(dev->stubDriverName); + dev->stubDriverName = g_steal_pointer(&drvName); + return 0; + } }
+ virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("module '%1$s' does not implement any pci driver"), + moduleName); return -1; }
+ int virPCIDeviceUnbind(virPCIDevice *dev) { @@ -1291,7 +1420,6 @@ virPCIDeviceUnbindFromStub(virPCIDevice *dev) static int virPCIDeviceBindToStub(virPCIDevice *dev) { - const char *stubDriverName = dev->stubDriverName; g_autofree char *stubDriverPath = NULL; g_autofree char *driverLink = NULL;
@@ -1303,30 +1431,35 @@ virPCIDeviceBindToStub(virPCIDevice *dev) return -1; }
- if (!stubDriverName - && !(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown stub driver configured for PCI device %1$s"), - dev->name); - return -1; + if (!dev->stubDriverName) { + + const char *stubDriverName = NULL; + + if (!(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriverType))) { + virReportError(VIR_ERR_INTERNAL_ERROR,
Not an VIR_ERR_INTERNAL_ERROR
+ _("Unknown stub driver configured for PCI device %1$s"), + dev->name); + return -1; + } + dev->stubDriverName = g_strdup(stubDriverName); }
- if (virPCIProbeDriver(stubDriverName) < 0) + if (virPCIDeviceFindDriver(dev) < 0) return -1;
- stubDriverPath = virPCIDriverDir(stubDriverName); + stubDriverPath = virPCIDriverDir(dev->stubDriverName); driverLink = virPCIFile(dev->name, "driver");
if (virFileExists(driverLink)) { if (virFileLinkPointsTo(driverLink, stubDriverPath)) { /* The device is already bound to the correct driver */ VIR_DEBUG("Device %s is already bound to %s", - dev->name, stubDriverName); + dev->name, dev->stubDriverName); return 0; } }
- if (virPCIDeviceBindWithDriverOverride(dev, stubDriverName) < 0) + if (virPCIDeviceBindWithDriverOverride(dev, dev->stubDriverName) < 0) return -1;
dev->unbind_from_stub = true;
With the stuff above addressed:
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

The exact same element can appear in <hostdev> and <interface type='hostdev'>, and nearly identical in <network> and <networkport> (these latter two don't include "xen" as a possible driver, but that's coincidental - there's no reason Xen couldn't also use the VF pools in virtual networks, it just doesn't). This patch modifies all 4 to use the same <ref name="hostdevDriver"/> so that it is simpler to add something new. A side effect of this patch is that the grammar for the <interface> element in domain XML has been tightened up a bit - previously it was accepted by the schema (but nonsensical) to have virtio and network interface options specified; as a part of making the two different <driver> choices each a complete element (rather than each being a collection of attributes and subelements) these extra attributes/subelements that were irrelevant to the hostdev-type <driver> were made to be valid only for an emulated interface's <driver>. Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/schemas/basictypes.rng | 13 +++ src/conf/schemas/domaincommon.rng | 173 ++++++++++++++---------------- src/conf/schemas/network.rng | 10 +- src/conf/schemas/networkport.rng | 10 +- 4 files changed, 94 insertions(+), 112 deletions(-) diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng index 26eb538077..8d5f4475ca 100644 --- a/src/conf/schemas/basictypes.rng +++ b/src/conf/schemas/basictypes.rng @@ -656,4 +656,17 @@ </choice> </define> + <define name="hostdevDriver"> + <element name="driver"> + <attribute name="name"> + <choice> + <value>kvm</value> + <value>vfio</value> + <value>xen</value> + </choice> + </attribute> + <empty/> + </element> + </define> + </grammar> diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index b98a2ae602..d9754bf418 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -3759,18 +3759,12 @@ </element> </optional> <optional> - <element name="driver"> - <choice> - <group> - <attribute name="name"> - <choice> - <value>kvm</value> - <value>vfio</value> - <value>xen</value> - </choice> - </attribute> - </group> - <group> + <choice> + <group> + <ref name="hostdevDriver"/> + </group> + <group> + <element name="driver"> <optional> <attribute name="name"> <choice> @@ -3808,90 +3802,90 @@ <optional> <ref name="event_idx"/> </optional> - </group> - </choice> - <ref name="virtioOptions"/> - <interleave> - <optional> - <element name="host"> - <optional> - <attribute name="csum"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="gso"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="tso4"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="tso6"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="ecn"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="ufo"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="mrg_rxbuf"> - <ref name="virOnOff"/> - </attribute> - </optional> - </element> - </optional> - <optional> - <element name="guest"> - <optional> - <attribute name="csum"> - <ref name="virOnOff"/> - </attribute> - </optional> + <ref name="virtioOptions"/> + <interleave> <optional> - <attribute name="tso4"> - <ref name="virOnOff"/> - </attribute> + <element name="host"> + <optional> + <attribute name="csum"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="gso"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="tso4"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="tso6"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="ecn"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="ufo"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="mrg_rxbuf"> + <ref name="virOnOff"/> + </attribute> + </optional> + </element> </optional> <optional> - <attribute name="tso6"> - <ref name="virOnOff"/> - </attribute> + <element name="guest"> + <optional> + <attribute name="csum"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="tso4"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="tso6"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="ecn"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="ufo"> + <ref name="virOnOff"/> + </attribute> + </optional> + </element> </optional> <optional> - <attribute name="ecn"> + <attribute name="rss"> <ref name="virOnOff"/> </attribute> </optional> <optional> - <attribute name="ufo"> + <attribute name="rss_hash_report"> <ref name="virOnOff"/> </attribute> </optional> - </element> - </optional> - <optional> - <attribute name="rss"> - <ref name="virOnOff"/> - </attribute> - </optional> - <optional> - <attribute name="rss_hash_report"> - <ref name="virOnOff"/> - </attribute> - </optional> - </interleave> - </element> + </interleave> + </element> + </group> + </choice> </optional> <optional> <ref name="alias"/> @@ -6224,16 +6218,7 @@ </attribute> <interleave> <optional> - <element name="driver"> - <attribute name="name"> - <choice> - <value>kvm</value> - <value>vfio</value> - <value>xen</value> - </choice> - </attribute> - <empty/> - </element> + <ref name="hostdevDriver"/> </optional> <optional> <ref name="teaming"/> diff --git a/src/conf/schemas/network.rng b/src/conf/schemas/network.rng index cda174ab4b..e56e07d130 100644 --- a/src/conf/schemas/network.rng +++ b/src/conf/schemas/network.rng @@ -179,15 +179,7 @@ </element> </optional> <optional> - <element name="driver"> - <attribute name="name"> - <choice> - <value>kvm</value> - <value>vfio</value> - </choice> - </attribute> - <empty/> - </element> + <ref name="hostdevDriver"/> </optional> <optional> <element name="nat"> diff --git a/src/conf/schemas/networkport.rng b/src/conf/schemas/networkport.rng index 14db949578..50995559e8 100644 --- a/src/conf/schemas/networkport.rng +++ b/src/conf/schemas/networkport.rng @@ -145,15 +145,7 @@ </optional> <interleave> <optional> - <element name="driver"> - <attribute name="name"> - <choice> - <value>kvm</value> - <value>vfio</value> - </choice> - </attribute> - <empty/> - </element> + <ref name="hostdevDriver"/> </optional> <element name="address"> <ref name="pciaddress"/> -- 2.43.0

Currently this enum is defined in domain_conf.h and named virDomainHostdevSubsysPCIDriverType. I want to use it in parts of the network and networkport config, so am moving its definition to device_conf.h which is / can be included by all interested parties, and renaming it to match the name of the corresponding XML attribute ("driver name"). The name change (which includes enum values) does cause a lot of churn, but it's all mechanical. Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- Change from V2: the name of the enum and its values has changed (due to my decision to no longer repurpose the driver name attribute) src/conf/device_conf.c | 9 ++++++++ src/conf/device_conf.h | 12 +++++++++++ src/conf/domain_capabilities.c | 2 +- src/conf/domain_capabilities.h | 2 +- src/conf/domain_conf.c | 36 ++++++++++++-------------------- src/conf/domain_conf.h | 14 +------------ src/hypervisor/virhostdev.c | 8 +++---- src/libvirt_private.syms | 2 +- src/libxl/libxl_capabilities.c | 3 +-- src/libxl/libxl_domain.c | 6 +++--- src/libxl/libxl_driver.c | 4 ++-- src/qemu/qemu_capabilities.c | 4 ++-- src/qemu/qemu_command.c | 12 +++++------ src/qemu/qemu_domain.c | 22 +++++++++---------- src/qemu/qemu_validate.c | 2 +- src/security/security_apparmor.c | 2 +- src/security/security_dac.c | 4 ++-- src/security/security_selinux.c | 4 ++-- src/security/virt-aa-helper.c | 7 ++++--- src/test/test_driver.c | 14 ++++++------- tests/domaincapstest.c | 4 ++-- tests/virhostdevtest.c | 2 +- tools/virsh-completer-nodedev.c | 4 ++-- 23 files changed, 89 insertions(+), 90 deletions(-) diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c index f3d977f2b7..a80b901214 100644 --- a/src/conf/device_conf.c +++ b/src/conf/device_conf.c @@ -29,6 +29,15 @@ #define VIR_FROM_THIS VIR_FROM_DEVICE +VIR_ENUM_IMPL(virDeviceHostdevPCIDriverName, + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST, + "default", + "kvm", + "vfio", + "xen", +); + + VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "none", diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index a83377417a..18aa4125fa 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -31,6 +31,18 @@ #include "virnetdev.h" #include "virenum.h" +/* the backend driver used for PCI hostdev devices */ +typedef enum { + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT = 0, /* detect automatically, prefer VFIO */ + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM, /* force legacy kvm style */ + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO, /* force vfio */ + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN, /* force legacy xen style, use pciback */ + + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST +} virDeviceHostdevPCIDriverName; + +VIR_ENUM_DECL(virDeviceHostdevPCIDriverName); + typedef enum { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE = 0, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index f6e09dc584..68eb3c9797 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -524,7 +524,7 @@ virDomainCapsDeviceHostdevFormat(virBuffer *buf, ENUM_PROCESS(hostdev, startupPolicy, virDomainStartupPolicyTypeToString); ENUM_PROCESS(hostdev, subsysType, virDomainHostdevSubsysTypeToString); ENUM_PROCESS(hostdev, capsType, virDomainHostdevCapsTypeToString); - ENUM_PROCESS(hostdev, pciBackend, virDomainHostdevSubsysPCIBackendTypeToString); + ENUM_PROCESS(hostdev, pciBackend, virDeviceHostdevPCIDriverNameTypeToString); FORMAT_EPILOGUE(hostdev); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 01bcfa2e39..fadc30cdd7 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -99,7 +99,7 @@ STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_MODE_LAST); STATIC_ASSERT_ENUM(VIR_DOMAIN_STARTUP_POLICY_LAST); STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST); STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST); -STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST); +STATIC_ASSERT_ENUM(VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST); typedef struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev; struct _virDomainCapsDeviceHostdev { virTristateBool supported; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 22ad43e1d7..e7e6296f9c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1054,13 +1054,6 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, "mdev", ); -VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST, - "default", - "kvm", - "vfio", - "xen", -); VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol, VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST, @@ -6290,7 +6283,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, driver_node = virXPathNode("./driver", ctxt); if (virXMLPropEnum(driver_node, "name", - virDomainHostdevSubsysPCIBackendTypeFromString, + virDeviceHostdevPCIDriverNameTypeFromString, VIR_XML_PROP_NONZERO, &pcisrc->backend) < 0) return -1; @@ -23387,8 +23380,8 @@ virDomainHostdevDefFormatSubsysPCI(virBuffer *buf, virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'", virTristateBoolTypeToString(def->writeFiltering)); - if (pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) { - const char *backend = virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend); + if (pcisrc->backend != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { + const char *backend = virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend); if (!backend) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -29919,18 +29912,15 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface, actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr; switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) { case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT: - actual->data.hostdev.def.source.subsys.u.pci.backend = - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT; + actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM: - actual->data.hostdev.def.source.subsys.u.pci.backend = - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; + actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO: - actual->data.hostdev.def.source.subsys.u.pci.backend = - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST: @@ -30041,26 +30031,26 @@ virDomainNetDefActualToNetworkPort(virDomainDef *dom, port->plug.hostdevpci.managed = virTristateBoolFromBool(actual->data.hostdev.def.managed); port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr; switch (actual->data.hostdev.def.source.subsys.u.pci.backend) { - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT; break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_KVM; break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO; break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Unexpected PCI backend 'xen'")); break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: default: - virReportEnumRangeError(virDomainHostdevSubsysPCIBackendType, + virReportEnumRangeError(virDeviceHostdevPCIDriverName, actual->data.hostdev.def.source.subsys.u.pci.backend); return NULL; } @@ -31005,7 +30995,7 @@ virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev) { return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + hostdev->source.subsys.u.pci.backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ed07859bc5..0582cc928d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -201,18 +201,6 @@ typedef enum { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST } virDomainHostdevSubsysType; -/* the backend driver used for PCI hostdev devices */ -typedef enum { - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT = 0, /* detect automatically, prefer VFIO */ - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, /* force legacy kvm style */ - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO, /* force vfio */ - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN, /* force legacy xen style, use pciback */ - - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST -} virDomainHostdevSubsysPCIBackendType; - -VIR_ENUM_DECL(virDomainHostdevSubsysPCIBackend); - typedef enum { VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE, VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI, @@ -247,7 +235,7 @@ struct _virDomainHostdevSubsysUSB { struct _virDomainHostdevSubsysPCI { virPCIDeviceAddress addr; /* host address */ - virDomainHostdevSubsysPCIBackendType backend; + virDeviceHostdevPCIDriverName backend; virBitmap *origstates; }; diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c index 4672bd8785..26c9ac3c28 100644 --- a/src/hypervisor/virhostdev.c +++ b/src/hypervisor/virhostdev.c @@ -243,14 +243,14 @@ virHostdevGetPCIHostDevice(const virDomainHostdevDef *hostdev, virPCIDeviceSetManaged(actual, hostdev->managed); - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { virPCIDeviceSetStubDriverType(actual, VIR_PCI_STUB_DRIVER_VFIO); - } else if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN) { + } else if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN) { virPCIDeviceSetStubDriverType(actual, VIR_PCI_STUB_DRIVER_XEN); } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("pci backend driver '%1$s' is not supported"), - virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend)); + _("pci backend driver type '%1$s' is not supported"), + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend)); return -1; } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 553b01b8c0..002a3986d1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -126,6 +126,7 @@ virCPUModeTypeToString; # conf/device_conf.h virCCWDeviceAddressParseXML; +virDeviceHostdevPCIDriverNameTypeToString; virDeviceInfoPCIAddressExtensionIsPresent; virDeviceInfoPCIAddressExtensionIsWanted; virDeviceInfoPCIAddressIsPresent; @@ -467,7 +468,6 @@ virDomainHostdevInsert; virDomainHostdevMatch; virDomainHostdevModeTypeToString; virDomainHostdevRemove; -virDomainHostdevSubsysPCIBackendTypeToString; virDomainHostdevSubsysSCSIVHostModelTypeFromString; virDomainHostdevSubsysSCSIVHostModelTypeToString; virDomainHostdevSubsysTypeToString; diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index 177e8b988e..de88c00e15 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -630,8 +630,7 @@ libxlMakeDomainDeviceHostdevCaps(virDomainCapsDeviceHostdev *dev) virDomainCapsEnumClear(&dev->capsType); virDomainCapsEnumClear(&dev->pciBackend); - VIR_DOMAIN_CAPS_ENUM_SET(dev->pciBackend, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN); + VIR_DOMAIN_CAPS_ENUM_SET(dev->pciBackend, VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN); return 0; } diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 0c4beffd6a..88d977e79b 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -160,8 +160,8 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDef *dev, if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) - pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN; + pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) + pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; } if (dev->type == VIR_DOMAIN_DEVICE_VIDEO) { @@ -997,7 +997,7 @@ libxlNetworkPrepareDevices(virDomainDef *def) if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN; + pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; if (virDomainHostdevInsert(def, hostdev) < 0) return -1; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c98d2d737a..d7f79089c3 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3398,12 +3398,12 @@ libxlDomainAttachNetDevice(libxlDriverPrivate *driver, virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci; /* For those just allocated from a network pool whose backend is - * still VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, we need to set + * still VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT, we need to set * backend correctly. */ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN; + pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 83119e871a..1a3d75eeab 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6352,8 +6352,8 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCaps *qemuCaps, if (supportsPassthroughVFIO && virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) { VIR_DOMAIN_CAPS_ENUM_SET(hostdev->pciBackend, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT, + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO); } } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 23909dbbab..2f0b1d0acd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4709,16 +4709,16 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, /* caller has to assign proper passthrough backend type */ switch (pcisrc->backend) { - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("invalid PCI passthrough type '%1$s'"), - virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend)); + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend)); return NULL; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 953808fcfe..1e2b74af02 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10531,7 +10531,7 @@ qemuDomainGetHostdevPath(virDomainHostdevDef *dev, case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { if (!(tmpPath = virPCIDeviceAddressGetIOMMUGroupDev(&pcisrc->addr))) return -1; @@ -11302,14 +11302,14 @@ qemuDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev, virQEMUCaps *qemuCaps) { bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO(); - virDomainHostdevSubsysPCIBackendType *backend = &hostdev->source.subsys.u.pci.backend; + virDeviceHostdevPCIDriverName *driverName = &hostdev->source.subsys.u.pci.backend; /* assign defaults for hostdev passthrough */ - switch (*backend) { - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: + switch (*driverName) { + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: if (supportsPassthroughVFIO) { if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) { - *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + *driverName = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("VFIO PCI device assignment is not supported by this version of QEMU")); @@ -11322,7 +11322,7 @@ qemuDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev, } break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: if (!supportsPassthroughVFIO) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("host doesn't support VFIO PCI passthrough")); @@ -11330,20 +11330,20 @@ qemuDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev, } break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("host doesn't support legacy PCI passthrough")); return false; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("QEMU does not support device assignment mode '%1$s'"), - virDomainHostdevSubsysPCIBackendTypeToString(*backend)); + virDeviceHostdevPCIDriverNameTypeToString(*driverName)); return false; default: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: - virReportEnumRangeError(virDomainHostdevSubsysPCIBackendType, *backend); + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: + virReportEnumRangeError(virDeviceHostdevPCIDriverName, *driverName); break; } diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e475ad035e..2aab0d9db2 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2464,7 +2464,7 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: backend = hostdev->source.subsys.u.pci.backend; - if (backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("VFIO PCI device assignment is not supported by this version of qemu")); diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 6fd0aedacf..a1cbbc77e9 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -869,7 +869,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr, if (!pci) goto done; - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) { diff --git a/src/security/security_dac.c b/src/security/security_dac.c index c07e488db7..cb8b72b289 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1257,7 +1257,7 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) @@ -1418,7 +1418,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 84c5ce75ed..2ee542f6a4 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2201,7 +2201,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) @@ -2437,7 +2437,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index be13979cef..d01df8710d 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1092,9 +1092,10 @@ get_files(vahControl * ctl) case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { virPCIDevice *pci = virPCIDeviceNew(&dev->source.subsys.u.pci.addr); - virDomainHostdevSubsysPCIBackendType backend = dev->source.subsys.u.pci.backend; - if (backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO || - backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) { + virDeviceHostdevPCIDriverName driverName = dev->source.subsys.u.pci.backend; + + if (driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO || + driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { needsVfio = true; } diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 67f8e75296..63e1f743c3 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -10045,16 +10045,16 @@ testDomainAttachHostPCIDevice(testDriver *driver G_GNUC_UNUSED, int backend = hostdev->source.subsys.u.pci.backend; switch (backend) { - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("test hypervisor does not support device assignment mode '%1$s'"), - virDomainHostdevSubsysPCIBackendTypeToString(backend)); + virDeviceHostdevPCIDriverNameTypeToString(backend)); return -1; } @@ -10080,7 +10080,7 @@ testDomainAttachHostDevice(testDriver *driver, if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("hotplug is not supported for hostdev subsys type '%1$s'"), - virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type)); + virDeviceHostdevPCIDriverNameTypeToString(hostdev->source.subsys.type)); return -1; } diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index c4a4508430..97b306f652 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -109,8 +109,8 @@ fillQemuCaps(virDomainCaps *domCaps, * successfully mocked as they are not exposed as internal APIs. Therefore, * instead of mocking set the expected values here by hand. */ VIR_DOMAIN_CAPS_ENUM_SET(domCaps->hostdev.pciBackend, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT, + VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO); /* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which * may not exists everywhere. */ diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c index 04e6c00908..89b4fb5e7c 100644 --- a/tests/virhostdevtest.c +++ b/tests/virhostdevtest.c @@ -134,7 +134,7 @@ myInit(void) subsys->u.pci.addr.bus = 0; subsys->u.pci.addr.slot = i + 1; subsys->u.pci.addr.function = 0; - subsys->u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + subsys->u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; } for (i = 0; i < nhostdevs; i++) { diff --git a/tools/virsh-completer-nodedev.c b/tools/virsh-completer-nodedev.c index d743df460e..72951a54f6 100644 --- a/tools/virsh-completer-nodedev.c +++ b/tools/virsh-completer-nodedev.c @@ -110,6 +110,6 @@ virshNodeDevicePCIBackendCompleter(vshControl *ctl G_GNUC_UNUSED, { virCheckFlags(0, NULL); - return virshEnumComplete(VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST, - virDomainHostdevSubsysPCIBackendTypeToString); + return virshEnumComplete(VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST, + virDeviceHostdevPCIDriverNameTypeToString); } -- 2.43.0

The hostdev version of the <driver> subelement appears in four places: * The domain XML in the <hostdev> and <interface type='hostdev'> elements (that's 2) * The network XML inside <forward> when the network is a pool of SRIOV VFs * the <networkport> XML, which is used to communicate between the hypervisor driver and network driver. In order to make the pending addition of a new attribute to <driver> in all these cases simpler, this patch refactors the parsing of <driver> in all four places to use virXMLProp*() and virXMLFormatElement(). Making all of the different instances of the separate parse/format for <driver> look nearly identical will make it easier to see that the upcoming patch that converges all four to use a common parser/formatter is a functional NOP. Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/domain_conf.c | 28 ++++++++++++++++------------ src/conf/network_conf.c | 26 ++++++++++++-------------- src/conf/network_conf.h | 2 +- src/conf/virnetworkportdef.c | 31 +++++++++++++++++++------------ src/conf/virnetworkportdef.h | 2 +- 5 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e7e6296f9c..35a9138a95 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -6281,13 +6281,14 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (virDomainHostdevSubsysPCIDefParseXML(sourcenode, ctxt, def, flags) < 0) return -1; - driver_node = virXPathNode("./driver", ctxt); - if (virXMLPropEnum(driver_node, "name", - virDeviceHostdevPCIDriverNameTypeFromString, - VIR_XML_PROP_NONZERO, - &pcisrc->backend) < 0) - return -1; - + if ((driver_node = virXPathNode("./driver", ctxt))) { + if (virXMLPropEnum(driver_node, "name", + virDeviceHostdevPCIDriverNameTypeFromString, + VIR_XML_PROP_NONZERO, + &pcisrc->backend) < 0) { + return -1; + } + } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: @@ -23372,14 +23373,11 @@ virDomainHostdevDefFormatSubsysPCI(virBuffer *buf, unsigned int flags, bool includeTypeInAddr) { + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf); virDomainHostdevSubsysPCI *pcisrc = &def->source.subsys.u.pci; - if (def->writeFiltering != VIR_TRISTATE_BOOL_ABSENT) - virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'", - virTristateBoolTypeToString(def->writeFiltering)); - if (pcisrc->backend != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { const char *backend = virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend); @@ -23390,9 +23388,15 @@ virDomainHostdevDefFormatSubsysPCI(virBuffer *buf, return -1; } - virBufferAsprintf(buf, "<driver name='%s'/>\n", backend); + virBufferAsprintf(&driverAttrBuf, " name='%s'", backend); } + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + + if (def->writeFiltering != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'", + virTristateBoolTypeToString(def->writeFiltering)); + virPCIDeviceAddressFormat(&sourceChildBuf, pcisrc->addr, includeTypeInAddr); if (pcisrc->origstates && diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 0449b6f07c..984ff564b2 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1334,8 +1334,8 @@ virNetworkForwardDefParseXML(const char *networkName, g_autofree xmlNodePtr *forwardNatNodes = NULL; g_autofree char *forwardDev = NULL; g_autofree char *forwardManaged = NULL; - g_autofree char *forwardDriverName = NULL; g_autofree char *type = NULL; + xmlNodePtr driverNode = NULL; VIR_XPATH_NODE_AUTORESTORE(ctxt) ctxt->node = node; @@ -1356,18 +1356,13 @@ virNetworkForwardDefParseXML(const char *networkName, def->managed = true; } - forwardDriverName = virXPathString("string(./driver/@name)", ctxt); - if (forwardDriverName) { - int driverName - = virNetworkForwardDriverNameTypeFromString(forwardDriverName); - - if (driverName <= 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unknown forward <driver name='%1$s'/> in network %2$s"), - forwardDriverName, networkName); + if ((driverNode = virXPathNode("./driver", ctxt))) { + if (virXMLPropEnum(driverNode, "name", + virNetworkForwardDriverNameTypeFromString, + VIR_XML_PROP_NONZERO, + &def->driverName) < 0) { return -1; } - def->driverName = driverName; } /* bridge and hostdev modes can use a pool of physical interfaces */ @@ -2329,6 +2324,7 @@ virNetworkDefFormatBuf(virBuffer *buf, if (def->forward.type != VIR_NETWORK_FORWARD_NONE) { const char *dev = NULL; const char *mode = virNetworkForwardTypeToString(def->forward.type); + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; if (!def->forward.npfs) dev = virNetworkDefForwardIf(def, 0); @@ -2359,8 +2355,7 @@ virNetworkDefFormatBuf(virBuffer *buf, virBufferAsprintf(buf, "%s>\n", shortforward ? "/" : ""); virBufferAdjustIndent(buf, 2); - if (def->forward.driverName - != VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT) { + if (def->forward.driverName) { const char *driverName = virNetworkForwardDriverNameTypeToString(def->forward.driverName); if (!driverName) { @@ -2369,8 +2364,11 @@ virNetworkDefFormatBuf(virBuffer *buf, def->forward.driverName); return -1; } - virBufferAsprintf(buf, "<driver name='%s'/>\n", driverName); + virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); } + + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + if (def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (virNetworkForwardNatDefFormat(buf, &def->forward) < 0) return -1; diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 5a1bdb1284..497ae765f2 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -216,7 +216,7 @@ typedef struct _virNetworkForwardDef virNetworkForwardDef; struct _virNetworkForwardDef { int type; /* One of virNetworkForwardType constants */ bool managed; /* managed attribute for hostdev mode */ - int driverName; /* enum virNetworkForwardDriverNameType */ + virNetworkForwardDriverNameType driverName; /* If there are multiple forward devices (i.e. a pool of * interfaces), they will be listed here. diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c index fc06ef41d5..ac17313f83 100644 --- a/src/conf/virnetworkportdef.c +++ b/src/conf/virnetworkportdef.c @@ -87,10 +87,10 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) xmlNodePtr addressNode; xmlNodePtr rxfiltersNode = NULL; xmlNodePtr plugNode = NULL; + xmlNodePtr driverNode = NULL; g_autofree char *mac = NULL; g_autofree char *macmgr = NULL; g_autofree char *mode = NULL; - g_autofree char *driver = NULL; def = g_new0(virNetworkPortDef, 1); @@ -223,14 +223,16 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) VIR_XML_PROP_NONE, &def->plug.hostdevpci.managed) < 0) return NULL; - driver = virXPathString("string(./plug/driver/@name)", ctxt); - if (driver && - (def->plug.hostdevpci.driver = - virNetworkForwardDriverNameTypeFromString(driver)) <= 0) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Missing network port driver name")); - return NULL; + + if ((driverNode = virXPathNode("./plug/driver", ctxt))) { + if (virXMLPropEnum(driverNode, "name", + virNetworkForwardDriverNameTypeFromString, + VIR_XML_PROP_NONZERO, + &def->plug.hostdevpci.driver) < 0) { + return NULL; + } } + if (!(addressNode = virXPathNode("./plug/address", ctxt))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing network port PCI address")); @@ -319,6 +321,8 @@ virNetworkPortDefFormatBuf(virBuffer *buf, virTristateBoolTypeToString(def->trustGuestRxFilters)); if (def->plugtype != VIR_NETWORK_PORT_PLUG_TYPE_NONE) { + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; + virBufferAsprintf(buf, "<plug type='%s'", virNetworkPortPlugTypeToString(def->plugtype)); @@ -351,10 +355,13 @@ virNetworkPortDefFormatBuf(virBuffer *buf, } virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - if (def->plug.hostdevpci.driver) - virBufferEscapeString(buf, "<driver name='%s'/>\n", - virNetworkForwardDriverNameTypeToString( - def->plug.hostdevpci.driver)); + + if (def->plug.hostdevpci.driver) { + virBufferEscapeString(&driverAttrBuf, " name='%s'", + virNetworkForwardDriverNameTypeToString(def->plug.hostdevpci.driver)); + } + + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); virPCIDeviceAddressFormat(buf, def->plug.hostdevpci.addr, false); virBufferAdjustIndent(buf, -2); diff --git a/src/conf/virnetworkportdef.h b/src/conf/virnetworkportdef.h index 48e73dbefd..bfe1dae9ea 100644 --- a/src/conf/virnetworkportdef.h +++ b/src/conf/virnetworkportdef.h @@ -69,7 +69,7 @@ struct _virNetworkPortDef { } direct; struct { virPCIDeviceAddress addr; /* PCI Address of device */ - int driver; /* virNetworkForwardDriverNameType */ + unsigned int driver; /* virNetworkForwardDriverNameType */ virTristateBool managed; } hostdevpci; } plug; -- 2.43.0

The new struct is virDeviceHostdevPCIDriverInfo, and the "backend" enum in the hostdevDef will be replaced with a virDeviceHostdevPCIDriverInfo named "driver'. Since the enum value in this new struct is called "name", it means that all references to "backend" will become "driver.name". This will allow easily adding other items for new attributes in the <driver> element / C struct, which will be useful once we are using this new struct in multiple places. Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- Change from V2: names have changed, extra line breaks removed src/conf/device_conf.h | 4 ++++ src/conf/domain_conf.c | 30 +++++++++++++----------------- src/conf/domain_conf.h | 2 +- src/conf/virconftypes.h | 2 ++ src/hypervisor/virhostdev.c | 6 +++--- src/libxl/libxl_domain.c | 6 +++--- src/libxl/libxl_driver.c | 6 +++--- src/qemu/qemu_command.c | 6 +++--- src/qemu/qemu_domain.c | 4 ++-- src/qemu/qemu_validate.c | 6 +++--- src/security/security_apparmor.c | 2 +- src/security/security_dac.c | 4 ++-- src/security/security_selinux.c | 4 ++-- src/security/virt-aa-helper.c | 2 +- src/test/test_driver.c | 6 +++--- tests/virhostdevtest.c | 2 +- 16 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 18aa4125fa..1f7e066142 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -43,6 +43,10 @@ typedef enum { VIR_ENUM_DECL(virDeviceHostdevPCIDriverName); +struct _virDeviceHostdevPCIDriverInfo { + virDeviceHostdevPCIDriverName name; +}; + typedef enum { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE = 0, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 35a9138a95..887b871589 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -6285,7 +6285,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (virXMLPropEnum(driver_node, "name", virDeviceHostdevPCIDriverNameTypeFromString, VIR_XML_PROP_NONZERO, - &pcisrc->backend) < 0) { + &pcisrc->driver.name) < 0) { return -1; } } @@ -23378,17 +23378,17 @@ virDomainHostdevDefFormatSubsysPCI(virBuffer *buf, g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf); virDomainHostdevSubsysPCI *pcisrc = &def->source.subsys.u.pci; - if (pcisrc->backend != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { - const char *backend = virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend); + if (pcisrc->driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { + const char *driverName = virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name); - if (!backend) { + if (!driverName) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected pci hostdev driver name type %1$d"), - pcisrc->backend); + _("unexpected pci hostdev driver type %1$d"), + pcisrc->driver.name); return -1; } - virBufferAsprintf(&driverAttrBuf, " name='%s'", backend); + virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); } virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); @@ -29916,15 +29916,15 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface, actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr; switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) { case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT: - actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT; + actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM: - actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM; + actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO: - actual->data.hostdev.def.source.subsys.u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; + actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; break; case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST: @@ -30034,7 +30034,7 @@ virDomainNetDefActualToNetworkPort(virDomainDef *dom, } port->plug.hostdevpci.managed = virTristateBoolFromBool(actual->data.hostdev.def.managed); port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr; - switch (actual->data.hostdev.def.source.subsys.u.pci.backend) { + switch (actual->data.hostdev.def.source.subsys.u.pci.driver.name) { case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT; break; @@ -30048,14 +30048,10 @@ virDomainNetDefActualToNetworkPort(virDomainDef *dom, break; case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Unexpected PCI backend 'xen'")); - break; - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: default: virReportEnumRangeError(virDeviceHostdevPCIDriverName, - actual->data.hostdev.def.source.subsys.u.pci.backend); + actual->data.hostdev.def.source.subsys.u.pci.driver.name); return NULL; } @@ -30999,7 +30995,7 @@ virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev) { return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - hostdev->source.subsys.u.pci.backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; + hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0582cc928d..ee8bcbc6b3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -235,7 +235,7 @@ struct _virDomainHostdevSubsysUSB { struct _virDomainHostdevSubsysPCI { virPCIDeviceAddress addr; /* host address */ - virDeviceHostdevPCIDriverName backend; + virDeviceHostdevPCIDriverInfo driver; virBitmap *origstates; }; diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 26cb966194..0779bc224b 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -66,6 +66,8 @@ typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel; typedef struct _virCapsStoragePool virCapsStoragePool; +typedef struct _virDeviceHostdevPCIDriverInfo virDeviceHostdevPCIDriverInfo; + typedef struct _virDomainABIStability virDomainABIStability; typedef struct _virDomainActualNetDef virDomainActualNetDef; diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c index 26c9ac3c28..27b0acdc91 100644 --- a/src/hypervisor/virhostdev.c +++ b/src/hypervisor/virhostdev.c @@ -243,14 +243,14 @@ virHostdevGetPCIHostDevice(const virDomainHostdevDef *hostdev, virPCIDeviceSetManaged(actual, hostdev->managed); - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { virPCIDeviceSetStubDriverType(actual, VIR_PCI_STUB_DRIVER_VFIO); - } else if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN) { + } else if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN) { virPCIDeviceSetStubDriverType(actual, VIR_PCI_STUB_DRIVER_XEN); } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("pci backend driver type '%1$s' is not supported"), - virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend)); + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name)); return -1; } diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 88d977e79b..1a7de00704 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -160,8 +160,8 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDef *dev, if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) - pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) + pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; } if (dev->type == VIR_DOMAIN_DEVICE_VIDEO) { @@ -997,7 +997,7 @@ libxlNetworkPrepareDevices(virDomainDef *def) if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; if (virDomainHostdevInsert(def, hostdev) < 0) return -1; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index d7f79089c3..29fbc823dd 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3397,13 +3397,13 @@ libxlDomainAttachNetDevice(libxlDriverPrivate *driver, virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net); virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci; - /* For those just allocated from a network pool whose backend is + /* For those just allocated from a network pool whose driver type is * still VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT, we need to set - * backend correctly. + * driver name correctly. */ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2f0b1d0acd..b3ebf711e5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4707,8 +4707,8 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, g_autofree char *host = virPCIDeviceAddressAsString(&pcisrc->addr); const char *failover_pair_id = NULL; - /* caller has to assign proper passthrough backend type */ - switch (pcisrc->backend) { + /* caller has to assign proper passthrough driver name */ + switch (pcisrc->driver.name) { case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: break; @@ -4718,7 +4718,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("invalid PCI passthrough type '%1$s'"), - virDeviceHostdevPCIDriverNameTypeToString(pcisrc->backend)); + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name)); return NULL; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1e2b74af02..1aeeb74503 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10531,7 +10531,7 @@ qemuDomainGetHostdevPath(virDomainHostdevDef *dev, case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { if (!(tmpPath = virPCIDeviceAddressGetIOMMUGroupDev(&pcisrc->addr))) return -1; @@ -11302,7 +11302,7 @@ qemuDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev, virQEMUCaps *qemuCaps) { bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO(); - virDeviceHostdevPCIDriverName *driverName = &hostdev->source.subsys.u.pci.backend; + virDeviceHostdevPCIDriverName *driverName = &hostdev->source.subsys.u.pci.driver.name; /* assign defaults for hostdev passthrough */ switch (*driverName) { diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 2aab0d9db2..4d388bbcc4 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2437,7 +2437,7 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev, const virDomainDef *def, virQEMUCaps *qemuCaps) { - int backend; + virDeviceHostdevPCIDriverName driverName; /* forbid capabilities mode hostdev in this kind of hypervisor */ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) { @@ -2462,9 +2462,9 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev, break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - backend = hostdev->source.subsys.u.pci.backend; + driverName = hostdev->source.subsys.u.pci.driver.name; - if (backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("VFIO PCI device assignment is not supported by this version of qemu")); diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index a1cbbc77e9..c1dc859751 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -869,7 +869,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr, if (!pci) goto done; - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) { diff --git a/src/security/security_dac.c b/src/security/security_dac.c index cb8b72b289..4b8130630f 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1257,7 +1257,7 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) @@ -1418,7 +1418,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 2ee542f6a4..ffad058d9a 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2201,7 +2201,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) @@ -2437,7 +2437,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr, if (!pci) return -1; - if (pcisrc->backend == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci); if (!vfioGroupDev) diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index d01df8710d..0374581f07 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1092,7 +1092,7 @@ get_files(vahControl * ctl) case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: { virPCIDevice *pci = virPCIDeviceNew(&dev->source.subsys.u.pci.addr); - virDeviceHostdevPCIDriverName driverName = dev->source.subsys.u.pci.backend; + virDeviceHostdevPCIDriverName driverName = dev->source.subsys.u.pci.driver.name; if (driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO || driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 63e1f743c3..ed545848af 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -10042,9 +10042,9 @@ testDomainAttachHostPCIDevice(testDriver *driver G_GNUC_UNUSED, virDomainObj *vm, virDomainHostdevDef *hostdev) { - int backend = hostdev->source.subsys.u.pci.backend; + int driverName = hostdev->source.subsys.u.pci.driver.name; - switch (backend) { + switch (driverName) { case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: @@ -10054,7 +10054,7 @@ testDomainAttachHostPCIDevice(testDriver *driver G_GNUC_UNUSED, case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("test hypervisor does not support device assignment mode '%1$s'"), - virDeviceHostdevPCIDriverNameTypeToString(backend)); + virDeviceHostdevPCIDriverNameTypeToString(driverName)); return -1; } diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c index 89b4fb5e7c..aec474a148 100644 --- a/tests/virhostdevtest.c +++ b/tests/virhostdevtest.c @@ -134,7 +134,7 @@ myInit(void) subsys->u.pci.addr.bus = 0; subsys->u.pci.addr.slot = i + 1; subsys->u.pci.addr.function = 0; - subsys->u.pci.backend = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; + subsys->u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; } for (i = 0; i < nhostdevs; i++) { -- 2.43.0

The next step in consolidating parsing/formatting of the <driver> element of these objects using a common struct and common code. This eliminates the virNetworkForwardDriverNameType enum which is nearly identical to virDeviceHostdevPCIDriverName (the only non-identical bit was just because they'd gotten out of sync over time) and replaces its uses with a virDeviceHostdevPCIDriverInfo (which is a struct that contains a virDeviceHostdevPCIDriverName). Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/domain_conf.c | 43 ++---------------------------------- src/conf/network_conf.c | 23 ++++++------------- src/conf/network_conf.h | 17 ++------------ src/conf/virnetworkportdef.c | 8 +++---- src/conf/virnetworkportdef.h | 4 +++- src/network/bridge_driver.c | 2 +- 6 files changed, 19 insertions(+), 78 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 887b871589..e19a2817c4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -29914,26 +29914,7 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface, } actual->data.hostdev.def.source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr; - switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) { - case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT: - actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT; - break; - - case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM: - actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM; - break; - - case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO: - actual->data.hostdev.def.source.subsys.u.pci.driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; - break; - - case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST: - default: - virReportEnumRangeError(virNetworkForwardDriverNameType, - port->plug.hostdevpci.driver); - goto error; - } - + actual->data.hostdev.def.source.subsys.u.pci.driver.name = port->plug.hostdevpci.driver.name; break; case VIR_NETWORK_PORT_PLUG_TYPE_LAST: @@ -30034,27 +30015,7 @@ virDomainNetDefActualToNetworkPort(virDomainDef *dom, } port->plug.hostdevpci.managed = virTristateBoolFromBool(actual->data.hostdev.def.managed); port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr; - switch (actual->data.hostdev.def.source.subsys.u.pci.driver.name) { - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: - port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT; - break; - - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: - port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_KVM; - break; - - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: - port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO; - break; - - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: - case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: - default: - virReportEnumRangeError(virDeviceHostdevPCIDriverName, - actual->data.hostdev.def.source.subsys.u.pci.driver.name); - return NULL; - } - + port->plug.hostdevpci.driver.name = actual->data.hostdev.def.source.subsys.u.pci.driver.name; break; case VIR_DOMAIN_NET_TYPE_CLIENT: diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 984ff564b2..d732e90b6d 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -56,13 +56,6 @@ VIR_ENUM_IMPL(virNetworkForwardHostdevDevice, "none", "pci", "netdev", ); -VIR_ENUM_IMPL(virNetworkForwardDriverName, - VIR_NETWORK_FORWARD_DRIVER_NAME_LAST, - "default", - "kvm", - "vfio", -); - VIR_ENUM_IMPL(virNetworkTaint, VIR_NETWORK_TAINT_LAST, "hook-script", @@ -1358,9 +1351,9 @@ virNetworkForwardDefParseXML(const char *networkName, if ((driverNode = virXPathNode("./driver", ctxt))) { if (virXMLPropEnum(driverNode, "name", - virNetworkForwardDriverNameTypeFromString, + virDeviceHostdevPCIDriverNameTypeFromString, VIR_XML_PROP_NONZERO, - &def->driverName) < 0) { + &def->driver.name) < 0) { return -1; } } @@ -2349,19 +2342,17 @@ virNetworkDefFormatBuf(virBuffer *buf, || VIR_SOCKET_ADDR_VALID(&def->forward.addr.end) || def->forward.port.start || def->forward.port.end - || (def->forward.driverName - != VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT) + || (def->forward.driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) || def->forward.natIPv6); virBufferAsprintf(buf, "%s>\n", shortforward ? "/" : ""); virBufferAdjustIndent(buf, 2); - if (def->forward.driverName) { - const char *driverName - = virNetworkForwardDriverNameTypeToString(def->forward.driverName); + if (def->forward.driver.name) { + const char *driverName = virDeviceHostdevPCIDriverNameTypeToString(def->forward.driver.name); if (!driverName) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected hostdev driver name type %1$d "), - def->forward.driverName); + _("unexpected hostdev driver name %1$d "), + def->forward.driver.name); return -1; } virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 497ae765f2..1d7fd3ab6a 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -24,6 +24,7 @@ #define DNS_RECORD_LENGTH_SRV (512 - 30) /* Limit minus overhead as mentioned in RFC-2782 */ #include "internal.h" +#include "virconftypes.h" #include "virsocketaddr.h" #include "virnetdevbandwidth.h" #include "virnetdevvportprofile.h" @@ -88,20 +89,6 @@ typedef enum { VIR_ENUM_DECL(virNetworkDHCPLeaseTimeUnit); -/* The backend driver used for devices from the pool. Currently used - * only for PCI devices (vfio vs. kvm), but could be used for other - * device types in the future. - */ -typedef enum { - VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT, /* kvm now, could change */ - VIR_NETWORK_FORWARD_DRIVER_NAME_KVM, /* force legacy kvm style */ - VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO, /* force vfio */ - - VIR_NETWORK_FORWARD_DRIVER_NAME_LAST -} virNetworkForwardDriverNameType; - -VIR_ENUM_DECL(virNetworkForwardDriverName); - typedef struct _virNetworkDHCPLeaseTimeDef virNetworkDHCPLeaseTimeDef; struct _virNetworkDHCPLeaseTimeDef { unsigned long long expiry; @@ -216,7 +203,7 @@ typedef struct _virNetworkForwardDef virNetworkForwardDef; struct _virNetworkForwardDef { int type; /* One of virNetworkForwardType constants */ bool managed; /* managed attribute for hostdev mode */ - virNetworkForwardDriverNameType driverName; + virDeviceHostdevPCIDriverInfo driver; /* If there are multiple forward devices (i.e. a pool of * interfaces), they will be listed here. diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c index ac17313f83..c7902f0174 100644 --- a/src/conf/virnetworkportdef.c +++ b/src/conf/virnetworkportdef.c @@ -226,9 +226,9 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) if ((driverNode = virXPathNode("./plug/driver", ctxt))) { if (virXMLPropEnum(driverNode, "name", - virNetworkForwardDriverNameTypeFromString, + virDeviceHostdevPCIDriverNameTypeFromString, VIR_XML_PROP_NONZERO, - &def->plug.hostdevpci.driver) < 0) { + &def->plug.hostdevpci.driver.name) < 0) { return NULL; } } @@ -356,9 +356,9 @@ virNetworkPortDefFormatBuf(virBuffer *buf, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - if (def->plug.hostdevpci.driver) { + if (def->plug.hostdevpci.driver.name) { virBufferEscapeString(&driverAttrBuf, " name='%s'", - virNetworkForwardDriverNameTypeToString(def->plug.hostdevpci.driver)); + virDeviceHostdevPCIDriverNameTypeToString(def->plug.hostdevpci.driver.name)); } virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); diff --git a/src/conf/virnetworkportdef.h b/src/conf/virnetworkportdef.h index bfe1dae9ea..9e51ab1a8b 100644 --- a/src/conf/virnetworkportdef.h +++ b/src/conf/virnetworkportdef.h @@ -22,6 +22,8 @@ #pragma once #include "internal.h" +#include "virconftypes.h" +#include "device_conf.h" #include "virnetdevvlan.h" #include "virnetdevvportprofile.h" #include "virnetdevbandwidth.h" @@ -69,7 +71,7 @@ struct _virNetworkPortDef { } direct; struct { virPCIDeviceAddress addr; /* PCI Address of device */ - unsigned int driver; /* virNetworkForwardDriverNameType */ + virDeviceHostdevPCIDriverInfo driver; virTristateBool managed; } hostdevpci; } plug; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 4be740de2c..d156333626 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3930,7 +3930,7 @@ networkAllocatePort(virNetworkObj *obj, return -1; } port->plug.hostdevpci.addr = dev->device.pci; - port->plug.hostdevpci.driver = netdef->forward.driverName; + port->plug.hostdevpci.driver.name = netdef->forward.driver.name; port->plug.hostdevpci.managed = virTristateBoolFromBool(netdef->forward.managed); if (port->virtPortProfile) { -- 2.43.0

This is done so that we can re-use the same parser/formatter for <network> and <networkport> Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/device_conf.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/conf/device_conf.h | 7 +++++++ src/conf/domain_conf.c | 27 +++++---------------------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c index a80b901214..68a8c7690a 100644 --- a/src/conf/device_conf.c +++ b/src/conf/device_conf.c @@ -55,6 +55,46 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, "unassigned", ); + +int +virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node, + virDeviceHostdevPCIDriverInfo *driver) +{ + if (virXMLPropEnum(node, "name", + virDeviceHostdevPCIDriverNameTypeFromString, + VIR_XML_PROP_NONZERO, + &driver->name) < 0) { + return -1; + } + + return 0; +} + + +int +virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf, + const virDeviceHostdevPCIDriverInfo *driver) +{ + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; + + if (driver->name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { + const char *driverName = virDeviceHostdevPCIDriverNameTypeToString(driver->name); + + if (!driverName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected pci hostdev driver name %1$d"), + driver->name); + return -1; + } + + virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); + } + + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + return 0; +} + + static int virZPCIDeviceAddressParseXML(xmlNodePtr node, virPCIDeviceAddress *addr) diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 1f7e066142..0b3f17a3aa 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -25,6 +25,7 @@ #include <libxml/xpath.h> #include "internal.h" +#include "virconftypes.h" #include "virbuffer.h" #include "virccw.h" #include "virpci.h" @@ -185,6 +186,12 @@ struct _virDomainDeviceInfo { bool isolationGroupLocked; }; +int virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node, + virDeviceHostdevPCIDriverInfo *driver); + +int virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf, + const virDeviceHostdevPCIDriverInfo *driver); + void virDomainDeviceInfoClear(virDomainDeviceInfo *info); void virDomainDeviceInfoFree(virDomainDeviceInfo *info); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e19a2817c4..b3c7b50f97 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -6281,13 +6281,9 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (virDomainHostdevSubsysPCIDefParseXML(sourcenode, ctxt, def, flags) < 0) return -1; - if ((driver_node = virXPathNode("./driver", ctxt))) { - if (virXMLPropEnum(driver_node, "name", - virDeviceHostdevPCIDriverNameTypeFromString, - VIR_XML_PROP_NONZERO, - &pcisrc->driver.name) < 0) { - return -1; - } + if ((driver_node = virXPathNode("./driver", ctxt)) && + virDeviceHostdevPCIDriverInfoParseXML(driver_node, &pcisrc->driver) < 0) { + return -1; } break; @@ -23373,25 +23369,12 @@ virDomainHostdevDefFormatSubsysPCI(virBuffer *buf, unsigned int flags, bool includeTypeInAddr) { - g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf); virDomainHostdevSubsysPCI *pcisrc = &def->source.subsys.u.pci; - if (pcisrc->driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { - const char *driverName = virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name); - - if (!driverName) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected pci hostdev driver type %1$d"), - pcisrc->driver.name); - return -1; - } - - virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); - } - - virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + if (virDeviceHostdevPCIDriverInfoFormat(buf, &pcisrc->driver) < 0) + return -1; if (def->writeFiltering != VIR_TRISTATE_BOOL_ABSENT) virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'", -- 2.43.0

Now if a new attribute is added to <driver>, we only need to update the formatting/parsing in one place. Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/network_conf.c | 23 ++++------------------- src/conf/virnetworkportdef.c | 20 ++++++-------------- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index d732e90b6d..890c16b3b1 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1349,13 +1349,9 @@ virNetworkForwardDefParseXML(const char *networkName, def->managed = true; } - if ((driverNode = virXPathNode("./driver", ctxt))) { - if (virXMLPropEnum(driverNode, "name", - virDeviceHostdevPCIDriverNameTypeFromString, - VIR_XML_PROP_NONZERO, - &def->driver.name) < 0) { + if ((driverNode = virXPathNode("./driver", ctxt)) && + virDeviceHostdevPCIDriverInfoParseXML(driverNode, &def->driver) < 0) { return -1; - } } /* bridge and hostdev modes can use a pool of physical interfaces */ @@ -2317,7 +2313,6 @@ virNetworkDefFormatBuf(virBuffer *buf, if (def->forward.type != VIR_NETWORK_FORWARD_NONE) { const char *dev = NULL; const char *mode = virNetworkForwardTypeToString(def->forward.type); - g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; if (!def->forward.npfs) dev = virNetworkDefForwardIf(def, 0); @@ -2347,18 +2342,8 @@ virNetworkDefFormatBuf(virBuffer *buf, virBufferAsprintf(buf, "%s>\n", shortforward ? "/" : ""); virBufferAdjustIndent(buf, 2); - if (def->forward.driver.name) { - const char *driverName = virDeviceHostdevPCIDriverNameTypeToString(def->forward.driver.name); - if (!driverName) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected hostdev driver name %1$d "), - def->forward.driver.name); - return -1; - } - virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); - } - - virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + if (virDeviceHostdevPCIDriverInfoFormat(buf, &def->forward.driver) < 0) + return -1; if (def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (virNetworkForwardNatDefFormat(buf, &def->forward) < 0) diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c index c7902f0174..49d00b2ea6 100644 --- a/src/conf/virnetworkportdef.c +++ b/src/conf/virnetworkportdef.c @@ -224,13 +224,10 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) &def->plug.hostdevpci.managed) < 0) return NULL; - if ((driverNode = virXPathNode("./plug/driver", ctxt))) { - if (virXMLPropEnum(driverNode, "name", - virDeviceHostdevPCIDriverNameTypeFromString, - VIR_XML_PROP_NONZERO, - &def->plug.hostdevpci.driver.name) < 0) { - return NULL; - } + if ((driverNode = virXPathNode("./plug/driver", ctxt)) && + virDeviceHostdevPCIDriverInfoParseXML(driverNode, + &def->plug.hostdevpci.driver) < 0) { + return NULL; } if (!(addressNode = virXPathNode("./plug/address", ctxt))) { @@ -321,7 +318,6 @@ virNetworkPortDefFormatBuf(virBuffer *buf, virTristateBoolTypeToString(def->trustGuestRxFilters)); if (def->plugtype != VIR_NETWORK_PORT_PLUG_TYPE_NONE) { - g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; virBufferAsprintf(buf, "<plug type='%s'", virNetworkPortPlugTypeToString(def->plugtype)); @@ -356,12 +352,8 @@ virNetworkPortDefFormatBuf(virBuffer *buf, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - if (def->plug.hostdevpci.driver.name) { - virBufferEscapeString(&driverAttrBuf, " name='%s'", - virDeviceHostdevPCIDriverNameTypeToString(def->plug.hostdevpci.driver.name)); - } - - virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + if (virDeviceHostdevPCIDriverInfoFormat(buf, &def->plug.hostdevpci.driver) < 0) + return -1; virPCIDeviceAddressFormat(buf, def->plug.hostdevpci.addr, false); virBufferAdjustIndent(buf, -2); -- 2.43.0

virHostdevIsVFIODevice() and virDomainDefHasVFIOHostdev() are only ever called from the QEMU driver, and in the case of the QEMU driver, any PCI hostdev by definition uses VFIO, so really all these callers only need to know if the device is a PCI hostdev. (It turned out that the less specific virHostdevIsPCIDevice() already existed in hypervisor/virhostdev.c, so I had to remove one of them; since conf is a lower level directory than hypervisor, and the function is called from conf, keeping the copy in hypervisor would have required moving its caller (virDomainDefHasPCIHostdev()) into hypervisor as well, so I just removed the copy in hypervisor.) Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/domain_conf.c | 13 ++++++------- src/conf/domain_conf.h | 4 ++-- src/hypervisor/virhostdev.c | 8 -------- src/hypervisor/virhostdev.h | 2 -- src/libvirt_private.syms | 5 ++--- src/qemu/qemu_domain.c | 6 +++--- src/qemu/qemu_hostdev.c | 2 +- src/qemu/qemu_hotplug.c | 2 +- 8 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b3c7b50f97..0f137543e0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -30653,12 +30653,12 @@ virDomainDefHasNVMeDisk(const virDomainDef *def) bool -virDomainDefHasVFIOHostdev(const virDomainDef *def) +virDomainDefHasPCIHostdev(const virDomainDef *def) { size_t i; for (i = 0; i < def->nhostdevs; i++) { - if (virHostdevIsVFIODevice(def->hostdevs[i])) + if (virHostdevIsPCIDevice(def->hostdevs[i])) return true; } @@ -30929,17 +30929,16 @@ virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev) /** - * virHostdevIsVFIODevice: + * virHostdevIsPCIDevice: * @hostdev: host device to check * - * Returns true if @hostdev is a PCI device with VFIO backend, false otherwise. + * Returns true if @hostdev is a PCI device, false otherwise. */ bool -virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev) +virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev) { return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && - hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ee8bcbc6b3..7dd5bdbe56 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -4418,7 +4418,7 @@ bool virDomainDefHasNVMeDisk(const virDomainDef *def); bool -virDomainDefHasVFIOHostdev(const virDomainDef *def); +virDomainDefHasPCIHostdev(const virDomainDef *def); bool virDomainDefHasMdevHostdev(const virDomainDef *def); @@ -4476,7 +4476,7 @@ bool virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev) ATTRIBUTE_NONNULL(1); bool -virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev) +virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev) ATTRIBUTE_NONNULL(1); int diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c index 27b0acdc91..40f8a4bc2c 100644 --- a/src/hypervisor/virhostdev.c +++ b/src/hypervisor/virhostdev.c @@ -344,14 +344,6 @@ virHostdevNetDevice(virDomainHostdevDef *hostdev, } -bool -virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev) -{ - return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && - hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; -} - - static bool virHostdevIsPCINetDevice(const virDomainHostdevDef *hostdev) { diff --git a/src/hypervisor/virhostdev.h b/src/hypervisor/virhostdev.h index 642d753ffb..22ec3068db 100644 --- a/src/hypervisor/virhostdev.h +++ b/src/hypervisor/virhostdev.h @@ -232,5 +232,3 @@ virHostdevUpdateActiveNVMeDevices(virHostdevManager *hostdev_mgr, const char *dom_name, virDomainDiskDef **disks, size_t ndisks); - -bool virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 002a3986d1..cccefe5a81 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -340,11 +340,11 @@ virDomainDefHasMemoryHotplug; virDomainDefHasNVMeDisk; virDomainDefHasOldStyleROUEFI; virDomainDefHasOldStyleUEFI; +virDomainDefHasPCIHostdev; virDomainDefHasSpiceGraphics; virDomainDefHasUSB; virDomainDefHasVcpusOffline; virDomainDefHasVDPANet; -virDomainDefHasVFIOHostdev; virDomainDefLifecycleActionAllowed; virDomainDefMaybeAddController; virDomainDefMaybeAddInput; @@ -777,8 +777,8 @@ virDomainEventWatchdogNewFromObj; virDomainQemuMonitorEventNew; virDomainQemuMonitorEventStateRegisterID; virHostdevIsMdevDevice; +virHostdevIsPCIDevice; virHostdevIsSCSIDevice; -virHostdevIsVFIODevice; # conf/domain_nwfilter.h @@ -1641,7 +1641,6 @@ virCloseCallbacksDomainRunForConn; # hypervisor/virhostdev.h virHostdevFindUSBDevice; -virHostdevIsPCIDevice; virHostdevManagerGetDefault; virHostdevPCINodeDeviceDetach; virHostdevPCINodeDeviceReAttach; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1aeeb74503..9357ce8d62 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9343,7 +9343,7 @@ getPPC64MemLockLimitBytes(virDomainDef *def) for (i = 0; i < def->nhostdevs; i++) { virDomainHostdevDef *dev = def->hostdevs[i]; - if (virHostdevIsVFIODevice(dev)) { + if (virHostdevIsPCIDevice(dev)) { pciAddr = &dev->source.subsys.u.pci.addr; if (virPCIDeviceAddressIsValid(pciAddr, false)) { @@ -9448,7 +9448,7 @@ qemuDomainGetNumVFIOHostdevs(const virDomainDef *def) int n = 0; for (i = 0; i < def->nhostdevs; i++) { - if (virHostdevIsVFIODevice(def->hostdevs[i]) || + if (virHostdevIsPCIDevice(def->hostdevs[i]) || virHostdevIsMdevDevice(def->hostdevs[i])) n++; } @@ -10489,7 +10489,7 @@ qemuDomainSupportsVideoVga(const virDomainVideoDef *video, bool qemuDomainNeedsVFIO(const virDomainDef *def) { - return virDomainDefHasVFIOHostdev(def) || + return virDomainDefHasPCIHostdev(def) || virDomainDefHasMdevHostdev(def) || virDomainDefHasNVMeDisk(def); } diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 4992c23ee0..15b543dbff 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -133,7 +133,7 @@ qemuHostdevUpdateActiveDomainDevices(virQEMUDriver *driver, bool qemuHostdevNeedsVFIO(const virDomainHostdevDef *hostdev) { - return virHostdevIsVFIODevice(hostdev) || + return virHostdevIsPCIDevice(hostdev) || virHostdevIsMdevDevice(hostdev); } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 75e1d39b60..0e45bd53e1 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4738,7 +4738,7 @@ qemuDomainRemoveHostDevice(virQEMUDriver *driver, virDomainAuditHostdev(vm, hostdev, "detach", true); - if (!virHostdevIsVFIODevice(hostdev) && + if (!virHostdevIsPCIDevice(hostdev) && qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0) VIR_WARN("Failed to restore host device labelling"); -- 2.43.0

Xen only supports a single type of PCI hostdev assignment, so it is superfluous to have <driver name='xen'/> peppered throughout the config. It *is* necessary to have the driver type explicitly set in the hostdev object before calling into the hypervisor-agnostic "hostdev manager" though (otherwise the hostdev manager doesn't know whether it should do Xen-specific setup, or VFIO-specific setup). Historically, the Xen driver has checked for "default" driver name (i.e. not set in the XML), and set it to "xen', during the XML postparse, thus guaranteeing that it will be set by the time the object is sent to the hostdev manager at runtime, but also setting it so early that a simple round-trip of parse-format results in the XML always containing an explicit <driver name='xen'/>, even if that wasn't specified in the original XML. The QEMU driver *doesn't* set driver.name during postparse though; instead, it waits until domain startup time (or device attach time for hotplug), and sets the driver.name then. The result is that a parse-format round trip of the XML in the QEMU driver *doesn't* add in the <driver name='vfio'/>. This patch modifies the Xen driver to behave similarly to the QEMU driver - the PostParse just checks for a driver.name that isn't supported by the Xen driver, and any explicit setting to "xen" is deferred until domain runtime rather than during the postparse, thus Xen domain XML also doesn't get extraneous <driver name='xen'/>. This delayed setting of driver.name of course results in slightly different xml2xml parse-format results, so the unit test data is modified accordingly. Signed-off-by: Laine Stump <laine@redhat.com> --- Change from V2: add note in source code that the default value set internally for driver name during libxlPrepareDevices should never change unless the new and old defaults are guest ABI compatible. (this will only have meaning if a 2nd type of device assignment for the Xen driver is ever introduced) src/libxl/libxl_domain.c | 73 ++++++++++++++++--- src/libxl/libxl_driver.c | 25 ++++--- tests/libxlxml2domconfigdata/moredevs-hvm.xml | 1 - tests/xlconfigdata/test-fullvirt-pci.xml | 2 - tests/xmconfigdata/test-pci-dev-syntax.xml | 2 - tests/xmconfigdata/test-pci-devs.xml | 2 - 6 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 1a7de00704..670fd2881e 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -160,8 +160,15 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDef *dev, if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) - pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + pcisrc->driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT && + pcisrc->driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN) { + + /* Xen only supports "Xen" style of hostdev */ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("XEN does not support device assignment mode '%1$s'"), + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name)); + return -1; + } } if (dev->type == VIR_DOMAIN_DEVICE_VIDEO) { @@ -986,18 +993,9 @@ libxlNetworkPrepareDevices(virDomainDef *def) if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV && net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { /* Each type='hostdev' network device must also have a - * corresponding entry in the hostdevs array. For netdevs - * that are hardcoded as type='hostdev', this is already - * done by the parser, but for those allocated from a - * network / determined at runtime, we need to do it - * separately. + * corresponding entry in the hostdevs array. */ virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net); - virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci; - - if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && - hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; if (virDomainHostdevInsert(def, hostdev) < 0) return -1; @@ -1007,6 +1005,54 @@ libxlNetworkPrepareDevices(virDomainDef *def) return 0; } + +static int +libxlHostdevPrepareDevices(virDomainDef *def) +{ + size_t i; + + for (i = 0; i < def->nhostdevs; i++) { + virDomainHostdevDef *hostdev = def->hostdevs[i]; + virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci; + + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && + pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) { + + + pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + + /* Q: Why do we set an explicit driver.name here even + * though Xen (currently) only supports one driver.name for + * PCI hostdev assignment? + * + * A: Setting the driver name *in the domain XML config* + * is optional (and actually pointless at the time of + * writing, since each hypervisor only supports a single + * type of PCI hostdev device assignment). But the + * hypervisor-agnostic virHostdevPrepareDomainDevices(), + * which is called immediately after this function in + * order to do any driver-related setup (e.g. bind the + * host device to a driver kernel driver), requires that + * the driver.name be explicitly set (otherwise it wouldn't + * know whether to bind to the Xen driver or VFIO driver, + * for example). + * + * NB: If there are ever multiple types of device + * assignment supported by Xen, DO NOT CHANGE the value of + * driver.name set above when the config is "default" to + * anything other than "xen", unless the guest ABI of the + * new type is compatible with that of current "xen" + * device assignment. + * + */ + } + } + + return 0; +} + + static void libxlConsoleCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback) { @@ -1174,6 +1220,9 @@ libxlDomainStartPrepare(libxlDriverPrivate *driver, if (libxlNetworkPrepareDevices(vm->def) < 0) goto error; + if (libxlHostdevPrepareDevices(vm->def) < 0) + goto error; + if (virHostdevPrepareDomainDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME, vm->def, hostdev_flags) < 0) goto error; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 29fbc823dd..6c843b9054 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3087,6 +3087,22 @@ libxlDomainAttachHostPCIDevice(libxlDriverPrivate *driver, VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1); + /* The only supported driverType for Xen is + * VIR_DOMAIN_HOSTDEV_PCI_DRIVER_TYPE_XEN, which normally isn't + * set in the config (because it doesn't need to be), but it does + * need to be set for the impending call to + * virHostdevPreparePCIDevices() + */ + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) + pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; + + if (pcisrc->driver.name != VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("XEN does not support device assignment mode '%1$s'"), + virDeviceHostdevPCIDriverNameTypeToString(pcisrc->driver.name)); + goto cleanup; + } + if (virHostdevPreparePCIDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME, vm->def->name, vm->def->uuid, &hostdev, 1, 0) < 0) @@ -3395,15 +3411,6 @@ libxlDomainAttachNetDevice(libxlDriverPrivate *driver, if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net); - virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci; - - /* For those just allocated from a network pool whose driver type is - * still VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT, we need to set - * driver name correctly. - */ - if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && - hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - pcisrc->driver.name = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN; /* This is really a "smart hostdev", so it should be attached * as a hostdev (the hostdev code will reach over into the diff --git a/tests/libxlxml2domconfigdata/moredevs-hvm.xml b/tests/libxlxml2domconfigdata/moredevs-hvm.xml index 89ad80631d..64eeeff889 100644 --- a/tests/libxlxml2domconfigdata/moredevs-hvm.xml +++ b/tests/libxlxml2domconfigdata/moredevs-hvm.xml @@ -43,7 +43,6 @@ </interface> <interface type='hostdev' managed='yes'> <mac address='00:16:3e:2e:e7:fc'/> - <driver name='xen'/> <source> <address type='pci' domain='0x0000' bus='0x0a' slot='0x10' function='0x0'/> </source> diff --git a/tests/xlconfigdata/test-fullvirt-pci.xml b/tests/xlconfigdata/test-fullvirt-pci.xml index 75aa6ac25b..6826d14b9e 100644 --- a/tests/xlconfigdata/test-fullvirt-pci.xml +++ b/tests/xlconfigdata/test-fullvirt-pci.xml @@ -37,13 +37,11 @@ <model type='cirrus' vram='8192' heads='1' primary='yes'/> </video> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source> <address domain='0x0000' bus='0x01' slot='0x1a' function='0x1'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source writeFiltering='no'> <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> </source> diff --git a/tests/xmconfigdata/test-pci-dev-syntax.xml b/tests/xmconfigdata/test-pci-dev-syntax.xml index 5d5d29c61c..1d5d857072 100644 --- a/tests/xmconfigdata/test-pci-dev-syntax.xml +++ b/tests/xmconfigdata/test-pci-dev-syntax.xml @@ -55,13 +55,11 @@ <model type='cirrus' vram='8192' heads='1' primary='yes'/> </video> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source> <address domain='0x0001' bus='0x0c' slot='0x1b' function='0x2'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source> <address domain='0x0000' bus='0x01' slot='0x13' function='0x0'/> </source> diff --git a/tests/xmconfigdata/test-pci-devs.xml b/tests/xmconfigdata/test-pci-devs.xml index 5d5d29c61c..1d5d857072 100644 --- a/tests/xmconfigdata/test-pci-devs.xml +++ b/tests/xmconfigdata/test-pci-devs.xml @@ -55,13 +55,11 @@ <model type='cirrus' vram='8192' heads='1' primary='yes'/> </video> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source> <address domain='0x0001' bus='0x0c' slot='0x1b' function='0x2'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='xen'/> <source> <address domain='0x0000' bus='0x01' slot='0x13' function='0x0'/> </source> -- 2.43.0

On Fri, Jan 05, 2024 at 03:20:13 -0500, Laine Stump wrote:
Xen only supports a single type of PCI hostdev assignment, so it is superfluous to have <driver name='xen'/> peppered throughout the config. It *is* necessary to have the driver type explicitly set in the hostdev object before calling into the hypervisor-agnostic "hostdev manager" though (otherwise the hostdev manager doesn't know whether it should do Xen-specific setup, or VFIO-specific setup).
Historically, the Xen driver has checked for "default" driver name (i.e. not set in the XML), and set it to "xen', during the XML postparse, thus guaranteeing that it will be set by the time the object is sent to the hostdev manager at runtime, but also setting it so early that a simple round-trip of parse-format results in the XML always containing an explicit <driver name='xen'/>, even if that wasn't specified in the original XML.
The QEMU driver *doesn't* set driver.name during postparse though; instead, it waits until domain startup time (or device attach time for hotplug), and sets the driver.name then. The result is that a parse-format round trip of the XML in the QEMU driver *doesn't* add in the <driver name='vfio'/>.
This patch modifies the Xen driver to behave similarly to the QEMU driver - the PostParse just checks for a driver.name that isn't supported by the Xen driver, and any explicit setting to "xen" is deferred until domain runtime rather than during the postparse, thus Xen domain XML also doesn't get extraneous <driver name='xen'/>.
This delayed setting of driver.name of course results in slightly different xml2xml parse-format results, so the unit test data is modified accordingly.
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V2: add note in source code that the default value set internally for driver name during libxlPrepareDevices should never change unless the new and old defaults are guest ABI compatible. (this will only have meaning if a 2nd type of device assignment for the Xen driver is ever introduced)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

The long-deprecated use of <driver name='vfio|xen|kvm'/> in domain xml for <hostdev> devices was only ever necessary during the period when libvirt (and the Linux kernel) supported both VFIO and "legacy KVM" styles of hostdev device assignment for QEMU. This became pointless many years ago when legacy KVM device assignment was removed from the kernel, and support for that style of device assignment was completely disabled in the libvirt source in 2019 (commit v5.6.0-316-g2e7225ea8c). Nevertheless, there were instances of <driver name='vfio'/> in the unit test data that were then (unnecessarily) propagated to several more tests over the years. This patch cleans out those unnecessary explicit settings of driver name='vfio' in all QEMU unit test data, proving that the attribute is no longer (externally) needed. (A later patch which adds a 2nd attribute to the <driver> element will include a test case that explicitly exercises the driver name attribute). Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- Change from V2: eliminated more <driver name='vfio'/> occurences in test XML, made possible by moving the "replace virHostdevisVFIODevice ..." patch in front of this one. docs/formatdomain.rst | 1 - docs/formatnetwork.rst | 1 - docs/formatnetworkport.rst | 1 - docs/pci-addresses.rst | 1 - tests/networkxml2xmlin/hostdev-pf.xml | 1 - tests/networkxml2xmlout/hostdev-pf.xml | 1 - .../qemuhotplug-hostdev-pci.xml | 1 - .../qemumemlock-pc-hardlimit+hostdev.xml | 1 - ...emumemlock-pc-hardlimit+locked+hostdev.xml | 1 - .../qemumemlock-pc-hostdev-nvme.xml | 1 - .../qemumemlock-pc-hostdev.xml | 1 - .../qemumemlock-pc-locked+hostdev.xml | 1 - .../qemumemlock-pseries-hardlimit+hostdev.xml | 1 - ...mlock-pseries-hardlimit+locked+hostdev.xml | 1 - .../qemumemlock-pseries-hostdev.xml | 1 - .../qemumemlock-pseries-locked+hostdev.xml | 1 - tests/qemustatusxml2xmldata/modern-in.xml | 1 - .../hostdev-pci-address-unassigned.xml | 4 -- .../hostdev-pci-multifunction.xml | 7 --- .../hostdev-vfio-multidomain.xml | 1 - .../hostdev-vfio-zpci-autogenerate-fids.xml | 2 - .../hostdev-vfio-zpci-autogenerate-uids.xml | 2 - .../hostdev-vfio-zpci-autogenerate.xml | 1 - .../hostdev-vfio-zpci-boundaries.xml | 2 - .../hostdev-vfio-zpci-ccw-memballoon.xml | 1 - .../hostdev-vfio-zpci-duplicate.xml | 2 - ...ostdev-vfio-zpci-invalid-uid-valid-fid.xml | 1 - .../hostdev-vfio-zpci-multidomain-many.xml | 8 ---- .../hostdev-vfio-zpci-set-zero.xml | 1 - .../hostdev-vfio-zpci-uid-set-zero.xml | 1 - .../hostdev-vfio-zpci-wrong-arch.xml | 1 - tests/qemuxml2argvdata/hostdev-vfio-zpci.xml | 1 - tests/qemuxml2argvdata/hostdev-vfio.xml | 1 - .../net-hostdev-vfio-multidomain.xml | 1 - tests/qemuxml2argvdata/net-hostdev-vfio.xml | 1 - tests/qemuxml2argvdata/pseries-hostdevs-1.xml | 3 -- tests/qemuxml2argvdata/pseries-hostdevs-2.xml | 2 - tests/qemuxml2argvdata/pseries-hostdevs-3.xml | 2 - ...v-pci-address-unassigned.x86_64-latest.xml | 4 -- ...ostdev-pci-multifunction.x86_64-latest.xml | 7 --- ...dev-vfio-old-driver-name.x86_64-latest.xml | 46 +++++++++++++++++++ ...io-zpci-autogenerate-fids.s390x-latest.xml | 2 - ...io-zpci-autogenerate-uids.s390x-latest.xml | 2 - ...ev-vfio-zpci-autogenerate.s390x-latest.xml | 1 - ...tdev-vfio-zpci-boundaries.s390x-latest.xml | 2 - ...-vfio-zpci-ccw-memballoon.s390x-latest.xml | 1 - ...fio-zpci-multidomain-many.s390x-latest.xml | 8 ---- .../hostdev-vfio-zpci.s390x-latest.xml | 1 - .../hostdev-vfio.x86_64-latest.xml | 1 - .../net-hostdev-vfio.x86_64-latest.xml | 1 - .../pseries-hostdevs-1.ppc64-latest.xml | 3 -- .../pseries-hostdevs-2.ppc64-latest.xml | 2 - .../pseries-hostdevs-3.ppc64-latest.xml | 2 - 53 files changed, 46 insertions(+), 99 deletions(-) create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-old-driver-name.x86_64-latest.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 310d2bc427..c08033f940 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -5224,7 +5224,6 @@ or stopping the guest. ... <devices> <interface type='hostdev' managed='yes'> - <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> diff --git a/docs/formatnetwork.rst b/docs/formatnetwork.rst index c54d53070a..5d300a035e 100644 --- a/docs/formatnetwork.rst +++ b/docs/formatnetwork.rst @@ -392,7 +392,6 @@ to the physical LAN (if at all). ... <forward mode='hostdev' managed='yes'> - <driver name='vfio'/> <address type='pci' domain='0' bus='4' slot='0' function='1'/> <address type='pci' domain='0' bus='4' slot='0' function='2'/> <address type='pci' domain='0' bus='4' slot='0' function='3'/> diff --git a/docs/formatnetworkport.rst b/docs/formatnetworkport.rst index 40a4f0e85b..e60445b3b4 100644 --- a/docs/formatnetworkport.rst +++ b/docs/formatnetworkport.rst @@ -163,7 +163,6 @@ rather than emulation. ... <plug type='hostdev-pci' managed='yes'> - <driver name='vfio'/> <address domain='0x0001' bus='0x02' slot='0x03' function='0x4'/> </plug> ... diff --git a/docs/pci-addresses.rst b/docs/pci-addresses.rst index eb4945f169..bfc0bbccc3 100644 --- a/docs/pci-addresses.rst +++ b/docs/pci-addresses.rst @@ -223,7 +223,6 @@ For example, the domain XML snippet :: <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x08' slot='0x00' function='0x0'/> </source> diff --git a/tests/networkxml2xmlin/hostdev-pf.xml b/tests/networkxml2xmlin/hostdev-pf.xml index 5b8f59858c..7bf857d3a1 100644 --- a/tests/networkxml2xmlin/hostdev-pf.xml +++ b/tests/networkxml2xmlin/hostdev-pf.xml @@ -2,7 +2,6 @@ <name>hostdev</name> <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> <forward mode='hostdev' managed='yes'> - <driver name='vfio'/> <pf dev='eth2'/> </forward> </network> diff --git a/tests/networkxml2xmlout/hostdev-pf.xml b/tests/networkxml2xmlout/hostdev-pf.xml index 5b8f59858c..7bf857d3a1 100644 --- a/tests/networkxml2xmlout/hostdev-pf.xml +++ b/tests/networkxml2xmlout/hostdev-pf.xml @@ -2,7 +2,6 @@ <name>hostdev</name> <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> <forward mode='hostdev' managed='yes'> - <driver name='vfio'/> <pf dev='eth2'/> </forward> </network> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-hostdev-pci.xml b/tests/qemuhotplugtestdevices/qemuhotplug-hostdev-pci.xml index 6f7c99c943..0d6dec9d26 100644 --- a/tests/qemuhotplugtestdevices/qemuhotplug-hostdev-pci.xml +++ b/tests/qemuhotplugtestdevices/qemuhotplug-hostdev-pci.xml @@ -1,5 +1,4 @@ <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml index e03f5a585d..18bafaa355 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml @@ -11,7 +11,6 @@ <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml index 7070e5a12c..34a3960e8b 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml @@ -14,7 +14,6 @@ <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hostdev-nvme.xml b/tests/qemumemlockdata/qemumemlock-pc-hostdev-nvme.xml index 06f1496970..ac20d2b3a0 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hostdev-nvme.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hostdev-nvme.xml @@ -15,7 +15,6 @@ <target dev='vda' bus='virtio'/> </disk> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml index cd517ee226..cc8b6b00ab 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml index da79cb5277..3cbe4a17b3 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml @@ -11,7 +11,6 @@ <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml index baf0649db7..b9c2aefc28 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml @@ -11,7 +11,6 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml index 04ae4e93bf..731d4a5392 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml @@ -14,7 +14,6 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml index a52768cb31..3d016928af 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml index f5abef0b06..b942fa4834 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml @@ -11,7 +11,6 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemustatusxml2xmldata/modern-in.xml b/tests/qemustatusxml2xmldata/modern-in.xml index 67e0aa4952..f0f5df84ab 100644 --- a/tests/qemustatusxml2xmldata/modern-in.xml +++ b/tests/qemustatusxml2xmldata/modern-in.xml @@ -502,7 +502,6 @@ <address type='drive' controller='0' bus='0' target='2' unit='4'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> <origstates> diff --git a/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml b/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml index 9a2685ca0e..864ef303c0 100644 --- a/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml +++ b/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml @@ -14,26 +14,22 @@ <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> </source> <address type='unassigned'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x3'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-pci-multifunction.xml b/tests/qemuxml2argvdata/hostdev-pci-multifunction.xml index 06c889c64d..ba0a593628 100644 --- a/tests/qemuxml2argvdata/hostdev-pci-multifunction.xml +++ b/tests/qemuxml2argvdata/hostdev-pci-multifunction.xml @@ -14,43 +14,36 @@ <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x3'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-multidomain.xml b/tests/qemuxml2argvdata/hostdev-vfio-multidomain.xml index b720883913..7afe18b24e 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-multidomain.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-multidomain.xml @@ -23,7 +23,6 @@ <controller type='ide' index='0'/> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0021' bus='222' slot='31' function='1'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-fids.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-fids.xml index 49c26e2434..e72c524a98 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-fids.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-fids.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-s390x</emulator> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -17,7 +16,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-uids.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-uids.xml index e74e0116c7..1ed75aae48 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-uids.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate-uids.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-s390x</emulator> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -17,7 +16,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml index 36161006ab..b4b1ce315f 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-s390x</emulator> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml index 1e6060345b..fe005af488 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0xffff' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -18,7 +17,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-ccw-memballoon.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-ccw-memballoon.xml index ef5e97fc9c..bb6861f103 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-ccw-memballoon.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-ccw-memballoon.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-s390x</emulator> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-duplicate.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-duplicate.xml index 6062ae4940..53cf48ea6a 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-duplicate.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-duplicate.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -18,7 +17,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-invalid-uid-valid-fid.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-invalid-uid-valid-fid.xml index 6e7101489e..1026661730 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-invalid-uid-valid-fid.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-invalid-uid-valid-fid.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml index da8305dd6d..36c11a8311 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -18,7 +17,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0002' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -27,20 +25,17 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0003' bus='0x00' slot='0x00' function='0x0'/> </source> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0004' bus='0x00' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -49,7 +44,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0006' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -58,7 +52,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0007' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -67,7 +60,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0008' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-set-zero.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-set-zero.xml index fd3d1193f1..eefe05de39 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-set-zero.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-set-zero.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-uid-set-zero.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-uid-set-zero.xml index 6bfbfe611b..fb0e680b55 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-uid-set-zero.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-uid-set-zero.xml @@ -8,7 +8,6 @@ <devices> <emulator>/usr/bin/qemu-system-s390x</emulator> <hostdev mode='subsystem' type='pci'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml index a9a5afd6dd..8b3cc45ddf 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml @@ -21,7 +21,6 @@ </disk> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='00' slot='00' function='0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml index 002b99c52d..5f439eff73 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml @@ -9,7 +9,6 @@ <emulator>/usr/bin/qemu-system-s390x</emulator> <controller type='pci' index='0' model='pci-root'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/hostdev-vfio.xml b/tests/qemuxml2argvdata/hostdev-vfio.xml index 1b438a2eef..a03870f6e0 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio.xml @@ -25,7 +25,6 @@ <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> diff --git a/tests/qemuxml2argvdata/net-hostdev-vfio-multidomain.xml b/tests/qemuxml2argvdata/net-hostdev-vfio-multidomain.xml index ae8c4e7e80..cdadf4f2cb 100644 --- a/tests/qemuxml2argvdata/net-hostdev-vfio-multidomain.xml +++ b/tests/qemuxml2argvdata/net-hostdev-vfio-multidomain.xml @@ -24,7 +24,6 @@ <controller type='pci' index='0' model='pci-root'/> <interface type='hostdev' managed='yes'> <mac address='00:11:22:33:44:55'/> - <driver name='vfio'/> <source> <address type='pci' domain='0x0021' bus='0xde' slot='0x1f' function='0x1'/> </source> diff --git a/tests/qemuxml2argvdata/net-hostdev-vfio.xml b/tests/qemuxml2argvdata/net-hostdev-vfio.xml index e6e6b6e5d3..9cdb8a602d 100644 --- a/tests/qemuxml2argvdata/net-hostdev-vfio.xml +++ b/tests/qemuxml2argvdata/net-hostdev-vfio.xml @@ -24,7 +24,6 @@ <controller type='pci' index='0' model='pci-root'/> <interface type='hostdev' managed='yes'> <mac address='00:11:22:33:44:55'/> - <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> diff --git a/tests/qemuxml2argvdata/pseries-hostdevs-1.xml b/tests/qemuxml2argvdata/pseries-hostdevs-1.xml index 04f3ec4759..5d09413a98 100644 --- a/tests/qemuxml2argvdata/pseries-hostdevs-1.xml +++ b/tests/qemuxml2argvdata/pseries-hostdevs-1.xml @@ -11,7 +11,6 @@ <!-- This hostdev will cause a new PHB to be created because its isolation group is 1 (IOMMU group 0) --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> @@ -19,7 +18,6 @@ <!-- This hostdev can't share the PHB that was just created, because its isolation group is 2 (IOMMU group 1) --> <interface type='hostdev' managed='yes'> - <driver name='vfio'/> <source> <address type='pci' domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> @@ -28,7 +26,6 @@ <!-- This hostdev will be placed on the first PHB, since its isolation group is 1 (IOMMU group 0) just like the first hostdev --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> diff --git a/tests/qemuxml2argvdata/pseries-hostdevs-2.xml b/tests/qemuxml2argvdata/pseries-hostdevs-2.xml index 6568475c72..00d4228499 100644 --- a/tests/qemuxml2argvdata/pseries-hostdevs-2.xml +++ b/tests/qemuxml2argvdata/pseries-hostdevs-2.xml @@ -17,7 +17,6 @@ despite being in the separate isolation group 1 (IOMMU group 0), because the address has been requested explicitly by the user --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> @@ -26,7 +25,6 @@ <!-- This hostdev can use neither the PHB that was just created, nor the default one, because it's in isolation group 2 (IOMMU group 1) --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> diff --git a/tests/qemuxml2argvdata/pseries-hostdevs-3.xml b/tests/qemuxml2argvdata/pseries-hostdevs-3.xml index 4f51f48c90..64ba95ca30 100644 --- a/tests/qemuxml2argvdata/pseries-hostdevs-3.xml +++ b/tests/qemuxml2argvdata/pseries-hostdevs-3.xml @@ -11,7 +11,6 @@ <!-- This hostdev will cause a new PHB to be created because its isolation group is 1 (IOMMU group 0). It will be PHB 2 due to the address --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> @@ -20,7 +19,6 @@ <!-- This hostdev will be placed on the same PHB, since its isolation group is also 1 (IOMMU group 0) --> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.x86_64-latest.xml b/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.x86_64-latest.xml index 480d2f8363..9da9a8a07e 100644 --- a/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.x86_64-latest.xml @@ -28,28 +28,24 @@ <input type='keyboard' bus='ps2'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> </source> <address type='unassigned'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x3'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-pci-multifunction.x86_64-latest.xml b/tests/qemuxml2xmloutdata/hostdev-pci-multifunction.x86_64-latest.xml index a29a27e85b..9530c28e14 100644 --- a/tests/qemuxml2xmloutdata/hostdev-pci-multifunction.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-pci-multifunction.x86_64-latest.xml @@ -28,49 +28,42 @@ <input type='keyboard' bus='ps2'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x3'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-old-driver-name.x86_64-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-old-driver-name.x86_64-latest.xml new file mode 100644 index 0000000000..3915b515f2 --- /dev/null +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-old-driver-name.x86_64-latest.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <hostdev mode='subsystem' type='pci' managed='yes'> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-fids.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-fids.s390x-latest.xml index dd1dea4e99..f23ad5b90c 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-fids.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-fids.s390x-latest.xml @@ -20,7 +20,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -29,7 +28,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-uids.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-uids.s390x-latest.xml index 1a52487692..9bf2ce32be 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-uids.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate-uids.s390x-latest.xml @@ -20,7 +20,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -29,7 +28,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.s390x-latest.xml index 670f8c68b4..94f3c04b9a 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.s390x-latest.xml @@ -20,7 +20,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.s390x-latest.xml index df55f79501..8b0044af1c 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.s390x-latest.xml @@ -25,7 +25,6 @@ </controller> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0xffff' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -34,7 +33,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-ccw-memballoon.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-ccw-memballoon.s390x-latest.xml index 7df6491b68..e0ff360553 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-ccw-memballoon.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-ccw-memballoon.s390x-latest.xml @@ -18,7 +18,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.s390x-latest.xml index e64d7de561..70d592f2df 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.s390x-latest.xml @@ -20,7 +20,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -29,7 +28,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0002' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -38,7 +36,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0003' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -47,7 +44,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0004' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -56,7 +52,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -65,7 +60,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0006' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -74,7 +68,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0007' bus='0x00' slot='0x00' function='0x0'/> </source> @@ -83,7 +76,6 @@ </address> </hostdev> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0008' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.s390x-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.s390x-latest.xml index 5e14a63810..c8a1407427 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.s390x-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.s390x-latest.xml @@ -20,7 +20,6 @@ <controller type='pci' index='0' model='pci-root'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='no'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml index b660d245a1..3915b515f2 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml @@ -34,7 +34,6 @@ <input type='keyboard' bus='ps2'/> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> diff --git a/tests/qemuxml2xmloutdata/net-hostdev-vfio.x86_64-latest.xml b/tests/qemuxml2xmloutdata/net-hostdev-vfio.x86_64-latest.xml index 167e1b1fea..1eee425593 100644 --- a/tests/qemuxml2xmloutdata/net-hostdev-vfio.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/net-hostdev-vfio.x86_64-latest.xml @@ -32,7 +32,6 @@ <controller type='pci' index='0' model='pci-root'/> <interface type='hostdev' managed='yes'> <mac address='00:11:22:33:44:55'/> - <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> diff --git a/tests/qemuxml2xmloutdata/pseries-hostdevs-1.ppc64-latest.xml b/tests/qemuxml2xmloutdata/pseries-hostdevs-1.ppc64-latest.xml index db369a1fc7..d0ad114d34 100644 --- a/tests/qemuxml2xmloutdata/pseries-hostdevs-1.ppc64-latest.xml +++ b/tests/qemuxml2xmloutdata/pseries-hostdevs-1.ppc64-latest.xml @@ -32,7 +32,6 @@ </controller> <interface type='hostdev' managed='yes'> <mac address='52:54:00:6d:90:02'/> - <driver name='vfio'/> <source> <address type='pci' domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> @@ -40,14 +39,12 @@ </interface> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> diff --git a/tests/qemuxml2xmloutdata/pseries-hostdevs-2.ppc64-latest.xml b/tests/qemuxml2xmloutdata/pseries-hostdevs-2.ppc64-latest.xml index 09b657698d..4ffcae80b8 100644 --- a/tests/qemuxml2xmloutdata/pseries-hostdevs-2.ppc64-latest.xml +++ b/tests/qemuxml2xmloutdata/pseries-hostdevs-2.ppc64-latest.xml @@ -35,14 +35,12 @@ </controller> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> diff --git a/tests/qemuxml2xmloutdata/pseries-hostdevs-3.ppc64-latest.xml b/tests/qemuxml2xmloutdata/pseries-hostdevs-3.ppc64-latest.xml index 58ffb09c3b..e06901a9a4 100644 --- a/tests/qemuxml2xmloutdata/pseries-hostdevs-3.ppc64-latest.xml +++ b/tests/qemuxml2xmloutdata/pseries-hostdevs-3.ppc64-latest.xml @@ -32,14 +32,12 @@ </controller> <audio id='1' type='none'/> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> - <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> -- 2.43.0

This patch makes it possible to manually specify which VFIO variant driver to use for PCI hostdev device assignment, so that, e.g. you could force use of a VFIO "variant" driver, with e.g. <driver model='mlx5_vfio_pci'/> or alternately to force use of the generic vfio-pci driver with <driver model='vfio-pci'/> when libvirt would have normally (after applying a subsequent patch) found a "better match" for a device in the active kernel's modules.alias file. (The main potential use of this manual override would probably be to work around a bug in a new VFIO variant driver by temporarily not using that driver). Signed-off-by: Laine Stump <laine@redhat.com> --- Change from V2: use new <driver model='blah'/> instead of repurposing existing <driver name='blah'/> docs/formatdomain.rst | 54 +++++++++++++------ docs/formatnetwork.rst | 21 ++++---- src/conf/device_conf.c | 10 ++++ src/conf/device_conf.h | 4 ++ src/conf/domain_conf.c | 3 ++ src/conf/network_conf.c | 2 + src/conf/schemas/basictypes.rng | 21 +++++--- src/conf/virnetworkportdef.c | 1 + src/network/bridge_driver.c | 1 + tests/networkxml2xmlin/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmlout/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmltest.c | 6 +++ .../hostdev-vfio.x86_64-latest.args | 5 +- tests/qemuxml2argvdata/hostdev-vfio.xml | 18 +++++++ .../hostdev-vfio.x86_64-latest.xml | 23 +++++++- .../plug-hostdev-pci-unmanaged.xml | 1 - .../plug-hostdev-pci.xml | 1 - 17 files changed, 148 insertions(+), 39 deletions(-) create mode 100644 tests/networkxml2xmlin/hostdev-pf-old.xml create mode 100644 tests/networkxml2xmlout/hostdev-pf-old.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index c08033f940..36c74d9eae 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -4500,24 +4500,46 @@ or: an error. See the `Device Addresses`_ section for more details on the address element. ``driver`` - PCI devices can have an optional ``driver`` subelement that specifies which - backend driver to use for PCI device assignment. Use the ``name`` attribute - to select either "vfio" (for the new VFIO device assignment backend, which is - compatible with UEFI SecureBoot) or "kvm" (the legacy device assignment - handled directly by the KVM kernel module) :since:`Since 1.0.5 (QEMU and KVM - only, requires kernel 3.6 or newer)` . When specified, device assignment will - fail if the requested method of device assignment isn't available on the - host. When not specified, the default is "vfio" on systems where the VFIO - driver is available and loaded, and "kvm" on older systems, or those where - the VFIO driver hasn't been loaded :since:`Since 1.1.3` (prior to that the - default was always "kvm"). + PCI hostdev devices can have an optional ``driver`` subelement that + specifies which host driver to bind to the device when preparing it + for assignment to a guest. :since:`Since 10.0.0 (useful for QEMU and + KVM only)`. This is done by setting the ``<driver>`` element's ``model`` + attribute, for example:: + + ... + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver model='vfio-pci-igb'/> + ... + + tells libvirt to bind the driver "vfio-pci-igb" to the device on + the host before handing it off to QEMU for assignment to the + guest. Normally libvirt will bind the device to the "best match" + VFIO-type driver that it finds in the kernel's modules.alias file + (based on matching the corresponding fields of the device's + modalias file in sysfs) or to the generic "vfio-pci" driver if no + better match is found (vfio-pci is always used prior to libvirt + 10.0.0), but in cases when the correct driver isn't listed in + modules.alias then the desired device-specific driver can be forced + by setting driver name, or if the device-specific driver that is + found is "problematic" in some way, the generic vfio-pci driver + similarly be forced. + + (Note: :since:`Since 1.0.5, the ``name`` attribute has been + described to be used to select the type of PCI device assignment + ("vfio", "kvm", or "xen"), but those values have been mostly + useless, since the type of device assignment is actually determined + by which hypservisor is in use. This means that you may + occasionally see ``<driver name='vfio'/>`` or ``<driver + name='xen'/>`` in a domain's status XML, or more rarely in config, + but those specific values are essentially ignored.) + ``readonly`` - Indicates that the device is readonly, only supported by SCSI host device - now. :since:`Since 1.0.6 (QEMU and KVM only)` + Indicates that the device is readonly, only supported by SCSI host + device now. :since:`Since 1.0.6 (QEMU and KVM only)` ``shareable`` - If present, this indicates the device is expected to be shared between - domains (assuming the hypervisor and OS support this). Only supported by SCSI - host device. :since:`Since 1.0.6` + If present, this indicates the device is expected to be shared + between domains (assuming the hypervisor and OS support this). Only + supported by SCSI host device. :since:`Since 1.0.6` Note: Although ``shareable`` was introduced :since:`in 1.0.6` , it did not work as as expected until :since:`1.2.2` . diff --git a/docs/formatnetwork.rst b/docs/formatnetwork.rst index 5d300a035e..d4181ac029 100644 --- a/docs/formatnetwork.rst +++ b/docs/formatnetwork.rst @@ -315,17 +315,14 @@ to the physical LAN (if at all). guest, use the traditional ``<hostdev>`` device definition. :since:` Since 0.10.0` - To force use of a particular type of device assignment, a <forward - type='hostdev'> interface can have an optional ``driver`` sub-element with - a ``name`` attribute set to either "vfio" (VFIO is a new method of device - assignment that is compatible with UEFI Secure Boot) or "kvm" (the legacy - device assignment handled directly by the KVM kernel module) :since:`Since - 1.0.5 (QEMU and KVM only, requires kernel 3.6 or newer)` . When specified, - device assignment will fail if the requested method of device assignment - isn't available on the host. When not specified, the default is "vfio" on - systems where the VFIO driver is available and loaded, and "kvm" on older - systems, or those where the VFIO driver hasn't been loaded :since:`Since - 1.1.3` (prior to that the default was always "kvm"). + To force use of a particular device-specific VFIO driver when + assigning the devices to a guest, a <forward type='hostdev'> + interface can have an optional ``driver`` sub-element with a + ``model`` attribute set to the name of the driver to use + :since:`Since 10.0.0 (QEMU only)`. When not specified, libvirt + will attempt to find a suitable VFIO variant driver for the + device, and if not found it will use the generic driver + "vfio-pci". Note that this "intelligent passthrough" of network devices is very similar to the functionality of a standard ``<hostdev>`` device, the @@ -337,7 +334,7 @@ to the physical LAN (if at all). to the guest domain), or if you are using a version of libvirt older than 0.10.0, you should use a standard ``<hostdev>`` device definition in the domain's configuration to assign the device to the guest instead of - defining an ``<interface type='network'>`` pointing to a + defining an ``<interface type='network'>`` pointing to a network with ``<forward mode='hostdev'/>``. As mentioned above, a ``<forward>`` element can have multiple ``<interface>`` diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c index 68a8c7690a..f840efc1b5 100644 --- a/src/conf/device_conf.c +++ b/src/conf/device_conf.c @@ -67,6 +67,7 @@ virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node, return -1; } + driver->model = virXMLPropString(node, "model"); return 0; } @@ -90,11 +91,20 @@ virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf, virBufferAsprintf(&driverAttrBuf, " name='%s'", driverName); } + virBufferEscapeString(&driverAttrBuf, " model='%s'", driver->model); + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); return 0; } +void +virDeviceHostdevPCIDriverInfoClear(virDeviceHostdevPCIDriverInfo *driver) +{ + VIR_FREE(driver->model); +} + + static int virZPCIDeviceAddressParseXML(xmlNodePtr node, virPCIDeviceAddress *addr) diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 0b3f17a3aa..2d674ecd85 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -46,6 +46,7 @@ VIR_ENUM_DECL(virDeviceHostdevPCIDriverName); struct _virDeviceHostdevPCIDriverInfo { virDeviceHostdevPCIDriverName name; + char *model; }; typedef enum { @@ -192,6 +193,9 @@ int virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node, int virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf, const virDeviceHostdevPCIDriverInfo *driver); +void virDeviceHostdevPCIDriverInfoPostParse(virDeviceHostdevPCIDriverInfo *driver); +void virDeviceHostdevPCIDriverInfoClear(virDeviceHostdevPCIDriverInfo *driver); + void virDomainDeviceInfoClear(virDomainDeviceInfo *info); void virDomainDeviceInfoFree(virDomainDeviceInfo *info); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0f137543e0..02fd5815cc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2636,6 +2636,7 @@ virDomainHostdevDefClear(virDomainHostdevDef *def) VIR_FREE(def->source.subsys.u.scsi_host.wwpn); break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + virDeviceHostdevPCIDriverInfoClear(&def->source.subsys.u.pci.driver); g_clear_pointer(&def->source.subsys.u.pci.origstates, virBitmapFree); break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: @@ -29898,6 +29899,7 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface, actual->data.hostdev.def.source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr; actual->data.hostdev.def.source.subsys.u.pci.driver.name = port->plug.hostdevpci.driver.name; + actual->data.hostdev.def.source.subsys.u.pci.driver.model = g_strdup(port->plug.hostdevpci.driver.model); break; case VIR_NETWORK_PORT_PLUG_TYPE_LAST: @@ -29999,6 +30001,7 @@ virDomainNetDefActualToNetworkPort(virDomainDef *dom, port->plug.hostdevpci.managed = virTristateBoolFromBool(actual->data.hostdev.def.managed); port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr; port->plug.hostdevpci.driver.name = actual->data.hostdev.def.source.subsys.u.pci.driver.name; + port->plug.hostdevpci.driver.model = g_strdup(actual->data.hostdev.def.source.subsys.u.pci.driver.model); break; case VIR_DOMAIN_NET_TYPE_CLIENT: diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 890c16b3b1..5c781d06af 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -229,6 +229,8 @@ virNetworkForwardDefClear(virNetworkForwardDef *def) { size_t i; + virDeviceHostdevPCIDriverInfoClear(&def->driver); + for (i = 0; i < def->npfs && def->pfs; i++) virNetworkForwardPfDefClear(&def->pfs[i]); VIR_FREE(def->pfs); diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng index 8d5f4475ca..b65d210091 100644 --- a/src/conf/schemas/basictypes.rng +++ b/src/conf/schemas/basictypes.rng @@ -658,13 +658,20 @@ <define name="hostdevDriver"> <element name="driver"> - <attribute name="name"> - <choice> - <value>kvm</value> - <value>vfio</value> - <value>xen</value> - </choice> - </attribute> + <optional> + <attribute name="name"> + <choice> + <value>kvm</value> + <value>vfio</value> + <value>xen</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="model"> + <ref name="genericName"/> + </attribute> + </optional> <empty/> </element> </define> diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c index 49d00b2ea6..64db63ae66 100644 --- a/src/conf/virnetworkportdef.c +++ b/src/conf/virnetworkportdef.c @@ -64,6 +64,7 @@ virNetworkPortDefFree(virNetworkPortDef *def) break; case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + virDeviceHostdevPCIDriverInfoClear(&def->plug.hostdevpci.driver); break; case VIR_NETWORK_PORT_PLUG_TYPE_LAST: diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index d156333626..9921c7cd14 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3931,6 +3931,7 @@ networkAllocatePort(virNetworkObj *obj, } port->plug.hostdevpci.addr = dev->device.pci; port->plug.hostdevpci.driver.name = netdef->forward.driver.name; + port->plug.hostdevpci.driver.model = g_strdup(netdef->forward.driver.model); port->plug.hostdevpci.managed = virTristateBoolFromBool(netdef->forward.managed); if (port->virtPortProfile) { diff --git a/tests/networkxml2xmlin/hostdev-pf-old.xml b/tests/networkxml2xmlin/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlin/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/> + <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmlout/hostdev-pf-old.xml b/tests/networkxml2xmlout/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlout/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/> + <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index b0814c7529..928f28b579 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -146,6 +146,12 @@ mymain(void) DO_TEST_FLAGS("passthrough-pf", VIR_NETWORK_XML_INACTIVE); DO_TEST("hostdev"); DO_TEST_FLAGS("hostdev-pf", VIR_NETWORK_XML_INACTIVE); + + /* libvirt pre-9.9.0 used "name='vfio'" which should be + * automatically translated to "type='vfio'" by new parser + */ + DO_TEST_FLAGS("hostdev-pf-old", VIR_NETWORK_XML_INACTIVE); + DO_TEST("passthrough-address-crash"); DO_TEST("nat-network-explicit-flood"); DO_TEST("host-bridge-no-flood"); diff --git a/tests/qemuxml2argvdata/hostdev-vfio.x86_64-latest.args b/tests/qemuxml2argvdata/hostdev-vfio.x86_64-latest.args index c1f9258844..8529cde269 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio.x86_64-latest.args +++ b/tests/qemuxml2argvdata/hostdev-vfio.x86_64-latest.args @@ -32,6 +32,9 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.config \ -device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -device '{"driver":"vfio-pci","host":"0000:06:12.1","id":"hostdev0","bus":"pci.0","addr":"0x2"}' \ --device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-device '{"driver":"vfio-pci","host":"0000:06:12.2","id":"hostdev1","bus":"pci.0","addr":"0x3"}' \ +-device '{"driver":"vfio-pci","host":"0000:06:12.3","id":"hostdev2","bus":"pci.0","addr":"0x4"}' \ +-device '{"driver":"vfio-pci","host":"0000:06:12.4","id":"hostdev3","bus":"pci.0","addr":"0x5"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x6"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/qemuxml2argvdata/hostdev-vfio.xml b/tests/qemuxml2argvdata/hostdev-vfio.xml index a03870f6e0..812bac2cfd 100644 --- a/tests/qemuxml2argvdata/hostdev-vfio.xml +++ b/tests/qemuxml2argvdata/hostdev-vfio.xml @@ -29,6 +29,24 @@ <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> </source> </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver model='vfio-pci-igb'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x3'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio' model='vfio-pci-igb'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x4'/> + </source> + </hostdev> <memballoon model='virtio'/> </devices> </domain> diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml b/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml index 3915b515f2..2042ba6c16 100644 --- a/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/hostdev-vfio.x86_64-latest.xml @@ -39,8 +39,29 @@ </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </hostdev> - <memballoon model='virtio'> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> + </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver model='vfio-pci-igb'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x3'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio' model='vfio-pci-igb'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x4'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </hostdev> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </memballoon> </devices> </domain> diff --git a/tests/virnetworkportxml2xmldata/plug-hostdev-pci-unmanaged.xml b/tests/virnetworkportxml2xmldata/plug-hostdev-pci-unmanaged.xml index da5f568031..fa974affee 100644 --- a/tests/virnetworkportxml2xmldata/plug-hostdev-pci-unmanaged.xml +++ b/tests/virnetworkportxml2xmldata/plug-hostdev-pci-unmanaged.xml @@ -6,7 +6,6 @@ </owner> <mac address='52:54:00:7b:35:93'/> <plug type='hostdev-pci' managed='no'> - <driver name='vfio'/> <address domain='0x0001' bus='0x02' slot='0x03' function='0x4'/> </plug> </networkport> diff --git a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml index cc4419f3fd..7354e1d48c 100644 --- a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml +++ b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml @@ -6,7 +6,6 @@ </owner> <mac address='52:54:00:7b:35:93'/> <plug type='hostdev-pci' managed='yes'> - <driver name='vfio'/> <address domain='0x0001' bus='0x02' slot='0x03' function='0x4'/> </plug> </networkport> -- 2.43.0

On Fri, Jan 05, 2024 at 03:20:15 -0500, Laine Stump wrote:
This patch makes it possible to manually specify which VFIO variant driver to use for PCI hostdev device assignment, so that, e.g. you could force use of a VFIO "variant" driver, with e.g.
<driver model='mlx5_vfio_pci'/>
or alternately to force use of the generic vfio-pci driver with
<driver model='vfio-pci'/>
when libvirt would have normally (after applying a subsequent patch) found a "better match" for a device in the active kernel's modules.alias file. (The main potential use of this manual override would probably be to work around a bug in a new VFIO variant driver by temporarily not using that driver).
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V2: use new <driver model='blah'/> instead of repurposing existing <driver name='blah'/>
docs/formatdomain.rst | 54 +++++++++++++------ docs/formatnetwork.rst | 21 ++++---- src/conf/device_conf.c | 10 ++++ src/conf/device_conf.h | 4 ++ src/conf/domain_conf.c | 3 ++ src/conf/network_conf.c | 2 + src/conf/schemas/basictypes.rng | 21 +++++--- src/conf/virnetworkportdef.c | 1 + src/network/bridge_driver.c | 1 + tests/networkxml2xmlin/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmlout/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmltest.c | 6 +++ .../hostdev-vfio.x86_64-latest.args | 5 +- tests/qemuxml2argvdata/hostdev-vfio.xml | 18 +++++++ .../hostdev-vfio.x86_64-latest.xml | 23 +++++++- .../plug-hostdev-pci-unmanaged.xml | 1 - .../plug-hostdev-pci.xml | 1 - 17 files changed, 148 insertions(+), 39 deletions(-) create mode 100644 tests/networkxml2xmlin/hostdev-pf-old.xml create mode 100644 tests/networkxml2xmlout/hostdev-pf-old.xml
[...]
diff --git a/docs/formatnetwork.rst b/docs/formatnetwork.rst index 5d300a035e..d4181ac029 100644 --- a/docs/formatnetwork.rst +++ b/docs/formatnetwork.rst @@ -315,17 +315,14 @@ to the physical LAN (if at all). guest, use the traditional ``<hostdev>`` device definition. :since:` Since 0.10.0`
- To force use of a particular type of device assignment, a <forward - type='hostdev'> interface can have an optional ``driver`` sub-element with - a ``name`` attribute set to either "vfio" (VFIO is a new method of device - assignment that is compatible with UEFI Secure Boot) or "kvm" (the legacy - device assignment handled directly by the KVM kernel module) :since:`Since - 1.0.5 (QEMU and KVM only, requires kernel 3.6 or newer)` . When specified, - device assignment will fail if the requested method of device assignment - isn't available on the host. When not specified, the default is "vfio" on - systems where the VFIO driver is available and loaded, and "kvm" on older - systems, or those where the VFIO driver hasn't been loaded :since:`Since - 1.1.3` (prior to that the default was always "kvm"). + To force use of a particular device-specific VFIO driver when + assigning the devices to a guest, a <forward type='hostdev'> + interface can have an optional ``driver`` sub-element with a + ``model`` attribute set to the name of the driver to use + :since:`Since 10.0.0 (QEMU only)`. When not specified, libvirt + will attempt to find a suitable VFIO variant driver for the + device, and if not found it will use the generic driver + "vfio-pci".
There aren't any tests for this, the test added below just tests the old code
Note that this "intelligent passthrough" of network devices is very similar to the functionality of a standard ``<hostdev>`` device, the @@ -337,7 +334,7 @@ to the physical LAN (if at all). to the guest domain), or if you are using a version of libvirt older than 0.10.0, you should use a standard ``<hostdev>`` device definition in the domain's configuration to assign the device to the guest instead of - defining an ``<interface type='network'>`` pointing to a + defining an ``<interface type='network'>`` pointing to a network with ``<forward mode='hostdev'/>``.
diff --git a/tests/networkxml2xmlin/hostdev-pf-old.xml b/tests/networkxml2xmlin/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlin/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/>
'name'
+ <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmlout/hostdev-pf-old.xml b/tests/networkxml2xmlout/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlout/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/>
'name'
+ <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index b0814c7529..928f28b579 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -146,6 +146,12 @@ mymain(void) DO_TEST_FLAGS("passthrough-pf", VIR_NETWORK_XML_INACTIVE); DO_TEST("hostdev"); DO_TEST_FLAGS("hostdev-pf", VIR_NETWORK_XML_INACTIVE); + + /* libvirt pre-9.9.0 used "name='vfio'" which should be
This version is no longer correct
+ * automatically translated to "type='vfio'" by new parser + */
And based on the files added above, this is not true.
+ DO_TEST_FLAGS("hostdev-pf-old", VIR_NETWORK_XML_INACTIVE); + DO_TEST("passthrough-address-crash"); DO_TEST("nat-network-explicit-flood"); DO_TEST("host-bridge-no-flood");
With the network testing stuff addressed: Reviewed-by: Peter Krempa <pkrempa@redhat.com>

On 1/5/24 7:36 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:15 -0500, Laine Stump wrote:
This patch makes it possible to manually specify which VFIO variant driver to use for PCI hostdev device assignment, so that, e.g. you could force use of a VFIO "variant" driver, with e.g.
<driver model='mlx5_vfio_pci'/>
or alternately to force use of the generic vfio-pci driver with
<driver model='vfio-pci'/>
when libvirt would have normally (after applying a subsequent patch) found a "better match" for a device in the active kernel's modules.alias file. (The main potential use of this manual override would probably be to work around a bug in a new VFIO variant driver by temporarily not using that driver).
Signed-off-by: Laine Stump <laine@redhat.com> ---
Change from V2: use new <driver model='blah'/> instead of repurposing existing <driver name='blah'/>
docs/formatdomain.rst | 54 +++++++++++++------ docs/formatnetwork.rst | 21 ++++---- src/conf/device_conf.c | 10 ++++ src/conf/device_conf.h | 4 ++ src/conf/domain_conf.c | 3 ++ src/conf/network_conf.c | 2 + src/conf/schemas/basictypes.rng | 21 +++++--- src/conf/virnetworkportdef.c | 1 + src/network/bridge_driver.c | 1 + tests/networkxml2xmlin/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmlout/hostdev-pf-old.xml | 8 +++ tests/networkxml2xmltest.c | 6 +++ .../hostdev-vfio.x86_64-latest.args | 5 +- tests/qemuxml2argvdata/hostdev-vfio.xml | 18 +++++++ .../hostdev-vfio.x86_64-latest.xml | 23 +++++++- .../plug-hostdev-pci-unmanaged.xml | 1 - .../plug-hostdev-pci.xml | 1 - 17 files changed, 148 insertions(+), 39 deletions(-) create mode 100644 tests/networkxml2xmlin/hostdev-pf-old.xml create mode 100644 tests/networkxml2xmlout/hostdev-pf-old.xml
[...]
diff --git a/docs/formatnetwork.rst b/docs/formatnetwork.rst index 5d300a035e..d4181ac029 100644 --- a/docs/formatnetwork.rst +++ b/docs/formatnetwork.rst @@ -315,17 +315,14 @@ to the physical LAN (if at all). guest, use the traditional ``<hostdev>`` device definition. :since:` Since 0.10.0`
- To force use of a particular type of device assignment, a <forward - type='hostdev'> interface can have an optional ``driver`` sub-element with - a ``name`` attribute set to either "vfio" (VFIO is a new method of device - assignment that is compatible with UEFI Secure Boot) or "kvm" (the legacy - device assignment handled directly by the KVM kernel module) :since:`Since - 1.0.5 (QEMU and KVM only, requires kernel 3.6 or newer)` . When specified, - device assignment will fail if the requested method of device assignment - isn't available on the host. When not specified, the default is "vfio" on - systems where the VFIO driver is available and loaded, and "kvm" on older - systems, or those where the VFIO driver hasn't been loaded :since:`Since - 1.1.3` (prior to that the default was always "kvm"). + To force use of a particular device-specific VFIO driver when + assigning the devices to a guest, a <forward type='hostdev'> + interface can have an optional ``driver`` sub-element with a + ``model`` attribute set to the name of the driver to use + :since:`Since 10.0.0 (QEMU only)`. When not specified, libvirt + will attempt to find a suitable VFIO variant driver for the + device, and if not found it will use the generic driver + "vfio-pci".
There aren't any tests for this, the test added below just tests the old code
yeah, you're correct that the added test (hostdev-old) doesn't exercise the new code - that test should have been added back in the patch where I removed most of the explicit <driver name='vfio'/> from the test cases (so that there was at least one left). But the additions to the hostdev-vfio test *do* exercise the new code.
Note that this "intelligent passthrough" of network devices is very similar to the functionality of a standard ``<hostdev>`` device, the @@ -337,7 +334,7 @@ to the physical LAN (if at all). to the guest domain), or if you are using a version of libvirt older than 0.10.0, you should use a standard ``<hostdev>`` device definition in the domain's configuration to assign the device to the guest instead of - defining an ``<interface type='network'>`` pointing to a + defining an ``<interface type='network'>`` pointing to a
Hmm. this change removing extra whitespace shouldn't be in this patch. Not sure how that happened.
network with ``<forward mode='hostdev'/>``.
diff --git a/tests/networkxml2xmlin/hostdev-pf-old.xml b/tests/networkxml2xmlin/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlin/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/>
'name'
Yeah - I'll move this new test to patch 11
+ <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmlout/hostdev-pf-old.xml b/tests/networkxml2xmlout/hostdev-pf-old.xml new file mode 100644 index 0000000000..5b8f59858c --- /dev/null +++ b/tests/networkxml2xmlout/hostdev-pf-old.xml @@ -0,0 +1,8 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode='hostdev' managed='yes'> + <driver name='vfio'/>
'name'
+ <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index b0814c7529..928f28b579 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -146,6 +146,12 @@ mymain(void) DO_TEST_FLAGS("passthrough-pf", VIR_NETWORK_XML_INACTIVE); DO_TEST("hostdev"); DO_TEST_FLAGS("hostdev-pf", VIR_NETWORK_XML_INACTIVE); + + /* libvirt pre-9.9.0 used "name='vfio'" which should be
This version is no longer correct
+ * automatically translated to "type='vfio'" by new parser + */
And based on the files added above, this is not true.
Oops, that comment is left over from before when I was trying to re-purpose driver name. When I move the addition of the test back to patch 11, I'll also eliminate this comment completely, since it is obsolete.
+ DO_TEST_FLAGS("hostdev-pf-old", VIR_NETWORK_XML_INACTIVE); + DO_TEST("passthrough-address-crash"); DO_TEST("nat-network-explicit-flood"); DO_TEST("host-bridge-no-flood");
With the network testing stuff addressed:
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Rather than always binding to the vfio-pci driver, use the new function virPCIDeviceFindBestVFIOVariant() to see if the running kernel has a VFIO variant driver available that is a better match for the device, and if one is found, use that instead. virPCIDeviceFindBestVFIOVariant() function reads the modalias file for the given device from sysfs, then looks through /lib/modules/${kernel_release}/modules.alias for the vfio_pci alias that matches with the least number of wildcard ('*') fields. The appropriate "VFIO variant" driver for a device will be the PCI driver implemented by the discovered module - these drivers are compatible with (and provide the entire API of) the standard vfio-pci driver, but have additional device-specific APIs that can be useful for, e.g., saving/restoring state for migration. If a specific driver is named (using <driver model='blah'/> in the device XML), that will still be used rather than searching modules.alias; this makes it possible to force binding of vfio-pci if there is an issue with the auto-selected variant driver. Signed-off-by: Laine Stump <laine@redhat.com> --- Changes from V2: * fail if device modalias file isn't found. * use unsigned int instead of int for wildcardCt * increase file memory buffer from 4MB to 8MB * other minor nits pointed out by Peter src/libvirt_private.syms | 1 + src/util/virpci.c | 219 +++++++++++++++++++++++++++++++++++++++ src/util/virpci.h | 2 + tests/virpcimock.c | 9 ++ 4 files changed, 231 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cccefe5a81..2cf01c5f50 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3076,6 +3076,7 @@ virPCIDeviceCopy; virPCIDeviceDetach; virPCIDeviceExists; virPCIDeviceFileIterate; +virPCIDeviceFindBestVFIOVariant; virPCIDeviceFree; virPCIDeviceGetAddress; virPCIDeviceGetConfigPath; diff --git a/src/util/virpci.c b/src/util/virpci.c index f6bdf56057..99d6740ed1 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -30,6 +30,10 @@ #include <sys/stat.h> #include <unistd.h> +#ifdef __linux__ +# include <sys/utsname.h> +#endif + #include "virlog.h" #include "virerror.h" #include "virfile.h" @@ -1321,6 +1325,206 @@ virPCIDeviceFindDriver(virPCIDevice *dev) } +#ifdef __linux__ +typedef struct { + /* this is the decomposed version of a string like: + * + * vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN + * + * (followed by a space or newline). The "NNNN" are always of the + * length in the example unless replaced with a wildcard ("*"), + * but we make no assumptions about length. + * + * Rather than name each field, we just put them + * all in an array of 7 elements, so that we + * can write a simple loop to compare them + */ + char *fields[7]; /* v, d, sv, sd, bc, sc, i */ +} virPCIDeviceAliasInfo; + + +/* NULL in last position makes parsing loop simpler */ +static const char *fieldnames[] = { "v", "d", "sv", "sd", "bc", "sc", "i", NULL }; + + +static void +virPCIDeviceAliasInfoFree(virPCIDeviceAliasInfo *info) +{ + if (info) { + size_t i; + + for (i = 0; i < G_N_ELEMENTS(info->fields); i++) + g_free(info->fields[i]); + + g_free(info); + } +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIDeviceAliasInfo, virPCIDeviceAliasInfoFree); + + +static virPCIDeviceAliasInfo * +virPCIDeviceAliasInfoNew(const char *str) +{ + const char *field = str; + + size_t i; + g_autoptr(virPCIDeviceAliasInfo) ret = g_new0(virPCIDeviceAliasInfo, 1); + + /* initialize from str */ + for (i = 0; i < G_N_ELEMENTS(ret->fields); i++) { + int len = strlen(fieldnames[i]); + const char *next; + + if (strncmp(field, fieldnames[i], len)) + return NULL; + + field += len; + if (fieldnames[i + 1]) { + if (!(next = strstr(field, fieldnames[i + 1]))) + return NULL; + } else { + next = field; + while (*next && !g_ascii_isspace(*next)) + next++; + } + + ret->fields[i] = g_strndup(field, next - field); + field = next; + } + + return g_steal_pointer(&ret); +} + + +static bool +virPCIDeviceAliasInfoMatch(virPCIDeviceAliasInfo *orig, + virPCIDeviceAliasInfo *match, + unsigned int *wildCardCt) +{ + size_t i; + + *wildCardCt = 0; + + for (i = 0; i < G_N_ELEMENTS(orig->fields); i++) { + if (STREQ(match->fields[i], "*")) + (*wildCardCt)++; + else if (STRNEQ(orig->fields[i], match->fields[i])) + return false; + } + return true; +} + + +/* virPCIDeviceFindBestVFIOVariant: + * + * Find the "best" match of all vfio_pci aliases for @dev in the host + * modules.alias file. This uses the algorithm of finding every + * modules.alias line that begins with "vfio_pci:", then picking the + * one that matches the device's own modalias value (from the file of + * that name in the device's sysfs directory) with the fewest + * "wildcards" (* character, meaning "match any value for this + * attribute"). + */ +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, + char **moduleName) +{ + g_autofree char *devModAliasPath = NULL; + g_autofree char *devModAliasContent = NULL; + const char *devModAlias; + g_autoptr(virPCIDeviceAliasInfo) devModAliasInfo = NULL; + struct utsname unameInfo; + g_autofree char *modulesAliasPath = NULL; + g_autofree char *modulesAliasContent = NULL; + const char *line; + unsigned int currentBestWildcardCt = INT_MAX; + + *moduleName = NULL; + + /* get the modalias values for the device from sysfs */ + devModAliasPath = virPCIFile(dev->name, "modalias"); + if (virFileReadAll(devModAliasPath, 100, &devModAliasContent) < 0) + return -1; + + VIR_DEBUG("modalias path: '%s' contents: '%s'", + devModAliasPath, devModAliasContent); + + /* "pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN\n" */ + if ((devModAlias = STRSKIP(devModAliasContent, "pci:")) == NULL || + !(devModAliasInfo = virPCIDeviceAliasInfoNew(devModAlias))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("device modalias file %1$s content has improper format"), + devModAliasPath); + return -1; + } + + uname(&unameInfo); + modulesAliasPath = g_strdup_printf("/lib/modules/%s/modules.alias", unameInfo.release); + if (virFileReadAll(modulesAliasPath, 8 * 1024 * 1024, &modulesAliasContent) < 0) + return -1; + + /* Look for all lines that are aliases for vfio_pci drivers. + * (The first line is always a comment, so we can be sure "alias" + * is preceded by a newline) + */ + line = modulesAliasContent; + + while ((line = strstr(line, "\nalias vfio_pci:"))) { + g_autoptr(virPCIDeviceAliasInfo) fileModAliasInfo = NULL; + unsigned int wildCardCt; + + /* "alias vfio_pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN XXXX\n" */ + line += strlen("\nalias vfio_pci:"); + if (!(fileModAliasInfo = virPCIDeviceAliasInfoNew(line))) + continue; + + if (virPCIDeviceAliasInfoMatch(devModAliasInfo, + fileModAliasInfo, &wildCardCt)) { + + const char *aliasStart = strchr(line, ' '); + const char *aliasEnd = NULL; + g_autofree char *aliasName = NULL; + + if (!aliasStart) { + VIR_WARN("malformed modules.alias vfio_pci: line"); + continue; + } + + aliasStart++; + line = aliasEnd = strchrnul(aliasStart, '\n'); + aliasName = g_strndup(aliasStart, aliasEnd - aliasStart); + + VIR_DEBUG("matching alias '%s' found, %u wildcards, best previously was %u", + aliasName, wildCardCt, currentBestWildcardCt); + + if (wildCardCt < currentBestWildcardCt) { + + /* this is a better match than previous */ + currentBestWildcardCt = wildCardCt; + g_free(*moduleName); + *moduleName = g_steal_pointer(&aliasName); + } + } + } + return 0; +} + + +#else /* __linux__ */ + + +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev G_GNUC_UNUSED, + char **moduleName G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("VFIO device assignment is not available on this platform")); + return -1; +} +#endif /* __linux__ */ + + int virPCIDeviceUnbind(virPCIDevice *dev) { @@ -1431,6 +1635,21 @@ virPCIDeviceBindToStub(virPCIDevice *dev) return -1; } + if (dev->stubDriverType == VIR_PCI_STUB_DRIVER_VFIO && !dev->stubDriverName) { + g_autofree char *autodetectModuleName = NULL; + + /* automatically use a VFIO variant driver if available for + * this device. + */ + + if (virPCIDeviceFindBestVFIOVariant(dev, &autodetectModuleName) < 0) + return -1; + + g_free(dev->stubDriverName); + dev->stubDriverName = g_steal_pointer(&autodetectModuleName); + } + + /* if a driver name hasn't been decided by now, use default for this type */ if (!dev->stubDriverName) { const char *stubDriverName = NULL; diff --git a/src/util/virpci.h b/src/util/virpci.h index bc7cb2329f..a5bfe9c35d 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -124,6 +124,8 @@ int virPCIDeviceReset(virPCIDevice *dev, virPCIDeviceList *activeDevs, virPCIDeviceList *inactiveDevs); +int virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, char **moduleName) G_NO_INLINE; + void virPCIDeviceSetManaged(virPCIDevice *dev, bool managed); bool virPCIDeviceGetManaged(virPCIDevice *dev); diff --git a/tests/virpcimock.c b/tests/virpcimock.c index b2111794e6..13b37bb23d 100644 --- a/tests/virpcimock.c +++ b/tests/virpcimock.c @@ -25,6 +25,7 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) # define VIR_MOCK_LOOKUP_MAIN # include "virmock.h" +# include "virpci.h" # include <unistd.h> # include <fcntl.h> # include <sys/stat.h> @@ -925,6 +926,14 @@ pci_driver_handle_unbind(const char *path) } + +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev G_GNUC_UNUSED, + char **moduleName G_GNUC_UNUSED) +{ + return 0; +} + /* * Functions to load the symbols and init the environment */ -- 2.43.0

On Fri, Jan 05, 2024 at 03:20:16 -0500, Laine Stump wrote:
Rather than always binding to the vfio-pci driver, use the new function virPCIDeviceFindBestVFIOVariant() to see if the running kernel has a VFIO variant driver available that is a better match for the device, and if one is found, use that instead.
virPCIDeviceFindBestVFIOVariant() function reads the modalias file for the given device from sysfs, then looks through /lib/modules/${kernel_release}/modules.alias for the vfio_pci alias that matches with the least number of wildcard ('*') fields.
The appropriate "VFIO variant" driver for a device will be the PCI driver implemented by the discovered module - these drivers are compatible with (and provide the entire API of) the standard vfio-pci driver, but have additional device-specific APIs that can be useful for, e.g., saving/restoring state for migration.
If a specific driver is named (using <driver model='blah'/> in the device XML), that will still be used rather than searching modules.alias; this makes it possible to force binding of vfio-pci if there is an issue with the auto-selected variant driver.
Signed-off-by: Laine Stump <laine@redhat.com> ---
Changes from V2:
* fail if device modalias file isn't found.
This [1] ...
* use unsigned int instead of int for wildcardCt * increase file memory buffer from 4MB to 8MB * other minor nits pointed out by Peter
[...]
+/* virPCIDeviceFindBestVFIOVariant: + * + * Find the "best" match of all vfio_pci aliases for @dev in the host + * modules.alias file. This uses the algorithm of finding every + * modules.alias line that begins with "vfio_pci:", then picking the + * one that matches the device's own modalias value (from the file of + * that name in the device's sysfs directory) with the fewest + * "wildcards" (* character, meaning "match any value for this + * attribute"). + */ +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, + char **moduleName) +{ + g_autofree char *devModAliasPath = NULL; + g_autofree char *devModAliasContent = NULL; + const char *devModAlias; + g_autoptr(virPCIDeviceAliasInfo) devModAliasInfo = NULL; + struct utsname unameInfo; + g_autofree char *modulesAliasPath = NULL; + g_autofree char *modulesAliasContent = NULL; + const char *line; + unsigned int currentBestWildcardCt = INT_MAX;
UINT_MAX
+ + *moduleName = NULL; + + /* get the modalias values for the device from sysfs */ + devModAliasPath = virPCIFile(dev->name, "modalias"); + if (virFileReadAll(devModAliasPath, 100, &devModAliasContent) < 0)
... [1] isn't true.
+ return -1; + + VIR_DEBUG("modalias path: '%s' contents: '%s'", + devModAliasPath, devModAliasContent); + + /* "pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN\n" */ + if ((devModAlias = STRSKIP(devModAliasContent, "pci:")) == NULL || + !(devModAliasInfo = virPCIDeviceAliasInfoNew(devModAlias))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("device modalias file %1$s content has improper format"), + devModAliasPath); + return -1; + } + + uname(&unameInfo); + modulesAliasPath = g_strdup_printf("/lib/modules/%s/modules.alias", unameInfo.release); + if (virFileReadAll(modulesAliasPath, 8 * 1024 * 1024, &modulesAliasContent) < 0) + return -1;
IIUC this is picking a driver which is 'better' than the default 'vfio_pci', but the device itself would still work if the default were used, right? In such case do we really want to treat any of the errors above as failures? I presueme a workaround for if any of the above breaks is to use an explicitly specified driver, right?
+ + /* Look for all lines that are aliases for vfio_pci drivers. + * (The first line is always a comment, so we can be sure "alias" + * is preceded by a newline) + */ + line = modulesAliasContent; +

On 1/5/24 8:46 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:16 -0500, Laine Stump wrote:
Rather than always binding to the vfio-pci driver, use the new function virPCIDeviceFindBestVFIOVariant() to see if the running kernel has a VFIO variant driver available that is a better match for the device, and if one is found, use that instead.
virPCIDeviceFindBestVFIOVariant() function reads the modalias file for the given device from sysfs, then looks through /lib/modules/${kernel_release}/modules.alias for the vfio_pci alias that matches with the least number of wildcard ('*') fields.
The appropriate "VFIO variant" driver for a device will be the PCI driver implemented by the discovered module - these drivers are compatible with (and provide the entire API of) the standard vfio-pci driver, but have additional device-specific APIs that can be useful for, e.g., saving/restoring state for migration.
If a specific driver is named (using <driver model='blah'/> in the device XML), that will still be used rather than searching modules.alias; this makes it possible to force binding of vfio-pci if there is an issue with the auto-selected variant driver.
Signed-off-by: Laine Stump <laine@redhat.com> ---
Changes from V2:
* fail if device modalias file isn't found.
This [1] ...
* use unsigned int instead of int for wildcardCt * increase file memory buffer from 4MB to 8MB * other minor nits pointed out by Peter
[...]
+/* virPCIDeviceFindBestVFIOVariant: + * + * Find the "best" match of all vfio_pci aliases for @dev in the host + * modules.alias file. This uses the algorithm of finding every + * modules.alias line that begins with "vfio_pci:", then picking the + * one that matches the device's own modalias value (from the file of + * that name in the device's sysfs directory) with the fewest + * "wildcards" (* character, meaning "match any value for this + * attribute"). + */ +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, + char **moduleName) +{ + g_autofree char *devModAliasPath = NULL; + g_autofree char *devModAliasContent = NULL; + const char *devModAlias; + g_autoptr(virPCIDeviceAliasInfo) devModAliasInfo = NULL; + struct utsname unameInfo; + g_autofree char *modulesAliasPath = NULL; + g_autofree char *modulesAliasContent = NULL; + const char *line; + unsigned int currentBestWildcardCt = INT_MAX;
UINT_MAX
+ + *moduleName = NULL; + + /* get the modalias values for the device from sysfs */ + devModAliasPath = virPCIFile(dev->name, "modalias"); + if (virFileReadAll(devModAliasPath, 100, &devModAliasContent) < 0)
... [1] isn't true.
How so? If the file can't be opened, then virFileReadAll logs an error and returns -1, and changed changed this code from ignoring that to also returning -1, which will cause the caller to fail. What am I missing?
+ return -1; + + VIR_DEBUG("modalias path: '%s' contents: '%s'", + devModAliasPath, devModAliasContent); + + /* "pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN\n" */ + if ((devModAlias = STRSKIP(devModAliasContent, "pci:")) == NULL || + !(devModAliasInfo = virPCIDeviceAliasInfoNew(devModAlias))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("device modalias file %1$s content has improper format"), + devModAliasPath); + return -1; + } + + uname(&unameInfo); + modulesAliasPath = g_strdup_printf("/lib/modules/%s/modules.alias", unameInfo.release); + if (virFileReadAll(modulesAliasPath, 8 * 1024 * 1024, &modulesAliasContent) < 0) + return -1;
IIUC this is picking a driver which is 'better' than the default 'vfio_pci', but the device itself would still work if the default were used, right?
Correct.
In such case do we really want to treat any of the errors above as failures?
I was on the fence about this, which was why earlier versions ignored the error. But your earlier suggestion to check for file existence before trying to read the file (thus eliminating any sort of message at all, which I think would be wrong) pushed me in the direction of logging the error and failing (since it would be *really* broken for the modalias file to be missing). I would also be fine with logging the error when virFileReadAll() fails (ie *not* checking if the file exists so we could silently avoid the error log), but then clearing the and returning success. Does that work for you?
I presueme a workaround for if any of the above breaks is to use an explicitly specified driver, right?
Correct. If a driver is explicitly given, then we don't attempt to find a better match. So in the case that a device really had no modalias file but was otherwise working, the error could be worked around by adding <driver model='vfio-pci'/> to the XML (assuming that whatever is creating the XML is able to do that).
+ + /* Look for all lines that are aliases for vfio_pci drivers. + * (The first line is always a comment, so we can be sure "alias" + * is preceded by a newline) + */ + line = modulesAliasContent; +

On Fri, Jan 05, 2024 at 10:06:13 -0500, Laine Stump wrote:
On 1/5/24 8:46 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:16 -0500, Laine Stump wrote:
Rather than always binding to the vfio-pci driver, use the new function virPCIDeviceFindBestVFIOVariant() to see if the running kernel has a VFIO variant driver available that is a better match for the device, and if one is found, use that instead.
virPCIDeviceFindBestVFIOVariant() function reads the modalias file for the given device from sysfs, then looks through /lib/modules/${kernel_release}/modules.alias for the vfio_pci alias that matches with the least number of wildcard ('*') fields.
The appropriate "VFIO variant" driver for a device will be the PCI driver implemented by the discovered module - these drivers are compatible with (and provide the entire API of) the standard vfio-pci driver, but have additional device-specific APIs that can be useful for, e.g., saving/restoring state for migration.
If a specific driver is named (using <driver model='blah'/> in the device XML), that will still be used rather than searching modules.alias; this makes it possible to force binding of vfio-pci if there is an issue with the auto-selected variant driver.
Signed-off-by: Laine Stump <laine@redhat.com> ---
Changes from V2:
* fail if device modalias file isn't found.
This [1] ...
* use unsigned int instead of int for wildcardCt * increase file memory buffer from 4MB to 8MB * other minor nits pointed out by Peter
[...]
+/* virPCIDeviceFindBestVFIOVariant: + * + * Find the "best" match of all vfio_pci aliases for @dev in the host + * modules.alias file. This uses the algorithm of finding every + * modules.alias line that begins with "vfio_pci:", then picking the + * one that matches the device's own modalias value (from the file of + * that name in the device's sysfs directory) with the fewest + * "wildcards" (* character, meaning "match any value for this + * attribute"). + */ +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, + char **moduleName) +{ + g_autofree char *devModAliasPath = NULL; + g_autofree char *devModAliasContent = NULL; + const char *devModAlias; + g_autoptr(virPCIDeviceAliasInfo) devModAliasInfo = NULL; + struct utsname unameInfo; + g_autofree char *modulesAliasPath = NULL; + g_autofree char *modulesAliasContent = NULL; + const char *line; + unsigned int currentBestWildcardCt = INT_MAX;
UINT_MAX
+ + *moduleName = NULL; + + /* get the modalias values for the device from sysfs */ + devModAliasPath = virPCIFile(dev->name, "modalias"); + if (virFileReadAll(devModAliasPath, 100, &devModAliasContent) < 0)
... [1] isn't true.
How so? If the file can't be opened, then virFileReadAll logs an error and returns -1, and changed changed this code from ignoring that to also returning -1, which will cause the caller to fail. What am I missing?
I think I misremembered. I thought that the idea was that this should not fail if the file is missing.
+ return -1; + + VIR_DEBUG("modalias path: '%s' contents: '%s'", + devModAliasPath, devModAliasContent); + + /* "pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN\n" */ + if ((devModAlias = STRSKIP(devModAliasContent, "pci:")) == NULL || + !(devModAliasInfo = virPCIDeviceAliasInfoNew(devModAlias))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("device modalias file %1$s content has improper format"), + devModAliasPath); + return -1; + } + + uname(&unameInfo); + modulesAliasPath = g_strdup_printf("/lib/modules/%s/modules.alias", unameInfo.release); + if (virFileReadAll(modulesAliasPath, 8 * 1024 * 1024, &modulesAliasContent) < 0) + return -1;
IIUC this is picking a driver which is 'better' than the default 'vfio_pci', but the device itself would still work if the default were used, right?
Correct.
In such case do we really want to treat any of the errors above as failures?
I was on the fence about this, which was why earlier versions ignored the error. But your earlier suggestion to check for file existence before trying to read the file (thus eliminating any sort of message at all, which I think would be wrong) pushed me in the direction of logging the error and failing (since it would be *really* broken for the modalias file to be missing).
I would also be fine with logging the error when virFileReadAll() fails (ie *not* checking if the file exists so we could silently avoid the error log), but then clearing the and returning success. Does that work for you?
Hmmm, yeah I understand why. Each option has benefits. I was worried a bit about short-term occuring bugs, but long term it makes sense to just report teh error if it doesnt' work ...
I presueme a workaround for if any of the above breaks is to use an explicitly specified driver, right?
Correct. If a driver is explicitly given, then we don't attempt to find a better match. So in the case that a device really had no modalias file but was otherwise working, the error could be worked around by adding <driver model='vfio-pci'/> to the XML (assuming that whatever is creating the XML is able to do that).
... and there is a workaround for if stuff breaks. Thus: Reviewed-by: Peter Krempa <pkrempa@redhat.com> (fix the UINT_MAX thing)

On 1/5/24 10:30 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 10:06:13 -0500, Laine Stump wrote:
On 1/5/24 8:46 AM, Peter Krempa wrote:
On Fri, Jan 05, 2024 at 03:20:16 -0500, Laine Stump wrote:
Rather than always binding to the vfio-pci driver, use the new function virPCIDeviceFindBestVFIOVariant() to see if the running kernel has a VFIO variant driver available that is a better match for the device, and if one is found, use that instead.
virPCIDeviceFindBestVFIOVariant() function reads the modalias file for the given device from sysfs, then looks through /lib/modules/${kernel_release}/modules.alias for the vfio_pci alias that matches with the least number of wildcard ('*') fields.
The appropriate "VFIO variant" driver for a device will be the PCI driver implemented by the discovered module - these drivers are compatible with (and provide the entire API of) the standard vfio-pci driver, but have additional device-specific APIs that can be useful for, e.g., saving/restoring state for migration.
If a specific driver is named (using <driver model='blah'/> in the device XML), that will still be used rather than searching modules.alias; this makes it possible to force binding of vfio-pci if there is an issue with the auto-selected variant driver.
Signed-off-by: Laine Stump <laine@redhat.com> ---
Changes from V2:
* fail if device modalias file isn't found.
This [1] ...
* use unsigned int instead of int for wildcardCt * increase file memory buffer from 4MB to 8MB * other minor nits pointed out by Peter
[...]
+/* virPCIDeviceFindBestVFIOVariant: + * + * Find the "best" match of all vfio_pci aliases for @dev in the host + * modules.alias file. This uses the algorithm of finding every + * modules.alias line that begins with "vfio_pci:", then picking the + * one that matches the device's own modalias value (from the file of + * that name in the device's sysfs directory) with the fewest + * "wildcards" (* character, meaning "match any value for this + * attribute"). + */ +int +virPCIDeviceFindBestVFIOVariant(virPCIDevice *dev, + char **moduleName) +{ + g_autofree char *devModAliasPath = NULL; + g_autofree char *devModAliasContent = NULL; + const char *devModAlias; + g_autoptr(virPCIDeviceAliasInfo) devModAliasInfo = NULL; + struct utsname unameInfo; + g_autofree char *modulesAliasPath = NULL; + g_autofree char *modulesAliasContent = NULL; + const char *line; + unsigned int currentBestWildcardCt = INT_MAX;
UINT_MAX
+ + *moduleName = NULL; + + /* get the modalias values for the device from sysfs */ + devModAliasPath = virPCIFile(dev->name, "modalias"); + if (virFileReadAll(devModAliasPath, 100, &devModAliasContent) < 0)
... [1] isn't true.
How so? If the file can't be opened, then virFileReadAll logs an error and returns -1, and changed changed this code from ignoring that to also returning -1, which will cause the caller to fail. What am I missing?
I think I misremembered. I thought that the idea was that this should not fail if the file is missing.
Well, it *was*, so you didn't misremember, you were just remembering one iteration into the past :-)
+ return -1; + + VIR_DEBUG("modalias path: '%s' contents: '%s'", + devModAliasPath, devModAliasContent); + + /* "pci:vNNNNNNNNdNNNNNNNNsvNNNNNNNNsdNNNNNNNNbcNNscNNiNN\n" */ + if ((devModAlias = STRSKIP(devModAliasContent, "pci:")) == NULL || + !(devModAliasInfo = virPCIDeviceAliasInfoNew(devModAlias))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("device modalias file %1$s content has improper format"), + devModAliasPath); + return -1; + } + + uname(&unameInfo); + modulesAliasPath = g_strdup_printf("/lib/modules/%s/modules.alias", unameInfo.release); + if (virFileReadAll(modulesAliasPath, 8 * 1024 * 1024, &modulesAliasContent) < 0) + return -1;
IIUC this is picking a driver which is 'better' than the default 'vfio_pci', but the device itself would still work if the default were used, right?
Correct.
In such case do we really want to treat any of the errors above as failures?
I was on the fence about this, which was why earlier versions ignored the error. But your earlier suggestion to check for file existence before trying to read the file (thus eliminating any sort of message at all, which I think would be wrong) pushed me in the direction of logging the error and failing (since it would be *really* broken for the modalias file to be missing).
I would also be fine with logging the error when virFileReadAll() fails (ie *not* checking if the file exists so we could silently avoid the error log), but then clearing the and returning success. Does that work for you?
Hmmm, yeah I understand why. Each option has benefits.
I was worried a bit about short-term occuring bugs, but long term it makes sense to just report teh error if it doesnt' work ...
I presueme a workaround for if any of the above breaks is to use an explicitly specified driver, right?
Correct. If a driver is explicitly given, then we don't attempt to find a better match. So in the case that a device really had no modalias file but was otherwise working, the error could be worked around by adding <driver model='vfio-pci'/> to the XML (assuming that whatever is creating the XML is able to do that).
... and there is a workaround for if stuff breaks. Thus:
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(fix the UINT_MAX thing)
Yup! Thanks!
participants (2)
-
Laine Stump
-
Peter Krempa