Linux Device Drivers test environment setup

busyboxlinuxlinux-kernel

What is the best way to setup a test environment while working through Linux Device Drivers?

I have compiled a bzImage for x86 from the latest Linux source using x86_64_defconfig.

I have followed the Gentoo custom initramfs tutorial so that I am booting to an isolated filesystem based on Busybox. I use the exact same init file that they use. The only difference between what I am doing and what they do is that I am running on Ubuntu and download the latest Busybox x86_64 binary instead of using emerge.

On my Ubuntu 16.04 system, I am running

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -append "console=ttyS0" -initrd custom-initramfs.cpio.gz -nographic

where custom-initramfs.cpio.gz refers to the initramfs I built and compressed like in the Gentoo tutorial.

I run all of this and still end up with a kernel error, as seen below

[    2.893799] md: Waiting for all devices to be available before autodetect
[    2.894724] md: If you don't use raid, use raid=noautodetect
[    2.913768] md: Autodetecting RAID arrays.
[    2.914465] md: Scanned 0 and added 0 devices.
[    2.914879] md: autorun ...
[    2.915478] md: ... autorun DONE.
[    2.920719] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[    2.921465] Please append a correct "root=" boot option; here are the available partitions:
[    2.922493] 0b00         1048575 sr0  driver: sr
[    2.923069] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    2.923101] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.8.0-rc1+ #18
[    2.923101] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[    2.923101]  0000000000000000 ffff8800070ffde0 ffffffff81328158 ffff8800066aa000
[    2.923101]  ffffffff81b98e58 ffff8800070ffe60 ffffffff81124120 0000000000000010
[    2.923101]  ffff8800070ffe70 ffff8800070ffe08 ffffffff8112441e ffff8800070ffe78
[    2.923101] Call Trace:
[    2.923101]  [<ffffffff81328158>] dump_stack+0x4d/0x65
[    2.923101]  [<ffffffff81124120>] panic+0xca/0x1fc
[    2.923101]  [<ffffffff8112441e>] ? printk+0x43/0x4b
[    2.923101]  [<ffffffff81f4a364>] mount_block_root+0x175/0x229
[    2.923101]  [<ffffffff81f4a519>] mount_root+0x101/0x10a
[    2.923101]  [<ffffffff81f4a653>] prepare_namespace+0x131/0x169
[    2.923101]  [<ffffffff81f4a03c>] kernel_init_freeable+0x1c0/0x1d5
[    2.923101]  [<ffffffff818e7669>] kernel_init+0x9/0x100
[    2.923101]  [<ffffffff818ed30f>] ret_from_fork+0x1f/0x40
[    2.923101]  [<ffffffff818e7660>] ? rest_init+0x80/0x80
[    2.923101] Kernel Offset: disabled
[    2.923101] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

I am able to boot to initramfs though when booting locally and not using QEMU. This grub menu option works

menuentry 'linux latest' {
    linux /boot/bzImage-latest
    initrd /boot/custom-initramfs.cpio.gz
}

where bzImage and initramfs refer to the same default x86_64 config kernel image and the custom initramfs built before.

The issue seems to stem from QEMU not having the same access to devices in /dev that the local machine does.

What can I fix to make this work in a QEMU environment? My goal here is just to be able to get through kernel bootup and into some sort of minimal filesystem.

I just made my first device driver patch at work, which was exciting, and I want to continue learning more. Any help would be appreciated!

Best Answer

Self- taught kernel hacker here (and still maintain a small part of it).

Maybe not much of a definitive answer, but I'd firstly recommend using a small embedded board such as a raspberry pi, as during kernel development you'll need to use physical hardware sooner or later - software emulation and VMs just don't use the same drivers and code as physical hardware, or add extra layers of complexity when you're trying to figure out how something works that is already complex enough.

However, working on a secondary embedded system will involve using a cross compiler that may also cause issues. If you do have an older x86 system lying around, then use that - get used to setting up the system from scratch, as you will bork it sooner or later and the exercise of doing so isn't a bad thing, as real kernel development will involve developing on less than stable systems (wax on/wax off...).

In the absence of any secondary system to hack on, dual boot your main system and use the second system to work on - but make sure you back up everything, just in case.

Oh, and one final thought - don't use Ubuntu, fedora or any distribution where the user space is likely to change between updates - otherwise you'll end up debugging ghost issues. Use Debian, centos or another stable userspace, at least until you can instinctively spot such issues.

Related Question