[libvirt] [PATCH 0/4]use newer video device by -device in qemu commandline

This patch set aims to use qemu VGA device with -device option to replace -vga option. The mapping is as follows. '-device VGA' maps to '-vga std' '-device cirrus-vga' maps to '-vga cirrus' '-device qxl-vga' maps to '-vga qxl' (there is also '-device qxl' for secondary devices) '-device vmware-svga' maps to '-vga vmware' Through this change, guests will be able to use any available PCI slot number rather than fixed 0x2 slot for primary video device. For backwards compatibility, if a certain qemu version does not support one of the above video device arguments to -device or even -device itself, the -vga will still be used. Guannan Ren(4) [PATCH 1/4] qemu: add qemu various VGA devices Caps flag [PATCH 2/4] conf: add optional attribte primary to video <model> [PATCH 3/4] qemu: use newer -device video device in qemu commandline [PATCH 4/4] doc: add attribute primary doc to video model element docs/formatdomain.html.in | 6 +- src/conf/domain_conf.c | 27 +++- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 10 +- src/qemu/qemu_capabilities.h | 4 + src/qemu/qemu_command.c | 183 +++++++++++++++++++--------- tests/qemuhelptest.c | 48 ++++++-- .../qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.args | 5 +- tests/qemuxml2argvtest.c | 12 +- 9 files changed, 220 insertions(+), 76 deletions(-)

QEMU_CAPS_DEVICE_QXL -device qxl QEMU_CAPS_DEVICE_VGA -device VGA QEMU_CAPS_DEVICE_CIRRUS_VGA -device cirrus-vga QEMU_CAPS_DEVICE_VMWARE_SVGA -device vmware-svga Fix a typo in qemuCapsObjectTypes, the string 'qxl' here should be -device qxl rather than -vga [...|qxl|..] --- src/qemu/qemu_capabilities.c | 10 ++++++++- src/qemu/qemu_capabilities.h | 4 ++++ tests/qemuhelptest.c | 48 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 01a1b98..97bc968 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -194,6 +194,11 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "usb-redir.bootindex", "usb-host.bootindex", "blockdev-snapshot-sync", + "qxl", + + "VGA", /* 200 */ + "cirrus-vga", + "vmware-svga", ); struct _qemuCaps { @@ -1322,11 +1327,14 @@ struct qemuCapsStringFlags qemuCapsObjectTypes[] = { { "virtio-scsi-pci", QEMU_CAPS_VIRTIO_SCSI_PCI }, { "spicevmc", QEMU_CAPS_DEVICE_SPICEVMC }, { "qxl-vga", QEMU_CAPS_DEVICE_QXL_VGA }, - { "qxl", QEMU_CAPS_VGA_QXL }, + { "qxl", QEMU_CAPS_DEVICE_QXL }, { "sga", QEMU_CAPS_SGA }, { "scsi-block", QEMU_CAPS_SCSI_BLOCK }, { "scsi-cd", QEMU_CAPS_SCSI_CD }, { "ide-cd", QEMU_CAPS_IDE_CD }, + { "VGA", QEMU_CAPS_DEVICE_VGA }, + { "cirrus-vga", QEMU_CAPS_DEVICE_CIRRUS_VGA }, + { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 3da8672..28604ce 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -156,6 +156,10 @@ enum qemuCapsFlags { QEMU_CAPS_USB_REDIR_BOOTINDEX = 116, /* usb-redir.bootindex */ QEMU_CAPS_USB_HOST_BOOTINDEX = 117, /* usb-host.bootindex */ QEMU_CAPS_DISK_SNAPSHOT = 118, /* blockdev-snapshot-sync command */ + QEMU_CAPS_DEVICE_QXL = 119, /* -device qxl */ + QEMU_CAPS_DEVICE_VGA = 120, /* -device VGA */ + QEMU_CAPS_DEVICE_CIRRUS_VGA = 121, /* -device cirrus-vga */ + QEMU_CAPS_DEVICE_VMWARE_SVGA = 122, /* -device vmware-svga */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 021b3dc..2280f2d 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -391,7 +391,11 @@ mymain(void) QEMU_CAPS_NO_ACPI, QEMU_CAPS_VIRTIO_BLK_SG_IO, QEMU_CAPS_CPU_HOST, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -477,7 +481,6 @@ mymain(void) QEMU_CAPS_NESTING, QEMU_CAPS_NAME_PROCESS, QEMU_CAPS_SMBIOS_TYPE, - QEMU_CAPS_VGA_QXL, QEMU_CAPS_SPICE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, @@ -495,7 +498,11 @@ mymain(void) QEMU_CAPS_VIRTIO_BLK_SG_IO, QEMU_CAPS_CPU_HOST, QEMU_CAPS_SCSI_LSI, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -554,7 +561,11 @@ mymain(void) QEMU_CAPS_VIRTIO_BLK_SG_IO, QEMU_CAPS_CPU_HOST, QEMU_CAPS_BLOCKIO, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-kvm-0.12.1.2-rhel62-beta", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -623,7 +634,10 @@ mymain(void) QEMU_CAPS_CPU_HOST, QEMU_CAPS_SCSI_CD, QEMU_CAPS_BLOCKIO, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA); DO_TEST("qemu-1.0", 1000000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -697,7 +711,11 @@ mymain(void) QEMU_CAPS_IDE_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_BLOCKIO, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-1.1.0", 1001000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -779,7 +797,11 @@ mymain(void) QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_BLOCKIO, - QEMU_CAPS_VNC); + QEMU_CAPS_VNC, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-1.2.0", 1002000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -871,7 +893,11 @@ mymain(void) QEMU_CAPS_DUMP_GUEST_CORE, QEMU_CAPS_VNC, QEMU_CAPS_USB_REDIR_BOOTINDEX, - QEMU_CAPS_USB_HOST_BOOTINDEX); + QEMU_CAPS_USB_HOST_BOOTINDEX, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); DO_TEST("qemu-kvm-1.2.0", 1002000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -968,7 +994,11 @@ mymain(void) QEMU_CAPS_DUMP_GUEST_CORE, QEMU_CAPS_VNC, QEMU_CAPS_USB_REDIR_BOOTINDEX, - QEMU_CAPS_USB_HOST_BOOTINDEX); + QEMU_CAPS_USB_HOST_BOOTINDEX, + QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VGA, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DEVICE_VMWARE_SVGA); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.7.11.2

If there are multiple video devices primary = 'yes' marks this video device as the primary one. The rest are secondary video devices. No more than one could be mark as primary. If none of them has primary attribute, the first one will be the primary by default like what it was. The reason of this changing is that for qemu, only one primary video device is permitted which can be of any type. For secondary video devices, only qxl is allowd. Primary attribute removes the restriction that the first have to be the primary one. We always put the primary video device into the first position of video device structure array after parsing. --- src/conf/domain_conf.c | 27 ++++++++++++++++++++++++++- src/conf/domain_conf.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6aa5f79..53f02ef 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7275,6 +7275,7 @@ virDomainVideoDefParseXML(const xmlNodePtr node, char *type = NULL; char *heads = NULL; char *vram = NULL; + char *primary = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -7289,6 +7290,11 @@ virDomainVideoDefParseXML(const xmlNodePtr node, type = virXMLPropString(cur, "type"); vram = virXMLPropString(cur, "vram"); heads = virXMLPropString(cur, "heads"); + + if ((primary = virXMLPropString(cur, "primary"))!= NULL) + if (STREQ(primary, "yes")) + def->primary = 1; + def->accel = virDomainVideoAccelDefParseXML(cur); } } @@ -8669,6 +8675,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, xmlNodePtr cur; bool usb_none = false; bool usb_other = false; + bool primaryVideo = false; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -9955,12 +9962,28 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } if (n && VIR_ALLOC_N(def->videos, n) < 0) goto no_memory; - for (i = 0 ; i < n ; i++) { + for (i = 0; i < n; i++) { virDomainVideoDefPtr video = virDomainVideoDefParseXML(nodes[i], def, flags); if (!video) goto error; + + if (!primaryVideo && video->primary) { + if (def->nvideos != 0) + memmove(def->videos + 1, + def->videos, + (sizeof(def->videos[0]) * def->nvideos)); + + def->videos[0] = video; + def->nvideos++; + primaryVideo = true; + continue; + } else if (primaryVideo && video->primary) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only one primary video device is supported")); + goto error; + } def->videos[def->nvideos++] = video; } VIR_FREE(nodes); @@ -13109,6 +13132,8 @@ virDomainVideoDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " vram='%u'", def->vram); if (def->heads) virBufferAsprintf(buf, " heads='%u'", def->heads); + if (def->primary) + virBufferAddLit(buf, " primary='yes'"); if (def->accel) { virBufferAddLit(buf, ">\n"); virDomainVideoAccelDefFormat(buf, def->accel); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7ad5377..bf6b532 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1120,6 +1120,7 @@ struct _virDomainVideoDef { int type; unsigned int vram; unsigned int heads; + unsigned int primary : 1; virDomainVideoAccelDefPtr accel; virDomainDeviceInfo info; }; -- 1.7.11.2

'-device VGA' maps to '-vga std' '-device cirrus-vga' maps to '-vga cirrus' '-device qxl-vga' maps to '-vga qxl' (there is also '-device qxl' for secondary devices) '-device vmware-svga' maps to '-vga vmware' For the primary video device, we try to use 0x2 slot for matching old qemu. If the 0x2 slot is allocated already, the addr property of new video device could help for using any available slot. If there is no -device option for old qemu, we keep using -vga for primary device. If particular one of above four VGA devices doesn't exist, we switch to use -vga to generate video commandline. In this case, the 0:0:2.0 address must not be used by previous PCI device. For primary video device of xen type, there is no corresponding arg to -device, we still leave the handling to -vga. --- src/qemu/qemu_command.c | 183 ++++++++++++++------- .../qemuxml2argv-graphics-spice-qxl-vga.args | 5 +- tests/qemuxml2argvtest.c | 12 +- 3 files changed, 136 insertions(+), 64 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5335dcf..4fd2f83 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -93,6 +93,16 @@ VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, "", /* don't support vbox */ "qxl"); +VIR_ENUM_DECL(qemuDeviceVideo) + +VIR_ENUM_IMPL(qemuDeviceVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, + "VGA", + "cirrus-vga", + "vmware-svga", + "", /* no device for xen */ + "", /* don't support vbox */ + "qxl-vga"); + VIR_ENUM_DECL(qemuSoundCodec) VIR_ENUM_IMPL(qemuSoundCodec, VIR_DOMAIN_SOUND_CODEC_TYPE_LAST, @@ -1487,27 +1497,23 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) goto error; } - /* First VGA is hardcoded slot=2 */ - if (def->nvideos > 0) { - if (def->videos[0]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (def->videos[0]->info.addr.pci.domain != 0 || - def->videos[0]->info.addr.pci.bus != 0 || - def->videos[0]->info.addr.pci.slot != 2 || - def->videos[0]->info.addr.pci.function != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Primary video card must have PCI address 0:0:2.0")); - goto error; - } - /* If TYPE==PCI, then qemuCollectPCIAddress() function - * has already reserved the address, so we must skip */ - } else { - def->videos[0]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; - def->videos[0]->info.addr.pci.domain = 0; - def->videos[0]->info.addr.pci.bus = 0; - def->videos[0]->info.addr.pci.slot = 2; - def->videos[0]->info.addr.pci.function = 0; - if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0) + /* slot 2 is perferable to match the ordering of old qemu(< 0.12), + * but with qemu -device option, we could use next available slot number. + */ + if (def->nvideos > 0 && + def->videos[0]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + def->videos[0]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + def->videos[0]->info.addr.pci.domain = 0; + def->videos[0]->info.addr.pci.bus = 0; + def->videos[0]->info.addr.pci.slot = 2; + def->videos[0]->info.addr.pci.function = 0; + + if (qemuDomainPCIAddressCheckSlot(addrs, &def->videos[0]->info) < 0) { + virResetLastError(); + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[0]->info) < 0) goto error; + } else if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0) { + goto error; } } else { virDomainDeviceInfo dev; @@ -1516,8 +1522,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) if (qemuDomainPCIAddressCheckSlot(addrs, &dev) < 0) { VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video" - " device will not be possible without manual" - " intervention"); + " device might need manual intervention"); virResetLastError(); } else if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0) { goto error; @@ -1682,8 +1687,13 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) goto error; } - /* Further non-primary video cards */ + /* Further non-primary video cards which have to be qxl type */ for (i = 1; i < def->nvideos ; i++) { + if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("non-primary video device must be type of 'qxl'")); + goto error; + } if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) continue; if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info) < 0) @@ -3501,16 +3511,35 @@ error: } static char * -qemuBuildVideoDevStr(virDomainVideoDefPtr video, - qemuCapsPtr caps) +qemuBuildDeviceVideoStr(virDomainVideoDefPtr video, + qemuCapsPtr caps, + bool primary) { virBuffer buf = VIR_BUFFER_INITIALIZER; - const char *model = qemuVideoTypeToString(video->type); + const char *model; - if (!model) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("invalid video model")); - goto error; + if (primary) { + model = qemuDeviceVideoTypeToString(video->type); + if (!model || STREQ(model, "")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("video type %s is not supported with QEMU"), + virDomainVideoTypeToString(video->type)); + goto error; + } + } else { + if (video->type != VIR_DOMAIN_VIDEO_TYPE_QXL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("non-primary video device must be type of 'qxl'")); + goto error; + } + + if (!qemuCapsGet(caps, QEMU_CAPS_DEVICE_QXL)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("only one video card is currently supported")); + goto error; + } + + model = "qxl"; } virBufferAsprintf(&buf, "%s,id=%s", model, video->info.alias); @@ -6427,22 +6456,54 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } if (def->nvideos > 0) { - if (qemuCapsGet(caps, QEMU_CAPS_VGA)) { - if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_XEN) { + int primaryVideoType = def->videos[0]->type; + + if ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VGA && + qemuCapsGet(caps, QEMU_CAPS_DEVICE_VGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_CIRRUS && + qemuCapsGet(caps, QEMU_CAPS_DEVICE_CIRRUS_VGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VMVGA && + qemuCapsGet(caps, QEMU_CAPS_DEVICE_VMWARE_SVGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL && + qemuCapsGet(caps, QEMU_CAPS_DEVICE_QXL_VGA)) + ) { + for (i = 0 ; i < def->nvideos ; i++) { + char *str; + virCommandAddArg(cmd, "-device"); + if (!(str = qemuBuildDeviceVideoStr(def->videos[i], caps, !i))) + goto error; + + virCommandAddArg(cmd, str); + VIR_FREE(str); + } + } else if (qemuCapsGet(caps, QEMU_CAPS_VGA)) { + if (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_XEN) { /* nothing - vga has no effect on Xen pvfb */ } else { - if ((def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_QXL) && + if ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL) && !qemuCapsGet(caps, QEMU_CAPS_VGA_QXL)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("This QEMU does not support QXL graphics adapters")); goto error; } - const char *vgastr = qemuVideoTypeToString(def->videos[0]->type); + if (qemuCapsGet(caps, QEMU_CAPS_DEVICE)) { + if (def->videos[0]->info.addr.pci.domain != 0 || + def->videos[0]->info.addr.pci.bus != 0 || + def->videos[0]->info.addr.pci.slot != 2 || + def->videos[0]->info.addr.pci.function != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Primary video card must have " + " PCI address 0:0:2.0 for this QEMU")); + goto error; + } + } + + const char *vgastr = qemuVideoTypeToString(primaryVideoType); if (!vgastr || STREQ(vgastr, "")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("video type %s is not supported with QEMU"), - virDomainVideoTypeToString(def->videos[0]->type)); + virDomainVideoTypeToString(primaryVideoType)); goto error; } @@ -6469,9 +6530,35 @@ qemuBuildCommandLine(virConnectPtr conn, } } } - } else { - switch (def->videos[0]->type) { + /* code for -vga "primary VGA" with -device "non-primary VGA" */ + if (def->nvideos > 1) { + if (qemuCapsGet(caps, QEMU_CAPS_DEVICE)) { + for (i = 1 ; i < def->nvideos ; i++) { + char *str; + if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("non-primary video device " + "must be type of 'qxl'")); + goto error; + } + + virCommandAddArg(cmd, "-device"); + + if (!(str = qemuBuildDeviceVideoStr(def->videos[i], caps, false))) + goto error; + + virCommandAddArg(cmd, str); + VIR_FREE(str); + } + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("only one video card is currently supported")); + goto error; + } + } + } else { + switch (primaryVideoType) { case VIR_DOMAIN_VIDEO_TYPE_VGA: virCommandAddArg(cmd, "-std-vga"); break; @@ -6491,28 +6578,8 @@ qemuBuildCommandLine(virConnectPtr conn, virDomainVideoTypeToString(def->videos[0]->type)); goto error; } - } - - if (def->nvideos > 1) { - if (qemuCapsGet(caps, QEMU_CAPS_DEVICE)) { - for (i = 1 ; i < def->nvideos ; i++) { - char *str; - if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("video type %s is only valid as primary video card"), - virDomainVideoTypeToString(def->videos[0]->type)); - goto error; - } - virCommandAddArg(cmd, "-device"); - - if (!(str = qemuBuildVideoDevStr(def->videos[i], caps))) - goto error; - - virCommandAddArg(cmd, str); - VIR_FREE(str); - } - } else { + if (def->nvideos > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only one video card is currently supported")); goto error; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.args index 3954c03..9d4b833 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.args @@ -2,6 +2,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \ /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb -hda \ /dev/HostVG/QEMUGuest1 -spice port=5903,tls-port=5904,addr=127.0.0.1,\ -x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs -vga \ -qxl -global qxl-vga.vram_size=33554432 -device qxl,id=video1,vram_size=67108864,bus=pci.0,addr=0x4 \ +x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs \ +-device qxl-vga,id=video0,vram_size=33554432,bus=pci.0,addr=0x2 \ +-device qxl,id=video1,vram_size=67108864,bus=pci.0,addr=0x4 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index bb233ed..1d33e91 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -574,15 +574,18 @@ mymain(void) QEMU_CAPS_VGA, QEMU_CAPS_VGA_NONE); DO_TEST("graphics-spice", QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, - QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE); + QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE, + QEMU_CAPS_DEVICE_QXL); DO_TEST("graphics-spice-agentmouse", QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEVMC, - QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_QXL); DO_TEST("graphics-spice-compression", QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, - QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE); + QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE, + QEMU_CAPS_DEVICE_QXL); DO_TEST("graphics-spice-timeout", QEMU_CAPS_DRIVE, QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, @@ -591,7 +594,8 @@ mymain(void) DO_TEST("graphics-spice-qxl-vga", QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE, QEMU_CAPS_SPICE, - QEMU_CAPS_DEVICE_QXL_VGA); + QEMU_CAPS_DEVICE_QXL_VGA, + QEMU_CAPS_DEVICE_QXL); DO_TEST("graphics-spice-usb-redir", QEMU_CAPS_VGA, QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, -- 1.7.11.2

--- docs/formatdomain.html.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c81af8a..3d1fdf4 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3485,7 +3485,11 @@ qemu-kvm -net nic,model=? /dev/null will add a default <code>video</code> according to the guest type. For a guest of type "kvm", the default <code>video</code> for it is: <code>type</code> with value "cirrus", <code>vram</code> with value - "9216", and <code>heads</code> with value "1". + "9216", and <code>heads</code> with value "1". By default, the first + video device in domain xml is the primary one, but the optional + attribute <code>primary</code> with value 'yes' can be used to mark the + primary in cases of mutiple video device. The non-primary must be + type of "qxl". </dd> <dt><code>model</code></dt> -- 1.7.11.2

Hi,
For backwards compatibility, if a certain qemu version does not support one of the above video device arguments to -device or even -device itself, the -vga will still be used.
That will not work. You must check the qemu version. 1.2+ is safe, IIRC 1.1 will work too. Technical background: '-device VGA' (+variants) exists for a looooooong time, pretty much day one of the -device switch. Actually using it did not work though due to a nasty initialization order issue in qemu. The qemu memory api created by avi fixed it. cheers, Gerd

On 12/10/2012 05:37 PM, Gerd Hoffmann wrote:
Hi,
For backwards compatibility, if a certain qemu version does not support one of the above video device arguments to -device or even -device itself, the -vga will still be used. That will not work. You must check the qemu version. 1.2+ is safe, IIRC 1.1 will work too.
Technical background: '-device VGA' (+variants) exists for a looooooong time, pretty much day one of the -device switch. Actually using it did not work though due to a nasty initialization order issue in qemu. The qemu memory api created by avi fixed it.
cheers, Gerd
Okay, if so, I prefer 1.2+ to ensure -device VGA work as expected. A question here, all of these four vga device (VGA, cirrus-vga, vmware-svga, qxl-vga) has existed and been supported since 1.2 QEMU version, is it right? If so, libvirt doesn't need to check for them individually. Guannan

Okay, if so, I prefer 1.2+ to ensure -device VGA work as expected. A question here, all of these four vga device (VGA, cirrus-vga, vmware-svga, qxl-vga) has existed and been supported since 1.2 QEMU version, is it right?
Yes. qxl + qxl-vga have a compile time dependency on spice though, so they might not be present. I expect there already is a spice support check in libvirt, so I think you don't have to care in this patch series. cheers, Gerd
participants (2)
-
Gerd Hoffmann
-
Guannan Ren