Open-source project
kvmtool/kvmtool avatar
kvmtool/kvmtool

kvmtool boots a Linux guest in about 5 KLOC of C, and that is the whole point

Stand-alone Native Linux KVM Tool repo

646 stars174 forksCGPL-2.0

At a glance

What is it?
kvmtool is a stand-alone KVM host written in C with no BIOS dependencies and minimal device emulation, built as a teaching tool rather than a replacement for QEMU. It boots Linux guests with virtio devices over a serial console.
Who is it for?
Adopt kvmtool if you are learning how a KVM host actually works, or if you want to debug a Linux guest boot without a full machine emulator in the way. Do not adopt it to run production workloads, because it has no BIOS, no legacy device emulation to speak of, and the README itself frames it as a hobby that will not be as professional as QEMU.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 176 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A KVM host with no BIOS in the path

kvmtool is described in the repository as a lightweight tool for hosting KVM guests, and the README quotes the original announcement email, which sets out the goal: a clean, from scratch, lightweight KVM host tool implementation that can boot Linux guest images, with no BIOS dependencies and with only the minimal amount of legacy device emulation. The email calls it a hobby and says it will not be big and professional like QEMU.

That framing is the single most useful thing to read before anything else. This is not a stripped down QEMU. It is a different shape of program: one that talks to the KVM kernel interface directly and constructs the guest's devices itself.

The code size is stated in the announcement as about 5 KLOC of clean C, and the repository layout backs that up. The top level is a set of builtin-*.c files, one per command, sitting next to the core: kvm.c for the hypervisor interface, kvm-cpu.c for the vcpu, irq.c, mmio.c, pci.c, term.c for the serial console, framebuffer.c, devices.c and epoll.c. Virtio support lives in virtio/, disk formats in disk/ with raw, qcow and blk backends, and there is a vfio/ directory for passing real devices through.

The output is a serial console over the host terminal, so you can boot a guest image in a terminal or over ssh and log in without much guest or host side setup. For anyone who wants to see the layers between a bootloader and a kernel, that is the appeal.

One architecture at a time, and 32-bit guests on 64-bit hosts

Because kvmtool is a pure virtualization tool, it only supports guests using the same architecture as the host. That constraint is stated at the top of the README and it is a hard one. There is no instruction set translation layer, no emulator, nothing to fall back on.

There is one exception, and it is narrow. The tool supports running 32-bit guests on 64-bit architectures that allow this, which on x86 means a host kernel built with CONFIG_IA32_EMULATION enabled. The README lists that option under the guest kernel configuration, so the capability is a property of the guest kernel and the host, not something kvmtool negotiates at runtime.

The repository layout shows how much architecture-specific code there is. There are directories for arm64/, mips/, powerpc/, riscv/ and x86/, each holding the entry points for that architecture. The presence of five of them is a reminder of how much work supporting a new architecture is, even in a program this size.

A guest that needs real firmware, or a guest image built for a different architecture than the machine you are on, is simply out of scope. That is the boundary of the tool and it is worth knowing before you download anything.

The Makefile produces one binary with a shorter alias

Building is a plain make invocation in a cloned repository, and the README points to INSTALL for more elaborate instructions.

bash
  git clone git://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git
bash
  cd kvmtool && make

The Makefile at the top of the repository is a conventional kernel style build. The compiler is gcc and the linker is ld, both prefixed by a CROSS_COMPILE variable, so cross compiling is a matter of setting that variable rather than restructuring the build. There is a comment at the top of the file noting that WERROR=0 disables -Werror, which tells you the build treats warnings as errors by default.

The output name is defined by two variables, and the second one is worth noticing because it changes how you type every command.

make
PROGRAM	:= lkvm
PROGRAM_ALIAS := vm

So the binary is lkvm, with vm as a shorter alias, and the examples throughout the README use the lkvm form. The build also lists the object files it compiles, which doubles as a map of the codebase: one object per builtin command, then the core, then disk/, virtio/, hw/, net/uip/ and vfio/.

The net/uip/ directory is a user space IP stack implemented in the host program, which is how the tool does networking without handing the guest a tap device by default.

The guest kernel has to be built for virtio and a serial console

This is the part of the setup that catches people out. The README lists a specific set of guest kernel configuration options, and it is not a minimal list. The guest needs the 8250 serial driver with the console option enabled for the default output path.

code
	CONFIG_SERIAL_8250=y
	CONFIG_SERIAL_8250_CONSOLE=y

On top of that come the virtio options, and they are grouped by which device you actually want to use. The base requirements are CONFIG_VIRTIO, CONFIG_VIRTIO_RING and CONFIG_VIRTIO_PCI. Then each device has its own line: CONFIG_VIRTIO_BLK for the disk device behind the --disk option, CONFIG_VIRTIO_NET for virtio networking behind --network, CONFIG_VIRTIO_BALLOON for the balloon device behind --balloon, and CONFIG_VIRTIO_CONSOLE for the virtio console behind --console virtio.

There are two that do not fit the virtio pattern. The 9p support needs CONFIG_NET_9P, CONFIG_NET_9P_VIRTIO and CONFIG_9P_FS, and the vesa framebuffer used by the --sdl and --vnc options needs CONFIG_FB_VESA.

The consequence is that the stock distribution kernel of your distribution is unlikely to be usable as a guest. You are expected to build a guest kernel yourself, with the filesystem options that match your image, and the README gives an example with CONFIG_EXT2_FS and CONFIG_EXT4_FS. That is a real cost for a first run: a kernel build before you can boot anything.

Launching a guest with lkvm run and a raw disk image

The launch step needs a kernel image and a disk image. The README walks through downloading a raw userspace image and decompressing it.

bash
  wget http://wiki.qemu.org/download/linux-0.2.img.bz2 && bunzip2

Then the hypervisor is started with the run command, pointing at the disk image and at a bzImage kernel.

bash
  sudo ./lkvm run --disk linux-0.2.img \
		 --kernel ../../arch/x86/boot/bzImage \
		 --network virtio

Note the sudo in the example that adds networking. The README presents a plain variant of the same command for the case without a network device, and the network option is described as virtio in the option list. Running as root is what gives the process the access it needs to wire up a network interface and open the KVM device, so expect to run the tool under sudo.

The path to the kernel in the example, ../../arch/x86/boot/bzImage, points at a kernel build tree you keep next to the checkout. That tells you the intended workflow: keep a kernel source tree handy and point the tool at the bzImage you just built.

Once it runs, the guest console appears in your terminal. There is no graphical console by default, which is consistent with the whole design of a tool with no BIOS.

The builtin commands cover the guest lifecycle, and nothing else

The command set is visible in the file names, and it is small enough to enumerate. There are builtin-run.o and builtin-setup.o for starting a guest and preparing its environment, builtin-stop.o, builtin-pause.o and builtin-resume.o for controlling a running guest, builtin-list.o and builtin-stat.o for inspecting what is running, builtin-version.o and builtin-help.o for information, builtin-debug.o for debugging, and builtin-balloon.o for the memory balloon device.

Two of those deserve comment. builtin-sandbox.o points at a guest sandbox command, and builtin-debug.o suggests a built in debugging mode rather than an external debugger attach.

The point of the enumeration is what is absent. There is no networking management command, no image creation tool, no snapshot facility, no configuration file format described in the README. The disk backends exist in the code, with disk/qcow.o and disk/raw.o among the object files, so the tool can read qcow images, but the documentation does not describe a workflow for creating them.

For a learning tool this is the right size. For running infrastructure it would be the wrong size, because everything around the hypervisor, provisioning, storage pools, live migration and access control, has to come from somewhere else and none of it is here.

Where QEMU differs, and where kvmtool refuses to go

The README names the comparison itself, in the line that says this is a hobby and will not be big and professional like QEMU, and the difference in approach is concrete rather than a matter of degree.

QEMU is a machine emulator with a firmware model in front of it. It implements a chipset, legacy devices, a range of BIOS and UEFI implementations, and a wide collection of emulated peripherals, so a guest that expects a PC can boot without cooperation from the guest kernel. kvmtool takes the opposite route. It assumes a Linux guest, offers no BIOS at all, and implements the devices a modern Linux kernel can be told to use directly, which in practice means virtio. The two lines in the README that connect each guest kernel option to a specific kvmtool option, --disk, --network, --balloon, --console virtio, are exactly the shape of that contract.

That difference buys two things. The guest boots without any firmware stage, and the code stays small enough to read in an afternoon. It also costs the compatibility you get from an emulated PC, so anything that needs a BIOS, a specific chipset, or an emulated device is out of reach.

The tool also has a documented origin as a kernel side project, with patches sent to the kvm mailing list and maintainers listed as Will Deacon and Julien Thierry.

GPL-2.0, a last push in April 2026, and no tagged releases

The licence is GPL-2.0, with the text in the COPYING file. For a tool you run on your own machine that is a low friction licence, and the kernel community style of development it comes from treats it as a given.

On maintenance, the repository is not archived and the last push was on 2026-04-30. There are no GitHub releases at all, so there is no version list to check and no changelog to read before upgrading. The version has to come from the source tree or from the built binary itself, and the builtin-version command exists for that.

The contribution process is documented and unusual. Patches go to [email protected] in the usual git patch format with kvmtool in the subject line, and the README shows the git config line that sets a subject prefix automatically so you do not have to type it each time.

bash
 git config format.subjectprefix "PATCH kvmtool"

There is a CREDITS-Git file for authors, a Documentation/ directory, a tests/ directory and a config/ directory that holds the build includes. The INSTALL file referenced from the README is the place to look for the full build requirements, since the top level instructions deliberately stay short.

Editorial conclusion

Adopt kvmtool if you are learning how a KVM host actually works, or if you want to debug a Linux guest boot without a full machine emulator in the way. Do not adopt it to run production workloads, because it has no BIOS, no legacy device emulation to speak of, and the README itself frames it as a hobby that will not be as professional as QEMU. Before you spend time on it, read INSTALL for the full build requirements, confirm your guest kernel has the virtio options listed in the README enabled, and check that the guest image you picked is a raw image you can boot without firmware.

Frequently asked questions

How do I build kvmtool?

Clone the repository from git.kernel.org and run make in the kvmtool directory. The Makefile uses gcc and ld with a CROSS_COMPILE prefix, and defines WERROR=0 as a way to turn off -Werror. The README points to INSTALL for more elaborate instructions.

Does kvmtool need a BIOS to boot a guest?

No. The stated goal is a KVM host with no BIOS dependencies and only the minimal amount of legacy device emulation, which is why it can boot a Linux guest image directly from a bzImage.

Which guest kernel options does kvmtool need?

The README lists CONFIG_SERIAL_8250 and CONFIG_SERIAL_8250_CONSOLE for the default console, the virtio base options CONFIG_VIRTIO, CONFIG_VIRTIO_RING and CONFIG_VIRTIO_PCI, and per-device options such as CONFIG_VIRTIO_BLK for the disk, CONFIG_VIRTIO_NET for networking, CONFIG_VIRTIO_BALLOON for the balloon device and CONFIG_FB_VESA for the framebuffer.

Can kvmtool run a guest of a different architecture than the host?

No. As a pure virtualization tool it only supports guests using the same architecture, with the exception of running 32-bit guests on 64-bit architectures that allow this, which on x86 depends on CONFIG_IA32_EMULATION.

What is the output binary called?

The Makefile sets PROGRAM to lkvm and PROGRAM_ALIAS to vm, and the README examples use the lkvm form, for example ./lkvm run with the disk and kernel options.

Official sources

  1. Issues
  2. kvmtool/kvmtool on GitHub
  3. License: GPL-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kvmtool-kvmtool.svg)](https://hysenlabs.com/projects/kvmtool-kvmtool)

Was this useful?