[PATCH v3 20/21] qemu_hotplug: do not hotplug/hotunplug 'unassigned' hostdevs

Daniel Henrique Barboza danielhb413 at gmail.com
Wed May 20 21:11:42 UTC 2020


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 at gmail.com>
---
 src/qemu/qemu_domain.c                        |  1 +
 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 +++++++++++++++++++
 6 files changed, 141 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.c b/src/qemu/qemu_domain.c
index 0471a37803..7bff50ca09 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13412,6 +13412,7 @@ int qemuDomainValidateMultifunctionDeviceList(virDomainDeviceDefListPtr devlist)
         virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(devlist->devs[i]);
 
        if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+           info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED &&
            info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
            return -1;
        }
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 94d91a5daf..ebae69cc6d 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -3473,6 +3473,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 */
             qemuDomainFillDeviceIsolationGroup(vm->def, devlist->devs[i]);
@@ -3504,6 +3507,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 23c7d57682..64dd69b923 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1646,6 +1646,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;
 
@@ -6148,6 +6155,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) {
@@ -6180,6 +6190,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);
     }
 
@@ -6192,6 +6205,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 175f3ffed8..5e9d770cb1 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -865,6 +865,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.26.2




More information about the libvir-list mailing list