This patch introduces new XML parser/formatter functions. Uid is
16-bit and non-zero. Fid is 32-bit. They are the two attributes of zpci
which is introduced as PCI address element. Zpci element is parsed and
formatted along with PCI address. And add the related test cases.
Signed-off-by: Yi Min Zhao <zyimin(a)linux.ibm.com>
---
docs/schemas/basictypes.rng | 27 +++++++
docs/schemas/domaincommon.rng | 1 +
src/conf/device_conf.c | 74 +++++++++++++++++++
src/conf/domain_addr.c | 3 +
src/conf/domain_conf.c | 14 +++-
src/libvirt_private.syms | 1 +
src/util/virpci.c | 7 ++
src/util/virpci.h | 5 ++
.../disk-virtio-s390-zpci.args | 25 +++++++
.../disk-virtio-s390-zpci.xml | 19 +++++
tests/qemuxml2argvdata/hostdev-vfio-zpci.args | 23 ++++++
tests/qemuxml2argvdata/hostdev-vfio-zpci.xml | 21 ++++++
tests/qemuxml2argvtest.c | 7 ++
.../disk-virtio-s390-zpci.xml | 31 ++++++++
.../qemuxml2xmloutdata/hostdev-vfio-zpci.xml | 32 ++++++++
tests/qemuxml2xmltest.c | 6 ++
16 files changed, 295 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.args
create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
create mode 100644 tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 14a3670e5c..71a6db3bb4 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -65,6 +65,17 @@
</data>
</choice>
</define>
+ <define name="uint32">
+ <choice>
+ <data type="string">
+ <param name="pattern">(0x)?[0-9a-fA-F]{1,8}</param>
+ </data>
+ <data type="unsignedInt">
+ <param name="minInclusive">0</param>
+ <param name="maxInclusive">4294967295</param>
+ </data>
+ </choice>
+ </define>
<define name="UUID">
<choice>
@@ -111,6 +122,22 @@
</attribute>
</optional>
</define>
+ <define name="zpciaddress">
+ <optional>
+ <element name="zpci">
+ <optional>
+ <attribute name="uid">
+ <ref name="uint16"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="fid">
+ <ref name="uint32"/>
+ </attribute>
+ </optional>
+ </element>
+ </optional>
+ </define>
<!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC"
-->
<!-- The lowest bit of the 1st byte is the "multicast" bit. a
-->
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 099a949cf8..9eeae80452 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5220,6 +5220,7 @@
<value>pci</value>
</attribute>
<ref name="pciaddress"/>
+ <ref name="zpciaddress"/>
</group>
<group>
<attribute name="type">
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 98a419f40f..d9b2c8f477 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -47,6 +47,65 @@ VIR_ENUM_IMPL(virDomainDeviceAddress,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"dimm",
);
+static bool
+virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci)
+{
+ /* We don't need to check fid because fid covers
+ * all range of uint32 type.
+ */
+ if (zpci->uid > VIR_DOMAIN_DEVICE_ZPCI_MAX_UID ||
+ zpci->uid == 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address uid='0x%.4x', "
+ "must be > 0x0000 and <= 0x%.4x"),
+ zpci->uid,
+ VIR_DOMAIN_DEVICE_ZPCI_MAX_UID);
+ return false;
+ }
+
+ return true;
+}
+
+static int
+virZPCIDeviceAddressParseXML(xmlNodePtr node,
+ virPCIDeviceAddressPtr addr)
+{
+ virZPCIDeviceAddress def = { 0 };
+ char *uid;
+ char *fid;
+ int ret = -1;
+
+ uid = virXMLPropString(node, "uid");
+ fid = virXMLPropString(node, "fid");
+
+ if (uid &&
+ virStrToLong_uip(uid, NULL, 0, &def.uid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'uid'
attribute"));
+ goto cleanup;
+ }
+
+ if (fid &&
+ virStrToLong_uip(fid, NULL, 0, &def.fid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'fid'
attribute"));
+ goto cleanup;
+ }
+
+ if (!virZPCIDeviceAddressIsEmpty(&def) &&
+ !virZPCIDeviceAddressIsValid(&def)) {
+ goto cleanup;
+ }
+
+ addr->zpci = def;
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(uid);
+ VIR_FREE(fid);
+ return ret;
+}
+
int
virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
virDomainDeviceInfoPtr src)
@@ -181,6 +240,8 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
virPCIDeviceAddressPtr addr)
{
char *domain, *slot, *bus, *function, *multi;
+ xmlNodePtr cur;
+ xmlNodePtr zpci = NULL;
int ret = -1;
memset(addr, 0, sizeof(*addr));
@@ -227,9 +288,22 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
goto cleanup;
}
+
if (!virPCIDeviceAddressIsEmpty(addr) && !virPCIDeviceAddressIsValid(addr,
true))
goto cleanup;
+ cur = node->children;
+ while (cur) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ virXMLNodeNameEqual(cur, "zpci")) {
+ zpci = cur;
+ }
+ cur = cur->next;
+ }
+
+ if (zpci && virZPCIDeviceAddressParseXML(zpci, addr) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index deb58fa7c9..7e5ce48b3f 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -1034,6 +1034,9 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
dev->isolationGroup, false) < 0)
return -1;
+ addr.extFlags = dev->addr.pci.extFlags;
+ addr.zpci = dev->addr.pci.zpci;
+
if (!addrs->dryRun) {
dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
dev->addr.pci = addr;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9911d56130..6dfa0aef27 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6528,7 +6528,19 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
break;
}
- virBufferAddLit(buf, "/>\n");
+ if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+ !virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci)) {
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ virBufferAsprintf(buf,
+ "<zpci uid='0x%.4x'
fid='0x%.8x'/>\n",
+ info->addr.pci.zpci.uid,
+ info->addr.pci.zpci.fid);
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</address>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
}
static int
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b662d2f01e..64f894ef74 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2566,6 +2566,7 @@ virPCIHeaderTypeToString;
virPCIIsVirtualFunction;
virPCIStubDriverTypeFromString;
virPCIStubDriverTypeToString;
+virZPCIDeviceAddressIsEmpty;
# util/virperf.h
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 0f680efbe6..8fdbad3b98 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -3236,3 +3236,10 @@ virPCIDeviceAddressFree(virPCIDeviceAddressPtr address)
{
VIR_FREE(address);
}
+
+
+bool
+virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr)
+{
+ return !(addr->uid || addr->fid);
+}
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 0e40d86b97..ea35234d7c 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -37,6 +37,9 @@ typedef virPCIDeviceAddress *virPCIDeviceAddressPtr;
typedef struct _virPCIDeviceList virPCIDeviceList;
typedef virPCIDeviceList *virPCIDeviceListPtr;
+# define VIR_DOMAIN_DEVICE_ZPCI_MAX_UID UINT16_MAX
+# define VIR_DOMAIN_DEVICE_ZPCI_MAX_FID UINT32_MAX
+
typedef struct _virZPCIDeviceAddress virZPCIDeviceAddress;
typedef virZPCIDeviceAddress *virZPCIDeviceAddressPtr;
struct _virZPCIDeviceAddress {
@@ -272,4 +275,6 @@ VIR_DEFINE_AUTOPTR_FUNC(virPCIDevice, virPCIDeviceFree)
VIR_DEFINE_AUTOPTR_FUNC(virPCIDeviceAddress, virPCIDeviceAddressFree)
VIR_DEFINE_AUTOPTR_FUNC(virPCIEDeviceInfo, virPCIEDeviceInfoFree)
+bool virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr);
+
#endif /* __VIR_PCI_H__ */
diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
new file mode 100644
index 0000000000..8ac435cb3e
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
@@ -0,0 +1,25 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-s390x \
+-name QEMUGuest1 \
+-S \
+-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=1 \
+-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0000
diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
new file mode 100644
index 0000000000..8bf4a23670
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
@@ -0,0 +1,19 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219136</memory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
+ </os>
+ <devices>
+ <emulator>/usr/bin/qemu-system-s390x</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x08' function='0x0'>
+ <zpci uid='0x0019' fid='0x0000001f'/>
+ </address>
+ </disk>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
new file mode 100644
index 0000000000..d6b1520c47
--- /dev/null
+++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
@@ -0,0 +1,23 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-s390x \
+-name QEMUGuest1 \
+-S \
+-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-device vfio-pci,host=00:00.0,id=hostdev0,bus=pci.0,addr=0x8 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x1
diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
new file mode 100644
index 0000000000..002b99c52d
--- /dev/null
+++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
@@ -0,0 +1,21 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
+ </os>
+ <devices>
+ <emulator>/usr/bin/qemu-system-s390x</emulator>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0000' bus='0x00' slot='0x00'
function='0x0'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x08' function='0x0'>
+ <zpci uid='0x0019' fid='0x0000001f'/>
+ </address>
+ </hostdev>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index a7cde3ed7e..7ecd9342bc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1076,6 +1076,10 @@ mymain(void)
QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
DO_TEST("disk-virtio-scsi-ccw", QEMU_CAPS_VIRTIO_SCSI,
QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
+ DO_TEST("disk-virtio-s390-zpci",
+ QEMU_CAPS_DEVICE_ZPCI,
+ QEMU_CAPS_CCW,
+ QEMU_CAPS_VIRTIO_S390);
DO_TEST("disk-order", QEMU_CAPS_VIRTIO_BLK_SCSI);
DO_TEST("disk-virtio-queues",
QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES);
@@ -1667,6 +1671,9 @@ mymain(void)
DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics",
QEMU_CAPS_DEVICE_VFIO_PCI,
QEMU_CAPS_VFIO_PCI_DISPLAY);
+ DO_TEST("hostdev-vfio-zpci",
+ QEMU_CAPS_DEVICE_VFIO_PCI,
+ QEMU_CAPS_DEVICE_ZPCI);
DO_TEST("pci-rom", NONE);
DO_TEST("pci-rom-disabled", NONE);
DO_TEST("pci-rom-disabled-invalid", NONE);
diff --git a/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
new file mode 100644
index 0000000000..37684c82b1
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
@@ -0,0 +1,31 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>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-s390x</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x08' function='0x0'>
+ <zpci uid='0x0019' fid='0x0000001f'/>
+ </address>
+ </disk>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'>
+ <address type='ccw' cssid='0xfe' ssid='0x0'
devno='0x0000'/>
+ </memballoon>
+ <panic model='s390'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
new file mode 100644
index 0000000000..fc8c38ab66
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>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-s390x</emulator>
+ <controller type='pci' index='0' model='pci-root'/>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0000' bus='0x00' slot='0x00'
function='0x0'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x08' function='0x0'>
+ <zpci uid='0x0019' fid='0x0000001f'/>
+ </address>
+ </hostdev>
+ <memballoon model='virtio'>
+ <address type='ccw' cssid='0xfe' ssid='0x0'
devno='0x0000'/>
+ </memballoon>
+ <panic model='s390'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 89640f641a..53de9726f4 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -376,6 +376,9 @@ mymain(void)
QEMU_CAPS_VIRTIO_SCSI);
DO_TEST("disk-virtio-scsi-ioeventfd",
QEMU_CAPS_VIRTIO_SCSI);
+ DO_TEST("disk-virtio-s390-zpci",
+ QEMU_CAPS_DEVICE_ZPCI,
+ QEMU_CAPS_CCW);
DO_TEST("disk-scsi-megasas",
QEMU_CAPS_SCSI_MEGASAS);
DO_TEST("disk-scsi-mptsas1068",
@@ -458,6 +461,9 @@ mymain(void)
DO_TEST("hostdev-usb-address", NONE);
DO_TEST("hostdev-pci-address", NONE);
DO_TEST("hostdev-vfio", NONE);
+ DO_TEST("hostdev-vfio-zpci",
+ QEMU_CAPS_DEVICE_ZPCI,
+ QEMU_CAPS_CCW);
DO_TEST("hostdev-mdev-precreated", NONE);
DO_TEST("hostdev-mdev-display", QEMU_CAPS_VFIO_PCI_DISPLAY);
DO_TEST("pci-rom", NONE);
--
Yi Min