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
Software requirements and conventions used
|Category||Requirements, Conventions or Software Version Used|
|Software||qemu, qemu-system-arm, kvm and git|
|Conventions||# – requires given linux-commands to be executed with root privileges either directly as a root user or by use of
$ – requires given linux-commands to be executed as a regular non-privileged user
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:
- Raspberry Pi Os Lite
- Raspberry Pi Os with desktop
- Raspberry Pi Os with desktop and additional packages
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:
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
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
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:
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.
--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.
--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.
--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
--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.
--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
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!
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.