</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>
</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 -->
<value>pci</value>
</attribute>
<ref name="pciaddress"/>
+ <ref name="zpciaddress"/>
</group>
<group>
<attribute name="type">
"dimm",
);
+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)
virPCIDeviceAddressPtr addr)
{
char *domain, *slot, *bus, *function, *multi;
+ xmlNodePtr cur;
+ xmlNodePtr zpci = NULL;
int ret = -1;
memset(addr, 0, sizeof(*addr));
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:
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;
unsigned int flags)
{
virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
+ virBuffer childBuf = VIR_BUFFER_INITIALIZER;
if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
virBufferAsprintf(&attrBuf, " multifunction='%s'",
virTristateSwitchTypeToString(info->addr.pci.multi));
}
+
+ if (!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci)) {
+ virBufferSetChildIndent(&childBuf, buf);
+ virBufferAsprintf(&childBuf,
+ "<zpci uid='0x%.4x' fid='0x%.8x'/>\n",
+ info->addr.pci.zpci.uid,
+ info->addr.pci.zpci.fid);
+ }
break;
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
break;
}
- virXMLFormatElement(buf, "address", &attrBuf, NULL);
+ virXMLFormatElement(buf, "address", &attrBuf, &childBuf);
virBufferFreeAndReset(&attrBuf);
+ virBufferFreeAndReset(&childBuf);
}
static int
virPCIIsVirtualFunction;
virPCIStubDriverTypeFromString;
virPCIStubDriverTypeToString;
+virZPCIDeviceAddressIsEmpty;
+virZPCIDeviceAddressIsValid;
# util/virperf.h
#ifdef __linux__
+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;
+}
+
+bool
+virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr)
+{
+ return !(addr->uid || addr->fid);
+}
+
+
/*
* returns true if equal
*/
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 {
int virPCIDeviceAddressParse(char *address, virPCIDeviceAddressPtr bdf);
+bool virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci);
+bool virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr);
+
int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path,
int pfNetDevIdx,
char **pfname,
--- /dev/null
+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
--- /dev/null
+<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>
--- /dev/null
+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
--- /dev/null
+<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>
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);
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);
--- /dev/null
+<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>
--- /dev/null
+<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>
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",
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);