Running Linux under QEMU emulation

When running QEMU just as an emulator, rather than as a virtualiser, the emulation is, unsurprisingly, quite slow.

This means that if you install and run a Linux distribution under QEMU it'll also be slow, particularly in terms of any X environment or GUI.

There are, however, additional problems beyond the slowness.

Firstly, the techniques that Linux uses to keep track of time are likely to fail simply because the virtual hardware created by QEMU is running too slowly to do everything a typical Linux needs it to do. For example, a typical Linux kernel expects to see 1000 hardware signals (ticks) per second from the computer hardware. It uses these to keep track of time passing. In QEMU emulation land, it's unlikely that your virtual hardware can generate ticks this quickly, and the virtual CPU is probably going to miss some of them when the host on which you're running QEMU is doing something else.

This means that, as far as your virtual computer is concerned, time slows down and its virtual clock gets out of sync with reality. More than this, it happens erratically. Depending on what your host computer is doing, such as when you're reading email or browsing the web at the same time as your running QEMU, more or less ticks will get generated (or lost!) and the rate at which the virtual computer's clock is drifting will change.

Secondly, Linux is designed to run on a relatively fast computer, and when the virtual computer isn't fast enough, some of the virtual signals in your virtual computer will get handled at the wrong time, or may get lost, or may get overtaken by other signals. This can cause software problems such as segmentation faults, unexpected signals, the system hangs or virtual hardware seems to stop working, and other errors.

Ameliorating problems

Most issues involving QEMU emulations and Linux have to do with either clocks, timers, or interrupt signals. These are the things which are most time-sensitive.

Fortunately, these have to do mainly with the Linux kernel---which is the first thing loaded into memory when you boot your computer---and there are things you can do to resolve them. In fact, when booting your computer, you can pass configuration commands and parameters to the kernel before it starts, and these can change its behaviour. In particular, these can change what it does with clocks, times, and interrupts.

These commands and parameters are passed to the kernel on its command line. How you do this for your particular Linux distribution varies from distribution to distribution. Look for documentation regarding booting, lilo or grub (these last two being software which loads Linux into a computer's memory before starting it).

Timers and clocks

The Linux kernel has available to it a number of different ways it can keep track of time. It works out what timer hardware is available in the computer (your virtual computer) when it boots and it uses the one(s) it thinks most reliable. In an emulation, it can get this wrong.

The available timers you might see mentioned are:

  • jiffies
  • pit (Programmable Interrupt Timer)
  • tsc (Time Stamp Counter)
  • hpet (High Precision Event Timer)
  • acpi_pm

The hpet is supposed to be a high-precision timer and on real hardware it is, but on virtual hardware it isn't. Linux generally will want to trust the hpet above all else and it often will need to be told not to. You can disable Linux's use of the hpet with the parameter:

hpet=disabled

The tsc derives from hardware which counts time. Like the hpet, it can be wildly inaccurate under emulation. It can't be completely disabled, but some of the things done with it can be:

tsc=reliable
tsc=noirqtime

The APIC is the Advanded Programmable Interrupt Controller and it can be unreliable under emulation when Linux tries to get it to do too much. It can be disabled (and Linux will fall back to a simpler alternative) by this:

noapic

You can also suggest to the Linux kernel that when it starts up it should use one of the more reliable time sources:

clocksource=acpi_pm

Building a new kernel

Because one of the main problems with running Linux under QEMU is the speed at which ticks and other signals occur being too fast, one solution is to build a Linux kernel that operates at a slower tick rate (100 per second instead of 1000 per second). There are a few advantages to this:

  1. The reduced tick rate means that ticks are less likely to get lost and therefore the virtual computer's clock won't drift,
  2. There is less likelihood of timing conflicts,
  3. You can build the kernel with fewer options so that it runs faster.

See below for a kernel config file for an i386 QEMU kernel for Linux 3.7.6. It has the tick rate set to 100 Hz (100 ticks per second), does not include a large number of device drivers which don't exist under QEMU, has simplified networking (e.g., no netfilter or iptables), and omits many kernel debugging options

Other interesting, but unrelated, kernel parameters

ipv6.disable=1 Disables the entire IPv6 stack and prevents interfaces having IPv6 addresses
selinux=0 Disables SElinux at boot time
consoleblank=0 Disables automatic console blanking. Not required on virtual machines because they don't have screens which can get burnt in

Tags: