diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index defc3e910f23fb37b6714a85bb3a522e1c8263f4..ba8c2162812e17d033b4a35d4853dc0d6042c27c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3690,7 +3690,7 @@ qemuBuildSoundCodecStr(virDomainSoundDefPtr sound, } static char * -qemuBuildDeviceVideoStr(virDomainDefPtr def, +qemuBuildDeviceVideoStr(const virDomainDef *def, virDomainVideoDefPtr video, virQEMUCapsPtr qemuCaps) { @@ -3803,6 +3803,176 @@ qemuBuildDeviceVideoStr(virDomainDefPtr def, } +static int +qemuBuildVideoCommandLine(virCommandPtr cmd, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + size_t i; + int primaryVideoType = def->videos[0]->type; + + if (!def->nvideos) { + /* If we have -device, then we set -nodefaults already */ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_NONE)) + virCommandAddArgList(cmd, "-vga", "none", NULL); + return 0; + } + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY) && + ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VGA && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_CIRRUS && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_CIRRUS_VGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VMVGA && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMWARE_SVGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_QXL_VGA)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VIRTIO && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_GPU))) + ) { + for (i = 0; i < def->nvideos; i++) { + char *str; + virCommandAddArg(cmd, "-device"); + if (!(str = qemuBuildDeviceVideoStr(def, def->videos[i], + qemuCaps))) + return -1; + + virCommandAddArg(cmd, str); + VIR_FREE(str); + } + } else { + if (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_XEN) { + /* nothing - vga has no effect on Xen pvfb */ + } else { + if ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL) && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_QXL)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU does not support QXL graphics adapters")); + return -1; + } + + const char *vgastr = qemuVideoTypeToString(primaryVideoType); + if (!vgastr || STREQ(vgastr, "")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("video type %s is not supported with QEMU"), + virDomainVideoTypeToString(primaryVideoType)); + return -1; + } + + virCommandAddArgList(cmd, "-vga", vgastr, NULL); + + /* If we cannot use --device option to specify the video device + * in QEMU we will fallback to the old --vga option. To get the + * correct device name for the --vga option the 'qemuVideo' is + * used, but to set some device attributes we need to use the + * --global option and for that we need to specify the device + * name the same as for --device option and for that we need to + * use 'qemuDeviceVideo'. + * + * See 'Graphics Devices' section in docs/qdev-device-use.txt in + * QEMU repository. + */ + const char *dev = qemuDeviceVideoTypeToString(primaryVideoType); + + if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_QXL && + (def->videos[0]->vram || def->videos[0]->ram) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { + unsigned int ram = def->videos[0]->ram; + unsigned int vram = def->videos[0]->vram; + unsigned int vram64 = def->videos[0]->vram64; + unsigned int vgamem = def->videos[0]->vgamem; + + if (vram > (UINT_MAX / 1024)) { + virReportError(VIR_ERR_OVERFLOW, + _("value for 'vram' must be less than '%u'"), + UINT_MAX / 1024); + return -1; + } + if (ram > (UINT_MAX / 1024)) { + virReportError(VIR_ERR_OVERFLOW, + _("value for 'ram' must be less than '%u'"), + UINT_MAX / 1024); + return -1; + } + + if (ram) { + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.ram_size=%u", + dev, ram * 1024); + } + if (vram) { + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.vram_size=%u", + dev, vram * 1024); + } + if (vram64 && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VRAM64)) { + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.vram64_size_mb=%u", + dev, vram64 / 1024); + } + if (vgamem && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) { + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u", + dev, vgamem / 1024); + } + } + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && + def->videos[0]->vram && + ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VGA && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) || + (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VMVGA && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)))) { + unsigned int vram = def->videos[0]->vram; + + if (vram < 1024) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("value for 'vgamem' must be at " + "least 1 MiB (1024 KiB)")); + return -1; + } + + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u", + dev, vram / 1024); + } + } + + if (def->nvideos > 1) { + if (virQEMUCapsGet(qemuCaps, 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)); + return -1; + } + + virCommandAddArg(cmd, "-device"); + + if (!(str = qemuBuildDeviceVideoStr(def, def->videos[i], + qemuCaps))) + return -1; + + virCommandAddArg(cmd, str); + VIR_FREE(str); + } + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only one video card is currently supported")); + return -1; + } + } + } + + return 0; +} + + int qemuOpenPCIConfig(virDomainHostdevDefPtr dev) { @@ -8586,164 +8756,8 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } - if (def->nvideos > 0) { - int primaryVideoType = def->videos[0]->type; - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY) && - ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VGA && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VGA)) || - (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_CIRRUS && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_CIRRUS_VGA)) || - (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VMVGA && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMWARE_SVGA)) || - (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_QXL_VGA)) || - (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VIRTIO && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_GPU))) - ) { - for (i = 0; i < def->nvideos; i++) { - char *str; - virCommandAddArg(cmd, "-device"); - if (!(str = qemuBuildDeviceVideoStr(def, def->videos[i], - qemuCaps))) - goto error; - - virCommandAddArg(cmd, str); - VIR_FREE(str); - } - } else { - if (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_XEN) { - /* nothing - vga has no effect on Xen pvfb */ - } else { - if ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_QXL) && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_QXL)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU does not support QXL graphics adapters")); - 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(primaryVideoType)); - goto error; - } - - virCommandAddArgList(cmd, "-vga", vgastr, NULL); - - /* If we cannot use --device option to specify the video device - * in QEMU we will fallback to the old --vga option. To get the - * correct device name for the --vga option the 'qemuVideo' is - * used, but to set some device attributes we need to use the - * --global option and for that we need to specify the device - * name the same as for --device option and for that we need to - * use 'qemuDeviceVideo'. - * - * See 'Graphics Devices' section in docs/qdev-device-use.txt in - * QEMU repository. - */ - const char *dev = qemuDeviceVideoTypeToString(primaryVideoType); - - if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_QXL && - (def->videos[0]->vram || def->videos[0]->ram) && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - unsigned int ram = def->videos[0]->ram; - unsigned int vram = def->videos[0]->vram; - unsigned int vram64 = def->videos[0]->vram64; - unsigned int vgamem = def->videos[0]->vgamem; - - if (vram > (UINT_MAX / 1024)) { - virReportError(VIR_ERR_OVERFLOW, - _("value for 'vram' must be less than '%u'"), - UINT_MAX / 1024); - goto error; - } - if (ram > (UINT_MAX / 1024)) { - virReportError(VIR_ERR_OVERFLOW, - _("value for 'ram' must be less than '%u'"), - UINT_MAX / 1024); - goto error; - } - - if (ram) { - virCommandAddArg(cmd, "-global"); - virCommandAddArgFormat(cmd, "%s.ram_size=%u", - dev, ram * 1024); - } - if (vram) { - virCommandAddArg(cmd, "-global"); - virCommandAddArgFormat(cmd, "%s.vram_size=%u", - dev, vram * 1024); - } - if (vram64 && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VRAM64)) { - virCommandAddArg(cmd, "-global"); - virCommandAddArgFormat(cmd, "%s.vram64_size_mb=%u", - dev, vram64 / 1024); - } - if (vgamem && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) { - virCommandAddArg(cmd, "-global"); - virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u", - dev, vgamem / 1024); - } - } - - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && - def->videos[0]->vram && - ((primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VGA && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) || - (primaryVideoType == VIR_DOMAIN_VIDEO_TYPE_VMVGA && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)))) { - unsigned int vram = def->videos[0]->vram; - - if (vram < 1024) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("value for 'vgamem' must be at " - "least 1 MiB (1024 KiB)")); - goto error; - } - - virCommandAddArg(cmd, "-global"); - virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u", - dev, vram / 1024); - } - } - - if (def->nvideos > 1) { - if (virQEMUCapsGet(qemuCaps, 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 = qemuBuildDeviceVideoStr(def, def->videos[i], - qemuCaps))) - 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 { - /* If we have -device, then we set -nodefault already */ - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_NONE)) - virCommandAddArgList(cmd, "-vga", "none", NULL); - } + if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0) + goto error; /* Add sound hardware */ if (def->nsounds) {