]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: introduce vram64 attribute for QXL video device
authorPavel Hrdina <phrdina@redhat.com>
Tue, 23 Feb 2016 16:04:19 +0000 (17:04 +0100)
committerPavel Hrdina <phrdina@redhat.com>
Tue, 1 Mar 2016 13:17:09 +0000 (14:17 +0100)
This attribute is used to extend secondary PCI bar and expose it to the
guest as 64bit memory.  It works like this: attribute vram is there to
set size of secondary PCI bar and guest sees it as 32bit memory,
attribute vram64 can extend this secondary PCI bar.  If both attributes
are used, guest sees two memory bars, both address the same memory, with
the difference that the 32bit bar can address only the first part of the
whole memory.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1260749

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
14 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_command.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_process.c
tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.xml [new file with mode: 0644]

index 07248e113e485d0a1119d7b6baaacec170d8996f..360410913de7b6e5b7452e0bdb707daa5165a7e2 100644 (file)
@@ -5200,6 +5200,8 @@ qemu-kvm -net nic,model=? /dev/null
           two as <code>vram</code>. There is also optional attribute
           <code>vgamem</code> (<span class="since">since 1.2.11</span>) to set
           the size of VGA framebuffer for fallback mode of QXL device.
+          Attribute <code>vram64</code> (<span class="since">since 1.3.2</span>)
+          extends secondary bar and makes it addressable as 64bit memory.
         </p>
       </dd>
 
index 18ef51092ec82b93dc1546eac51c87e48938de17..4e5739473751248be0b37517ff7b161114b6ee20 100644 (file)
                   <ref name="unsignedInt"/>
                 </attribute>
               </optional>
+              <optional>
+                <attribute name="vram64">
+                  <ref name="unsignedInt"/>
+                </attribute>
+              </optional>
             </group>
           </choice>
           <optional>
index 1f6bc75f30e84c1aab60fb404bc9f3157bd05029..7d7594e89f1e208d8f7c36de4b18f22bbeb5ea74 100644 (file)
@@ -11918,6 +11918,7 @@ virDomainVideoDefParseXML(xmlNodePtr node,
     char *type = NULL;
     char *heads = NULL;
     char *vram = NULL;
+    char *vram64 = NULL;
     char *ram = NULL;
     char *vgamem = NULL;
     char *primary = NULL;
@@ -11933,6 +11934,7 @@ virDomainVideoDefParseXML(xmlNodePtr node,
                 type = virXMLPropString(cur, "type");
                 ram = virXMLPropString(cur, "ram");
                 vram = virXMLPropString(cur, "vram");
+                vram64 = virXMLPropString(cur, "vram64");
                 vgamem = virXMLPropString(cur, "vgamem");
                 heads = virXMLPropString(cur, "heads");
 
@@ -11987,6 +11989,19 @@ virDomainVideoDefParseXML(xmlNodePtr node,
         def->vram = virDomainVideoDefaultRAM(dom, def->type);
     }
 
+    if (vram64) {
+        if (def->type != VIR_DOMAIN_VIDEO_TYPE_QXL) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("vram64 attribute only supported for type of qxl"));
+            goto error;
+        }
+        if (virStrToLong_uip(vram64, NULL, 10, &def->vram64) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("cannot parse video vram64 '%s'"), vram64);
+            goto error;
+        }
+    }
+
     if (vgamem) {
         if (def->type != VIR_DOMAIN_VIDEO_TYPE_QXL) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
@@ -12013,9 +12028,11 @@ virDomainVideoDefParseXML(xmlNodePtr node,
     if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
         goto error;
 
+ cleanup:
     VIR_FREE(type);
     VIR_FREE(ram);
     VIR_FREE(vram);
+    VIR_FREE(vram64);
     VIR_FREE(vgamem);
     VIR_FREE(heads);
 
@@ -12023,12 +12040,8 @@ virDomainVideoDefParseXML(xmlNodePtr node,
 
  error:
     virDomainVideoDefFree(def);
-    VIR_FREE(type);
-    VIR_FREE(ram);
-    VIR_FREE(vram);
-    VIR_FREE(vgamem);
-    VIR_FREE(heads);
-    return NULL;
+    def = NULL;
+    goto cleanup;
 }
 
 static virDomainHostdevDefPtr
@@ -17041,6 +17054,13 @@ virDomainVideoDefCheckABIStability(virDomainVideoDefPtr src,
         return false;
     }
 
+    if (src->vram64 != dst->vram64) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target video card vram64 %u does not match source %u"),
+                       dst->vram64, src->vram64);
+        return false;
+    }
+
     if (src->vgamem != dst->vgamem) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target video card vgamem %u does not match source %u"),
@@ -20726,6 +20746,8 @@ virDomainVideoDefFormat(virBufferPtr buf,
         virBufferAsprintf(buf, " ram='%u'", def->ram);
     if (def->vram)
         virBufferAsprintf(buf, " vram='%u'", def->vram);
+    if (def->vram64)
+        virBufferAsprintf(buf, " vram64='%u'", def->vram64);
     if (def->vgamem)
         virBufferAsprintf(buf, " vgamem='%u'", def->vgamem);
     if (def->heads)
index d3b3ed289e8fcc99c1ca24f170bb2ecb3d92c2aa..7e437fa90f4885705bfbd3c5fda142c85b3864fc 100644 (file)
@@ -1399,6 +1399,7 @@ struct _virDomainVideoDef {
     int type;
     unsigned int ram;  /* kibibytes (multiples of 1024) */
     unsigned int vram; /* kibibytes (multiples of 1024) */
+    unsigned int vram64; /* kibibytes (multiples of 1024) */
     unsigned int vgamem; /* kibibytes (multiples of 1024) */
     unsigned int heads;
     bool primary;
index 7864b98b9feeda8d8a309288d552a6b4dce8414f..06804786432316c0bc7e93893be215bff4dfde3a 100644 (file)
@@ -3346,6 +3346,14 @@ qemuBuildDeviceVideoStr(virDomainDefPtr def,
             virBufferAsprintf(&buf, ",vram_size=%u", video->vram * 1024);
         }
 
+        if ((video->primary &&
+             virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VRAM64)) ||
+            (!video->primary &&
+             virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VRAM64))) {
+            /* QEMU accepts mebibytes for vram64_size_mb. */
+            virBufferAsprintf(&buf, ",vram64_size_mb=%u", video->vram64 / 1024);
+        }
+
         if ((video->primary &&
              virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) ||
             (!video->primary &&
@@ -8272,6 +8280,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                     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)) {
@@ -8297,6 +8306,12 @@ qemuBuildCommandLine(virConnectPtr conn,
                         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");
index cb87412a8d045521ebf214b2fa56f471a61bf6ff..ace3bb4af2822a83c51b78e761dfa7427f76d5d1 100644 (file)
@@ -1154,6 +1154,41 @@ qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
 }
 
 
+/**
+ * To update video vram64 size in status XML we need to load correct value from
+ * QEMU.  This is supported only with JSON monitor.
+ *
+ * Returns 0 on success, -1 on failure and sets proper error message.
+ */
+int
+qemuMonitorUpdateVideoVram64Size(qemuMonitorPtr mon,
+                                 virDomainVideoDefPtr video,
+                                 const char *videoName)
+{
+    int ret = -1;
+    char *path = NULL;
+
+    QEMU_CHECK_MONITOR(mon);
+
+    if (mon->json) {
+        ret = qemuMonitorJSONFindLinkPath(mon, videoName, &path);
+        if (ret < 0) {
+            if (ret == -2)
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Failed to find QOM Object path for "
+                                 "device '%s'"), videoName);
+            return -1;
+        }
+
+        ret = qemuMonitorJSONUpdateVideoVram64Size(mon, video, path);
+        VIR_FREE(path);
+        return ret;
+    }
+
+    return 0;
+}
+
+
 int
 qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
                             const char *cmd,
index 6a2a985ad8980ba96af74af0560ea802ea9ed1c6..4467a4180b572d1884d4e7ef261a2cbedd1d2270 100644 (file)
@@ -269,6 +269,10 @@ int qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
                                      virDomainVideoDefPtr video,
                                      const char *videoName)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+int qemuMonitorUpdateVideoVram64Size(qemuMonitorPtr mon,
+                                     virDomainVideoDefPtr video,
+                                     const char *videoName)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
                                 const char *cmd,
                                 int scm_fd,
index d2b641fc67513ef9e3264944be26c5509fa98cbf..8352e53ffd95c2d513686e2eef02cdb04a2c055b 100644 (file)
@@ -1436,6 +1436,18 @@ qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
             return -1;
         }
         video->vram = prop.val.ul / 1024;
+
+        if (video->vram64 != 0) {
+            if (qemuMonitorJSONGetObjectProperty(mon, path,
+                                                 "vram64_size_mb", &prop) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("QOM Object '%s' has no property 'vram64_size_mb'"),
+                               path);
+                return -1;
+            }
+            video->vram64 = prop.val.ul / 1024;
+        }
+
         if (qemuMonitorJSONGetObjectProperty(mon, path, "ram_size", &prop) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("QOM Object '%s' has no property 'ram_size'"),
@@ -1471,6 +1483,48 @@ qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
 }
 
 
+/**
+ * Loads correct video vram64 size value from QEMU and update the video
+ * definition.
+ *
+ * Return 0 on success, -1 on failure and set proper error message.
+ */
+int
+qemuMonitorJSONUpdateVideoVram64Size(qemuMonitorPtr mon,
+                                     virDomainVideoDefPtr video,
+                                     char *path)
+{
+    qemuMonitorJSONObjectProperty prop = {
+        QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
+        {0}
+    };
+
+    switch (video->type) {
+    case VIR_DOMAIN_VIDEO_TYPE_QXL:
+        if (video->vram64 != 0) {
+            if (qemuMonitorJSONGetObjectProperty(mon, path,
+                                                 "vram64_size_mb", &prop) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("QOM Object '%s' has no property 'vram64_size_mb'"),
+                               path);
+                return -1;
+            }
+            video->vram64 = prop.val.ul / 1024;
+        }
+        break;
+    case VIR_DOMAIN_VIDEO_TYPE_VGA:
+    case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
+    case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
+    case VIR_DOMAIN_VIDEO_TYPE_XEN:
+    case VIR_DOMAIN_VIDEO_TYPE_VBOX:
+    case VIR_DOMAIN_VIDEO_TYPE_LAST:
+        break;
+    }
+
+    return 0;
+}
+
+
 int
 qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
                               unsigned long long *currmem)
index 2c27c6f9c7df61f446abba15123c0cd97588aa8f..4068187c40d75d0ba7d99b786d092870d819622c 100644 (file)
@@ -60,6 +60,9 @@ int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
 int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
                                          virDomainVideoDefPtr video,
                                          char *path);
+int qemuMonitorJSONUpdateVideoVram64Size(qemuMonitorPtr mon,
+                                         virDomainVideoDefPtr video,
+                                         char *path);
 int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
                                   unsigned long long *currmem);
 int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
index 7d8cf9d3cd4437bac9c2a50f5274cfde2cccb50a..ded20b157c588265d8e27853766c035c1b53c8c5 100644 (file)
@@ -2740,17 +2740,25 @@ qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
             break;
         case VIR_DOMAIN_VIDEO_TYPE_QXL:
             if (i == 0) {
-                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) {
-                    if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
-                                                         "qxl-vga") < 0)
+                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM) &&
+                    qemuMonitorUpdateVideoMemorySize(priv->mon, video,
+                                                     "qxl-vga") < 0)
                         goto error;
-                }
+
+                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGA_VRAM64) &&
+                    qemuMonitorUpdateVideoVram64Size(priv->mon, video,
+                                                     "qxl-vga") < 0)
+                    goto error;
             } else {
-                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
-                    if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
-                                                         "qxl") < 0)
+                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGAMEM) &&
+                    qemuMonitorUpdateVideoMemorySize(priv->mon, video,
+                                                     "qxl") < 0)
+                        goto error;
+
+                if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VRAM64) &&
+                    qemuMonitorUpdateVideoVram64Size(priv->mon, video,
+                                                     "qxl") < 0)
                         goto error;
-                }
             }
             break;
         case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.args b/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.args
new file mode 100644 (file)
index 0000000..b9e65ea
--- /dev/null
@@ -0,0 +1,25 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 1024 \
+-smp 1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/var/lib/libvirt/images/QEMUGuest1,format=qcow2,if=none,\
+id=drive-ide0-0-0,cache=none \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,\
+vram64_size_mb=128,vgamem_mb=16,bus=pci.0,addr=0x2 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.xml b/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-device-vram64.xml
new file mode 100644 (file)
index 0000000..1e89d06
--- /dev/null
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>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-system-x86_64</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='qcow2' cache='none'/>
+      <source file='/var/lib/libvirt/images/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <video>
+      <model type='qxl' vram64='131072' heads='1'/>
+    </video>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.args b/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.args
new file mode 100644 (file)
index 0000000..fadc3ed
--- /dev/null
@@ -0,0 +1,27 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 1024 \
+-smp 1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/var/lib/libvirt/images/QEMUGuest1,format=qcow2,if=none,\
+id=drive-ide0-0-0,cache=none \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vgamem_mb=16,\
+bus=pci.0,addr=0x2 \
+-device qxl,id=video1,ram_size=67108864,vram_size=67108864,vram64_size_mb=128,\
+vgamem_mb=16,bus=pci.0,addr=0x4 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.xml b/tests/qemuxml2argvdata/qemuxml2argv-video-qxl-sec-device-vram64.xml
new file mode 100644 (file)
index 0000000..72e8bad
--- /dev/null
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>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='file' device='disk'>
+      <driver name='qemu' type='qcow2' cache='none'/>
+      <source file='/var/lib/libvirt/images/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <video>
+      <model type='qxl' heads='1'/>
+    </video>
+    <video>
+      <model type='qxl' vram64='131072' heads='1'/>
+    </video>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>