đź’» Kernel dev light setup

Summary

This explains my steps into creating a “lightweight” Linux kernel development environment using qemu.

Setup base system

Create the installation image

qemu-img create -f qcow2 <image-name>.qcow2 <size>

Install an Operating system of choice ( I use debian for this )

qemu-system-x86_64 -cpu host     \
                    -vga virtio  \
                    -enable-kvm  \
                    -usb -device usb-tablet \
                    -hda <qemu image> -boot d \
                    -cdrom <debian iso file> \
                    -serial stdio -m <ram> \
                    -smp <cpu>

Perform os installation then reboot using this command

qemu-system-x86_64 -nic user,hostfwd=tcp::1234-:22 \
                    -cpu host \
                    -vga virtio \
                    -enable-kvm \
                    -usb -device usb-tablet \
                    -hda <qemu image> -boot d \
                    -serial stdio \
                    -m <ram> -smp <cpu>

Prepare the system

On the graphical output do this

su
<input root password>
apt install ssh

You can now ssh into the vm to setup the required packages

ssh -p 1234 <username>@localhost
apt update
apt install build-essential \
			neovim \
  			libncurses-dev \
    		libssl-dev \
     		bc \
			libelf-dev \
  			git \
    		flex \
     		bison \
      		fakeroot \
       		libperl-dev \
        	qt5-qmake \
        	qtbase5-dev \
        	rsync

Build a new kernel

Now download the Linux sources

Execute as user

git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -b <kernel_version>
cd linux

Next is to build a kernel compatible with your vm

make mrproper && make localmodconfig

Compile it

make -j$(nrpoc)

Executed as root

make modules_install && make install

Ensure you have access to sbin to update grub in order to boot onto the new kernel.

echo "export PATH=/usr/sbin:$PATH" >> ~/.bashrc
source ~/.bashrc

Writing the export in the shell profile allow to not worry about exporting it again later

update-grub or grub-update

Now you’re done, reboot to start with the new kernel !

Compacting the qcow2 image

First off, install zerofree on the host

On the host

# Load nbd kernel module
sudo modprobe nbd max_part=8

# Connect the QCOW2 image to a /dev/nbd device
sudo qemu-nbd --connect=/dev/nbd0 working-image.qcow2

# Create partition mappings
sudo kpartx -av /dev/nbd0

# Identify partition mappings
sudo blkid /dev/mapper/nbd0p*

# Check and clear partition if needed
sudo e2fsck -f /dev/mapper/nbd0p1

# Ensure the partition isn't mounted
mount | grep /dev/mapper/nbd0p1  # should be empty

# Apply zerofree
sudo zerofree /dev/mapper/nbd0p1

# Cleanup mounts
sudo kpartx -dv /dev/nbd0
sudo qemu-nbd --disconnect /dev/nbd0

Now your image should be as minimal as possible !

Qemu keyboard emulation

To emulate a keyboard with qemu, you can add this flag to the launch command

qemu ... --monitor stdio ...

This will enable the qemu monitor on the current terminal

To trigger a keyboard plugged in

device_add usb-kbd,id=keyboard1

To trigger a keyboard removed

device_del keyboard1

Retrospective

Since then, I have tried many other methods, and even though qemu is practical, I rather used a more commonly use method like a dockerfile ( used in this project ). At the time this post was made, I was still studying at a school where there were no best practices and hand-holding.