Linux KVM as a Learning Tool

Low-level system programming is a difficult task, but with Linux KVM, it's a whole lot easier.

Low-level system programming is a difficult task, and acquiring expertise in the areas of interrupt handling and memory segmentation/paging can be a time-consuming and frustrating process if you're working right down on the metal. An alternative choice is to use a virtual machine or the Linux KVM module to create and run your own mini-kernels from scratch quickly.

The KVM Module

The KVM (Kernel-based Virtual Machine) module turns a Linux host into a VMM (Virtual Machine Monitor), and it has been included in the mainline Linux kernel since version 2.6.20. A VMM allows multiple operating systems to run concurrently on a computer. These guest operating systems execute on the real (physical) processor, but the VMM (or hypervisor) retains selective control over certain real system resources, such as the physical memory and the I/O capabilities.

When a guest tries to perform an action on a controlled resource, the VMM takes control from the guest and executes the action in a fashion that keeps it from interfering with other guest operating systems. As far as the guest knows, it thinks it is running on a platform with no VMM—that is, it has the illusion of running on a real machine. For example, the guest can do memory paging and segmentation and interrupt manipulation without interfering with the same mechanisms within other guest operating systems or within the VMM itself.

A normal Linux process has two modes of execution: kernel mode and user mode. KVM adds a third one: guest mode (Figure 1). When a guest process is executing non-I/O guest code, it will run in guest mode or perhaps better-named guest-user mode. This is the “user” mode shown inside the “Guest mode” box in Figure 1. In kernel mode (guest-kernel), the process handles exits from guest-user mode due to I/O or other special instructions. This is the “kernel” mode shown inside the “Guest mode” box in Figure 1. In user mode, the process performs I/O on behalf of the guest. This is the “I/O Ops” box shown within the normal “User mode” box in Figure 1. For more on how KVM itself operates, see the KVM Web site and the many on-line articles about it.

Figure 1. KVM Modes of Execution

The examples presented here require a recent Linux kernel with the KVM module installed and the LibKVM library to interact with the module from userspace. You can install the corresponding package(s) from your favorite distribution or compile the KVM source package (from SourceForge) to create both the module and LibKVM library. Note that the KVM module works only on platforms with hardware support for virtualization; most newer Intel and AMD 64-bit-capable processors have this support.

The rest of this article shows how to build a series of guest-mode programs (kernels) as well as a user-mode program to emulate their I/O (a virtual machine launcher).

What Gets Virtualized?

The basic components of contemporaneous computer machines are memory, one or more CPUs and one or more I/O devices. Therefore, a virtual computer machine should have these three kinds of components. Linux KVM has the ability to handle the virtual machine's memory and CPUs (with hardware help). The third ingredient, I/O, currently is left to the programmer and has to be handled in a custom way.

For instance, the KVM distribution comes with qemu-kvm, a modified QEMU program that builds virtual machines using LibKVM and emulates various I/O devices, such as a VGA card, PS/2 mouse and keyboard and an IDE disk. We are not going to use qemu-kvm here, but rather we will code a virtual machine launcher from scratch to keep our first examples simple and to learn how a program like qemu-kvm does its work.

How to Create a Virtual Machine Launcher

The KVM module exposes a character device (/dev/kvm) for interaction with userspace. For simplicity, we won't access this device directly but instead through LibKVM (API defined in libkvm.h). Use the methods shown in Listing 1 to build the virtual machine launcher (code based on Avi Kivity's test driver program included in the KVM sources).

To start, create a KVM context with kvm_init(). The first argument is a kvm_callbacks structure to specify the handlers to be called when I/O or some system-sensitive instructions are executed inside the virtual machine—for example, when the guest executes something like this:

mov     $0x0a,%al
outb    %al,$0xf1    // output value 0x0a to I/O port 0xf1



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Exit instead of hlt

Curious's picture

Thanks for this excellent article. I've tested out the sample but the program never returns after the kvm_run() call. I guess this is because the vcpu is halted in the last instruction of the test program. But how do I exit the KVM altogether and resume execution from kvm_run() onwards? Is there any documentation for libkvm somewhere I can consult?

This appears to be the libkvm in question, no?

Ben Scherrey's picture

See the userspace git tree. Is this the lib we need to be building to follow this article? I've been looking to do something like this with KVM for a while to create my own forth-like environment without having to screw around with low level hardware (or at least put it off til something interesting already works). Look forward to the follow up article. When is it scheduled?

-- Ben Scherrey

LibKVM on Ubuntu? Nonesuch...

basicman's picture

My attempt to follow this tutorial died on page 2, when it announced that all of the examples would be using the LibKVM library. Several hours of searching on Google and I've found nothing; no way to install or use the LibKVM library unless I'm on BSD.

If anyone has a workaround for this, I'd love to hear it. I was really looking forward to following the tutorial.

Different libkvm

Mitch Frazier's picture

That's a different library. You need to install the qemu-kvm-devel package. Note you will probably have to get it directly from sourceforge since it does not appear to be in the Ubuntu repos. I don't use Ubuntu much so maybe I'm overlooking something, however, I know that openSUSE does not have a package for it either (at least in the standard places at 11.0). Make sure that you get the version that corresponds to the version of kvm that you have installed. For example, here is a link to the -devel package for release 88.

If you have to install it from sourceforge some fiddling around will probably be required. First, you'll have to build it, then install it, and then potentially modify your include/library paths to find the needed items.

Mitch Frazier is an Associate Editor for Linux Journal.

I used REHL5.5 installed devel package for release 88

jniu's picture

I used REHL5.5 installed devel package for release 88, but still cannot find libkvm.h and libkvm.a, the installation was successful, can you give me some suggestion? thanks.