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(a)gmail.com>
---
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