libvirt with QEMU/KVM supports Virtio consoles, which are paravirtualized serial consoles. This is natively supported by Linux (for the guest system) and unlike with serial emulation, you don’t have to care about stuff like baud rate and bit parameters.
virt-install, a Virtio console can be added using
--console pty,target_type=virtio. In the libvirt XML format, the result will look something like this:
<console type='pty' tty='/dev/pts/4'> <source path='/dev/pts/4'/> <target type='virtio' port='0'/> <alias name='console0'/> </console>
The console will be available inside the guest at /dev/hvc0. To be able to actually use it, a TTY has to be spawned on it, i.e.
getty has to be started. However, this is not the case by default on Debian (as of Stretch, with systemd).
The Quick Fix
Common wisdom is to manually enable
getty, i.e. run
systemctl enable serial-getty@hvc0.
This will work, but should actually not be necessary: systemd-getty-generator is supposed to automatically spawn
getty for virtualization consoles. Looking at its source code, you see that this includes /dev/hvc0.
Freezing the Boot
After reading this article by Lennart Poettering, one might be tempted to activate the console using a kernel parameter, i.e. adding “console=hvc0” to “GRUB_CMDLINE_LINUX” in /etc/default/grub. However, this will not work and actually freeze the boot process since the kernel apparently cannot find the “hvc0” device.
This is because the Virtio console driver only gets loaded later in the boot process, which means it is not available at kernel start.
The Proper Solution
As it turns out, the reason for systemd-getty-generator not spawning
getty is actually the same: systemd generators run pretty early during the boot process; apparently also before the Virtio console driver has been loaded.
The fix for this is to add the Virtio console kernel module to the guest’s initrd. On Debian, this can be done by putting “virtio_console” into /etc/initramfs-tools/modules and running
update-initramfs -u afterwards.
After rebooting, you should be able to get a TTY using
virsh console. If you want to get boot messages on the Virtio console, you may now also add the “console=hvc0” kernel parameter without freezing the boot (use “console=tty0 console=hvc0” to keep the messages on the graphical console as well).