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).
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
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
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
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.