The new address type 'unassigned' allows for a hostdev to be managed by Libvirt, but not be assigned for guest usage. This can allow us to execute PCI multifunction hotplug, with managed mode, leaving non-zero functions unassigned. For hotplug and unplug , we'll skip unassigned devices when setting or evaluating aggregateSlotIdx and when we're about to execute device_add/device_del in QEMU. For hotplug we'll also skip adress assignment. For unplug we won't mark the device for removal since we won't be executing device_del on it. Signed-off-by: Daniel Henrique Barboza <danielhb413@xxxxxxxxx> --- src/qemu/qemu_domain_address.c | 6 ++ src/qemu/qemu_hotplug.c | 16 ++++ tests/qemuhotplugtest.c | 9 ++ ...plug-multifunction-hostdev-pci-partial.xml | 27 ++++++ ...live+multifunction-hostdev-pci-partial.xml | 82 +++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-partial.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci-partial.xml diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 395f054b8d..c8fe6bbd64 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -3511,6 +3511,9 @@ qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr vm, for (i = 0; i < devlist->count; i++) { virDomainHostdevDefPtr hostdev = devlist->devs[i]->data.hostdev; + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) + continue; + if (qemuDomainIsPSeries(vm->def)) { /* Isolation groups are only relevant for pSeries guests */ if (qemuDomainFillDeviceIsolationGroup(vm->def, devlist->devs[i]) < 0) @@ -3544,6 +3547,9 @@ qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev = devlist->devs[i]->data.hostdev; virPCIDeviceAddress addr = hostdev->source.subsys.u.pci.addr; + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) + continue; + devinfos->infos[addr.function] = hostdev->info; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index fe823bb910..00bd5499fe 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1629,6 +1629,13 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, goto error; } + /* For an unassigned hostdev, add it to the domain definition + * and return without hotplugging it to QEMU. */ + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) { + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + return 0; + } + if (!(devstr = qemuBuildPCIHostdevDevStr(vm->def, hostdev, 0, priv->qemuCaps))) goto error; @@ -6058,6 +6065,9 @@ qemuDomainDetachMultifunctionDevice(virDomainObjPtr vm, /* Check if the devices belong to same guest slot.*/ FOR_EACH_DEV_IN_DEVLIST() + if (detach->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) + continue; + /* Pick one aggregateSlotIdx and compare against rest of them */ slotaggridx = slotaggridx ? slotaggridx : detach->info->aggregateSlotIdx; if (slotaggridx != detach->info->aggregateSlotIdx) { @@ -6090,6 +6100,9 @@ qemuDomainDetachMultifunctionDevice(virDomainObjPtr vm, if (qemuAssignDeviceHostdevAlias(vm->def, &detach->info->alias, -1) < 0) goto reset; + if (detach->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) + continue; + qemuDomainMarkDeviceAliasForRemoval(vm, detach->info->alias, false); } @@ -6102,6 +6115,9 @@ qemuDomainDetachMultifunctionDevice(virDomainObjPtr vm, pcisrc = &subsys->u.pci; virDomainHostdevFind(vm->def, hostdev, &detach); + if (detach->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED) + continue; + if (qemuMonitorDelDevice(priv->mon, detach->info->alias) < 0) { ignore_value(qemuDomainObjExitMonitor(driver, vm)); if (virDomainObjIsActive(vm)) diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index ffd91b5250..50e4bd535b 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -843,6 +843,15 @@ mymain(void) QMP_DEVICE_DELETED("hostdev1") QMP_DEVICE_DELETED("hostdev0") QMP_OK); + DO_TEST_ATTACH("base-live", "multifunction-hostdev-pci-partial", false, true, + "device_add", QMP_OK, + "device_add", QMP_OK, + "device_add", QMP_OK); + DO_TEST_DETACH("base-live", "multifunction-hostdev-pci-partial", false, false, + "device_del", QMP_DEVICE_DELETED("hostdev3") + QMP_DEVICE_DELETED("hostdev2") + QMP_DEVICE_DELETED("hostdev0") QMP_OK); + qemuTestSetHostArch(&driver, VIR_ARCH_PPC64); DO_TEST_ATTACH("pseries-base-live", "multifunction-hostdev-pci-2", false, true, "device_add", QMP_OK, diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-partial.xml b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-partial.xml new file mode 100644 index 0000000000..5e01564d2b --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-partial.xml @@ -0,0 +1,27 @@ +<devices> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> + </source> + <address type='unassigned'/> + </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='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> +</devices> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci-partial.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci-partial.xml new file mode 100644 index 0000000000..1808a0071e --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci-partial.xml @@ -0,0 +1,82 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x3'/> + </source> + <alias name='hostdev0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x3'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> + </source> + <alias name='hostdev1'/> + <address type='unassigned'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> + </source> + <alias name='hostdev2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x1'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <alias name='hostdev3'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' multifunction='on'/> + </hostdev> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> -- 2.24.1