How to run the Raspberry Pi Os in a virtual machine with Qemu and Kvm

Although many operating system are available for the Raspberry Pi, the official one is the Raspberry Pi Os. The operating system is made to run for the arm architecture, and can be easily installed on the SD card which will be used as the main Raspberry Pi storage device. Sometimes we may want to perform some tests or try some applications without having a physical Raspberry Pi machine; in this tutorial we will see how we can create a virtual machine with the Raspberry Pi Os system using Qemu and Kvm (Kernel Virtual Machine).

In this tutorial you will learn:

  • How to install qemu and kvm
  • How to download and check the integrity of the latest Raspberry Pi Os version (Buster)
  • How to run the Raspberry Pi Os in a virtual machine

How to run the Raspberry Pi Os in a virtual machine with Qemu and Kvm

How to run the Raspberry Pi Os in a virtual machine with Qemu and Kvm

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution independent
Software qemu, qemu-system-arm, kvm and git
Other None
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

Installing qemu

Qemu, as defined on the official website is a “generic and open source machine emulator and virtualizer”. We can use it to run operating system for any type of machine. On Linux it is often used in combination with kvm, which is a full virtualization solution included in the kernel. To be able to virtualize our Raspberry Pi Os we need to install it on our favorite distribution, together with the qemu-system-arm package, which provides the system emulator for ARM systems. Qemu and kvm are available in the software repositories of the main Linux distributions. To install them on Fedora, we can use the dnf package manager:

$ sudo dnf install @virtualization qemu-system-arm


Here we installed the virtualization package group (notice the @ prefix): it includes everything needed for virtualization on Fedora, except for the qemu-system-arm package, that we installed separately.

On Debian and Debian-based distributions we can launch the following commands to synchronize our distribution with the remote repositories and get the needed packages installed on our system:

$ sudo apt-get update && sudo apt-get install qemu-system-arm qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virtinst libvirt-daemon virt-manager

Downloading and verifying the latest Raspberry Pi Os image

We can download the latest release of the Raspberry Pi Os from the official Raspberry Pi site. We can basically choose between 3 versions of the system: some are more minimal, others comes with a larger set of packages and a
graphical Desktop already installed. The download links are the following:

In this tutorial we will use the Raspberry Pi Os “lite” version. Downloading it using a web browser it’s just a matter of clicking on one of the links provided above. If we want to download it from the command line, instead, we can use tools like wget or curl:

# Using wget
$ wget https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-01-12/2021-01-11-raspios-buster-armhf-lite.zip

# Using curl
$ curl -O https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-01-12/2021-01-11-raspios-buster-armhf-lite.zip

By executing one of the two commands above, the image will be downloaded in the current working directory. Once the download is complete we can verify the integrity of the image by comparing its sha256sum with the one provided on the website.
In our case the hashsum should be d49d6fab1b8e533f7efc40416e98ec16019b9c034bc89c59b83d0921c2aefeef. To verify it we can run the following command:

$ sha256sum 2021-01-11-raspios-buster-armhf-lite.zip

The command above, in our case returns the following result:

49d6fab1b8e533f7efc40416e98ec16019b9c034bc89c59b83d0921c2aefeef  2021-01-11-raspios-buster-armhf-lite.zip

You can see that the two hashsums matches, so we are good to go. What we need to do now, is to extract the image, since it is zipped. To do that we can run the following command:

$ unzip 2021-01-11-raspios-buster-armhf-lite.zip


Since the kernel included in the official system image can’t be booted directly from Qemu, we must clone a git repository which contains a series of kernel built for this exact purpose. We will see how to do this in the next section.

Obtaining qemu-ready kernels from github

The repository we need to clone from github is dhruvvyas90/qemu-rpi-kernel. All we have to do is to run the following command:

$ git clone https://github.com/dhruvvyas90/qemu-rpi-kernel

The cloning process could take a while to finish, that depends on the speed of your internet connection. Once the repository is cloned, we are good to go. Here is its content:

$ ls qemu-rpi-kernel
kernel-qemu-3.10.25-wheezy   README.md
kernel-qemu-4.14.79-stretch  tools
kernel-qemu-4.19.50-buster   versatile-pb-buster-5.4.51.dtb
kernel-qemu-4.4.34-jessie    versatile-pb-buster.dtb
kernel-qemu-5.4.51-buster    versatile-pb.dtb
native-emuation

Since we want to emulate the latest version of the Raspberry Pi Os, the files we need are kernel-qemu-4.19.50-buster and versatile-pb-buster.dtb. The first is the actual kernel image, the second is a device tree blob. What is the purpose of this file?

To describe the hardware available on a system on a Raspberry Pi board, DTS (Device Tree Source) files are used; the compiled version of those files are called DTB and stored in files with the .dtb extension. In our case we could alternatively use the kernel-qemu-5.4.51-buster, together with the versatile-pb-buster-5.4.51.dtb file.

Emulating the Raspberry Pi Os

With all the needed files in place, we can finally virtualize the Raspberry Pi Os image. Please notice that here I assume the working directory is the same where we downloaded the system image. Before we run the actual command, only on Debian we need to start the default NATed bridged network, which is not started automatically; to do that we must run:

$ sudo virsh --connect=qemu:///system net-start default

To make it start automatically, we can run:

$ sudo virsh --connect=qemu://system net-autostart default

Now, to build the virtual machine, we must run the following command:

$ sudo virt-install \
  --name rpios  \
  --arch armv6l \
  --machine versatilepb \
  --cpu arm1176 \
  --vcpus 1 \
  --memory 256 \
  --import  \
  --disk 2021-01-11-raspios-buster-armhf-lite.img,format=raw,bus=virtio \
  --network bridge,source=virbr0,model=virtio  \
  --video vga  \
  --graphics spice \
  --boot 'dtb=qemu-rpi-kernel/versatile-pb-buster.dtb,kernel=qemu-rpi-kernel/kernel-qemu-4.19.50-buster,kernel_args=root=/dev/vda2 panic=1' \
  --events on_reboot=destroy

A virt-viewer window should appear; in there we should be able to visualize the Raspberry Pi Os booting:

rpi-os-boot


Let’s take a brief look at the options we used to build the virtual machine with the virt-install command; some are pretty obvious, other a little more obscure.

First of all we used the --name option: with it we can set the name of the virtual machine instance (it should be unique). The second option we used is --arch: it is needed to request a non-native CPU architecture for the guest
system; if we don’t use it, the host architecture is assumed.

With the --machine option we pass the type of machine to emulate to qemu: in this case we used versatilepb. With the --cpu option we configure the CPU model and features exposed to the guest; here we used arm1176, since the
Raspberry Pi is based on the arm architecture.

The --vcpus option is needed to set the number of virtual CPUs for the guest machine, just one in this case. As it could be easily guessed, instead, the --memory option, instead, is used to set the memory to allocate for the guest.

The --import option is really important here, since it is used to instruct the application to skip the OS installation and just build a guest around an already existing image, which is later specified with the --disk option.

We use --network to connect the guest to the host network. In this case we connect via the virbr0 bridge, which is created by default by libvirt. With the --video option we specify which kind of video device should be attached to the guest, and with --graphics we specify how the guest’s graphical display can be accessed: in this case we used spice, to use the protocol with the same name.

With the --boot option it’s possible to specify the dtb and the kernel file to use, but also the kernel command line with kernel_args. Finally, with the --events option we specify events values for the guest. In this case we destroy for the on_reboot event.

Once the virtual machine is started we can also manage it graphically via the virt-manager application. We can now enjoy our virtualized Raspberry Pi Os!

Conclusion

In this tutorial we saw how we can run a raw Raspberry Pi Os image using qemu and kvm, without an actual Raspberry Pi hardware. We saw how to download and verify the system image, how to extract it, how to clone the git repository containing the kernel and dtb files needed to boot the image with qemu, and the actual command we should run to start the virtualization of the system.



Comments and Discussions
Linux Forum