kvm is QEMU with support for the VT Vanderpool or Virtualization Technology. This means you can now run QEMU on CPUs that have the VT instructions and you get a super quick emulated environment. Yay!
Previously to get spritely performance out of QEMU you needed the closed-source KQEMU kernel module. Now you don't. This interests me because I use QEMU quite heavily with my little screencasting project with Ubuntu-UK. Having a totally Free (GPL) and easy to use method for running virtual machines is essential. Of course there's Xen but kvm is a great drop-in solution with very little requirements on the host, no replacement kernels for example.
Here's what I did on a core 2 duo CPU machine - this is on an utterly clean 32-bit Ubuntu Edgy system - I know it's clean, I installed it last night. This assumes that you have a stock Ubuntu kernel, and not one that you have either compiled yourself or in any way patched.
* Check my CPU support VT
$ egrep '^flags.*(vmx|svm)' /proc/cpuinfo
If you get some output it does, if you don't, it doesn't. I got this:-
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
The important bit there being "vmx" - oh and the fact that there are two lines means it's dual core - more yay!
* Get the necessary pre-requisites
You need GCC version 3.4 to compile qemu (which is included in kvm).
$ sudo apt-get install gcc-3.4 g++-3.4 uuid-dev zlib1g-dev libsdl1.2-dev build-essential linux-headers-generic
You should see something like this:-
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
cpp-3.4 dpkg-dev g++ g++-4.1 gcc-3.4-base libaa1-dev libartsc0 libartsc0-dev
libasound2-dev libaudio-dev libaudiofile-dev libdirectfb-dev
libdirectfb-extra libesd0-dev libfreetype6-dev libgl1-mesa-dev
libglib2.0-dev libglu1-mesa-dev libice-dev libjpeg62-dev libncurses5-dev
libpng12-dev libslang2-dev libsm-dev libstdc++6-4.1-dev libstdc++6-dev
libx11-dev libxau-dev libxdmcp-dev libxext-dev libxt-dev
linux-headers-2.6.17-10-generic mesa-common-dev x-dev x11proto-core-dev
x11proto-input-dev x11proto-kb-dev x11proto-xext-dev xtrans-dev
Suggested packages:
debian-keyring gcc-3.4-doc lib64stdc++6 gcc-4.1-doc libc6-dev-amd64
lib64gcc1 libasound2-doc libglib2.0-doc libstdc++6-4.1-doc libstdc++6-doc
The following NEW packages will be installed:
build-essential cpp-3.4 dpkg-dev g++ g++-3.4 g++-4.1 gcc-3.4 gcc-3.4-base
libaa1-dev libartsc0 libartsc0-dev libasound2-dev libaudio-dev
libaudiofile-dev libdirectfb-dev libdirectfb-extra libesd0-dev
libfreetype6-dev libgl1-mesa-dev libglib2.0-dev libglu1-mesa-dev libice-dev
libjpeg62-dev libncurses5-dev libpng12-dev libsdl1.2-dev libslang2-dev
libsm-dev libstdc++6-4.1-dev libstdc++6-dev libx11-dev libxau-dev
libxdmcp-dev libxext-dev libxt-dev linux-headers-2.6.17-10-generic
linux-headers-generic mesa-common-dev uuid-dev x-dev x11proto-core-dev
x11proto-input-dev x11proto-kb-dev x11proto-xext-dev xtrans-dev zlib1g-dev
0 upgraded, 46 newly installed, 0 to remove and 2 not upgraded.
Need to get 0B/19.8MB of archives.
After unpacking 98.3MB of additional disk space will be used.
Do you want to continue [Y/n]?
(except the bit where it says "need to get 0B" will be something bigger - I cheated and already downloaded that lot)
* Get kvm
Go get kvm from their Sourceforge download page. I saved it to my desktop because I'm messy like that.
* Unpack it
$ mkdir ~/src
$ cd ~/src
$ tar zxvf ~/Desktop/kvm-3.tar.gz
* Configure it
$ cd kvm-3
$ ./configure --prefix=/usr/local/kvm --qemu-cc="/usr/bin/gcc-3.4"
If all goes well it should look like this:-
Install prefix /usr/local/kvm
BIOS directory /usr/local/kvm/share/qemu
binary directory /usr/local/kvm/bin
Manual directory /usr/local/kvm/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path /home/alan/src/kvm-3/qemu
C compiler /usr/bin/gcc-3.4
Host C compiler gcc
make make
install install
host CPU i386
host big endian no
target list i386-softmmu
gprof enabled no
profiler no
static build no
SDL support yes
SDL static link yes
mingw32 support no
Adlib support no
CoreAudio support no
ALSA support no
DSound support no
FMOD support no
kqemu support no
kvm support yes
Documentation no
Note: kqemu support is "no" and kvm support is "yes", that's the really good stuff
* Compile it
$ make
You should get a boatload of "stuff" starting with:-
make -C kernel
make[1]: Entering directory `/home/alan/src/kvm-3/kernel'
make -C /lib/modules/`uname -r`/build M=`pwd` "$@"
make[2]: Entering directory `/usr/src/linux-headers-2.6.17-10-generic'
LD /home/alan/src/kvm-3/kernel/built-in.o
CC [M] /home/alan/src/kvm-3/kernel/kvm_main.o
and finishing with something like:-
/usr/bin/gcc-3.4 -L /home/alan/src/kvm-3/qemu/../user -o qemu vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o scsi-disk.o cdrom.o lsi53c895a.o usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o ne2000.o rtl8139.o pcnet.o ide.o pckbd.o ps2.o vga.o sb16.o es1370.o dma.o audio.o noaudio.o wavaudio.o sdlaudio.o ossaudio.o wavcapture.o fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o usb-uhci.o gdbstub.o sdl.o vnc.o slirp/cksum.o slirp/if.o slirp/ip_icmp.o slirp/ip_input.o slirp/ip_output.o slirp/slirp.o slirp/mbuf.o slirp/misc.o slirp/sbuf.o slirp/socket.o slirp/tcp_input.o slirp/tcp_output.o slirp/tcp_subr.o slirp/tcp_timer.o slirp/udp.o slirp/bootp.o slirp/debug.o slirp/tftp.o libqemu.a -lm -lz -lkvm -L/usr/lib -lSDL -lpthread -lutil -lrt -luuid
make[2]: Leaving directory `/home/alan/src/kvm-3/qemu/i386-softmmu'
make[1]: Leaving directory `/home/alan/src/kvm-3/qemu'
Looking good!.
* Install it
$ sudo make install
* Insert the kernel module into the running kernel
$ sudo insmod kernel/kvm.ko
At this point you can now run qemu from the /usr/local/kvm directory into which we installed it.
I already have some disk images used by qemu which can of course be used by kvm also. It is based on qemu after all.
$ sudo /usr/local/kvm/bin/qemu -hda ~/vm/edgygold.qcow -m 512 -soundhw all -net nic -net user
There's more detail about qemu in a previous blog post called Creating Screencasts (down the bottom), and also on the HantsLUG wiki.
If the kvm module isn't loaded when you start qemu then you'll get this:-
Could not initialize KVM, will disable KVM support
Which is clearly bad.
If the kvm module is loaded correctly - i.e. you did everything above right then you should see this:-
set_vram_mapping: memory: e0000000 - e0800000
set_vram_mapping: return 0x9614a000
vga_update_vram: base 0x9614a000 ptr 0x9694a008
vga_update_vram: done
And of course, here's the obligatory screenshot
I thought I'd run a couple of benchmarks to see how it performs. I ran two. One is the amazing, nay reference gold standard benchmark that is Hugos Random Benchmark which is basically where you get a machine to count to a very big number and time it doing that. It's great for raw clock speed pissing contests, but not much more. I should point out that the pc running this qemu/kvm image is actually top of that list. Here's what the host gets when I run hugos random benchmark:-
alan@wopr:~$ time perl -e 'for($i=0;$i<1e8;$i++) { }'
real 0m6.689s
user 0m6.688s
sys 0m0.000s
And here's what the qemu/kvm image gets:-
alan@edgyvm:~$ time perl -e 'for($i=0;$i<1e8;$i++) { }'
real 0m7.230s
user 0m7.056s
sys 0m0.032s
That looks pretty good going to me!
Ok, lets try a more sane benchmark. The UnixBench benchmark should be more like it.
Here's the result from running UnixBench on the host computer.
==============================================================
BYTE UNIX Benchmarks (Version 4.1-wht)
System -- Linux wopr 2.6.17-10-generic #2 SMP Fri Oct 13 18:45:35 UTC 2006 i686 GNU/Linux
/dev/sdb1 235288032 30517988 192818088 14% /
Start Benchmark Run: Wed Nov 15 22:10:55 GMT 2006
22:10:55 up 2:28, 7 users, load average: 0.37, 0.34, 0.23
End Benchmark Run: Wed Nov 15 22:21:25 GMT 2006
22:21:25 up 2:39, 5 users, load average: 15.93, 6.89, 3.14
INDEX VALUES
TEST BASELINE RESULT INDEX
Dhrystone 2 using register variables 376783.7 19976788.8 530.2
Double-Precision Whetstone 83.1 2285.9 275.1
Execl Throughput 188.3 8953.1 475.5
File Copy 1024 bufsize 2000 maxblocks 2672.0 150910.0 564.8
File Copy 256 bufsize 500 maxblocks 1077.0 40765.0 378.5
File Read 4096 bufsize 8000 maxblocks 15382.0 1234477.0 802.5
Pipe-based Context Switching 15448.6 456975.1 295.8
Pipe Throughput 111814.6 1201420.9 107.4
Process Creation 569.3 23939.3 420.5
Shell Scripts (8 concurrent) 44.8 1180.8 263.6
System Call Overhead 114433.5 3513796.1 307.1
=========
FINAL SCORE 359.3
..and here we having running under qemu/kvm..
>==============================================================
BYTE UNIX Benchmarks (Version 4.1-wht)
System -- Linux edgyvm 2.6.17-10-generic #2 SMP Fri Oct 13 18:45:35 UTC 2006 i686 GNU/Linux
/dev/hda1 9859036 1931768 7426444 21% /
Start Benchmark Run: Wed Nov 15 22:34:21 GMT 2006
22:34:21 up 2 min, 2 users, load average: 1.65, 0.90, 0.35
End Benchmark Run: Wed Nov 15 22:35:20 GMT 2006
22:35:20 up 3 min, 2 users, load average: 0.67, 0.75, 0.33
INDEX VALUES
TEST BASELINE RESULT INDEX
Dhrystone 2 using register variables 376783.7 1.0 0.0
Double-Precision Whetstone 83.1 0.0 0.0
Execl Throughput 188.3 1.0 0.1
Pipe-based Context Switching 15448.6 1.0 0.0
Pipe Throughput 111814.6 1.0 0.0
Process Creation 569.3 1.0 0.0
Shell Scripts (8 concurrent) 44.8 1.0 0.2
System Call Overhead 114433.5 1.0 0.0
=========
FINAL SCORE 0.0
Hmm. Well that's not what I was expecting, that's for sure. Answers why on a postcard.
Overall, kvm receives the "popey 5 minute test" seal of approval.