Now that you have a fancy new kernel built with Rust support (from previous post) how do we easily test it? The easiest way (subjectively) is to use QEMU’KVM. One possible way is to create the initial ramdisk and separately a root filesystem and boot that way. The other is to just boot from a disk image with a completely installed OS on it and still specify what kernel you want to use. A good guide to look at to get that setup with Alpine is this post.

In my case I am using a disk image I setup with Pop!_OS. In that case, with the way I have it installed the kernel options are slightly different so my QEMU invocation looks like this:

qemu-system-x86_64 -drive file=~/development/pop\!_os_base.qcow2 -m 8192 -cpu host --enable-kvm -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 rw"

So we’re using a root filesystem from the qcow2 file but specifiying a different kernel to boot with and telling that kernel where to find the root (which partition on the disk image). So when we boot this what do we find? Well we get a login screen like normal but we can’t seem to use our mouse. We can use the keyboard and tab through things and login but the mouse is inoperable. So everything seems to work except the mouse. What’s going on?

Well, we can actually boot that disk image without the kernel because one already resides on that disk image and use that one and see what the difference in behavior is. So, does the mouse work? It does. That’s great because now we at least have a place to compare differences between one way that works and one way that does not.

Let’s look at the modules that are loaded but first let’s add the ability top SSH into our virtual machine by adding this to our invocation of QEMU.

-net user,hostfwd=tcp::10022-:22 -net nic

By doing this our guest can access the network and we can SSH into it (once installed and enabled) by using ssh <user>@localhost -p 10022. So once our guest is booted (assuming a Debian based system like Pop!_OS) then we simply run this at the terminal

sudo apt install openssh-server -y
sudo systemctl enable ssh
sudo systemctl start ssh

Now, let’s SSH in and look at those modules with lsmod.

When we do this we see a very extensive list of modules. I won’t include them all here but I will show the output format and one that caught my attention.

Module                  Size  Used by
...
psmouse               212992  0
...

So, the psmouse module is being loaded by this kernel. Let’s do the same thing again but boot with our kernel and SSH in. But when we do this we find a different problem. We can’t SSH in with the kernel we built it just hangs and then eventually gives us some unhelpful error. Why is that? Let’s go back and look at the module list from when we booted using the kernel included in the Pop!_OS installation.

Module                  Size  Used by
...
psmouse               212992  0
e1000                 180224  0
...

A picture about the problem should be starting to emerge. Something about the kernel that we build isn’t the same as the one included with the Pop!_OS distribution. Other than being newer, which we knew and including Rust support, which we also knew it should be the same.

If by now you’ve guessed the problem I wouldn’t be surprised. The kernel that ships with Pop!_OS has loadable module support which we also built into our kernel. But what it has that we don’t have are all the modules to support it on disk. What’s the easiest way to test / confirm this is the problem? Well, we can just build those two things into the kernel and not rely on modules for them.

So find the two options in the .config file and change =m to =y.

...
CONFIG_MOUSE_PS2=y
...
CONFIG_E1000=y
...

Rebuild the kernel and try again.

make LLVM=1 bzImage
qemu-system-x86_64 -drive file=~/development/pop\!_os_base.qcow2 -m 8192 -cpu host --enable-kvm -net user,hostfwd=tcp::10022-:22 -net nic -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 rw"

We should find our mouse works. If we try to SSH into the guest with port 10022 we should also find that it works.

Could we use the modules that are on the disk already? Almost certainly not because we had to disable MODVERSIONS which is a mechanism that would potentially allow for that but I’m uncertain. So what’s the next step? Well we want to build the modules for our kernel and load them. What’s an easy way to do this? We’ll explore that in the next day or two.

I’d like to go down the path of using a directory on the host as our root filesystem. That should be possible using QEMU’s 9p passthrough filesystem. Stay tuned!