Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Understanding the Environment

Container Image Structure

At that stage, you should have a desktop or web-based instance of VSCode connected to the running Docker container.

The main directory for this lab exercise is /root/workspace in the container filesystem, containing:

  • linux-6.6: a clone of the Linux kernel v6.6 sources you will modify, plus a pre-compiled, vanilla v6.6 kernel binary used as guest OS in a VM.
  • alpine.qcow2: a virtual disk image with a minimal root filesystem for the VM.
  • launch-vm.sh: a script that launches the VM using the pre-compiled kernel in linux-6.6 and alpine.qcow2 as the virtual disk.
  • shared-folder: a folder shared between the container and the VM for easy file transfer.

Alpine VM

Launching the VM

Place yourself in a terminal in /root/workspace and run:

root@container:~/workspace# ./launch-vm.sh

Inspect this script to see how the QEMU virtual machine manager/device emulator is invoked. Note the -kernel parameter (guest kernel binary) and -hda parameter (virtual disk). After a few seconds you should see the login prompt:

Welcome to Alpine Linux 3.19
Kernel 6.6.0 on an x86_64 (/dev/ttyS0)

alpine login:

🔑 VM Access Credentials. Log in to the VM with the username root and the password a.

The VM runs a minimal Alpine Linux installation, pre-installed with everything needed for the exercise. You can install extra software with the APK package manager (Alpine’s equivalent of apt-get).

In the VM, we can verify we are running the correct guest kernel:

alpine:~# uname -a
Linux alpine 6.6.0 #1 SMP PREEMPT_DYNAMIC Fri Sep  4 16:12:56 UTC 2026 x86_64 Linux

We can also list the PCI devices attached to the VM:

alpine:~# lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 Unclassified device [00ff]: Device 1234:cafe (rev 03)
00:02.0 Unclassified device [00ff]: Device 1234:f00d (rev 10)
00:03.0 Unclassified device [00ff]: Device 1234:beef (rev 01)
00:04.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:04.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:04.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:05.0 VGA compatible controller: Device 1234:1111 (rev 02)
00:06.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
00:07.0 Unclassified device [0002]: Red Hat, Inc. Virtio filesystem

The three Unclassified device [00ff] are the hardware components you will write drivers for in the next steps of this exercise.

SSH Access to the VM and File Transfers between the Container and the VM

SSH Access to the VM. The default console after launch-vm.sh is QEMU’s emulated serial output, which is not always stable (long commands and editors like vim may display poorly). For a stable console, and to open multiple terminals in the VM, SSH into it instead. QEMU forwards the VM’s SSH port (22) to port 1022 on the container:

root@container:~/workspace# ssh -p 1022 localhost

Transferring Files between the Container and the VM. The easiest way is to use the shared folder. For example, in the container:

root@container:~/workspace# echo "hello" > shared-folder/hello.txt

And in the VM:

alpine:~# cat shared-folder/hello.txt
hello

Files can also be transferred with scp.

Shutting Down the VM

Shut down the VM with:

alpine:~# halt

Wait until the kernel logs show reboot: System halted, then hit ctrl + a then x to return to the container’s terminal. You can use this same key combination at any time to abort the VM, e.g. if it hangs or crashes due to a bug in your drivers.

⚠️ ⚠️ ⚠️ Always try to shut down the VM properly with the halt command. Otherwise you risk corrupting the filesystem. If you brick the VM this way, you need to bring up a new container with a clean virtual disk, and transfer your work.

QEMU sometimes leaves the container’s console garbled on exit. If a command longer than one line displays badly, run reset in the container to fix it.

Linux Sources

Source Tree

The full Linux kernel v6.6 source tree is at /root/workspace/linux-6.6. Notable top-level folders include:

  • arch, containing the architecture-specific code.
  • mm, containing code related to memory management.
  • fs, containing the code of all filesystems supported by Linux.
  • init, containing the kernel initialisation C code.
  • drivers, containing the code for drivers.
  • include, containing the kernel header files.

In this exercise we will add new code to the last three folders.

Rebuilding the Kernel

Any modification to the sources of Linux requires rebuilding the kernel and relaunching the VM to take effect. To rebuild the kernel, from the root of the source tree:

root@container:~/workspace/linux-6.6# make

The build is incremental (only modified sources are recompiled) but may still take a bit of time, especially in slow environment (e.g., GitHub Codespaces). The resulting guest kernel binary is arch/x86_64/boot/bzImage.

Relaunching the VM after a Kernel Rebuild. Using reboot from within the VM after a new kernel is built will not load that new kernel, and the old version present in the VM’s memory will rather be reused. To effectively load a new kernel, you need to shut down the machine with halt, hit ctrl + a then x, and finally relaunch the launch-vm.sh script.