[libvirt] [PATCH 6/6] qemu: virtio console support

Cole Robinson crobinso at redhat.com
Mon Jul 26 19:16:25 UTC 2010


Enable specifying a virtio console device with:

<console type='pty'>
  <target type='virtio'/>
</console>

Signed-off-by: Cole Robinson <crobinso at redhat.com>
---
 docs/formatdomain.html.in                          |   18 +++++++-
 docs/schemas/domain.rng                            |    5 ++-
 src/conf/domain_conf.c                             |   32 +++++++++++----
 src/conf/domain_conf.h                             |    1 +
 src/libvirt_private.syms                           |    1 +
 src/qemu/qemu_conf.c                               |   44 +++++++++++++++++++-
 src/qemu/qemu_driver.c                             |    2 +
 .../qemuxml2argv-console-virtio.args               |    1 +
 .../qemuxml2argv-console-virtio.xml                |   27 ++++++++++++
 tests/qemuxml2argvtest.c                           |    2 +
 .../qemuxml2xmlout-console-virtio.xml              |   29 +++++++++++++
 tests/qemuxml2xmltest.c                            |    1 +
 12 files changed, 151 insertions(+), 12 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8714a14..b23a1c2 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1124,8 +1124,16 @@ qemu-kvm -net nic,model=? /dev/null
 
     <p>
       This represents the primary console. This can be the paravirtualized
-      console with Xen guests, or duplicates the primary serial port for fully
-      virtualized guests without a paravirtualized console.
+      console with Xen guests, virtio console for QEMU/KVM, or duplicates
+      the primary serial port for fully virtualized guests without a
+      paravirtualized console.
+    </p>
+
+    <p>
+      A virtio console device is exposed in the
+      guest as /dev/hvc[0-7] (for more information, see
+      <a href="http://fedoraproject.org/wiki/Features/VirtioSerial">http://fedoraproject.org/wiki/Features/VirtioSerial</a>)
+      <span class="since">Since 0.8.3</span>
     </p>
 
 <pre>
@@ -1135,6 +1143,12 @@ qemu-kvm -net nic,model=? /dev/null
       <source path='/dev/pts/4'/>
       <target port='0'/>
     </console>
+
+    <!-- KVM virtio console -->
+    <console type='pty'>
+      <source path='/dev/pts/5'/>
+      <target type='virtio' port='0'/>
+    </console>
   </devices>
   ...</pre>
 
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 1421711..833c018 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1216,6 +1216,7 @@
         <value>xen</value>
         <value>serial</value>
         <value>uml</value>
+        <value>virtio</value>
       </choice>
     </attribute>
   </define>
@@ -1292,7 +1293,9 @@
           </optional>
           <empty/>
         </group>
-        <ref name="qemucdev"/>
+        <choice>
+          <ref name="qemucdev"/>
+        </choice>
       </choice>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c9f2d25..1ff189c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -173,7 +173,8 @@ VIR_ENUM_IMPL(virDomainChrConsoleTarget,
               VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
               "serial",
               "xen",
-              "uml")
+              "uml",
+              "virtio")
 
 VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
               "monitor",
@@ -2426,13 +2427,12 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
 
     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
         target = virDomainChrConsoleTargetTypeFromString(targetType);
-        /* Fall through */
+        break;
 
     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
     default:
         /* No target type yet*/
-        target = 0;
         break;
     }
 
@@ -4567,7 +4567,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
          * For HVM console actually created a serial device
          * while for non-HVM it was a parvirt console
          */
-        if (STREQ(def->os.type, "hvm")) {
+        if (STREQ(def->os.type, "hvm") &&
+            chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
             if (def->nserials != 0) {
                 virDomainChrDefFree(chr);
             } else {
@@ -5111,7 +5112,7 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
 
 static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
 {
-    /* Look for any virtio serial device */
+    /* Look for any virtio serial or virtio console devs */
     int i;
 
     for (i = 0 ; i < def->nchannels ; i++) {
@@ -5128,6 +5129,21 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
         }
     }
 
+    if (def->console) {
+        virDomainChrDefPtr console = def->console;
+
+        if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
+            int idx = 0;
+            if (console->info.type ==
+                VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
+                idx = console->info.addr.vioserial.controller;
+
+            if (virDomainDefMaybeAddController(def,
+                VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx) < 0)
+                return -1;
+        }
+    }
+
     return 0;
 }
 
@@ -5722,14 +5738,14 @@ virDomainChrDefFormat(virBufferPtr buf,
     virBufferVSprintf(buf, "    <%s type='%s'",
                       elementName, type);
     if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+        def->target.port == 0 &&
         def->type == VIR_DOMAIN_CHR_TYPE_PTY &&
         !(flags & VIR_DOMAIN_XML_INACTIVE) &&
         def->data.file.path) {
-        virBufferEscapeString(buf, " tty='%s'>\n",
+        virBufferEscapeString(buf, " tty='%s'",
                               def->data.file.path);
-    } else {
-        virBufferAddLit(buf, ">\n");
     }
+    virBufferAddLit(buf, ">\n");
 
     switch (def->type) {
     case VIR_DOMAIN_CHR_TYPE_NULL:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c82dc60..fe09dbc 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -334,6 +334,7 @@ enum virDomainChrConsoleTargetType {
     VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL = 0,
     VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN,
     VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML,
+    VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO,
 
     VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
 };
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6b83cb9..b5944a7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -228,6 +228,7 @@ virDomainSnapshotAssignDef;
 virDomainObjAssignDef;
 virDomainChrDefForeach;
 virDomainDiskDefForeachPath;
+virDomainChrConsoleTargetTypeToString;
 
 
 # domain_event.h
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 3f77e6a..f79775b 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2028,6 +2028,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags)
         if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0)
             goto no_memory;
     }
+    if (def->console) {
+        if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
+            goto no_memory;
+    }
     if (def->watchdog) {
         if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0)
             goto no_memory;
@@ -3334,7 +3338,10 @@ char *
 qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virBufferAddLit(&buf, "virtserialport");
+    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE)
+        virBufferAddLit(&buf, "virtconsole");
+    else
+        virBufferAddLit(&buf, "virtserialport");
 
     if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
         /* Check it's a virtio-serial address */
@@ -4526,6 +4533,41 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
     }
 
+    /* Explicit console devices */
+    if (def->console) {
+        virDomainChrDefPtr console = def->console;
+        char *devstr;
+
+        switch(console->targetType) {
+        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
+            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+                qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
+                    _("virtio channel requires QEMU to support -device"));
+                goto error;
+            }
+
+            ADD_ARG_LIT("-chardev");
+            if (!(devstr = qemuBuildChrChardevStr(console)))
+                goto error;
+            ADD_ARG(devstr);
+
+            ADD_ARG_LIT("-device");
+            if (!(devstr = qemuBuildVirtioSerialPortDevStr(console)))
+                goto error;
+            ADD_ARG(devstr);
+            break;
+
+        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
+            break;
+
+        default:
+            qemuReportError(VIR_ERR_NO_SUPPORT,
+                            _("unsupported console target type %s"),
+                            NULLSTR(virDomainChrConsoleTargetTypeToString(console->targetType)));
+            goto error;
+        }
+    }
+
     ADD_ARG_LIT("-usb");
     for (i = 0 ; i < def->ninputs ; i++) {
         virDomainInputDefPtr input = def->inputs[i];
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4558674..4d21035 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2229,6 +2229,8 @@ qemudFindCharDevicePTYsMonitor(virDomainObjPtr vm,
     LOOKUP_PTYS(vm->def->serials,   vm->def->nserials,   "serial");
     LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel");
     LOOKUP_PTYS(vm->def->channels,  vm->def->nchannels,  "channel");
+    if (vm->def->console)
+        LOOKUP_PTYS(&vm->def->console, 1,  "console");
 #undef LOOKUP_PTYS
 
     return 0;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
new file mode 100644
index 0000000..a55000f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x2 -hda /dev/HostVG/QEMUGuest1 -chardev pty,id=console0 -device virtconsole,chardev=console0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
new file mode 100644
index 0000000..fd72421
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu cpuset='1-4,8-20,525'>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='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <console type='pty'>
+      <target type='virtio'/>
+    </console>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 566ab6b..017aad8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -353,6 +353,8 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_NODEFCONFIG);
     DO_TEST("channel-virtio-auto", QEMUD_CMD_FLAG_DEVICE |
             QEMUD_CMD_FLAG_NODEFCONFIG);
+    DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
+            QEMUD_CMD_FLAG_NODEFCONFIG);
 
     DO_TEST("watchdog", 0);
     DO_TEST("watchdog-device", QEMUD_CMD_FLAG_DEVICE |
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
new file mode 100644
index 0000000..431dd34
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu cpuset='1-4,8-20,525'>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='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <controller type='virtio-serial' index='0'/>
+    <console type='pty'>
+      <target type='virtio' port='0'/>
+    </console>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 08e0e73..dca9b9b 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -182,6 +182,7 @@ mymain(int argc, char **argv)
     DO_TEST_DIFFERENT("channel-virtio-auto");
     DO_TEST_DIFFERENT("console-compat-auto");
     DO_TEST_DIFFERENT("disk-scsi-device-auto");
+    DO_TEST_DIFFERENT("console-virtio");
 
     virCapabilitiesFree(driver.caps);
 
-- 
1.7.1.1




More information about the libvir-list mailing list