A lot has changed in a year, and progress stops for no man or woman. I documented last year how to get a standard Linux distribution running on the ARM powered Samsung Series 3 Chromebook, those steps also apply to the new HP 11 Chromebook. Thanks to the Cortex-A15 based Exynos 5 Dual by Samsung Electronics 5250 at the heart of these devices, we have some additional ARMv7 extensions that enable hardware virtualization, so this time round I'm going to show you how to enable virtualization on your Chromebook, utilising the KVM hypervisor.
Now I'll be honest, this isn't actually something new. The fine folks at Virtual Open Systems have documented how to do this already. So why am I going to do the same? Well my steps will differ from Virtual Open Systems' by using the current stable Linux kernel (3.12.2 as of this post), and I will also be using KVM-tool to manage the virtual machines. KVM-tool is a lightweight tool that is suited to testing and development. It allows you to quickly bring up a virtual machine with very low overheads.
CAUTION
These steps will only work on the Samsung Series 3 Chromebook due to upstream not having support for the HP 11. Also you will lose WiFi functionality, so make sure you have a USB Ethernet adapter.
Get the latest stable upstream kernel source:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout origin/linux-3.12.y -b linux-3.12.y
Apply the attached patches to fix an issue with DMA and also RTC (these patches should not be required after kernel 3.13.0):
git apply DMAfix.patch
git apply RTCfix.patch
Pull in the KVM-tool source:
git remote add kvm-tool git://github.com/penberg/linux-kvm.git
git remote update
git merge kvm-tool/master
Save the attached Chromebook.config file to PATH_TO_linux-stable/.config
Next step is to build the kernel. Make sure you have a recent cross-compiler, Linaro provide a build of GCC 4.8:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage dtbs
Copy the resulting binaries to a safe location for future use. The binaries are located at linux-stable/arch/arm/boot/uImage and linux-stable/arch/arm/boot/dts/exynos5250-snow.dtb
For the virtual machine guests, we will use the same kernel source as that running on the Chromebook host. As KVM tool provides a para-virtualised environment, so the guest operating system requires some .config options to be enabled in order to make use of any virtual devices. Here are the options required and an explanation of those options:
The guest must also have support for mach-virt or also known as the "linux,dummy-virt" machine, which is the virtual platform targeted by kvm tool.
The attached guest.config file has all the necessary config options enabled, just download it and save it to PATH_TO/linux-stable/.config
Then build the kernel:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all
Build KVM-tool:
cd tools/kvm
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
The result is the lkvm binary.
Again, copy the zImage to a safe place for future usage.
To enable access to the virtualization extensions, we need to boot the Chromebook into what is known as Hyp Mode (more information on Hyp Mode can be found at Chapter 27 of the Cortex-A Series Programmer’s Guide. To be able to enter Hyp Mode, we need to use a secondary bootloader as the Chromebook’s bootloader doesn’t support entering this higher privileged run level.
To do this we will build a version of u-boot. Rather than use upstream’s u-boot source tree, we will use Virtual Open Systems’ tree as they have integrated many of the fixes needed to fully support Hyp mode, and also have an easy to use script for building u-boot.
git clone git://github.com/virtualopensystems/u-boot.git
cd u-boot
./scripts/build.sh
Get your target root filesystem. Make sure that your target Distribution is built for Hard Float.
Obtain a target SD Card (I am using a 32GB class 10 micro-SD card with adapter) Now that the pre-requisites are completed, it's time to move onto preparing the target SD card. Insert the card into your desktop/laptop and note the device id, running 'dmesg' from a terminal after inserting the card will show you something along the lines of 'sd 6:0:0:0: [sdX] Attached SCSI removable disk'
Depending on your SD card reader it could also show up as mmcblk0. Replace 'sdX' with the correct id for your card. Ensure the target card is un-mounted and not ejected.
Virtual Open Systems supply a simple and friendly script that takes care of the numerous steps needed to get a working SD card, it is in the u-boot tree that we chacked out. It is always good practise to verify scripts before executing them, so by all means do have a look at it before running the command below.
cd PATH_TO/u-boot
sudo ./scripts/sdcard.sh /dev/sdX
The script creates 4 partitions:
Now that we have the target card almost ready we need to extract our filesystem to the root partition. Mount the correct partition somewhere (in this case we are using '/mnt')
sudo mount /dev/sdX4 /mntcd /mnt
Replace the path to the root filesystem below with the correct one for your choice
sudo tar xvpf ~/Downloads/target_rootfs.tar.bz2
sudo umount /dev/sdX4
Copy the supporting files for u-boot
sudo mount /dev/sdX3 /mnt
sudo cp /PATH_TO_BINARY/uImage /mnt
sudo cp /PATH_TO_BINARY/exynos5250-snow.dtb /mnt
sudo umount /dev/sdb3
Copy the kvm-tool binary
sudo mount /dev/sdX4 /mnt
sudo cp PATH_TO/linux-stable/tools/kvm/lkvm /mnt/usr/bin
Copy the guest kernel to the SD card
sudo cp PATH_TO_GUEST/zImage /mnt/home
sudo umount /dev/sdX3
Once you have completed the above steps, you are now ready to boot your Chromebook, just insert the SD card and boot. At the boot verification screen press Ctrl+U and it will boot from the SD card. Don’t be alarmed when you see a screen with timer information, give it a minute or two to settle down and it will then boot into Linux.
Once you have logged in you can run KVM-tool by opening up a terminal and running:
lkvm run /home/zImage --balloon --network trans=mmio,mode=user --console virtio –c 2 –m 1024 -p “console=hvc0,38400”
This will boot your VM with 2 CPUs (-c 2), 1 GB of memory (-m 1024), a network interface and memory ballooning.
As we are not specifying a disk image, lkvm will automatically mount the host file-system at /host using 9pfs. This provides an easy way to transfer files between guest and host.
See how much memory is available from within the guest:
$ free total used free shared buffers cached Mem: 1035068 42388 992680 0 1764 10900 -/+ buffers/cache: 29724 1005344 Swap: 0 0 0
Now, we can steal 256M from the guest by executing the following on the host:
$ lkvm list PID NAME STATE ------------------------------------ 8180 guest-8180 running default shut off $ ./lkvm balloon -n guest-8180 -i 256
Then, back on the guest:
$ free total used free shared buffers cached Mem: 772924 42220 730704 0 1764 10912 -/+ buffers/cache: 29544 743380 Swap: 0 0 0