[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 3/4] qemu: use newer -device video device in qemu commandline



'-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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]