[libvirt] [PATCHv2 0/5] S390: Support for native CCW bus

Originally, QEMU did not implement a native I/O bus for s390. The initial implementation had a machine type 's390-virtio' featuring a fully paravirtualized I/O system with an artificial bus type 'virtio-s390'. This bus had a number of short-comings, like the need for a non-standard device discovery mechanism, a limited number of devices, limited hotplugging capabilites and the lack of persistent device addresses. To resolve these issues a new machine type 's390-ccw-virtio' has been recently added to QEMU which implementa the native s390 CCW I/O bus. Guests with arch='s390x' and machine='s390-ccw-virtio' can now be defined with up to 262144 virtio devices. This series adds the support for the s390-ccw-virtio machine type and the CCW bus to libvirt. As usual we start with the documentation/schema, the generic configuration stuff, continue with the QEMU driver including device hotplug and finally add qemu2xml testcases. V2 Changes - use an attribute triple cssid, ssid, schid instead of devno to better represent the libvirt CCW address structure - rebase to current upstream, mainly address qemuCapsXXX rename J.B. Joret (1): S390: Add hotplug support for s390 virtio devices Viktor Mihajlovski (4): S390: Documentation for CCW address type S390: domain_conf support for CCW S390: QEMU driver support for CCW addresses S390: Testcases for virtio-ccw machines docs/formatdomain.html.in | 14 + docs/schemas/domaincommon.rng | 52 ++++ src/conf/domain_conf.c | 107 +++++++- src/conf/domain_conf.h | 16 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 47 +++- src/qemu/qemu_capabilities.h | 8 +- src/qemu/qemu_command.c | 269 +++++++++++++++++++- src/qemu/qemu_command.h | 6 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 3 + src/qemu/qemu_driver.c | 26 +- src/qemu/qemu_hotplug.c | 147 +++++++---- src/qemu/qemu_hotplug.h | 14 +- src/qemu/qemu_process.c | 12 +- .../qemuxml2argv-console-virtio-ccw.args | 10 + .../qemuxml2argv-console-virtio-ccw.xml | 27 ++ .../qemuxml2argv-console-virtio-s390.args | 4 +- .../qemuxml2argv-console-virtio-s390.xml | 2 +- .../qemuxml2argv-disk-virtio-ccw-many.args | 12 + .../qemuxml2argv-disk-virtio-ccw-many.xml | 40 +++ .../qemuxml2argv-disk-virtio-ccw.args | 8 + .../qemuxml2argv-disk-virtio-ccw.xml | 30 +++ .../qemuxml2argv-net-virtio-ccw.args | 8 + .../qemuxml2argv-net-virtio-ccw.xml | 30 +++ tests/qemuxml2argvtest.c | 11 +- tests/testutilsqemu.c | 3 +- 27 files changed, 812 insertions(+), 96 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.xml -- 1.7.9.5

The native bus for s390 I/O is called CCW (channel command word). As QEMU has added basic support for the CCW bus, i.e. the ability to assign CCW devnos (bus addresses) to devices. Domains with the new machine type s390-ccw-virtio can use the CCW bus. Currently QEMU will only allow to define virtio devices on the CCW bus. Here we add the new machine type and the new device address to the schema definition and add a new paragraph to the domain XML documentation. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - replace single devno attribute with cssid, ssid, schid triple in documentation section - add new data ranges for cssid, ssid and schid to domain schema docs/formatdomain.html.in | 14 +++++++++++ docs/schemas/domaincommon.rng | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c01f564..ffcc33e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2018,6 +2018,20 @@ of the starting register). <span class="since">Since 0.9.9.</span> </dd> + <dt><code>type='ccw'</code></dt> + <dd>s390 guests with a <code>machine</code> value of + s390-ccw-virtio use the native CCW bus for I/O devices. + CCW bus addresses have the following additional attributes: + <code>cssid</code> (a hex value between 0 and 0xfe, inclusive), + <code>ssid</code> (a value between 0 and 3, inclusive) and + <code>schid</code> (a hex value between 0 and 0xffff, inclusive). + Partially specified bus addresses are not allowed. + If omitted, libvirt will assign a free bus address with + cssid=0xfe and ssid=0. Virtio devices for s390 must have their + cssid set to 0xfe in order to be recognized by the guest + operating system. + <span class="since">Since 1.0.3.</span> + </dd> </dl> <h4><a name="elementsControllers">Controllers</a></h4> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 049f232..63be4aa 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -401,7 +401,10 @@ <optional> <attribute name="machine"> <choice> + <value>s390</value> <value>s390-virtio</value> + <value>s390-ccw</value> + <value>s390-ccw-virtio</value> </choice> </attribute> </optional> @@ -3037,6 +3040,19 @@ </attribute> </optional> </define> + <define name="ccwaddress"> + <optional> + <attribute name="cssid"> + <ref name="ccwCssidRange"/> + </attribute> + <attribute name="ssid"> + <ref name="ccwSsidRange"/> + </attribute> + <attribute name="schid"> + <ref name="ccwSchidRange"/> + </attribute> + </optional> + </define> <define name="driveaddress"> <optional> <attribute name="controller"> @@ -3469,6 +3485,12 @@ </attribute> <ref name="spaprvioaddress"/> </group> + <group> + <attribute name="type"> + <value>ccw</value> + </attribute> + <ref name="ccwaddress"/> + </group> </choice> </element> </define> @@ -3856,4 +3878,34 @@ </element> <empty/> </define> + <define name="ccwCssidRange"> + <choice> + <data type="string"> + <param name="pattern">0x[0-9a-eA-E][0-9a-fA-F]?</param> + </data> + <data type="string"> + <param name="pattern">0x[fF][0-9a-eA-E]?</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">254</param> + </data> + </choice> + </define> + <define name="ccwSsidRange"> + <data type="string"> + <param name="pattern">(0x)?[0-3]</param> + </data> + </define> + <define name="ccwSchidRange"> + <choice> + <data type="string"> + <param name="pattern">0x[0-9a-fA-F]{1,4}</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">65535</param> + </data> + </choice> + </define> </grammar> -- 1.7.9.5

On Fri, Feb 08, 2013 at 06:32:20PM +0100, Viktor Mihajlovski wrote:
The native bus for s390 I/O is called CCW (channel command word). As QEMU has added basic support for the CCW bus, i.e. the ability to assign CCW devnos (bus addresses) to devices. Domains with the new machine type s390-ccw-virtio can use the CCW bus. Currently QEMU will only allow to define virtio devices on the CCW bus. Here we add the new machine type and the new device address to the schema definition and add a new paragraph to the domain XML documentation.
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - replace single devno attribute with cssid, ssid, schid triple in documentation section - add new data ranges for cssid, ssid and schid to domain schema
docs/formatdomain.html.in | 14 +++++++++++ docs/schemas/domaincommon.rng | 52 +++++++++++++++++++++++++++++++++++++++++
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add necessary handling code for the new s390 CCW address type to virDomainDeviceInfo. Further, introduce memory management, XML parsing, output formatting and range validation for the new virDomainDeviceCCWAddress type. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - adapted virDomainDeviceCCWAddressParseXML to handle the new set of CCW address attributes src/conf/domain_conf.c | 107 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 16 +++++++ src/libvirt_private.syms | 1 + 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5e16ddf..1c925f0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -185,7 +185,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "ccid", "usb", "spapr-vio", - "virtio-s390") + "virtio-s390", + "ccw") VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", @@ -2124,6 +2125,13 @@ void virDomainObjListRemove(virDomainObjListPtr doms, virObjectUnlock(doms); } +static int +virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr) +{ + return addr->cssid <= VIR_DOMAIN_DEVICE_CCW_MAX_CSSID && + addr->ssid <= VIR_DOMAIN_DEVICE_CCW_MAX_SSID && + addr->schid <= VIR_DOMAIN_DEVICE_CCW_MAX_SCHID; +} int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type) @@ -2138,6 +2146,12 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: return 1; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + return 1; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + return virDomainDeviceCCWAddressIsValid(&info->addr.ccw); + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: return 1; } @@ -2219,6 +2233,19 @@ static int virDomainDeviceInfoClearPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUS return 0; } +static int +virDomainDeviceInfoClearCCWAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + memset(&info->addr, 0, sizeof(info->addr)); + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE; + } + return 0; +} + int virDomainDeviceInfoIterate(virDomainDefPtr def, virDomainDeviceInfoCallback cb, void *opaque) @@ -2331,6 +2358,11 @@ void virDomainDefClearPCIAddresses(virDomainDefPtr def) virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearPCIAddress, NULL); } +void virDomainDefClearCCWAddresses(virDomainDefPtr def) +{ + virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearCCWAddress, NULL); +} + void virDomainDefClearDeviceAliases(virDomainDefPtr def) { virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearAlias, NULL); @@ -2432,6 +2464,13 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virBufferAsprintf(buf, " reg='0x%llx'", info->addr.spaprvio.reg); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + virBufferAsprintf(buf, " cssid='0x%x' ssid='0x%x' schid='0x%04x'", + info->addr.ccw.cssid, + info->addr.ccw.ssid, + info->addr.ccw.schid); + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown address type '%d'"), info->type); @@ -2542,6 +2581,64 @@ cleanup: } static int +virDomainDeviceCCWAddressParseXML(xmlNodePtr node, + virDomainDeviceCCWAddressPtr addr) +{ + int ret = -1; + char *cssid; + char *ssid; + char *schid; + + memset(addr, 0, sizeof(*addr)); + + cssid = virXMLPropString(node, "cssid"); + ssid = virXMLPropString(node, "ssid"); + schid = virXMLPropString(node, "schid"); + + if (cssid && ssid && schid) { + if (cssid && + virStrToLong_ui(cssid, NULL, 0, &addr->cssid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'cssid' attribute")); + goto cleanup; + } + if (ssid && + virStrToLong_ui(ssid, NULL, 0, &addr->ssid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'ssid' attribute")); + goto cleanup; + } + if (schid && + virStrToLong_ui(schid, NULL, 0, &addr->schid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'schid' attribute")); + goto cleanup; + } + if (!virDomainDeviceCCWAddressIsValid(addr)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid specification for virtio ccw" + " address: cssid='%s' ssid='%s' schid='%s'"), + cssid, ssid, schid); + goto cleanup; + } + addr->assigned = true; + } else if (cssid || ssid || schid) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid partial specification for virtio ccw" + " address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cssid); + VIR_FREE(ssid); + VIR_FREE(schid); + return ret; +} + +static int virDomainDeviceCcidAddressParseXML(xmlNodePtr node, virDomainDeviceCcidAddressPtr addr) { @@ -2834,6 +2931,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, goto cleanup; break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + if (virDomainDeviceCCWAddressParseXML + (address, &info->addr.ccw) < 0) + goto cleanup; + break; + default: /* Should not happen */ virReportError(VIR_ERR_INTERNAL_ERROR, @@ -4685,6 +4788,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -5282,6 +5386,7 @@ virDomainNetDefParseXML(virCapsPtr caps, * them we should make sure address type is correct */ if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index dc411e4..9232ff9 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -190,6 +190,7 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; @@ -219,6 +220,19 @@ struct _virDomainDeviceVirtioSerialAddress { unsigned int port; }; +# define VIR_DOMAIN_DEVICE_CCW_MAX_CSSID 254 +# define VIR_DOMAIN_DEVICE_CCW_MAX_SSID 3 +# define VIR_DOMAIN_DEVICE_CCW_MAX_SCHID 65535 + +typedef struct _virDomainDeviceCCWAddress virDomainDeviceCCWAddress; +typedef virDomainDeviceCCWAddress *virDomainDeviceCCWAddressPtr; +struct _virDomainDeviceCCWAddress { + unsigned int cssid; + unsigned int ssid; + unsigned int schid; + bool assigned; +}; + typedef struct _virDomainDeviceCcidAddress virDomainDeviceCcidAddress; typedef virDomainDeviceCcidAddress *virDomainDeviceCcidAddressPtr; struct _virDomainDeviceCcidAddress { @@ -269,6 +283,7 @@ struct _virDomainDeviceInfo { virDomainDeviceCcidAddress ccid; virDomainDeviceUSBAddress usb; virDomainDeviceSpaprVioAddress spaprvio; + virDomainDeviceCCWAddress ccw; } addr; int mastertype; union { @@ -1951,6 +1966,7 @@ int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst, virDomainDeviceInfoPtr src); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); +void virDomainDefClearCCWAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a4f41ac..1069ce7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -323,6 +323,7 @@ virDomainCpuPlacementModeTypeToString; virDomainDefAddImplicitControllers; virDomainDefAddSecurityLabelDef; virDomainDefCheckABIStability; +virDomainDefClearCCWAddresses; virDomainDefClearDeviceAliases; virDomainDefClearPCIAddresses; virDomainDefCompatibleDevice; -- 1.7.9.5

On Fri, Feb 08, 2013 at 06:32:21PM +0100, Viktor Mihajlovski wrote:
Add necessary handling code for the new s390 CCW address type to virDomainDeviceInfo. Further, introduce memory management, XML parsing, output formatting and range validation for the new virDomainDeviceCCWAddress type.
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - adapted virDomainDeviceCCWAddressParseXML to handle the new set of CCW address attributes
src/conf/domain_conf.c | 107 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 16 +++++++ src/libvirt_private.syms | 1 + 3 files changed, 123 insertions(+), 1 deletion(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/11/2013 08:36 AM, Daniel P. Berrange wrote:
On Fri, Feb 08, 2013 at 06:32:21PM +0100, Viktor Mihajlovski wrote:
Add necessary handling code for the new s390 CCW address type to virDomainDeviceInfo. Further, introduce memory management, XML parsing, output formatting and range validation for the new virDomainDeviceCCWAddress type.
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - adapted virDomainDeviceCCWAddressParseXML to handle the new set of CCW address attributes
src/conf/domain_conf.c | 107 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 16 +++++++ src/libvirt_private.syms | 1 + 3 files changed, 123 insertions(+), 1 deletion(-)
ACK
I've gone ahead and pushed patches 1 and 2, since v3 of the series did not repost them. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 02/12/2013 12:28 AM, Eric Blake wrote:
I've gone ahead and pushed patches 1 and 2, since v3 of the series did not repost them.
Thanks :-) -- Mit freundlichen Grüßen/Kind Regards Viktor Mihajlovski IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

This commit adds the QEMU driver support for CCW addresses. The current QEMU only allows virtio devices to be attached to the CCW bus. We named the new capability indicating that support QEMU_CAPS_VIRTIO_CCW accordingly. The fact that CCW devices can only be assigned to domains with a machine type of s390-ccw-virtio requires a modification in the capability handling approach. First, the QEMU binary name alone will not suffice for capability lookup, we need the machine type as well. For that purpose we mangle the machine type into the cache lookup key. The other thing is that the device support probing will unfortunately always return both the old virtio-*-s390 and the new virtio-*-ccw devices. This makes it impossible to choose the correct default device address type if the domain definition XML doesn't contain explict addresses. Therefore we apply a fix up in the cache lookup: depending on the machine type we clear either the VIRTIO_S390 or the VIRTIO_CCW capability. The rest is more straight-forward, but since it's a new address type, a bit bulky. The majority of the new functions deals with CCW address generation and management. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - rebase, mainly addressing the rename of qemuCapsXXX to virQEMUCapsXXX src/qemu/qemu_capabilities.c | 47 ++++++-- src/qemu/qemu_capabilities.h | 8 +- src/qemu/qemu_command.c | 269 ++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_command.h | 6 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 3 + src/qemu/qemu_driver.c | 20 +++- src/qemu/qemu_process.c | 12 +- 8 files changed, 333 insertions(+), 33 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4efe052..011b88c 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -205,6 +205,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "usb-serial", /* 125 */ "usb-net", "add-fd", + "virtio-ccw", ); @@ -684,7 +685,7 @@ virQEMUCapsInitGuest(virCapsPtr caps, /* Ignore binary if extracting version info fails */ if (binary) { - if (!(qemubinCaps = virQEMUCapsCacheLookup(cache, binary))) { + if (!(qemubinCaps = virQEMUCapsCacheLookup(cache, binary, NULL))) { virResetLastError(); VIR_FREE(binary); } @@ -707,7 +708,7 @@ virQEMUCapsInitGuest(virCapsPtr caps, if (!kvmbin) continue; - if (!(kvmbinCaps = virQEMUCapsCacheLookup(cache, kvmbin))) { + if (!(kvmbinCaps = virQEMUCapsCacheLookup(cache, kvmbin, NULL))) { virResetLastError(); VIR_FREE(kvmbin); continue; @@ -1339,6 +1340,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "usb-hub", QEMU_CAPS_USB_HUB }, { "ich9-ahci", QEMU_CAPS_ICH9_AHCI }, { "virtio-blk-s390", QEMU_CAPS_VIRTIO_S390 }, + { "virtio-blk-ccw", QEMU_CAPS_VIRTIO_CCW }, { "sclpconsole", QEMU_CAPS_SCLP_S390 }, { "lsi53c895a", QEMU_CAPS_SCSI_LSI }, { "virtio-scsi-pci", QEMU_CAPS_VIRTIO_SCSI_PCI }, @@ -1356,7 +1358,6 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, }; - static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = { { "multifunction", QEMU_CAPS_PCI_MULTIFUNCTION }, { "bootindex", QEMU_CAPS_BOOTINDEX }, @@ -1411,6 +1412,10 @@ static struct virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = { ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) }, { "virtio-net-pci", virQEMUCapsObjectPropsVirtioNet, ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioNet) }, + { "virtio-blk-ccw", virQEMUCapsObjectPropsVirtioBlk, + ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) }, + { "virtio-net-ccw", virQEMUCapsObjectPropsVirtioNet, + ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioNet) }, { "virtio-blk-s390", virQEMUCapsObjectPropsVirtioBlk, ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) }, { "virtio-net-s390", virQEMUCapsObjectPropsVirtioNet, @@ -1662,7 +1667,7 @@ int virQEMUCapsGetDefaultVersion(virCapsPtr caps, return -1; } - if (!(qemucaps = virQEMUCapsCacheLookup(capsCache, binary))) + if (!(qemucaps = virQEMUCapsCacheLookup(capsCache, binary, NULL))) return -1; *version = virQEMUCapsGetVersion(qemucaps); @@ -2612,16 +2617,24 @@ error: virQEMUCapsPtr -virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary) +virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary, + const char *machine) { virQEMUCapsPtr ret = NULL; + char * cachekey; + + if (virAsprintf(&cachekey, "%s:%s", binary, machine ? machine : "") < 0) { + virReportOOMError(); + goto error; + } + virMutexLock(&cache->lock); - ret = virHashLookup(cache->binaries, binary); + ret = virHashLookup(cache->binaries, cachekey); if (ret && !virQEMUCapsIsValid(ret)) { VIR_DEBUG("Cached capabilities %p no longer valid for %s", ret, binary); - virHashRemoveEntry(cache->binaries, binary); + virHashRemoveEntry(cache->binaries, cachekey); ret = NULL; } if (!ret) { @@ -2632,7 +2645,17 @@ virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary) if (ret) { VIR_DEBUG("Caching capabilities %p for %s", ret, binary); - if (virHashAddEntry(cache->binaries, binary, ret) < 0) { + + /* fix up machine specific capabilities */ + if (machine) { + if (STREQLEN(machine,"s390-ccw",8)) { + virQEMUCapsClear(ret, QEMU_CAPS_VIRTIO_S390); + } else if (STREQLEN(machine,"s390",4)) { + virQEMUCapsClear(ret, QEMU_CAPS_VIRTIO_CCW); + } + } + + if (virHashAddEntry(cache->binaries, cachekey, ret) < 0) { virObjectUnref(ret); ret = NULL; } @@ -2641,14 +2664,18 @@ virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary) VIR_DEBUG("Returning caps %p for %s", ret, binary); virObjectRef(ret); virMutexUnlock(&cache->lock); + +error: + VIR_FREE(cachekey); return ret; } virQEMUCapsPtr -virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache, const char *binary) +virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache, const char *binary, + const char *machine) { - virQEMUCapsPtr qemuCaps = virQEMUCapsCacheLookup(cache, binary); + virQEMUCapsPtr qemuCaps = virQEMUCapsCacheLookup(cache, binary, machine); virQEMUCapsPtr ret; if (!qemuCaps) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e69d558..1a6df85 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -166,6 +166,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_USB_SERIAL = 125, /* -device usb-serial */ QEMU_CAPS_DEVICE_USB_NET = 126, /* -device usb-net */ QEMU_CAPS_ADD_FD = 127, /* -add-fd */ + QEMU_CAPS_VIRTIO_CCW = 128, /* -device virtio-*-ccw */ QEMU_CAPS_LAST, /* this must always be the last item */ }; @@ -218,13 +219,14 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps, bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps); - virQEMUCapsCachePtr virQEMUCapsCacheNew(const char *libDir, uid_t uid, gid_t gid); virQEMUCapsPtr virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, - const char *binary); + const char *binary, + const char *machine); virQEMUCapsPtr virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache, - const char *binary); + const char *binary, + const char *machine); void virQEMUCapsCacheFree(virQEMUCapsCachePtr cache); virCapsPtr virQEMUCapsInit(virQEMUCapsCachePtr cache); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 33f2ecd..0bb4a46 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -795,6 +795,100 @@ no_memory: return -1; } +/* S390 ccw bus support */ + +struct _qemuDomainCCWAddressSet { + virHashTablePtr defined; + virDomainDeviceCCWAddress next; +}; + +static char* +qemuCCWAddressAsString(virDomainDeviceCCWAddressPtr addr) +{ + char *addrstr = NULL; + + if (virAsprintf(&addrstr, "%x.%x.%04x", + addr->cssid, + addr->ssid, + addr->schid) < 0) { + virReportOOMError(); + return NULL; + } + + return addrstr; +} + +static int +qemuCCWAdressIncrement(virDomainDeviceCCWAddressPtr addr) +{ + virDomainDeviceCCWAddress ccwaddr = *addr; + + /* We are not touching subchannel sets and channel subsystems */ + if (++ccwaddr.schid > VIR_DOMAIN_DEVICE_CCW_MAX_SCHID) + return -1; + + *addr = ccwaddr; + return 0; +} + +static void +qemuDomainCCWAddressSetFreeEntry(void *payload, + const void *name ATTRIBUTE_UNUSED) +{ + VIR_FREE(payload); +} + +int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, + qemuDomainCCWAddressSetPtr addrs, + bool autoassign) +{ + int ret = -1; + char *addr = NULL; + + if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) + return 0; + + if (!autoassign && dev->addr.ccw.assigned) { + if (!(addr = qemuCCWAddressAsString(&dev->addr.ccw))) + goto cleanup; + + if (virHashLookup(addrs->defined, addr)) { + virReportError(VIR_ERR_XML_ERROR, + _("The CCW devno '%s' is in use already "), + addr); + goto cleanup; + } + } else if (autoassign && !dev->addr.ccw.assigned) { + if (!(addr = qemuCCWAddressAsString(&addrs->next)) < 0) + goto cleanup; + + while (virHashLookup(addrs->defined, addr)) { + if (qemuCCWAdressIncrement(&addrs->next) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("There are no more free CCW devnos.")); + goto cleanup; + } + VIR_FREE(addr); + addr = qemuCCWAddressAsString(&addrs->next); + } + dev->addr.ccw = addrs->next; + dev->addr.ccw.assigned = true; + } else { + return 0; + } + + if (virHashAddEntry(addrs->defined,addr,addr) < 0) + goto cleanup; + else + addr = NULL; /* memory will be freed by hash table */ + + ret = 0; + +cleanup: + VIR_FREE(addr); + return ret; +} + static void qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def, enum virDomainDeviceAddressType type) @@ -837,13 +931,137 @@ qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def, def->memballoon->info.type = type; } -static void -qemuDomainAssignS390Addresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) +static int +qemuDomainCCWAddressAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void * data) +{ + return qemuDomainCCWAddressAssign(info, + (qemuDomainCCWAddressSetPtr)data, + true); +} + +static int +qemuDomainCCWAddressValidate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void * data) +{ + return qemuDomainCCWAddressAssign(info,(qemuDomainCCWAddressSetPtr)data, + false); +} + +int qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs, + virDomainDeviceInfoPtr dev) +{ + char *addr; + int ret; + + addr = qemuCCWAddressAsString(&(dev->addr.ccw)); + if (!addr) + return -1; + + if ((ret = virHashRemoveEntry(addrs->defined, addr)) == 0 && + dev->addr.ccw.cssid == addrs->next.cssid && + dev->addr.ccw.ssid == addrs->next.ssid && + dev->addr.ccw.schid < addrs->next.schid) { + addrs->next.schid = dev->addr.ccw.schid; + addrs->next.assigned = false; + } + + VIR_FREE(addr); + + return ret; +} + +void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs) { - /* deal with legacy virtio-s390 */ - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) + if (!addrs) + return; + + virHashFree(addrs->defined); + VIR_FREE(addrs); +} + +static qemuDomainCCWAddressSetPtr +qemuDomainCCWAddressSetCreate(void) +{ + qemuDomainCCWAddressSetPtr addrs = NULL; + + if (VIR_ALLOC(addrs) < 0) + goto no_memory; + + if (!(addrs->defined = virHashCreate(10, qemuDomainCCWAddressSetFreeEntry))) + goto cleanup; + + /* must use cssid = 0xfe (254) for virtio-ccw devices */ + addrs->next.cssid = 254; + addrs->next.ssid = 0; + addrs->next.schid = 0; + addrs->next.assigned = 0; + return addrs; + +no_memory: + virReportOOMError(); +cleanup: + qemuDomainCCWAddressSetFree(addrs); + return addrs; +} + +/* + * Three steps populating CCW devnos + * 1. Allocate empty address set + * 2. Gather addresses with explicit devno + * 3. Assign defaults to the rest + */ +static int +qemuDomainAssignS390Addresses(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + virDomainObjPtr obj) +{ + int ret = -1; + qemuDomainCCWAddressSetPtr addrs = NULL; + qemuDomainObjPrivatePtr priv = NULL; + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + qemuDomainPrimeS390VirtioDevices( + def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW); + + if (!(addrs = qemuDomainCCWAddressSetCreate())) + goto cleanup; + + if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressValidate, + addrs) < 0) + goto cleanup; + + if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressAllocate, + addrs) < 0) + goto cleanup; + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) { + /* deal with legacy virtio-s390 */ qemuDomainPrimeS390VirtioDevices( def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390); + } + + if (obj && obj->privateData) { + priv = obj->privateData; + if (addrs) { + /* if this is the live domain object, we persist the CCW addresses*/ + qemuDomainCCWAddressSetFree(priv->ccwaddrs); + priv->persistentAddrs = 1; + priv->ccwaddrs = addrs; + addrs = NULL; + } else { + priv->persistentAddrs = 0; + } + } + ret = 0; + +cleanup: + qemuDomainCCWAddressSetFree(addrs); + + return ret; } static int @@ -1103,7 +1321,9 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, if (rc) return rc; - qemuDomainAssignS390Addresses(def, qemuCaps); + rc = qemuDomainAssignS390Addresses(def, qemuCaps, obj); + if (rc) + return rc; return qemuDomainAssignPCIAddresses(def, qemuCaps, obj); } @@ -1322,7 +1542,6 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs) VIR_FREE(addrs); } - static int qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs) { int i; @@ -1668,7 +1887,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, /* don't touch s390 devices */ if (def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI || def->disks[i]->info.type == - VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 || + def->disks[i]->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) continue; if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { @@ -1814,6 +2035,12 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) { if (info->addr.spaprvio.has_reg) virBufferAsprintf(buf, ",reg=0x%llx", info->addr.spaprvio.reg); + } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (info->addr.ccw.assigned) + virBufferAsprintf(buf, ",devno=%x.%x.%04x", + info->addr.ccw.cssid, + info->addr.ccw.ssid, + info->addr.ccw.schid); } return 0; @@ -2822,8 +3049,10 @@ qemuBuildDriveDevStr(virDomainDefPtr def, disk->info.addr.drive.unit); break; case VIR_DOMAIN_DISK_BUS_VIRTIO: - if (disk->info.type == - VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { + if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + virBufferAddLit(&opt, "virtio-blk-ccw"); + } else if (disk->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { virBufferAddLit(&opt, "virtio-blk-s390"); } else { virBufferAddLit(&opt, "virtio-blk-pci"); @@ -3105,6 +3334,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virBufferAddLit(&buf, "virtio-serial-pci"); } else if (def->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + virBufferAddLit(&buf, "virtio-serial-ccw"); + } else if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { virBufferAddLit(&buf, "virtio-serial-s390"); } else { @@ -3202,8 +3434,10 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, if (!net->model) { nic = "rtl8139"; } else if (STREQ(net->model, "virtio")) { - if (net->info.type == - VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { + if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + nic = "virtio-net-ccw"; + } else if (net->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { nic = "virtio-net-s390"; } else { nic = "virtio-net-pci"; @@ -3430,7 +3664,17 @@ qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev, { virBuffer buf = VIR_BUFFER_INITIALIZER; - virBufferAddLit(&buf, "virtio-balloon-pci"); + switch (dev->info.type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + virBufferAddLit(&buf, "virtio-balloon-pci"); + break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + virBufferAddLit(&buf, "virtio-balloon-ccw"); + break; + default: + goto error; + } + virBufferAsprintf(&buf, ",id=%s", dev->info.alias); if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0) goto error; @@ -4122,6 +4366,7 @@ qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev, } if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { /* Check it's a virtio-serial address */ if (dev->info.type != diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 7e52c5d..0f3bb5e 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -215,6 +215,12 @@ int qemuAssignDevicePCISlots(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, qemuDomainPCIAddressSetPtr addrs); +int qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs, + virDomainDeviceInfoPtr dev); +int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, qemuDomainCCWAddressSetPtr addrs, + bool autoassign); +void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs); + int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps); int qemuDomainNetVLAN(virDomainNetDefPtr def); int qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4917721..749aac0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -234,6 +234,7 @@ static void qemuDomainObjPrivateFree(void *data) virObjectUnref(priv->qemuCaps); qemuDomainPCIAddressSetFree(priv->pciaddrs); + qemuDomainCCWAddressSetFree(priv->ccwaddrs); virDomainChrSourceDefFree(priv->monConfig); qemuDomainObjFreeJob(priv); VIR_FREE(priv->vcpupids); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 51cd2dc..c9658fc 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -119,6 +119,8 @@ typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver, virDomainObjPtr vm); +typedef struct _qemuDomainCCWAddressSet qemuDomainCCWAddressSet; +typedef qemuDomainCCWAddressSet *qemuDomainCCWAddressSetPtr; typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; @@ -143,6 +145,7 @@ struct _qemuDomainObjPrivate { int *vcpupids; qemuDomainPCIAddressSetPtr pciaddrs; + qemuDomainCCWAddressSetPtr ccwaddrs; int persistentAddrs; virQEMUCapsPtr qemuCaps; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0651bc8..6e73558 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1538,7 +1538,9 @@ static virDomainPtr qemuDomainCreate(virConnectPtr conn, const char *xml, if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; - if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator))) + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + def->emulator, + def->os.machine))) goto cleanup; if (qemuCanonicalizeMachine(def, qemuCaps) < 0) @@ -5353,7 +5355,9 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, if (!def) goto cleanup; - if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator))) + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + def->emulator, + def->os.machine))) goto cleanup; /* Since we're just exporting args, we can't do bridge/network/direct @@ -5634,7 +5638,9 @@ static virDomainPtr qemuDomainDefine(virConnectPtr conn, const char *xml) { if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; - if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator))) + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + def->emulator, + def->os.machine))) goto cleanup; if (qemuCanonicalizeMachine(def, qemuCaps) < 0) @@ -6502,7 +6508,9 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, if (priv->qemuCaps) qemuCaps = virObjectRef(priv->qemuCaps); - else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator))) + else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + vm->def->emulator, + vm->def->os.machine))) goto cleanup; if (flags & VIR_DOMAIN_AFFECT_CONFIG) { @@ -12713,7 +12721,9 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn, goto cleanup; } - if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator))) + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + def->emulator, + def->os.machine))) goto cleanup; if (qemuCanonicalizeMachine(def, qemuCaps) < 0) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index abbee5e..c36b5c2 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3311,7 +3311,8 @@ qemuProcessReconnect(void *opaque) */ if (!priv->qemuCaps && !(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, - obj->def->emulator))) + obj->def->emulator, + obj->def->os.machine))) goto error; /* In case the domain shutdown while we were not running, @@ -3811,7 +3812,8 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG("Determining emulator version"); virObjectUnref(priv->qemuCaps); if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, - vm->def->emulator))) + vm->def->emulator, + vm->def->os.machine))) goto cleanup; if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0) @@ -4385,6 +4387,9 @@ void qemuProcessStop(virQEMUDriverPtr driver, virDomainDefClearPCIAddresses(vm->def); qemuDomainPCIAddressSetFree(priv->pciaddrs); priv->pciaddrs = NULL; + virDomainDefClearCCWAddresses(vm->def); + qemuDomainCCWAddressSetFree(priv->ccwaddrs); + priv->ccwaddrs = NULL; } qemuDomainReAttachHostDevices(driver, vm->def); @@ -4573,7 +4578,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, VIR_DEBUG("Determining emulator version"); virObjectUnref(priv->qemuCaps); if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, - vm->def->emulator))) + vm->def->emulator, + vm->def->os.machine))) goto cleanup; VIR_DEBUG("Preparing monitor state"); -- 1.7.9.5

On Fri, Feb 08, 2013 at 06:32:22PM +0100, Viktor Mihajlovski wrote:
This commit adds the QEMU driver support for CCW addresses. The current QEMU only allows virtio devices to be attached to the CCW bus. We named the new capability indicating that support QEMU_CAPS_VIRTIO_CCW accordingly.
The fact that CCW devices can only be assigned to domains with a machine type of s390-ccw-virtio requires a modification in the capability handling approach.
First, the QEMU binary name alone will not suffice for capability lookup, we need the machine type as well. For that purpose we mangle the machine type into the cache lookup key.
The other thing is that the device support probing will unfortunately always return both the old virtio-*-s390 and the new virtio-*-ccw devices. This makes it impossible to choose the correct default device address type if the domain definition XML doesn't contain explict addresses. Therefore we apply a fix up in the cache lookup: depending on the machine type we clear either the VIRTIO_S390 or the VIRTIO_CCW capability.
I'm not a fan of this approach. The capabilities data is reflecting what the QEMU binary is capable of supporting, *regardless* of what guest config is chosen. The decision about whether to use S390 or CCW based on the machine type value, should be made by the internal method at the point when it actually assigns addresses, not when we create the capabilities initially. Your approach here means we're going to be storing many many more capabilities instances, and we're going to be re-probing the QEMU binaries for each machine type. This is absolutely not something we want todo. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/11/2013 04:40 PM, Daniel P. Berrange wrote:
I'm not a fan of this approach. The capabilities data is reflecting what the QEMU binary is capable of supporting, *regardless* of what guest config is chosen.
not convinced this is the best possible definition ... we would have seen more issues with it if the machine type would really have had a meaning on other architectures, e.g., if -M isapc would not allow to instantiate PCI devices. But since...
The decision about whether to use S390 or CCW based on the machine type value, should be made by the internal method at the point when it actually assigns addresses, not when we create the capabilities initially.
...I can certainly use the vm definition to figure out which address type to choose that should work. Let me run a few tests to prove that and I will come back with a V3 for 3-5/5 in the next couple of days. -- Mit freundlichen Grüßen/Kind Regards Viktor Mihajlovski IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

To clarify my earlier reply - my point is that in the following method: On Fri, Feb 08, 2013 at 06:32:22PM +0100, Viktor Mihajlovski wrote:
+/* + * Three steps populating CCW devnos + * 1. Allocate empty address set + * 2. Gather addresses with explicit devno + * 3. Assign defaults to the rest + */ +static int +qemuDomainAssignS390Addresses(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + virDomainObjPtr obj) +{ + int ret = -1; + qemuDomainCCWAddressSetPtr addrs = NULL; + qemuDomainObjPrivatePtr priv = NULL; + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
change this to if (STREQ(def->os.machine), "virtio-s390-ccw") { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("This QEMU does not support CCW addressing")); } ... assign CCW based addresses ... }
+ } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) { + /* deal with legacy virtio-s390 */ qemuDomainPrimeS390VirtioDevices( def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390); + } +
This avoids need to pass machine type into the capabilities APIs at all. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/11/2013 06:41 PM, Daniel P. Berrange wrote:
To clarify my earlier reply - my point is that in the following method:
Thanks Daniel ... no clarification needed here. :-) -- Mit freundlichen Grüßen/Kind Regards Viktor Mihajlovski IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

From: "J.B. Joret" <jb@linux.vnet.ibm.com> We didn't yet expose the virtio device attach and detach functionality for s390 domains as the device hotplug was very limited with the old virtio-s390 bus. With the CCW bus there's full hotplug support for virtio devices in QEMU, so we are adding this to libvirt too. Since the virtio hotplug isn't limited to PCI anymore, we change the function names from xxxPCIyyy to xxxVirtioyyy, where we handle all three virtio bus types. Signed-off-by: J.B. Joret <jb@linux.vnet.ibm.com> Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - rebase, mainly addressing the rename of qemuCapsXXX to virQEMUCapsXXX src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_hotplug.c | 147 ++++++++++++++++++++++++++++++++--------------- src/qemu/qemu_hotplug.h | 14 ++--- 3 files changed, 110 insertions(+), 57 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6e73558..62c95d6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5865,7 +5865,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, ret = qemuDomainAttachUsbMassstorageDevice(conn, driver, vm, disk); } else if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ret = qemuDomainAttachPciDiskDevice(conn, driver, vm, disk); + ret = qemuDomainAttachVirtioDiskDevice(conn, driver, vm, disk); } else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { ret = qemuDomainAttachSCSIDisk(conn, driver, vm, disk); } else { @@ -5998,7 +5998,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver, case VIR_DOMAIN_DISK_DEVICE_DISK: case VIR_DOMAIN_DISK_DEVICE_LUN: if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) - ret = qemuDomainDetachPciDiskDevice(driver, vm, dev); + ret = qemuDomainDetachVirtioDiskDevice(driver, vm, dev); else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || disk->bus == VIR_DOMAIN_DISK_BUS_USB) ret = qemuDomainDetachDiskDevice(driver, vm, dev); @@ -6009,7 +6009,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver, default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk device type '%s' cannot be detached"), - virDomainDiskDeviceTypeToString(disk->type)); + virDomainDiskDeviceTypeToString(disk->device)); break; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 4504f0b..4cea71f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -224,11 +224,10 @@ cleanup: return ret; } - -int qemuDomainAttachPciDiskDevice(virConnectPtr conn, - virQEMUDriverPtr driver, - virDomainObjPtr vm, - virDomainDiskDefPtr disk) +int qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, + virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDiskDefPtr disk) { int i, ret = -1; const char* type = virDomainDiskBusTypeToString(disk->bus); @@ -238,6 +237,14 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, bool releaseaddr = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + if (!disk->info.type) { + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) + disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) + disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390; + else disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + } + for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, disk->dst)) { virReportError(VIR_ERR_OPERATION_FAILED, @@ -258,8 +265,14 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, } if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0) - goto error; + if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (qemuDomainCCWAddressAssign(&disk->info, priv->ccwaddrs, + !disk->info.addr.ccw.assigned) < 0) + goto error; + } else if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0) + goto error; + } releaseaddr = true; if (qemuAssignDeviceDiskAlias(vm->def, disk, priv->qemuCaps) < 0) goto error; @@ -294,16 +307,14 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, } } } - } else { + } else if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI){ virDevicePCIAddress guestAddr = disk->info.addr.pci; ret = qemuMonitorAddPCIDisk(priv->mon, disk->src, type, &guestAddr); - if (ret == 0) { - disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + if (ret == 0) memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr)); - } } qemuDomainObjExitMonitorWithDriver(driver, vm); @@ -321,12 +332,16 @@ cleanup: return ret; error: - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && - (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && - releaseaddr && - qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, - disk->info.addr.pci.slot) < 0) - VIR_WARN("Unable to release PCI address on %s", disk->src); + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && releaseaddr) { + if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && + qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, + disk->info.addr.pci.slot) < 0) + VIR_WARN("Unable to release PCI address on %s", disk->src); + else if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && + qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, + &disk->info) < 0) + VIR_WARN("Unable to release CCW address on %s", disk->src); + } if (virSecurityManagerRestoreImageLabel(driver->securityManager, vm->def, disk) < 0) @@ -409,7 +424,6 @@ cleanup: return ret; } - static virDomainControllerDefPtr qemuDomainFindOrCreateSCSIDiskController(virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -762,9 +776,17 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, goto cleanup; } - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && - qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) - goto cleanup; + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + if (qemuDomainCCWAddressAssign(&net->info, priv->ccwaddrs, + !net->info.addr.ccw.assigned) < 0) + goto cleanup; + } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-s390 net device cannot be hotplugged.")); + else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && + qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) + goto cleanup; releaseaddr = true; @@ -893,11 +915,17 @@ cleanup: vm->def->nets[vm->def->nnets++] = net; } else { if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && - (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && releaseaddr && qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, - net->info.addr.pci.slot) < 0) + net->info.addr.pci.slot) < 0) { VIR_WARN("Unable to release PCI address on NIC"); + } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW) && + net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && + releaseaddr && + qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, + &net->info) < 0) + VIR_WARN("Unable to release CCW address on NIC"); if (iface_connected) { virDomainConfNWFilterTeardown(net); @@ -2005,9 +2033,9 @@ static bool qemuIsMultiFunctionDevice(virDomainDefPtr def, } -int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver, - virDomainObjPtr vm, - virDomainDeviceDefPtr dev) +int qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) { int i, ret = -1; virDomainDiskDefPtr detach = NULL; @@ -2041,11 +2069,20 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver, } } - if (!virDomainDeviceAddressIsValid(&detach->info, - VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("device cannot be detached without a PCI address")); - goto cleanup; + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + if (!virDomainDeviceAddressIsValid(&detach->info, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("device cannot be detached without a valid CCW address")); + goto cleanup; + } + } else { + if (!virDomainDeviceAddressIsValid(&detach->info, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("device cannot be detached without a valid PCI address")); + goto cleanup; + } } /* build the actual drive id string as the disk->info.alias doesn't @@ -2079,9 +2116,14 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver, virDomainAuditDisk(vm, detach->src, NULL, "detach", true); - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && - qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, - detach->info.addr.pci.slot) < 0) + if (detach->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW) && + qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, &detach->info) < 0) { + VIR_WARN("Unable to release CCW address on %s", dev->data.disk->src); + } else if (detach->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && + qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, + detach->info.addr.pci.slot) < 0) VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src); virDomainDiskRemove(vm->def, i); @@ -2584,19 +2626,27 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, -1); goto cleanup; } + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + if (!virDomainDeviceAddressIsValid(&detach->info, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("device cannot be detached without a CCW address")); + goto cleanup; + } + } else { + if (!virDomainDeviceAddressIsValid(&detach->info, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("device cannot be detached without a PCI address")); + goto cleanup; + } - if (!virDomainDeviceAddressIsValid(&detach->info, - VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("device cannot be detached without a PCI address")); - goto cleanup; - } - - if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("cannot hot unplug multifunction PCI device :%s"), - dev->data.disk->dst); - goto cleanup; + if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("cannot hot unplug multifunction PCI device :%s"), + dev->data.disk->dst); + goto cleanup; + } } if ((vlan = qemuDomainNetVLAN(detach)) < 0) { @@ -2644,7 +2694,10 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, virDomainAuditNet(vm, detach, NULL, "detach", true); - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + if (qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, &detach->info) < 0) + VIR_WARN("Unable to release CCW address on NIC"); + } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, detach->info.addr.pci.slot) < 0) VIR_WARN("Unable to release PCI address on NIC"); diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 8f01d23..5c946db 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -35,10 +35,10 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, int qemuDomainCheckEjectableMedia(virQEMUDriverPtr driver, virDomainObjPtr vm, enum qemuDomainAsyncJob asyncJob); -int qemuDomainAttachPciDiskDevice(virConnectPtr conn, - virQEMUDriverPtr driver, - virDomainObjPtr vm, - virDomainDiskDefPtr disk); +int qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, + virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDiskDefPtr disk); int qemuDomainAttachPciControllerDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainControllerDefPtr controller); @@ -82,9 +82,9 @@ int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainNetDefPtr dev, int linkstate); -int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver, - virDomainObjPtr vm, - virDomainDeviceDefPtr dev); +int qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev); int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev); -- 1.7.9.5

This adds and corrects testcases for virtio devices on s390 guests. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- V2 Changes - adapt the testcase XML files to use the new attributes - use different variations for the values: hex, decimal, leading zeroes... .../qemuxml2argv-console-virtio-ccw.args | 10 +++++ .../qemuxml2argv-console-virtio-ccw.xml | 27 +++++++++++++ .../qemuxml2argv-console-virtio-s390.args | 4 +- .../qemuxml2argv-console-virtio-s390.xml | 2 +- .../qemuxml2argv-disk-virtio-ccw-many.args | 12 ++++++ .../qemuxml2argv-disk-virtio-ccw-many.xml | 40 ++++++++++++++++++++ .../qemuxml2argv-disk-virtio-ccw.args | 8 ++++ .../qemuxml2argv-disk-virtio-ccw.xml | 30 +++++++++++++++ .../qemuxml2argv-net-virtio-ccw.args | 8 ++++ .../qemuxml2argv-net-virtio-ccw.xml | 30 +++++++++++++++ tests/qemuxml2argvtest.c | 11 +++++- tests/testutilsqemu.c | 3 +- 12 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.args new file mode 100644 index 0000000..6660a30 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.args @@ -0,0 +1,10 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +s390-ccw -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi \ +-device virtio-serial-ccw,id=virtio-serial0,devno=fe.0.0001 \ +-usb -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-ccw,devno=fe.0.0000,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 \ +-chardev pty,id=charconsole0 \ +-device virtconsole,chardev=charconsole0,id=console0 \ +-device virtio-balloon-ccw,id=balloon0,devno=fe.0.000a diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.xml new file mode 100644 index 0000000..faaeeb8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-ccw.xml @@ -0,0 +1,27 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <os> + <type arch='s390x' machine='s390-ccw'>hvm</type> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='virtio'/> + <boot order='1'/> + </disk> + <console type='pty'> + <target type='virtio'/> + </console> + <memballoon model='virtio'> + <address type='ccw' cssid='0xfe' ssid='0' schid='0x000a'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.args index 3bd7817..bf7b180 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.args @@ -2,8 +2,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ s390-virtio -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ chardev=charmonitor,id=monitor,mode=readline -no-acpi \ --boot c -device virtio-serial-s390,id=virtio-serial0 \ +-device virtio-serial-s390,id=virtio-serial0 \ -usb -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-virtio-disk0 \ --device virtio-blk-s390,drive=drive-virtio-disk0,id=virtio-disk0 \ +-device virtio-blk-s390,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 \ -chardev pty,id=charconsole0 \ -device virtconsole,chardev=charconsole0,id=console0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.xml index 5a4a9d4..221232d 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-s390.xml @@ -5,7 +5,6 @@ <currentMemory>219100</currentMemory> <os> <type arch='s390x' machine='s390-virtio'>hvm</type> - <boot dev='hd'/> </os> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> @@ -16,6 +15,7 @@ <disk type='block' device='disk'> <source dev='/dev/HostVG/QEMUGuest1'/> <target dev='hda' bus='virtio'/> + <boot order='1'/> </disk> <console type='pty'> <target type='virtio'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.args new file mode 100644 index 0000000..ca0c157 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.args @@ -0,0 +1,12 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \ +-M s390-ccw -m 214 -smp 1 -nographic -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-ccw,devno=0.0.0007,drive=drive-virtio-disk0,id=virtio-disk0 \ +-drive file=/dev/HostVG/QEMUGuest4,if=none,id=drive-virtio-disk1 \ +-device virtio-blk-ccw,devno=fe.0.0000,drive=drive-virtio-disk1,id=virtio-disk1 \ +-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-virtio-disk2 \ +-device virtio-blk-ccw,devno=fe.0.0001,drive=drive-virtio-disk2,id=virtio-disk2 \ +-drive file=/dev/HostVG/QEMUGuest3,if=none,id=drive-virtio-disk3 \ +-device virtio-blk-ccw,devno=fe.2.f00f,drive=drive-virtio-disk3,id=virtio-disk3 \ +-device virtio-balloon-ccw,id=balloon0,devno=fe.0.000a diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml new file mode 100644 index 0000000..64689cf --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219136</memory> + <currentMemory>219136</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='s390x' machine='s390-ccw'>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</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='virtio'/> + <address type='ccw' cssid='0' ssid='0x0' schid='7'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hdc' bus='virtio'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest3'/> + <target dev='hdd' bus='virtio'/> + <address type='ccw' cssid='254' ssid='2' schid='0xf00f'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest4'/> + <target dev='hdb' bus='virtio'/> + <address type='ccw'/> + </disk> + <memballoon model='virtio'> + <address type='ccw' cssid='0xfe' ssid='0x0' schid='0x0a'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.args new file mode 100644 index 0000000..ec901bb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.args @@ -0,0 +1,8 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \ +-M s390-ccw -m 214 -smp 1 -nographic -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-ccw,devno=fe.0.0000,drive=drive-virtio-disk0,id=virtio-disk0 \ +-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-virtio-disk1 \ +-device virtio-blk-ccw,devno=0.0.0007,drive=drive-virtio-disk1,id=virtio-disk1 \ +-device virtio-balloon-ccw,id=balloon0,devno=fe.0.000a diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.xml new file mode 100644 index 0000000..f6175b0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219136</memory> + <currentMemory>219136</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='s390x' machine='s390-ccw'>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</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='virtio'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hdb' bus='virtio'/> + <address type='ccw' cssid='0' ssid='0' schid='7'/> + </disk> + <memballoon model='virtio'> + <address type='ccw' cssid='0xFe' ssid='0x0' schid='0xA'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.args new file mode 100644 index 0000000..f874afe --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.args @@ -0,0 +1,8 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \ +-M s390-ccw -m 214 -smp 1 -nographic -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -device virtio-net-ccw,vlan=0,id=net0,mac=00:11:22:33:44:55,devno=fe.0.0001 \ +-net user,vlan=0,name=hostnet0 \ +-device virtio-net-ccw,vlan=1,id=net1,mac=00:11:22:33:44:54,devno=fe.0.0000 \ +-net user,vlan=1,name=hostnet1 \ +-device virtio-balloon-ccw,id=balloon0,devno=fe.0.000a diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.xml new file mode 100644 index 0000000..583de3e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-ccw.xml @@ -0,0 +1,30 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219136</memory> + <currentMemory>219136</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='s390x' machine='s390-ccw'>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</emulator> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:54'/> + <model type='virtio'/> + <address type='ccw' cssid='0xfe' ssid='0x0' schid='0x0'/> + </interface> + <memballoon model='virtio'> + <address type='ccw' cssid='254' ssid='0' schid='10'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 4357068..302cda4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -438,6 +438,10 @@ mymain(void) QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_S390); DO_TEST("disk-many", NONE); DO_TEST("disk-virtio", QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT); + DO_TEST("disk-virtio-ccw", QEMU_CAPS_DRIVE, + QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_CCW); + DO_TEST("disk-virtio-ccw-many", QEMU_CAPS_DRIVE, + QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_CCW); DO_TEST("disk-order", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE_BOOT, QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO); @@ -625,6 +629,8 @@ mymain(void) QEMU_CAPS_DEVICE, QEMU_CAPS_NETDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("net-virtio-s390", QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_S390); + DO_TEST("net-virtio-ccw", + QEMU_CAPS_DEVICE, QEMU_CAPS_VIRTIO_CCW); DO_TEST("net-eth", NONE); DO_TEST("net-eth-ifname", NONE); DO_TEST("net-eth-names", QEMU_CAPS_NET_NAME); @@ -684,7 +690,10 @@ mymain(void) QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("console-virtio-s390", QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, - QEMU_CAPS_DRIVE, QEMU_CAPS_VIRTIO_S390); + QEMU_CAPS_DRIVE, QEMU_CAPS_BOOTINDEX, QEMU_CAPS_VIRTIO_S390); + DO_TEST("console-virtio-ccw", + QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DRIVE, QEMU_CAPS_BOOTINDEX, QEMU_CAPS_VIRTIO_CCW); DO_TEST("console-sclp", QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DRIVE, QEMU_CAPS_VIRTIO_S390, QEMU_CAPS_SCLP_S390); diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 966527c..c09d013 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -94,7 +94,8 @@ error: static int testQemuAddS390Guest(virCapsPtr caps) { - static const char *s390_machines[] = { "s390-virtio"}; + static const char *s390_machines[] = { "s390-virtio", + "s390-ccw-virtio" }; virCapsGuestMachinePtr *machines = NULL; virCapsGuestPtr guest; -- 1.7.9.5
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Viktor Mihajlovski