Mainline kernel on Qemu x86/64

At times, my task consists in debugging code embedded in the kernel. This process typically necessitates a complete kernel reload for every single modification applied. In practical terms, this equates to rebooting the entire machine — a task that is, unfortunately, time-intensive and costly.

This necessity for frequent reboots can significantly impede workflow efficiency, relegating me to a tedious cycle of waiting rather than actively engaging in productive work.

This is where leveraging QEMU proves to be immensely beneficial. Utilizing QEMU facilitates a rapid booting process of the kernel, thereby minimizing reboot time and markedly enhancing workflow efficiency.

In this page, I’ll list the steps to boot QEMU with a mainline kernel and a specially set up filesystem, tailored just for my needs (ref. 1).

Filesystem

Debian is my system of choice, it's easy to set up and use. It can be easily downloaded using debootstrap (ref. 2):

sudo debootstrap --arch amd64 sid debian-x86_64 http://deb.debian.org/debian

Finalize filesystem:

sudo chroot debian-x86_64 /bin/bash -c "/debootstrap/debootstrap --second-stage"

With chroot I can enter the newly built file system installing packages as I would normally do on Debian:

sudo chroot debian-x86_64

Create the image

I create an empty image file named 'debian-x86_64.img.' I allocate 10 GB to this image, as Debian typically requires significant disk space. Given ample hard drive capacity, this allocation ensures the file system will not feel constrained:

dd if=/dev/zero of=debian-x86_64.img bs=1G seek=10 count=1

I create an ext4 file system:

sudo mkfs.ext4 debian-x86_64.img

and I mount it locally:

sudo mount -o loop debian-x86_64.img /mnt/loop/

Finally I copy the debian file system in it:

sudo rsync -av debian-x86_64/ /mnt/loop/

Umount the image:

sync
sudo umount /mnt/loop

Compile kernel

First of all get the kernel:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

Get into it

cd linux

And configure it. The configuration that works for Quemu is:

make kvm_guest.config

Finally, compile

make -jX

The kernel we are going to use is here:

arch/x86_64/boot/bzImage

Execute Qemu

Finally run Quemu (ref. 3):

sudo qemu-system-x86_64 -m 2G \
			-smp 2 \
			-kernel ~/repo/linux/arch/x86_64/boot/bzImage \
			-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0 nokaslr" \
			-drive file=~/debian-x86_64.img,format=raw \
			-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
			-net nic,model=rtw_8822ce \
			-enable-kvm \
			-nographic \
			-pidfile vm.pid \
			- 2>&1 | tee vm.log

The vm.log file will collect the dmesg from the running kernel. It's very useful for offline debugging, copy/pasting, etc.

Reference

  1. Qemu Direct Linux Boot
  2. This is a guyde for ARM64, but the same steps are valid also for x86_64: Debian ARM64 Qemu Guide
  3. Víctor Colombo's blog post: Linux kernel QEMU setup

Home / Top

Andi Shyti
email: andi (at) smida (dot) it
IRC: cazzacarna