[libvirt] [PATCH v4 1/5] Introducing new address type='unassigned' for PCI hostdevs

Daniel Henrique Barboza danielhb413 at gmail.com
Mon Dec 16 13:36:03 UTC 2019


Today, to use a PCI hostdev "A" in a domain, all PCI devices
that belongs to the same IOMMU group must also be declared in
the domain XML, meaning that all IOMMU devices are detached
from the host and all of them are visible to the guest.

The result is that the guest will have access to all devices,
but this is not necessarily what the administrator wanted. If only
the hostdev "A" was intended for guest usage, but hostdevs "B" and
"C" happened to be in the same IOMMU group of "A", the guest will
gain access to all 3 devices. This makes the administrator rely
on alternative solutions, such as use all hostdevs with un-managed
mode and detached all the IOMMU before the guest starts. If
use un-managed mode is not an option, the only alternative left is
an ACS patch to deny guest access to "B" and "C".

This patch introduces a new address type called "unassigned" to
handle this situation where a hostdev will be owned by a domain, but
not visible to the guest OS. This allows the administrator to
declare all the IOMMU while also choosing which hostdevs will be
usable by the guest. This new mechanic applies to all PCI hostdevs,
regardless of whether they are a PCI multifunction hostdev or not.
Using <address type='unassigned'/> in any case other than a PCI
hostdev will result in error.

Next patch will use this new address type in the QEMU driver to
avoid adding unassigned devices to the QEMU launch command line.

Signed-off-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
---
 docs/schemas/domaincommon.rng                 |  5 ++
 src/conf/device_conf.c                        |  2 +
 src/conf/device_conf.h                        |  1 +
 src/conf/domain_conf.c                        |  7 ++-
 src/qemu/qemu_command.c                       |  1 +
 src/qemu/qemu_domain.c                        |  1 +
 src/qemu/qemu_domain_address.c                |  5 ++
 .../hostdev-pci-address-unassigned.xml        | 42 ++++++++++++++
 .../hostdev-pci-address-unassigned.xml        | 58 +++++++++++++++++++
 tests/qemuxml2xmltest.c                       |  1 +
 10 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml
 create mode 100644 tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.xml

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f5b51d20ad..372d248f25 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5470,6 +5470,11 @@
           </attribute>
           <ref name="dimmaddress"/>
         </group>
+        <group>
+          <attribute name="type">
+            <value>unassigned</value>
+          </attribute>
+        </group>
       </choice>
     </element>
   </define>
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 4c57f0995f..4dbd5c1ac9 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -45,6 +45,7 @@ VIR_ENUM_IMPL(virDomainDeviceAddress,
               "virtio-mmio",
               "isa",
               "dimm",
+              "unassigned",
 );
 
 static int
@@ -120,6 +121,7 @@ virDomainDeviceInfoAddressIsEqual(const virDomainDeviceInfo *a,
     /* address types below don't have any specific data */
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
         break;
 
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index d98fae775c..e091d7cfe2 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -45,6 +45,7 @@ typedef enum {
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO,
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA,
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM,
+    VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED,
 
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
 } virDomainDeviceAddressType;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index cfec86a24d..454eb63be6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6338,9 +6338,11 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev)
         switch ((virDomainHostdevSubsysType) hostdev->source.subsys.type) {
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
             if (hostdev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+                hostdev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED &&
                 hostdev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("PCI host devices must use 'pci' address type"));
+                               _("PCI host devices must use 'pci' or "
+                                 "'unassigned' address type"));
                 return -1;
             }
             break;
@@ -7357,6 +7359,7 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
 
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
         break;
     }
@@ -7557,6 +7560,7 @@ virDomainDeviceAddressParseXML(xmlNodePtr address,
         break;
 
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
         break;
     }
@@ -21871,6 +21875,7 @@ virDomainDeviceInfoCheckABIStability(virDomainDeviceInfoPtr src,
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
         break;
     }
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 49a0dad8d4..5d12ef3d63 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -461,6 +461,7 @@ qemuBuildVirtioDevStr(virBufferPtr buf,
         return -1;
 
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainDeviceAddressType, info->type);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index df21065e84..b3df2c4a7a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -7456,6 +7456,7 @@ qemuDomainDeviceDefValidateAddress(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
         /* No validation for these address types yet */
         break;
 
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 605984f80f..b077240899 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -2313,6 +2313,11 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
             continue;
         }
 
+        /* do not reserve address for info->type='unassigned' */
+        if (def->hostdevs[i]->info->type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED)
+            continue;
+
         if (qemuDomainPCIAddressReserveNextAddr(addrs,
                                                 def->hostdevs[i]->info) < 0)
             goto error;
diff --git a/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml b/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml
new file mode 100644
index 0000000000..9a2685ca0e
--- /dev/null
+++ b/tests/qemuxml2argvdata/hostdev-pci-address-unassigned.xml
@@ -0,0 +1,42 @@
+<domain type='kvm'>
+  <name>delete</name>
+  <uuid>583a8e8e-f0ce-4f53-89ab-092862148b25</uuid>
+  <memory unit='KiB'>262144</memory>
+  <vcpu placement='static'>4</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <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>
+    </hostdev>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.xml b/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.xml
new file mode 100644
index 0000000000..2341e8432b
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/hostdev-pci-address-unassigned.xml
@@ -0,0 +1,58 @@
+<domain type='kvm'>
+  <name>delete</name>
+  <uuid>583a8e8e-f0ce-4f53-89ab-092862148b25</uuid>
+  <memory unit='KiB'>262144</memory>
+  <currentMemory unit='KiB'>262144</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <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>
+    <controller type='usb' index='0'>
+      <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'/>
+    <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='0x03' 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='0x04' 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='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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 50b43e01d4..c02791c660 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -431,6 +431,7 @@ mymain(void)
 
     DO_TEST("hostdev-usb-address", NONE);
     DO_TEST("hostdev-pci-address", NONE);
+    DO_TEST("hostdev-pci-address-unassigned", NONE);
     DO_TEST("hostdev-pci-multifunction", NONE);
     DO_TEST("hostdev-vfio", NONE);
     DO_TEST("hostdev-vfio-zpci",
-- 
2.23.0





More information about the libvir-list mailing list