render / rpms / libvirt

Forked from rpms/libvirt 4 months ago
Clone
c313de
From fddd43e717869d56e481c3fde2d5ee6b5513a1f5 Mon Sep 17 00:00:00 2001
c313de
Message-Id: <fddd43e717869d56e481c3fde2d5ee6b5513a1f5@dist-git>
c313de
From: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Date: Mon, 8 Apr 2019 10:57:25 +0200
c313de
Subject: [PATCH] conf: Introduce parser, formatter for uid and fid
c313de
MIME-Version: 1.0
c313de
Content-Type: text/plain; charset=UTF-8
c313de
Content-Transfer-Encoding: 8bit
c313de
c313de
This patch introduces new XML parser/formatter functions. Uid is
c313de
16-bit and non-zero. Fid is 32-bit. They are the two attributes of zpci
c313de
which is introduced as PCI address element. Zpci element is parsed and
c313de
formatted along with PCI address. And add the related test cases.
c313de
c313de
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
c313de
Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
c313de
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c313de
c313de
(cherry picked from commit b4833b2c2f7be8a68eb6495ed57ed61918e3ecd8)
c313de
c313de
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
c313de
c313de
Conflicts:
c313de
c313de
  * src/conf/device_conf.c
c313de
    + context
c313de
      - missing edeef779585
c313de
c313de
  * tests/qemuxml2argvtest.c
c313de
    + context
c313de
      - missing a0ff9fbe5cad, 0bdb704383f7
c313de
c313de
Changed:
c313de
c313de
  * tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
c313de
    tests/qemuxml2argvdata/hostdev-vfio-zpci.args
c313de
    + no -boot in output
c313de
      - missing caccbba64aa9
c313de
c313de
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c313de
Message-Id: <20190408085732.28684-9-abologna@redhat.com>
c313de
Reviewed-by: Laine Stump <laine@redhat.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
---
c313de
 docs/schemas/basictypes.rng                   | 27 ++++++++++
c313de
 docs/schemas/domaincommon.rng                 |  1 +
c313de
 src/conf/device_conf.c                        | 53 +++++++++++++++++++
c313de
 src/conf/domain_addr.c                        |  3 ++
c313de
 src/conf/domain_conf.c                        | 12 ++++-
c313de
 src/libvirt_private.syms                      |  2 +
c313de
 src/util/virpci.c                             | 26 +++++++++
c313de
 src/util/virpci.h                             |  6 +++
c313de
 .../disk-virtio-s390-zpci.args                | 26 +++++++++
c313de
 .../disk-virtio-s390-zpci.xml                 | 19 +++++++
c313de
 tests/qemuxml2argvdata/hostdev-vfio-zpci.args | 24 +++++++++
c313de
 tests/qemuxml2argvdata/hostdev-vfio-zpci.xml  | 21 ++++++++
c313de
 tests/qemuxml2argvtest.c                      |  7 +++
c313de
 .../disk-virtio-s390-zpci.xml                 | 31 +++++++++++
c313de
 .../qemuxml2xmloutdata/hostdev-vfio-zpci.xml  | 32 +++++++++++
c313de
 tests/qemuxml2xmltest.c                       |  6 +++
c313de
 16 files changed, 295 insertions(+), 1 deletion(-)
c313de
 create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
c313de
 create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
c313de
 create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.args
c313de
 create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
c313de
 create mode 100644 tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
c313de
 create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
c313de
c313de
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
c313de
index b45a7fcdc8..97e14d7ca8 100644
c313de
--- a/docs/schemas/basictypes.rng
c313de
+++ b/docs/schemas/basictypes.rng
c313de
@@ -65,6 +65,17 @@
c313de
       </data>
c313de
     </choice>
c313de
   </define>
c313de
+  <define name="uint32">
c313de
+    <choice>
c313de
+      <data type="string">
c313de
+        <param name="pattern">(0x)?[0-9a-fA-F]{1,8}</param>
c313de
+      </data>
c313de
+      <data type="unsignedInt">
c313de
+        <param name="minInclusive">0</param>
c313de
+        <param name="maxInclusive">4294967295</param>
c313de
+      </data>
c313de
+    </choice>
c313de
+  </define>
c313de
 
c313de
   <define name="UUID">
c313de
     <choice>
c313de
@@ -111,6 +122,22 @@
c313de
       </attribute>
c313de
     </optional>
c313de
   </define>
c313de
+  <define name="zpciaddress">
c313de
+    <optional>
c313de
+      <element name="zpci">
c313de
+        <optional>
c313de
+          <attribute name="uid">
c313de
+            <ref name="uint16"/>
c313de
+          </attribute>
c313de
+        </optional>
c313de
+        <optional>
c313de
+          <attribute name="fid">
c313de
+            <ref name="uint32"/>
c313de
+          </attribute>
c313de
+        </optional>
c313de
+      </element>
c313de
+    </optional>
c313de
+  </define>
c313de
 
c313de
   
c313de
   
c313de
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
c313de
index 70a7767d9c..2b6d4dced6 100644
c313de
--- a/docs/schemas/domaincommon.rng
c313de
+++ b/docs/schemas/domaincommon.rng
c313de
@@ -5186,6 +5186,7 @@
c313de
             <value>pci</value>
c313de
           </attribute>
c313de
           <ref name="pciaddress"/>
c313de
+          <ref name="zpciaddress"/>
c313de
         </group>
c313de
         <group>
c313de
           <attribute name="type">
c313de
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
c313de
index d69f94fadf..cadac32603 100644
c313de
--- a/src/conf/device_conf.c
c313de
+++ b/src/conf/device_conf.c
c313de
@@ -32,6 +32,45 @@
c313de
 
c313de
 #define VIR_FROM_THIS VIR_FROM_DEVICE
c313de
 
c313de
+static int
c313de
+virZPCIDeviceAddressParseXML(xmlNodePtr node,
c313de
+                             virPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    virZPCIDeviceAddress def = { 0 };
c313de
+    char *uid;
c313de
+    char *fid;
c313de
+    int ret = -1;
c313de
+
c313de
+    uid = virXMLPropString(node, "uid");
c313de
+    fid = virXMLPropString(node, "fid");
c313de
+
c313de
+    if (uid &&
c313de
+        virStrToLong_uip(uid, NULL, 0, &def.uid) < 0) {
c313de
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c313de
+                       _("Cannot parse <address> 'uid' attribute"));
c313de
+        goto cleanup;
c313de
+    }
c313de
+
c313de
+    if (fid &&
c313de
+        virStrToLong_uip(fid, NULL, 0, &def.fid) < 0) {
c313de
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c313de
+                       _("Cannot parse <address> 'fid' attribute"));
c313de
+        goto cleanup;
c313de
+    }
c313de
+
c313de
+    if (!virZPCIDeviceAddressIsEmpty(&def) &&
c313de
+        !virZPCIDeviceAddressIsValid(&def))
c313de
+        goto cleanup;
c313de
+
c313de
+    addr->zpci = def;
c313de
+    ret = 0;
c313de
+
c313de
+ cleanup:
c313de
+    VIR_FREE(uid);
c313de
+    VIR_FREE(fid);
c313de
+    return ret;
c313de
+}
c313de
+
c313de
 int
c313de
 virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
c313de
                         virDomainDeviceInfoPtr src)
c313de
@@ -196,6 +235,8 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
c313de
                             virPCIDeviceAddressPtr addr)
c313de
 {
c313de
     char *domain, *slot, *bus, *function, *multi;
c313de
+    xmlNodePtr cur;
c313de
+    xmlNodePtr zpci = NULL;
c313de
     int ret = -1;
c313de
 
c313de
     memset(addr, 0, sizeof(*addr));
c313de
@@ -245,6 +286,18 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
c313de
     if (!virPCIDeviceAddressIsEmpty(addr) && !virPCIDeviceAddressIsValid(addr, true))
c313de
         goto cleanup;
c313de
 
c313de
+    cur = node->children;
c313de
+    while (cur) {
c313de
+        if (cur->type == XML_ELEMENT_NODE &&
c313de
+            virXMLNodeNameEqual(cur, "zpci")) {
c313de
+            zpci = cur;
c313de
+        }
c313de
+        cur = cur->next;
c313de
+    }
c313de
+
c313de
+    if (zpci && virZPCIDeviceAddressParseXML(zpci, addr) < 0)
c313de
+        goto cleanup;
c313de
+
c313de
     ret = 0;
c313de
 
c313de
  cleanup:
c313de
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
c313de
index 3e33549c3d..9e0a0fdf95 100644
c313de
--- a/src/conf/domain_addr.c
c313de
+++ b/src/conf/domain_addr.c
c313de
@@ -1054,6 +1054,9 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
c313de
                                                dev->isolationGroup, false) < 0)
c313de
         return -1;
c313de
 
c313de
+    addr.extFlags = dev->addr.pci.extFlags;
c313de
+    addr.zpci = dev->addr.pci.zpci;
c313de
+
c313de
     if (!addrs->dryRun) {
c313de
         dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
c313de
         dev->addr.pci = addr;
c313de
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c313de
index bcb0558bc3..29ebf0a930 100644
c313de
--- a/src/conf/domain_conf.c
c313de
+++ b/src/conf/domain_conf.c
c313de
@@ -6448,6 +6448,7 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
c313de
                           unsigned int flags)
c313de
 {
c313de
     virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
c313de
+    virBuffer childBuf = VIR_BUFFER_INITIALIZER;
c313de
 
c313de
     if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
c313de
         virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
c313de
@@ -6510,6 +6511,14 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
c313de
             virBufferAsprintf(&attrBuf, " multifunction='%s'",
c313de
                               virTristateSwitchTypeToString(info->addr.pci.multi));
c313de
         }
c313de
+
c313de
+        if (!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci)) {
c313de
+            virBufferSetChildIndent(&childBuf, buf);
c313de
+            virBufferAsprintf(&childBuf,
c313de
+                              "<zpci uid='0x%.4x' fid='0x%.8x'/>\n",
c313de
+                              info->addr.pci.zpci.uid,
c313de
+                              info->addr.pci.zpci.fid);
c313de
+        }
c313de
         break;
c313de
 
c313de
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
c313de
@@ -6577,9 +6586,10 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
c313de
         break;
c313de
     }
c313de
 
c313de
-    virXMLFormatElement(buf, "address", &attrBuf, NULL);
c313de
+    virXMLFormatElement(buf, "address", &attrBuf, &childBuf);
c313de
 
c313de
     virBufferFreeAndReset(&attrBuf);
c313de
+    virBufferFreeAndReset(&childBuf);
c313de
 }
c313de
 
c313de
 static int
c313de
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c313de
index df27ac4b3a..b2a2a1f265 100644
c313de
--- a/src/libvirt_private.syms
c313de
+++ b/src/libvirt_private.syms
c313de
@@ -2569,6 +2569,8 @@ virPCIHeaderTypeToString;
c313de
 virPCIIsVirtualFunction;
c313de
 virPCIStubDriverTypeFromString;
c313de
 virPCIStubDriverTypeToString;
c313de
+virZPCIDeviceAddressIsEmpty;
c313de
+virZPCIDeviceAddressIsValid;
c313de
 
c313de
 
c313de
 # util/virperf.h
c313de
diff --git a/src/util/virpci.c b/src/util/virpci.c
c313de
index 8d02366664..3a1e49a7a7 100644
c313de
--- a/src/util/virpci.c
c313de
+++ b/src/util/virpci.c
c313de
@@ -2597,6 +2597,32 @@ virPCIDeviceAddressParse(char *address,
c313de
 
c313de
 #ifdef __linux__
c313de
 
c313de
+bool
c313de
+virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci)
c313de
+{
c313de
+    /* We don't need to check fid because fid covers
c313de
+     * all range of uint32 type.
c313de
+     */
c313de
+    if (zpci->uid > VIR_DOMAIN_DEVICE_ZPCI_MAX_UID ||
c313de
+        zpci->uid == 0) {
c313de
+        virReportError(VIR_ERR_XML_ERROR,
c313de
+                       _("Invalid PCI address uid='0x%.4x', "
c313de
+                         "must be > 0x0000 and <= 0x%.4x"),
c313de
+                       zpci->uid,
c313de
+                       VIR_DOMAIN_DEVICE_ZPCI_MAX_UID);
c313de
+        return false;
c313de
+    }
c313de
+
c313de
+    return true;
c313de
+}
c313de
+
c313de
+bool
c313de
+virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr)
c313de
+{
c313de
+    return !(addr->uid || addr->fid);
c313de
+}
c313de
+
c313de
+
c313de
 /*
c313de
  * returns true if equal
c313de
  */
c313de
diff --git a/src/util/virpci.h b/src/util/virpci.h
c313de
index b366d7d9c3..1ed9e2381e 100644
c313de
--- a/src/util/virpci.h
c313de
+++ b/src/util/virpci.h
c313de
@@ -36,6 +36,9 @@ typedef virPCIDeviceAddress *virPCIDeviceAddressPtr;
c313de
 typedef struct _virPCIDeviceList virPCIDeviceList;
c313de
 typedef virPCIDeviceList *virPCIDeviceListPtr;
c313de
 
c313de
+# define VIR_DOMAIN_DEVICE_ZPCI_MAX_UID UINT16_MAX
c313de
+# define VIR_DOMAIN_DEVICE_ZPCI_MAX_FID UINT32_MAX
c313de
+
c313de
 typedef struct _virZPCIDeviceAddress virZPCIDeviceAddress;
c313de
 typedef virZPCIDeviceAddress *virZPCIDeviceAddressPtr;
c313de
 struct _virZPCIDeviceAddress {
c313de
@@ -235,6 +238,9 @@ int virPCIGetAddrString(unsigned int domain,
c313de
 
c313de
 int virPCIDeviceAddressParse(char *address, virPCIDeviceAddressPtr bdf);
c313de
 
c313de
+bool virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci);
c313de
+bool virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr);
c313de
+
c313de
 int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path,
c313de
                                  int pfNetDevIdx,
c313de
                                  char **pfname,
c313de
diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
c313de
new file mode 100644
c313de
index 0000000000..20e63a15b5
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
c313de
@@ -0,0 +1,26 @@
c313de
+LC_ALL=C \
c313de
+PATH=/bin \
c313de
+HOME=/home/test \
c313de
+USER=test \
c313de
+LOGNAME=test \
c313de
+QEMU_AUDIO_DRV=none \
c313de
+/usr/bin/qemu-system-s390x \
c313de
+-name QEMUGuest1 \
c313de
+-S \
c313de
+-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
c313de
+-m 214 \
c313de
+-smp 1,sockets=1,cores=1,threads=1 \
c313de
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
c313de
+-display none \
c313de
+-no-user-config \
c313de
+-nodefaults \
c313de
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
c313de
+server,nowait \
c313de
+-mon chardev=charmonitor,id=monitor,mode=control \
c313de
+-rtc base=utc \
c313de
+-no-shutdown \
c313de
+-boot c \
c313de
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
c313de
+-device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,\
c313de
+id=virtio-disk0 \
c313de
+-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0000
c313de
diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
c313de
new file mode 100644
c313de
index 0000000000..8bf4a23670
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
c313de
@@ -0,0 +1,19 @@
c313de
+<domain type='qemu'>
c313de
+  <name>QEMUGuest1</name>
c313de
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c313de
+  <memory>219136</memory>
c313de
+  <vcpu>1</vcpu>
c313de
+  <os>
c313de
+    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
c313de
+  </os>
c313de
+  <devices>
c313de
+    <emulator>/usr/bin/qemu-system-s390x</emulator>
c313de
+    <disk type='block' device='disk'>
c313de
+      <source dev='/dev/HostVG/QEMUGuest1'/>
c313de
+      <target dev='hda' bus='virtio'/>
c313de
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
c313de
+        <zpci uid='0x0019' fid='0x0000001f'/>
c313de
+      </address>
c313de
+    </disk>
c313de
+  </devices>
c313de
+</domain>
c313de
diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
c313de
new file mode 100644
c313de
index 0000000000..622c504da0
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
c313de
@@ -0,0 +1,24 @@
c313de
+LC_ALL=C \
c313de
+PATH=/bin \
c313de
+HOME=/home/test \
c313de
+USER=test \
c313de
+LOGNAME=test \
c313de
+QEMU_AUDIO_DRV=none \
c313de
+/usr/bin/qemu-system-s390x \
c313de
+-name QEMUGuest1 \
c313de
+-S \
c313de
+-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
c313de
+-m 214 \
c313de
+-smp 1,sockets=1,cores=1,threads=1 \
c313de
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
c313de
+-display none \
c313de
+-no-user-config \
c313de
+-nodefaults \
c313de
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
c313de
+server,nowait \
c313de
+-mon chardev=charmonitor,id=monitor,mode=control \
c313de
+-rtc base=utc \
c313de
+-no-shutdown \
c313de
+-boot c \
c313de
+-device vfio-pci,host=00:00.0,id=hostdev0,bus=pci.0,addr=0x8 \
c313de
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x1
c313de
diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
c313de
new file mode 100644
c313de
index 0000000000..002b99c52d
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
c313de
@@ -0,0 +1,21 @@
c313de
+<domain type='qemu'>
c313de
+  <name>QEMUGuest1</name>
c313de
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c313de
+  <memory>219100</memory>
c313de
+  <os>
c313de
+    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
c313de
+  </os>
c313de
+  <devices>
c313de
+    <emulator>/usr/bin/qemu-system-s390x</emulator>
c313de
+    <controller type='pci' index='0' model='pci-root'/>
c313de
+    <hostdev mode='subsystem' type='pci' managed='no'>
c313de
+      <driver name='vfio'/>
c313de
+      <source>
c313de
+        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
c313de
+      </source>
c313de
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
c313de
+        <zpci uid='0x0019' fid='0x0000001f'/>
c313de
+      </address>
c313de
+    </hostdev>
c313de
+  </devices>
c313de
+</domain>
c313de
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
c313de
index 7f25cccf9d..2eb2505971 100644
c313de
--- a/tests/qemuxml2argvtest.c
c313de
+++ b/tests/qemuxml2argvtest.c
c313de
@@ -1038,6 +1038,10 @@ mymain(void)
c313de
             QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
c313de
     DO_TEST("disk-virtio-scsi-ccw", QEMU_CAPS_VIRTIO_SCSI,
c313de
             QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
c313de
+    DO_TEST("disk-virtio-s390-zpci",
c313de
+            QEMU_CAPS_DEVICE_ZPCI,
c313de
+            QEMU_CAPS_CCW,
c313de
+            QEMU_CAPS_VIRTIO_S390);
c313de
     DO_TEST("disk-order",
c313de
             QEMU_CAPS_DRIVE_BOOT, QEMU_CAPS_VIRTIO_BLK_SCSI);
c313de
     DO_TEST("disk-virtio-drive-queues",
c313de
@@ -1628,6 +1632,9 @@ mymain(void)
c313de
     DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics",
c313de
             QEMU_CAPS_DEVICE_VFIO_PCI,
c313de
             QEMU_CAPS_VFIO_PCI_DISPLAY);
c313de
+    DO_TEST("hostdev-vfio-zpci",
c313de
+            QEMU_CAPS_DEVICE_VFIO_PCI,
c313de
+            QEMU_CAPS_DEVICE_ZPCI);
c313de
     DO_TEST("pci-rom", NONE);
c313de
     DO_TEST("pci-rom-disabled", NONE);
c313de
     DO_TEST("pci-rom-disabled-invalid", NONE);
c313de
diff --git a/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
c313de
new file mode 100644
c313de
index 0000000000..37684c82b1
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
c313de
@@ -0,0 +1,31 @@
c313de
+<domain type='qemu'>
c313de
+  <name>QEMUGuest1</name>
c313de
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c313de
+  <memory unit='KiB'>219136</memory>
c313de
+  <currentMemory unit='KiB'>219136</currentMemory>
c313de
+  <vcpu placement='static'>1</vcpu>
c313de
+  <os>
c313de
+    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
c313de
+    <boot dev='hd'/>
c313de
+  </os>
c313de
+  <clock offset='utc'/>
c313de
+  <on_poweroff>destroy</on_poweroff>
c313de
+  <on_reboot>restart</on_reboot>
c313de
+  <on_crash>destroy</on_crash>
c313de
+  <devices>
c313de
+    <emulator>/usr/bin/qemu-system-s390x</emulator>
c313de
+    <disk type='block' device='disk'>
c313de
+      <driver name='qemu' type='raw'/>
c313de
+      <source dev='/dev/HostVG/QEMUGuest1'/>
c313de
+      <target dev='hda' bus='virtio'/>
c313de
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
c313de
+        <zpci uid='0x0019' fid='0x0000001f'/>
c313de
+      </address>
c313de
+    </disk>
c313de
+    <controller type='pci' index='0' model='pci-root'/>
c313de
+    <memballoon model='virtio'>
c313de
+      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
c313de
+    </memballoon>
c313de
+    <panic model='s390'/>
c313de
+  </devices>
c313de
+</domain>
c313de
diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
c313de
new file mode 100644
c313de
index 0000000000..fc8c38ab66
c313de
--- /dev/null
c313de
+++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
c313de
@@ -0,0 +1,32 @@
c313de
+<domain type='qemu'>
c313de
+  <name>QEMUGuest1</name>
c313de
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c313de
+  <memory unit='KiB'>219100</memory>
c313de
+  <currentMemory unit='KiB'>219100</currentMemory>
c313de
+  <vcpu placement='static'>1</vcpu>
c313de
+  <os>
c313de
+    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
c313de
+    <boot dev='hd'/>
c313de
+  </os>
c313de
+  <clock offset='utc'/>
c313de
+  <on_poweroff>destroy</on_poweroff>
c313de
+  <on_reboot>restart</on_reboot>
c313de
+  <on_crash>destroy</on_crash>
c313de
+  <devices>
c313de
+    <emulator>/usr/bin/qemu-system-s390x</emulator>
c313de
+    <controller type='pci' index='0' model='pci-root'/>
c313de
+    <hostdev mode='subsystem' type='pci' managed='no'>
c313de
+      <driver name='vfio'/>
c313de
+      <source>
c313de
+        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
c313de
+      </source>
c313de
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
c313de
+        <zpci uid='0x0019' fid='0x0000001f'/>
c313de
+      </address>
c313de
+    </hostdev>
c313de
+    <memballoon model='virtio'>
c313de
+      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
c313de
+    </memballoon>
c313de
+    <panic model='s390'/>
c313de
+  </devices>
c313de
+</domain>
c313de
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
c313de
index 2a2bf01ffa..a787f4f4a3 100644
c313de
--- a/tests/qemuxml2xmltest.c
c313de
+++ b/tests/qemuxml2xmltest.c
c313de
@@ -400,6 +400,9 @@ mymain(void)
c313de
             QEMU_CAPS_VIRTIO_SCSI);
c313de
     DO_TEST("disk-virtio-scsi-ioeventfd",
c313de
             QEMU_CAPS_VIRTIO_SCSI);
c313de
+    DO_TEST("disk-virtio-s390-zpci",
c313de
+            QEMU_CAPS_DEVICE_ZPCI,
c313de
+            QEMU_CAPS_CCW);
c313de
     DO_TEST("disk-scsi-megasas",
c313de
             QEMU_CAPS_SCSI_MEGASAS);
c313de
     DO_TEST("disk-scsi-mptsas1068",
c313de
@@ -482,6 +485,9 @@ mymain(void)
c313de
     DO_TEST("hostdev-usb-address", NONE);
c313de
     DO_TEST("hostdev-pci-address", NONE);
c313de
     DO_TEST("hostdev-vfio", NONE);
c313de
+    DO_TEST("hostdev-vfio-zpci",
c313de
+            QEMU_CAPS_DEVICE_ZPCI,
c313de
+            QEMU_CAPS_CCW);
c313de
     DO_TEST("hostdev-mdev-precreated", NONE);
c313de
     DO_TEST("hostdev-mdev-display", QEMU_CAPS_VFIO_PCI_DISPLAY);
c313de
     DO_TEST("pci-rom", NONE);
c313de
-- 
c313de
2.22.0
c313de