Running the Raw Linux Kernel in QEMU
In the previous post we learned how to run a packaged Linux distribution in QEMU. This time, let’s explore running a raw Linux kernel in QEMU.
A Brief Introduction to Initial Ramdisk
Many Linux distributions ship a small, generic kernel image. The device drivers are included as loadable kernel modules and stored in file system, it is just not practical to include all the device drivers in the kernel image itself. On my machine, the size of vmlinuz-linux
is only 6.3 megabytes:
|
This presents a challenge of detecting and loading the necessary modules to mount the root file system during boot time. It’s a chicken-and-egg problem. Additionally, the root file system may require special preparations to mount, such as being on an encrypted partition.
To address these challenges, the initial ramdisk comes into play as a temporary, RAM-based root file system. It contains user-space utilities that detect hardwares, descover devices, load necessary modules, and mount the actual root file system. Once it is loaded into memory, a simple yet sufficient environment is set up for the Linux kernel to complete the boot process. This environment is often called “early user space”.
On my machine, the initial ramdisk image is located in the boot partition with the name initramfs-linux.img
. Not surprisingly, it is larger than the Linux kernel image itself:
|
We can examine the contents of the image by using command lsinitcpio /boot/initramfs-linux.img
. Indeed, it contains a simplified root system with various helper tools:
|
Creating an Initial Ramdisk
The command to create an initial ramdisk in Arch Linux mkinitcpio
, but it may defer in other distributions.
Quoting from the mkinitcpio
manual page:
(mkinitcpio) creates an initial ramdisk environment for booting the Linux kernel. The initial ramdisk is in essence a very small environment (early userspace) which loads various kernel modules and sets up necessary things before handing over control to init. This makes it possible to have, for example, encrypted root filesystems and root filesystems on a software RAID array. mkinitcpio allows for easy extension with custom hooks, has autodetection at runtime, and many other features.
Let’s proceed with creating the initial ramdisk.
|
Configuring and Building the Linux Kernel
Clone the Linux source code, and configure the Linux kernel with make ARCH=x86_64 menuconfig
.

Save the configurations and exit the configuration interface, now let’s compile the kernel image. The compiled kernel image will be located at arch/x86/boot/bzImage
.
|
Booting the Linux Kernel in QEMU
Now that we have both the Kernel image and the initial ramdisk, it’s time to boot the Linux kernel in QEMU.
|
You will soon see the [rootfs] #
prompt, indicating that we are now in the environment provided by the initial ramdisk. Cheers!