[libvirt] [PATCH 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. 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 | 12 + docs/schemas/domaincommon.rng | 21 ++ src/conf/domain_conf.c | 80 +++++- src/conf/domain_conf.h | 16 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 47 +++- src/qemu/qemu_capabilities.h | 7 +- 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 | 149 +++++++---- 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 | 39 +++ .../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, 752 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> --- docs/formatdomain.html.in | 12 ++++++++++++ docs/schemas/domaincommon.rng | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c01f564..1dac880 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2018,6 +2018,18 @@ 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. + A CCW bus address can be specified using the additional + attribute: <code>devno</code> consisting of three dot-seperated + numbers composed of 2, 1 and 4 hex digits, e.g., 'fe.0.1234'. + Since the current implemention of QEMU only supports virtio + devices for s390 and this class of devices is restricted to + channel subsystem number 'fe' by the s390 architecture, a valid + devno lies in the range from 'fe.0.0000' to 'fe.3.ffff'. + <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..744ab23 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,13 @@ </attribute> </optional> </define> + <define name="ccwaddress"> + <optional> + <attribute name="devno"> + <ref name="ccwDevno"/> + </attribute> + </optional> + </define> <define name="driveaddress"> <optional> <attribute name="controller"> @@ -3469,6 +3479,12 @@ </attribute> <ref name="spaprvioaddress"/> </group> + <group> + <attribute name="type"> + <value>ccw</value> + </attribute> + <ref name="ccwaddress"/> + </group> </choice> </element> </define> @@ -3856,4 +3872,9 @@ </element> <empty/> </define> + <define name="ccwDevno"> + <data type="string"> + <param name="pattern">[0-9a-fA-F]{1,2}\.[0-3]\.[0-9a-fA-F]{4}</param> + </data> + </define> </grammar> -- 1.7.9.5

On Thu, Jan 31, 2013 at 02:46:26PM +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> --- docs/formatdomain.html.in | 12 ++++++++++++ docs/schemas/domaincommon.rng | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c01f564..1dac880 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2018,6 +2018,18 @@ 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. + A CCW bus address can be specified using the additional + attribute: <code>devno</code> consisting of three dot-seperated + numbers composed of 2, 1 and 4 hex digits, e.g., 'fe.0.1234'. + Since the current implemention of QEMU only supports virtio + devices for s390 and this class of devices is restricted to + channel subsystem number 'fe' by the s390 architecture, a valid + devno lies in the range from 'fe.0.0000' to 'fe.3.ffff'. + <span class="since">Since 1.0.3.</span> + </dd>
Can you explaiin the semantics of the different components in this device address ? WIth PCI addresses there are 4 colon-separated numbers a:b:c:d, which we explicitly separate in the XML <address type="pci" domain="a" bus="b" device="c" function="d"/> Unless there's a compelling reason not to, I think CCW address XML ought to be similar, and use decimal notication for each part, rather than hex, or at least require an explicit 0x for hex. eg <address type="ccw" xxxx="254" yyyy="0" zzzz="1234" /> <address type="ccw" xxxx="0xfe" yyyy="0" zzzz="1234" /> 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/07/2013 04:02 PM, Daniel P. Berrange wrote:
Can you explaiin the semantics of the different components in this device address ? WIth PCI addresses there are 4 colon-separated numbers a:b:c:d, which we explicitly separate in the XML
<address type="pci" domain="a" bus="b" device="c" function="d"/>
Unless there's a compelling reason not to, I think CCW address XML ought to be similar, and use decimal notication for each part, rather than hex, or at least require an explicit 0x for hex. eg
<address type="ccw" xxxx="254" yyyy="0" zzzz="1234" /> <address type="ccw" xxxx="0xfe" yyyy="0" zzzz="1234" />
Daniel
Thanks for taking a look. To be true my initial version was following the PCI example with individual attributes. The s390 folks I've talked to didn't like it too much, finding it unwieldy. CCW addresses are much more visible (and relevant) to a Linux admin on s390 than usually PCI addresses on other systems. In fact on that platform they are more ubiquitous than say IPv6 addresses which by power of convention are written in a compact hex notation. -- 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

On Thu, Feb 07, 2013 at 05:16:04PM +0100, Viktor Mihajlovski wrote:
On 02/07/2013 04:02 PM, Daniel P. Berrange wrote:
Can you explaiin the semantics of the different components in this device address ? WIth PCI addresses there are 4 colon-separated numbers a:b:c:d, which we explicitly separate in the XML
<address type="pci" domain="a" bus="b" device="c" function="d"/>
Unless there's a compelling reason not to, I think CCW address XML ought to be similar, and use decimal notication for each part, rather than hex, or at least require an explicit 0x for hex. eg
<address type="ccw" xxxx="254" yyyy="0" zzzz="1234" /> <address type="ccw" xxxx="0xfe" yyyy="0" zzzz="1234" />
Daniel
Thanks for taking a look. To be true my initial version was following the PCI example with individual attributes. The s390 folks I've talked to didn't like it too much, finding it unwieldy.
I can understand that, but the livirt XML configuration schemas aren't intended to be user friendly - if they were, we wouldn't have used XML at all :-P The XML is all about getting a clear, canonical representation of data. Fully normalizing data by splitting up compound strings into separate attributes is an important part of good practice for XML design. By using separate attrbiutes, it allows applications to directly extract individual pieces of information, without having to then write further parsers to decode them. So using separate attributes for each part of the CCW address is the right thing from libvirt XML POV. Applications built on top of libvirt though, should be free to present them in the encoded format "x.y.z" if they think it is more user friendly.
CCW addresses are much more visible (and relevant) to a Linux admin on s390 than usually PCI addresses on other systems. In fact on that platform they are more ubiquitous than say IPv6 addresses which by power of convention are written in a compact hex notation.
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> --- src/conf/domain_conf.c | 80 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 16 ++++++++++ src/libvirt_private.syms | 1 + 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index abf2b6b..47f2cce 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -176,7 +176,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", @@ -1993,6 +1994,13 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, virHashRemoveEntry(doms->objs, uuidstr); } +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) @@ -2007,6 +2015,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; } @@ -2088,6 +2102,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) @@ -2200,6 +2227,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); @@ -2301,6 +2333,13 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virBufferAsprintf(buf, " reg='0x%llx'", info->addr.spaprvio.reg); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + virBufferAsprintf(buf, " devno='%x.%x.%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); @@ -2411,6 +2450,37 @@ cleanup: } static int +virDomainDeviceCCWAddressParseXML(xmlNodePtr node, + virDomainDeviceCCWAddressPtr addr) +{ + int ret = -1; + int num = 0; + char *devno; + char garbage; + + memset(addr, 0, sizeof(*addr)); + + devno = virXMLPropString(node, "devno"); + if (devno) + num = sscanf(devno, "%2x.%1x.%4x%c", &addr->cssid, &addr->ssid, + &addr->schid, &garbage); + + if (num != 3 || !virDomainDeviceCCWAddressIsValid(addr)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid specification for virtio ccw" + " address: %s"), devno ? devno : ""); + goto cleanup; + } + + addr->assigned = true; + ret = 0; + +cleanup: + VIR_FREE(devno); + return ret; +} + +static int virDomainDeviceCcidAddressParseXML(xmlNodePtr node, virDomainDeviceCcidAddressPtr addr) { @@ -2703,6 +2773,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, @@ -4554,6 +4630,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", @@ -5151,6 +5228,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 9a9e0b1..de0e134 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -191,6 +191,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 }; @@ -220,6 +221,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 { @@ -270,6 +284,7 @@ struct _virDomainDeviceInfo { virDomainDeviceCcidAddress ccid; virDomainDeviceUSBAddress usb; virDomainDeviceSpaprVioAddress spaprvio; + virDomainDeviceCCWAddress ccw; } addr; int mastertype; union { @@ -1958,6 +1973,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 c589236..0ce2341 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 Thu, Jan 31, 2013 at 02:46:27PM +0100, Viktor Mihajlovski wrote:
static int +virDomainDeviceCCWAddressParseXML(xmlNodePtr node, + virDomainDeviceCCWAddressPtr addr) +{ + int ret = -1; + int num = 0; + char *devno; + char garbage; + + memset(addr, 0, sizeof(*addr)); + + devno = virXMLPropString(node, "devno"); + if (devno) + num = sscanf(devno, "%2x.%1x.%4x%c", &addr->cssid, &addr->ssid, + &addr->schid, &garbage);
Ok, this confirms what I said in the previous patch. If you ever find yourself doing 'scanf' on an attribute from an XML document, that is an indication that you should have had multiple attributes in the first place. We should use <adddress type="ccw" cssid="XXX" ssid="YYY" schid="ZZZ"/> 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 :|

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> --- src/qemu/qemu_capabilities.c | 47 ++++++-- src/qemu/qemu_capabilities.h | 7 +- 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(+), 32 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 29693c3..a6da7bc 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -203,6 +203,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "usb-serial", /* 125 */ "usb-net", + "virtio-ccw", ); @@ -682,7 +683,7 @@ qemuCapsInitGuest(virCapsPtr caps, /* Ignore binary if extracting version info fails */ if (binary) { - if (!(qemubinCaps = qemuCapsCacheLookup(cache, binary))) { + if (!(qemubinCaps = qemuCapsCacheLookup(cache, binary, NULL))) { virResetLastError(); VIR_FREE(binary); } @@ -705,7 +706,7 @@ qemuCapsInitGuest(virCapsPtr caps, if (!kvmbin) continue; - if (!(kvmbinCaps = qemuCapsCacheLookup(cache, kvmbin))) { + if (!(kvmbinCaps = qemuCapsCacheLookup(cache, kvmbin, NULL))) { virResetLastError(); VIR_FREE(kvmbin); continue; @@ -1337,6 +1338,7 @@ struct qemuCapsStringFlags qemuCapsObjectTypes[] = { { "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 }, @@ -1354,7 +1356,6 @@ struct qemuCapsStringFlags qemuCapsObjectTypes[] = { { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, }; - static struct qemuCapsStringFlags qemuCapsObjectPropsVirtioBlk[] = { { "multifunction", QEMU_CAPS_PCI_MULTIFUNCTION }, { "bootindex", QEMU_CAPS_BOOTINDEX }, @@ -1409,6 +1410,10 @@ static struct qemuCapsObjectTypeProps qemuCapsObjectProps[] = { ARRAY_CARDINALITY(qemuCapsObjectPropsVirtioBlk) }, { "virtio-net-pci", qemuCapsObjectPropsVirtioNet, ARRAY_CARDINALITY(qemuCapsObjectPropsVirtioNet) }, + { "virtio-blk-ccw", qemuCapsObjectPropsVirtioBlk, + ARRAY_CARDINALITY(qemuCapsObjectPropsVirtioBlk) }, + { "virtio-net-ccw", qemuCapsObjectPropsVirtioNet, + ARRAY_CARDINALITY(qemuCapsObjectPropsVirtioNet) }, { "virtio-blk-s390", qemuCapsObjectPropsVirtioBlk, ARRAY_CARDINALITY(qemuCapsObjectPropsVirtioBlk) }, { "virtio-net-s390", qemuCapsObjectPropsVirtioNet, @@ -1660,7 +1665,7 @@ int qemuCapsGetDefaultVersion(virCapsPtr caps, return -1; } - if (!(qemucaps = qemuCapsCacheLookup(capsCache, binary))) + if (!(qemucaps = qemuCapsCacheLookup(capsCache, binary, NULL))) return -1; *version = qemuCapsGetVersion(qemucaps); @@ -2592,16 +2597,24 @@ error: qemuCapsPtr -qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary) +qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary, + const char *machine) { qemuCapsPtr 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 && !qemuCapsIsValid(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) { @@ -2612,7 +2625,17 @@ qemuCapsCacheLookup(qemuCapsCachePtr 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)) { + qemuCapsClear(ret, QEMU_CAPS_VIRTIO_S390); + } else if (STREQLEN(machine,"s390",4)) { + qemuCapsClear(ret, QEMU_CAPS_VIRTIO_CCW); + } + } + + if (virHashAddEntry(cache->binaries, cachekey, ret) < 0) { virObjectUnref(ret); ret = NULL; } @@ -2621,14 +2644,18 @@ qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary) VIR_DEBUG("Returning caps %p for %s", ret, binary); virObjectRef(ret); virMutexUnlock(&cache->lock); + +error: + VIR_FREE(cachekey); return ret; } qemuCapsPtr -qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary) +qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary, + const char *machine) { - qemuCapsPtr caps = qemuCapsCacheLookup(cache, binary); + qemuCapsPtr caps = qemuCapsCacheLookup(cache, binary, machine); qemuCapsPtr ret; if (!caps) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 5279d07..938094c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -165,6 +165,7 @@ enum qemuCapsFlags { QEMU_CAPS_SCLP_S390 = 124, /* -device sclp* */ QEMU_CAPS_DEVICE_USB_SERIAL = 125, /* -device usb-serial */ QEMU_CAPS_DEVICE_USB_NET = 126, /* -device usb-net */ + QEMU_CAPS_VIRTIO_CCW = 127, /* -device virtio-*-ccw */ QEMU_CAPS_LAST, /* this must always be the last item */ }; @@ -220,8 +221,10 @@ bool qemuCapsIsValid(qemuCapsPtr caps); qemuCapsCachePtr qemuCapsCacheNew(const char *libDir, uid_t uid, gid_t gid); -qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary); -qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary); +qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary, + const char *machine); +qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary, + const char *machine); void qemuCapsCacheFree(qemuCapsCachePtr cache); virCapsPtr qemuCapsInit(qemuCapsCachePtr cache); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f6273c1..40d5601 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -790,6 +790,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) @@ -832,13 +926,137 @@ qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def, def->memballoon->info.type = type; } -static void -qemuDomainAssignS390Addresses(virDomainDefPtr def, qemuCapsPtr caps) +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 (qemuCapsGet(caps, 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, + qemuCapsPtr caps, + virDomainObjPtr obj) +{ + int ret = -1; + qemuDomainCCWAddressSetPtr addrs = NULL; + qemuDomainObjPrivatePtr priv = NULL; + + if (qemuCapsGet(caps, 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 (qemuCapsGet(caps, 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 @@ -1098,7 +1316,9 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, if (rc) return rc; - qemuDomainAssignS390Addresses(def, caps); + rc = qemuDomainAssignS390Addresses(def, caps, obj); + if (rc) + return rc; return qemuDomainAssignPCIAddresses(def, caps, obj); } @@ -1317,7 +1537,6 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs) VIR_FREE(addrs); } - static int qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs) { int i; @@ -1663,7 +1882,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) { @@ -1809,6 +2030,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; @@ -2816,8 +3043,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"); @@ -3099,6 +3328,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 { @@ -3196,8 +3428,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"; @@ -3420,7 +3654,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, caps) < 0) goto error; @@ -4112,6 +4356,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 e15830a..34bc78b 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -215,6 +215,12 @@ int qemuAssignDevicePCISlots(virDomainDefPtr def, qemuCapsPtr caps, qemuDomainPCIAddressSetPtr addrs); +int qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs, + virDomainDeviceInfoPtr dev); +int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, qemuDomainCCWAddressSetPtr addrs, + bool autoassign); +void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs); + int qemuAssignDeviceAliases(virDomainDefPtr def, qemuCapsPtr caps); 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 1ae75e9..cf7772a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -234,6 +234,7 @@ static void qemuDomainObjPrivateFree(void *data) virObjectUnref(priv->caps); 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 68cf295..0160e9c 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; qemuCapsPtr caps; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 812bf95..5bc62a2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1662,7 +1662,9 @@ static virDomainPtr qemuDomainCreate(virConnectPtr conn, const char *xml, if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) goto cleanup; - if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator))) + if (!(caps = qemuCapsCacheLookup(driver->capsCache, + def->emulator, + def->os.machine))) goto cleanup; if (qemuCanonicalizeMachine(def, caps) < 0) @@ -5352,7 +5354,9 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, if (!def) goto cleanup; - if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator))) + if (!(caps = qemuCapsCacheLookup(driver->capsCache, + def->emulator, + def->os.machine))) goto cleanup; /* Since we're just exporting args, we can't do bridge/network/direct @@ -5628,7 +5632,9 @@ static virDomainPtr qemuDomainDefine(virConnectPtr conn, const char *xml) { if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0) goto cleanup; - if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator))) + if (!(caps = qemuCapsCacheLookup(driver->capsCache, + def->emulator, + def->os.machine))) goto cleanup; if (qemuCanonicalizeMachine(def, caps) < 0) @@ -6497,7 +6503,9 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, if (priv->caps) caps = virObjectRef(priv->caps); - else if (!(caps = qemuCapsCacheLookup(driver->capsCache, vm->def->emulator))) + else if (!(caps = qemuCapsCacheLookup(driver->capsCache, + vm->def->emulator, + vm->def->os.machine))) goto cleanup; if (flags & VIR_DOMAIN_AFFECT_CONFIG) { @@ -12574,7 +12582,9 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn, goto cleanup; } - if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator))) + if (!(caps = qemuCapsCacheLookup(driver->capsCache, + def->emulator, + def->os.machine))) goto cleanup; if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a2ce007..84c3933 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3206,7 +3206,8 @@ qemuProcessReconnect(void *opaque) */ if (!priv->caps && !(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache, - obj->def->emulator))) + obj->def->emulator, + obj->def->os.machine))) goto error; /* In case the domain shutdown while we were not running, @@ -3696,7 +3697,8 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG("Determining emulator version"); virObjectUnref(priv->caps); if (!(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache, - vm->def->emulator))) + vm->def->emulator, + vm->def->os.machine))) goto cleanup; if (qemuAssignDeviceAliases(vm->def, priv->caps) < 0) @@ -4264,6 +4266,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); @@ -4445,7 +4450,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, VIR_DEBUG("Determining emulator version"); virObjectUnref(priv->caps); if (!(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache, - vm->def->emulator))) + vm->def->emulator, + vm->def->os.machine))) goto cleanup; VIR_DEBUG("Preparing monitor state"); -- 1.7.9.5

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> --- src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_hotplug.c | 149 ++++++++++++++++++++++++++++++++--------------- src/qemu/qemu_hotplug.h | 14 ++--- 3 files changed, 111 insertions(+), 58 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5bc62a2..369f05f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5867,7 +5867,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 { @@ -6000,7 +6000,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); @@ -6011,7 +6011,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 18c4109..ad2ba8e 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -223,19 +223,26 @@ 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; + int i, ret = -1; const char* type = virDomainDiskBusTypeToString(disk->bus); qemuDomainObjPrivatePtr priv = vm->privateData; char *devstr = NULL; char *drivestr = NULL; bool releaseaddr = false; + if (!disk->info.type) { + if (qemuCapsGet(priv->caps, QEMU_CAPS_VIRTIO_CCW)) + disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + else if (qemuCapsGet(priv->caps, 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, @@ -256,8 +263,14 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, } if (qemuCapsGet(priv->caps, 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->caps) < 0) goto error; @@ -292,16 +305,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 @@ error: VIR_FREE(devstr); VIR_FREE(drivestr); - if (qemuCapsGet(priv->caps, 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 (qemuCapsGet(priv->caps, 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, @@ -763,9 +777,17 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, goto cleanup; } - if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) && - qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) - goto cleanup; + if (qemuCapsGet(priv->caps, 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 (qemuCapsGet(priv->caps, QEMU_CAPS_VIRTIO_S390)) + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-s390 net device cannot be hotplugged.")); + else if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) && + qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) + goto cleanup; releaseaddr = true; @@ -894,11 +916,17 @@ cleanup: vm->def->nets[vm->def->nnets++] = net; } else { if (qemuCapsGet(priv->caps, 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 (qemuCapsGet(priv->caps, 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); @@ -1998,9 +2026,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; @@ -2034,11 +2062,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 (qemuCapsGet(priv->caps, 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 @@ -2072,9 +2109,14 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver, virDomainAuditDisk(vm, detach->src, NULL, "detach", true); - if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) && - qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, - detach->info.addr.pci.slot) < 0) + if (detach->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && + qemuCapsGet(priv->caps, 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 && + qemuCapsGet(priv->caps, 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); @@ -2569,19 +2611,27 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, -1); goto cleanup; } + if (qemuCapsGet(priv->caps, 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) { @@ -2629,7 +2679,10 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, virDomainAuditNet(vm, detach, NULL, "detach", true); - if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) && + if (qemuCapsGet(priv->caps, QEMU_CAPS_VIRTIO_CCW)) { + if (qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, &detach->info) < 0) + VIR_WARN("Unable to release CCW address on NIC"); + } else if (qemuCapsGet(priv->caps, 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> --- .../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 | 39 ++++++++++++++++++++ .../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, 179 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..4dfbe18 --- /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' devno='fe.0.000a'/> + </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..f901ccd --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-virtio-ccw-many.xml @@ -0,0 +1,39 @@ +<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' devno='0.0.0007'/> + </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' devno='fe.2.f00f'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest4'/> + <target dev='hdb' bus='virtio'/> + </disk> + <memballoon model='virtio'> + <address type='ccw' devno='fe.0.000a'/> + </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..e87cca7 --- /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' devno='0.0.0007'/> + </disk> + <memballoon model='virtio'> + <address type='ccw' devno='fe.0.000a'/> + </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..24b837b --- /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' devno='fe.0.0000'/> + </interface> + <memballoon model='virtio'> + <address type='ccw' devno='fe.0.000a'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 88e1c36..8eac709 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -423,6 +423,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); @@ -611,6 +615,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); @@ -670,7 +676,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 573927d..ca52776 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 (2)
-
Daniel P. Berrange
-
Viktor Mihajlovski