0

I'm currently beginning kernel programming by implementing a block device driver. I was able to make a "simple" implementation and I would like to go further into what block sub-system offers.

To do so I would like to emulate my own operating system using qemu to avoid crashing my development OS each time I make a mistake into the kernel device code.

Host system configuration

On my work station I'm using Debian 9 running with kernel 4.9.0.

$ uname -a
Linux PC325 4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux

Image disk creation

To create the virtual machine, I have created a 500M raw image with dd if=/dev/zero of=vm-image.raw bs=1M count=512

And then format it to ext4 using mkfs.ext4 vm-image.raw


UPDATE after @meuh comment:
I have then populated the disk image as follow:

mount vm-image.raw /mnt
mkdir /mnt/dev /mnt/lib /mnt/proc /mnt/root /mnt/run /mnt/sbin /mnt/sys
cp -r /etc /mnt/
cp -r /lib/systemd /mnt/lib
ln -s /lib/systemd/systemd /mnt/sbin/init

I'm now trying to boot the emulated operating system but I'm having some trouble configuring it.

Run command

$ qemu-system-x86_64 -k fr -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) -hda vm/vm-image.raw -append "initrd=/boot/initrd.img-$(uname -r) root=/dev/sda rw console=ttyS0" -nographic

Boot trace

[...] Kernel boot sequence [...]

Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [    2.015241] tsc: Refined TSC clocksource calibration: 3392.292 MHz
[    2.016768] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x30e5dd94d34, max_idle_ns: 440795304975 ns
[    2.895630] random: fast init done
Begin: Waiting for suspend/resume device ... Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
[   11.111765] random: crng init done
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
done.
Gave up waiting for suspend/resume device
done.
Begin: Will now check root file system ... fsck from util-linux 2.29.2
[/sbin/fsck.ext4 (1) -- /dev/sda] fsck.ext4 -a -C0 /dev/sda 
/dev/sda: clean, 3607/32768 files, 12617/131072 blocks
done.
[   35.528453] EXT4-fs (sda): mounted filesystem with ordered data mode. Opts: (null)
done.
Begin: Running /scripts/local-bottom ... done.
Begin: Running /scripts/init-bottom ... done.
run-init: /sbin/init: No such file or directory
[   35.569247] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[   35.569247] 
[   35.570469] CPU: 0 PID: 1 Comm: run-init Not tainted 4.9.0-6-amd64 #1 Debian 4.9.82-1+deb9u3
[   35.571599] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[   35.572695]  0000000000000000 ffffffff9792e074 ffff974c05e14d00 ffffa66e8003feb8
[   35.573741]  ffffffff9777cfbd ffff974c00000010 ffffa66e8003fec8 ffffa66e8003fe60
[   35.574780]  a4112d94e56af84a ffff974c05e14d80 0000000000000100 ffff974c05e84490
[   35.575793] Call Trace:
[   35.576132]  [<ffffffff9792e074>] ? dump_stack+0x5c/0x78
[   35.576815]  [<ffffffff9777cfbd>] ? panic+0xe4/0x23f
[   35.577453]  [<ffffffff9767c2de>] ? do_exit+0xade/0xae0
[   35.578136]  [<ffffffff978058b4>] ? vfs_write+0x144/0x190
[   35.578830]  [<ffffffff9767c313>] ? SyS_exit+0x13/0x20
[   35.579510]  [<ffffffff97603b7f>] ? do_syscall_64+0x8f/0xf0
[   35.580223]  [<ffffffff97c113b8>] ? entry_SYSCALL_64_after_swapgs+0x42/0xb0
[   35.581209] Kernel Offset: 0x16600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[   35.582584] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[   35.582584] 

Issues

1 - Trying to read floppy device

At boot it seems that the kernel tries to read from a floppy device which doesn't exist or is not readable. The kernel gave up after 30 try so it's not a critical issue but it's slowing down the boot sequence by 30 seconds.

I tried to run qemu with -no-fd-bootchk option but it didn't change anything


UPDATE:
Precising -fda floppy.img with floppy.img being a raw zeroed image of 1ko suppress floppy related error messages and save up to 20 seconds at boot. However as you can see in boot trace, /scripts/local-block is still beeing run several times and take up to 10 seconds before passing to next step.


2 - Unable to initialize system


UPDATE after @meuh comment:

It seems that kernel is not able to find a valib init script. However /sbin/init is present on the disk image and is a symbolic link to /lib/systemd/systemd.

I'm experiencing a kernel panic but I don't know what is causing it.


Question

I'm very new to qemu and I think I'm not so far from having my emulated system working but I'm not able to go further.

I tried to play with parameters but I can't find a solution to be able to fully boot and have a bash prompt instead of initramdisk one.

UPDATED after @meuh comment:
What should I copy to disk image to be able to init the system ?

  • 1
    You dont have anything on your disk image. You need to mkfs it and copy some minimal files and directories, like /dev. – meuh Apr 16 '18 at 15:25
  • I should have precised that I did format the image to ext4. however I didn't create any directory on the disk image. Question Updated – Arkaik Apr 16 '18 at 15:50
1

I have not done this, as typically one would install qemu from an iso or an existing qemu image, so there is probably an easier way than the following. What you are missing is pretty much equivalent to the filesystem you would need for a chroot.

One thing to try is

sudo debootstrap --arch=amd64 unstable ~/debian-tree/

which descends and unpacks about 300Mbytes of files which you can "boot" as a systemd container and test with

sudo systemd-nspawn -D ~/debian-tree/ -b

See man machinectl. You can mount your qemu image by making it a block device:

sudo apt-get install qemu-utils
sudo modprobe nbd
ls /dev/nbd*   # gives /dev/nbd0  /dev/nbd1 ...
sudo qemu-nbd -c /dev/nbd0 /my/vm-image
sudo mount /dev/nbd0 /mnt/...  # nbd0p1 if you have partitioned
sudo rsync -HSaxX ~/debian-tree/ /mnt/... 

and copy this tree to it. When running qemu you typically need to provide a larger VM size to avoid crashes:

qemu-system-x86_64 -m 512M ... -machine pc,accel=kvm  -cpu host -enable-kvm

Using -boot d might avoid accessing the floppy.

  • Awesome !!! You just learnt me a incredible tool :) It's working like a charm. Just need to find how to set root password to 'root' by default and I'm done. Just for information using -boot d doesn't avoid floppy access. – Arkaik Apr 17 '18 at 13:50
  • To set the root password, you can use sudo systemd-nspawn -D ~/debian-tree/ /bin/sh to just get a shell and then use the passwd command there to set the password... Or perhaps just simply sudo systemd-nspawn -D ~/debian-tree/ /usr/bin/passwd root will work too. – filbranden Apr 18 '18 at 6:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.