Hafnium

Hafnium is a hypervisor, initially supporting aarch64 (64-bit ARMv8 CPUs).

Further details are available in the design doc.

Getting the source code

git clone --recurse-submodules sso://hafnium/hafnium && (cd hafnium && f=`git rev-parse --git-dir`/hooks/commit-msg ; curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f)

To upload a change for review:

git push origin HEAD:refs/for/master

Building

Compiling the hypervisor

By default, the hypervisor is built for an aarch64 QEMU target by running:

make

To build for the HiKey board, change the target platform:

PLATFORM=hikey make

To build using gcc instead of clang, the aarch64 variant must be installed:

sudo apt install gcc-aarch64-linux-gnu
GCC=true make

The compiled binary is stored in out/{clang,gcc}_aarch64/hafnium.bin.

Running on QEMU

You will need at least version 2.9 for QEMU. The following command line can be used to run Hafnium on it:

qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -machine virtualization=true -kernel out/aarch64/qemu/hafnium.bin

Though it is admittedly not very useful because it doesn't have any virtual machines to run. The next sections describe how to build an image that can be run using the following command-line:

qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -machine virtualization=true -kernel out/aarch64/qemu/hafnium.bin -initrd initrd.img -append "rdinit=/sbin/init"

Hafnium RAM disk

Hafnium expects to find the following files in the root directory of its ramdisk:

  • vmlinuz -- the kernel of the primary VM.
  • initrd.img -- the initial ramdisk of the primary VM.
  • vms.txt -- optionally describes the secondary VMs.
  • kernels for the secondary VMs, whose names vary and are described in vms.txt.

Format of vms.txt file

The format is currently one line per secondary VM, with the following format:

<memory-size-in-bytes> <number-of-cpus> <kernel-filename>

For example, the following defines two secondary VMs, the first one with 1MB of memory, 2 CPUs and kernel image called kernel0, while the second one has 2MB of memory, 4 CPUs and a kernel image called kernel1.

1048576 2 kernel0
2097152 4 kernel1

Creating a hafnium RAM disk

Assuming that a subdirectory called initrd contains the files listed in the previous section, we can build initrd.img with the following command:

cd initrd; find . | cpio -o > ../initrd.img; cd -

Primary VM

Kernel

The linux kernel for the primary VM can be built using the following command-line:

git clone https://github.com/torvalds/linux.git
cd linux
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j24

The compiled image is stored in arch/arm64/boot/Image. This should be copied to the Hafnium ramdisk's root as vmlinuz.

Kernel Module

From the hafnium root directory, the following commands can be used to compile the kernel module, replacing <kernel-path> with the path to the kernel built in the previous section:

cd hafnium/driver/linux/
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- KERNEL_PATH=<kernel-path> make

The compiled module is called hafnium.ko, and should be copied into the ramdisk described in the next section.

Busybox RAM disk

An initial ramdisk for the primary VM containing busybox can be built with the following commands:

git clone git://busybox.net/busybox.git
cd busybox
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make menuconfig

At this point you should ensure that the option Settings > Build static binary (no shared libs) is selected. Then you can proceed with the following commands:

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j24
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make install
cd _install
mkdir proc
mkdir sys
mkdir -p etc/init.d
cat <<EOF > etc/init.d/rcS
#!bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
EOF
chmod u+x etc/init.d/rcS
grep -v tty ../examples/inittab > ./etc/inittab

At this point you can copy into the current directory additional files you may want in the ramdisk, for example, the kernel module built in the previous section. Then run the following commands:

find . | cpio -o -H newc | gzip > ../initrd.img
cd ..

The resulting file is initrd.img. It should be copied to the Hafnium ramdisk's root.