To study Linux kernel, I need to setup a development environment to run/debug modified kernel. Two VM solutions are considered. One is KVM. And another is QEMU.
KVM (Kernel Virtual Machine) is a Linux kernel module that allows a user space program to utilize the hardware virtualization features of various processors. Today, it supports recent Intel and AMD processors (x86 and x86_64), PPC 440, PPC 970, S/390, ARM (Cortex A15), and MIPS32 processors.
QEMU can make use of KVM when running a target architecture that is the same as the host architecture. For instance, when running qemu-system-x86 on an x86 compatible processor, you can take advantage of the KVM acceleration - giving you benefit for your host and your guest system.
My requirement is to debug ARM Linux on X86 machine. So I choose QEMU.
Prerequisites
- Linux source code This could be download from git repository of kernel.org
-
Linaro GNU/Linux toolchain for ARM
apt-get install gcc-arm-linux-gnueabi
- cpio, an utility to create the Linux filesystem image
apt-get install cpio
- QEMU, qemu-system-arm
apt-get install qemu-system-arm
- etc like native gcc for x86 and other tools needed for kernel compilation
Target board selection
Kernel source code package includes some default config file for each arch. They are located in arch/arm/configs.
QEMU also has some machines supported by default. Type “qemu-system-arm -M help” to show the supported machines list.
According to Balau’s blog, I choose ARM Versatile Express for Cortex-A9 as my target board.
Linux Kernel: Below environment variables should be set before compile kernel.
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
The config file for ARM Versatile Express for Cortex-A9 board is vexpress_defconfig.
make vexpress_defconfig
Then build the kernel:
make -j 4 all
The generated zImage is located in arch/arm/boot/zImage.
Hello World
Write a simple c program “hello world”. Compile it with below command.
arm-linux-gnueabi-gcc -static init.c -o init
Then create ramdisk which includes this hello world.
echo init|cpio -o --format=newc > initramfs Run kernel and hello world ----------- **-M** vexpress-a9 means using Versatile Express board **-kernel** specify the kernel image **-initrd** specify the ramdisk **-serial stdio** QEMU can redirect the serial port of the emulated system on the host terminal **"console=ttyAMA0"** Linux can display its messages on the first serial port by passing "console=ttyAMA0" as a kernel parameter **-curses** Normally, QEMU uses SDL to display the VGA output. With this option, QEMU can display the VGA output when in text mode using a curses/ncurses interface. Nothing is displayed in graphical mode
qemu-system-arm -M vexpress-a9 -kernel workspace/code/linux/arch/arm/boot/zImage -initrd workspace/code/hello_world/initramfs -serial stdio -append "console=ttyAMA0" -curses
If you need GUI, you can execute below command.
qemu-system-arm -M vexpress-a9 -kernel workspace/code/linux/arch/arm/boot/zImage -initrd workspace/code/hello_world/initramfs -append "console=tty1"
Done!
Reference
- https://balau82.wordpress.com/2012/03/31/compile-linux-kernel-3-2-for-arm-and-emulate-with-qemu/
- http://saurorja.org/2011/07/04/creating-a-minimal-kernel-development-setup-using-kvmqemu/
- http://blog.vmsplice.net/2011/02/near-instant-kernel-development-cycle.html
- https://blog.nelhage.com/2013/12/lightweight-linux-kernel-development-with-kvm/
- http://ytliu.info/blog/2014/10/22/debugging-linux-kernel-using-gdb-and-qemu/