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:

Comment viewing options

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?

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?

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.

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.

Trending Topics

Upcoming Webinar

Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report

August 27, 2015
12:00 PM CDT

DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.