> F30.me

My personal place to publish… stuff.


Virtio consoles on Debian

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.

When using 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'/>

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).

No Responses

(oh-my-)zsh key bindings on Ubuntu 12.10

After upgrading my Ubuntu system to the 12.10 beta recently, I experienced some strange quirk in my shell related to the oh-my-zsh key bindings: The up-line-or-search feature on arrow-up (resp. down-line-or-search on arrow-down) had ceased to work. One could still browse the history using the arrow keys as that seems to be zsh’s default configuration, but the “search history for commands beginning with the first word I entered” feature didn’t work anymore.

I figured out that Ctrl+V reported the key code ^[OA for arrow-up, while the other tools I checked (namely cat and bash) still returned the ordinary ^[[A. At first I guessed that this behavior had to do with Ubuntu’s upgrade to zsh 5.0, but then some help from #zsh on freenode pointed me into the right direction:

Debian’s /etc/zsh/zshrc (and therefore Ubuntu’s as well), which is executed for every shell in addition to your personal .zshrc now contains those crucial lines:

if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
    function zle-line-init () {
        printf '%s' ${terminfo[smkx]}
    function zle-line-finish () {
        printf '%s' ${terminfo[rmkx]}
    zle -N zle-line-init
    zle -N zle-line-finish
    # ...

In general, it seems to be a good idea to put the terminal into “application mode” before executing zle, at least you can find code like that in some other zshrcs as well. I still don’t entirely understand what this is about, but some information about terminal modes can be found here. What’s important to know in order to understand the above snippet is that by outputting the smkx or rmkx codes, you enable or disable application mode.

Application mode, however, uses different key codes which don’t match the hardcoded ones from oh-my-zsh. I finally solved the issue by replacing the oh-my-zsh arrow key bindings with this:

bindkey "${terminfo[kcuu1]}" up-line-or-search
bindkey "${terminfo[kcud1]}" down-line-or-search

(Debian’s /etc/zshrc conveniently stores the codes in an associative array called keys, but I didn’t wanna rely on that.)

There might be more key bindings which are affected from the problem, but I only noticed it for the arrow keys in daily usage. In my opionion it is bad style to use hardcoded key codes for the bindings in the first place and this is something that should be fixed by oh-my-zsh. I’m even a bit surprised why I couldn’t already find a patch or at least a bug report – if I manage to find enough time, I’ll definitely do that.

Update: Heres’s my pull request targeting the problem. What I wasn’t aware of (even though there’s a comment describing it right above the relevant lines), is that the reason to enable application mode at all is making use of terminfo. Ironically enough, you have to make sure application mode is really active (using some code similar to the above one), if you want to fix the problem that it causes. After all, however, you get a cleaner and more portable configuration.

4 Responses