The goal of this assignment is to be able to compile and boot the Linux kernel on the KVM-qemu virtual machine. If you have never built or installed a kernel before then please start this assignment early. We will use the Ubuntu distribution of Linux.
There are three parts to this system: the KVM-qemu virtual machine, the virtual machine's disk image, and your own build of the Linux kernel. Modern versions of Linux allow you to boot another version of Linux inside a virtual machine. In order to boot Linux you need something that looks like a disk that has all of the programs and the file system that Linux needs in order to run. Finally, we want to play with the kernel, so we want to compile it ourselves.
Unfortunately, the CS machines do not support KVM, so you will need to find a machine that does. If you can't find one, you can use CloudLab.
If you can't get set up with either a personal machine or cloud VM, let us know.
The instructions for this lab are deliberately non-explicit. One of the main goals is giving you the opportunity to read some documentation and figure things out for yourself, and almost all of the steps here can be accomplished many different ways. That said, if you're stuck on something for a long time, do ask questions. The failure modes of many of these tools can be cryptic.
You should be able to get your VM running inside KVM by specifying the location of the VM with -drive or -hda. You may want to append "--snapshot" after the file name of your VM. This ensures that no changes are made to your image during an execution so you can do something dangerous and have the original image file preserved.
Once you've been able to get your VM running inside KVM, try installing a package using aptitude to verify your VM has network access.
Make sure you have the necessary dependencies to build the kernel. You'll need at least the following (these are the apt
package names):
git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
Download the latest stable Linux kernel release (v5.8.2 when we built it last) from kernel.org.
make -C <kernel dir> O=$(pwd) defconfig
CONFIG_SATA_AHCI=y
(the above should set it automatically). This builds the SATA disk driver into the kernel, it is not built as a module. That will allow your kernel to boot off a (virtual) SATA drive without having to load a module to do it.make INSTALL_MOD_PATH=<install_mod_dir> modules_install
After your copy your kernel modules, depending on how you boot,
you might need to run grub
-related utility (the
bootloader) to notify it that you are booting a new kernel from this
disk. Hint: if you are using the "-kernel" option below, you shouldn't
need to.
For the curious, other methods for manipulating your virtual disk and file system from the host include:
qemu-img
convert -O raw test.qcow2 test.raw
, and then do a loopback
mount mount -o loop,offset=32256 /path/to/image.img
/mnt/mountpoint
. Note, your offset might be different from
mine (maybe fdisk can help you), but loopback mounts are fast.Here is a good reference on qemu images.
# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.
start on stopped rc or RUNLEVEL=[2345]
stop on runlevel [!2345]
respawn
exec /sbin/getty -L 115200 ttyS0 vt102
Please complete a short writeup that you will print out and bring to class.
Identify completely your hardware and software.
Explain any changes you made to the kernel build process and why.
Report your qemu command line.
Boot the Kernel, and run dmesg
to capture the kernel output from the
boot. In your writeup, report the elapsed wall clock time for your boot, and compare that with the time reported by the kernel. Are they the same? Why or why not?
For each device, quote the parts of the dmesg
output that show the kernel discovering that device, and then report
what kind of device it is, and how you made your determination. You may also use lspci
.Please only quote a maximum of 3 lines.
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd = open("/dev/urandom", O_RDONLY);
char data[4096];
read(fd, &data, 4096);
close(fd);
fd = open("/dev/null", O_WRONLY);
write(fd, &data, 4096);
close(fd);
}
$lx_current()
helper function provided by GDB.info registers
on QEMU console to get this value. If you have more than one CPU provisioned on your VM, make sure that you are looking at the correct register value.nopti
? You can use -append
in your QEMU command line to update the kernel command line.
Please think of your report like the papers we are reading for the class. Organize the information that you gathered and present it logically. For example, early in your report specify your experimental platform, including the hardware, the OS, whether you are running qemu or a hypervisor, etc. Include anything relevent to understand the results, but keep your description concise. Of course balancing completeness and concision is difficult, but that balance is generally well accomplished by the (modern) papers we read.
Some people use virsh
to manage their VM. This can be sort of useful, but it obscures exactly what is going on, for example with your exact command line to qemu. I would suggest not using it.
Please report how much time you spent on the lab.