qemu: virtio console support

Enable specifying a virtio console device with:

<console type='pty'>
  <target type='virtio'/>
</console>
This commit is contained in:
Cole Robinson 2010-07-14 13:02:04 -04:00
parent 6b24755235
commit 82b6d7600e
12 changed files with 151 additions and 12 deletions

View File

@ -1132,8 +1132,16 @@ qemu-kvm -net nic,model=? /dev/null
<p> <p>
This represents the primary console. This can be the paravirtualized This represents the primary console. This can be the paravirtualized
console with Xen guests, or duplicates the primary serial port for fully console with Xen guests, virtio console for QEMU/KVM, or duplicates
virtualized guests without a paravirtualized console. 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> </p>
<pre> <pre>
@ -1143,6 +1151,12 @@ qemu-kvm -net nic,model=? /dev/null
&lt;source path='/dev/pts/4'/&gt; &lt;source path='/dev/pts/4'/&gt;
&lt;target port='0'/&gt; &lt;target port='0'/&gt;
&lt;/console&gt; &lt;/console&gt;
&lt;!-- KVM virtio console --&gt;
&lt;console type='pty'&gt;
&lt;source path='/dev/pts/5'/&gt;
&lt;target type='virtio' port='0'/&gt;
&lt;/console&gt;
&lt;/devices&gt; &lt;/devices&gt;
...</pre> ...</pre>

View File

@ -1226,6 +1226,7 @@
<value>xen</value> <value>xen</value>
<value>serial</value> <value>serial</value>
<value>uml</value> <value>uml</value>
<value>virtio</value>
</choice> </choice>
</attribute> </attribute>
</define> </define>
@ -1302,7 +1303,9 @@
</optional> </optional>
<empty/> <empty/>
</group> </group>
<ref name="qemucdev"/> <choice>
<ref name="qemucdev"/>
</choice>
</choice> </choice>
</element> </element>
</define> </define>

View File

@ -173,7 +173,8 @@ VIR_ENUM_IMPL(virDomainChrConsoleTarget,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST, VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
"serial", "serial",
"xen", "xen",
"uml") "uml",
"virtio")
VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST, VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
"monitor", "monitor",
@ -2426,13 +2427,12 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
target = virDomainChrConsoleTargetTypeFromString(targetType); target = virDomainChrConsoleTargetTypeFromString(targetType);
/* Fall through */ break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
default: default:
/* No target type yet*/ /* No target type yet*/
target = 0;
break; break;
} }
@ -4578,7 +4578,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
* For HVM console actually created a serial device * For HVM console actually created a serial device
* while for non-HVM it was a parvirt console * 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) { if (def->nserials != 0) {
virDomainChrDefFree(chr); virDomainChrDefFree(chr);
} else { } else {
@ -5122,7 +5123,7 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def) static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
{ {
/* Look for any virtio serial device */ /* Look for any virtio serial or virtio console devs */
int i; int i;
for (i = 0 ; i < def->nchannels ; i++) { for (i = 0 ; i < def->nchannels ; i++) {
@ -5139,6 +5140,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; return 0;
} }
@ -5733,14 +5749,14 @@ virDomainChrDefFormat(virBufferPtr buf,
virBufferVSprintf(buf, " <%s type='%s'", virBufferVSprintf(buf, " <%s type='%s'",
elementName, type); elementName, type);
if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
def->target.port == 0 &&
def->type == VIR_DOMAIN_CHR_TYPE_PTY && def->type == VIR_DOMAIN_CHR_TYPE_PTY &&
!(flags & VIR_DOMAIN_XML_INACTIVE) && !(flags & VIR_DOMAIN_XML_INACTIVE) &&
def->data.file.path) { def->data.file.path) {
virBufferEscapeString(buf, " tty='%s'>\n", virBufferEscapeString(buf, " tty='%s'",
def->data.file.path); def->data.file.path);
} else {
virBufferAddLit(buf, ">\n");
} }
virBufferAddLit(buf, ">\n");
switch (def->type) { switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_NULL:

View File

@ -334,6 +334,7 @@ enum virDomainChrConsoleTargetType {
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL = 0, VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL = 0,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN, VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML, VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST, VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
}; };

View File

@ -228,6 +228,7 @@ virDomainSnapshotAssignDef;
virDomainObjAssignDef; virDomainObjAssignDef;
virDomainChrDefForeach; virDomainChrDefForeach;
virDomainDiskDefForeachPath; virDomainDiskDefForeachPath;
virDomainChrConsoleTargetTypeToString;
# domain_event.h # domain_event.h

View File

@ -2031,6 +2031,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags)
if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0) if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0)
goto no_memory; goto no_memory;
} }
if (def->console) {
if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
goto no_memory;
}
if (def->watchdog) { if (def->watchdog) {
if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0) if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0)
goto no_memory; goto no_memory;
@ -3337,7 +3341,10 @@ char *
qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev) qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev)
{ {
virBuffer buf = VIR_BUFFER_INITIALIZER; 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) { if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
/* Check it's a virtio-serial address */ /* Check it's a virtio-serial address */
@ -4547,6 +4554,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"); ADD_ARG_LIT("-usb");
for (i = 0 ; i < def->ninputs ; i++) { for (i = 0 ; i < def->ninputs ; i++) {
virDomainInputDefPtr input = def->inputs[i]; virDomainInputDefPtr input = def->inputs[i];

View File

@ -2229,6 +2229,8 @@ qemudFindCharDevicePTYsMonitor(virDomainObjPtr vm,
LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial"); LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial");
LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel"); LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel");
LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel"); LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel");
if (vm->def->console)
LOOKUP_PTYS(&vm->def->console, 1, "console");
#undef LOOKUP_PTYS #undef LOOKUP_PTYS
return 0; return 0;

View File

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

View File

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

View File

@ -355,6 +355,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_NODEFCONFIG); QEMUD_CMD_FLAG_NODEFCONFIG);
DO_TEST("channel-virtio-auto", QEMUD_CMD_FLAG_DEVICE | DO_TEST("channel-virtio-auto", QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_NODEFCONFIG); QEMUD_CMD_FLAG_NODEFCONFIG);
DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_NODEFCONFIG);
DO_TEST("watchdog", 0); DO_TEST("watchdog", 0);
DO_TEST("watchdog-device", QEMUD_CMD_FLAG_DEVICE | DO_TEST("watchdog-device", QEMUD_CMD_FLAG_DEVICE |

View File

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

View File

@ -184,6 +184,7 @@ mymain(int argc, char **argv)
DO_TEST_DIFFERENT("channel-virtio-auto"); DO_TEST_DIFFERENT("channel-virtio-auto");
DO_TEST_DIFFERENT("console-compat-auto"); DO_TEST_DIFFERENT("console-compat-auto");
DO_TEST_DIFFERENT("disk-scsi-device-auto"); DO_TEST_DIFFERENT("disk-scsi-device-auto");
DO_TEST_DIFFERENT("console-virtio");
virCapabilitiesFree(driver.caps); virCapabilitiesFree(driver.caps);