Skip to main content

QEMU Direct Linux Kernel Boot

Here, I will employ QEMU to emulate a minimal Linux x86_64 platform with a minimal root filesystem from scratch, as well as debugging with GDB:

  • Build Linux x86_64 kernel
  • Build Linux x86_64 rootfs(root filesystem)
  • Run QEMU
  • Debug with GDB

Why do I use QEMU to boot Linux kernel directly with skipping BIOS/UEFI boot procedures?

Use QEMU to launch a Linux kernel directly without having to make a fully bootable disk image. This is very useful for:

  • Linux kernel testing
  • root filesystem testing
  • arm system emulation

Prerequisites

On Ubuntu,

sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison

On macOS, you need create a Case Sensitive filesystem and use GNU GCC instead of Clang the following ways:

hdiutil create -size 20g -type SPARSE -fs "Case-sensitive HFS+" -volname brosx brosx.sparseimage
hdiutil attach brosx.sparseimage
hdiutil detach /Volumes/brosx -force
brew install gpatch gcc flock attr libtool libart
ln -s /opt/homebrew/bin/gcc-13 /opt/homebrew/bin/gcc
n -s /opt/homebrew/bin/gcc-13 /opt/homebrew/bin/cc
ln -s /opt/homebrew/bin/g++-13 /opt/homebrew/bin/g++
ln -s /opt/homebrew/bin/g++-13 /opt/homebrew/bin/c++
rm /opt/homebrew/bin/gcc /opt/homebrew/bin/cc /opt/homebrew/bin/g++ /opt/homebrew/bin/c++

Build Linux kernel

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.55.tar.xz
tar xvf linux-6.1.55.tar.xz
cd linux-6.1.55
# Use the default `x86_64` configuration file form `/x86/configs/x86_64_defconfig`
make ARCH=x86_64 x86_64_defconfig
# Tweak some options for GDB and initramfs
make menuconfig
make -j8

Generate kernel file ./arch/x86/boot/bzImage.

note

To extract vmlinux from bzImage,

./scripts/extract-vmlinux ./arch/x86_64/boot/bzImage >./arch/x86_64/boot/vmlinux

Build root filesystem

git clone https://github.com/buildroot/buildroot.git
cd buildroot
make menuconfig

Choose x86_64 as Target Architecture and ext4 root file system.

make -j8

Generate root filesystem disk ./output/images/rootfs.ext4.

Run QEMU

Copy bzImage and rootfs.ext4 to any host machine with QEMU available.

rsync -l ./linux-6.1.55/arch/x86/boot/bzImage destination_directory/
rsync -l ./buildroot/output/images/rootfs.ext4 destination_directory/
kernel="$PWD/linux_qemu/x86_64/bzImage"
vmlinuz="$PWD/linux_qemu/x86_64/vmlinux"
initrd="$PWD/linux_qemu/x86_64/rootfs.ext4"
img="$PWD/linux_qemu/x86_64/rootfs.ext4"
qemu-system-x86_64 \
-nographic \
-m 4G \
-kernel $kernel \
-append "earlyprintk loglevel=8 root=/dev/zero console=ttyS0"
qemu-system-x86_64 \
-nographic \
-m 4G \
-kernel $kernel \
-hda $img \
-append "earlyprintk loglevel=8 root=/dev/sda rootfstype=ext4 console=ttyS0" \
-netdev user,id=mynet,hostfwd=tcp::2222-:22 \
-device virtio-net-pci,netdev=mynet

Default password: root

Debug Linux kernel

qemu-system-x86_64 \
-s -S \
-nographic \
-m 4G \
-kernel $kernel \
-append "earlyprintk loglevel=8 root=/dev/zero console=ttyS0 nokaslr"

Options in details,

  • -s: allows port tcp::1234 for remote debug
  • -S: stop CPU until continue from GDB what is connected to tcp 1234 port
  • -append
    • nokaslr: turn off KASLR

Or with root filesystem,

qemu-system-x86_64 \
-nographic \
-m 4G \
-s -S \
-kernel $kernel \
-hda $img \
-append "earlyprintk loglevel=8 root=/dev/sda rootfstype=ext4 console=ttyS0 nokaslr" \
-netdev user,id=mynet,hostfwd=tcp::2222-:22 \
-device virtio-net-pci,netdev=mynet

Enter gdb,

$ gdb ./vmlinux

In gdb shell,

(gdb) target remote 10.6.64.243:1234
Remote debugging using 10.6.64.243:1234
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x000000000000fff0 in ?? ()
(gdb) continue
Continuing.

Resources

Daniel P. Berrangé » Blog Archive » make-tiny-image.py: creating tiny initrds for testing QEMU or Linux kernel/userspace behaviour

GitHub - dhruvvyas90/qemu-rpi-kernel: Qemu kernel for emulating Rpi on QEMU https://medicineyeh.wordpress.com/2016/03/29/buildup-your-arm-image-for-qemu/

Prepare the environment for developing Linux kernel with qemu. | by DaeSeok Youn | Medium