Thursday, November 16, 2023

How to create a virtual linux machine with qemu under Debian or Ubuntu with near native graphics performance

It's been a long time since my latest post. I know, I'm lazy. But every now and then I like to publish something that other people can find useful.


Today I'm going to give you a simple and effective way of creating a virtual machine with QEMU that works fine and have a fast rendering of nice graphical programs that require some speed, such as simple videogames. I'm actually working with debian bookworm as a host system, and I want to create an Arch vm from scratch. For this purpose I will use a desktop iso for Arch.

Download and build QEMU from source

Most Linux distributions have QEMU in their repository, the problem is that the packages are often old versions. I need a recent version, possibly the latest, with pipewire enabled. So I will show you how to download the source package, uncompress it, configure it, and compile from source with make. At the time of writing the latest version is 8.2.0-rc0. Download it from this address.

Uncompress the file you have just downloaded in a directory of your choice using xz or your preinstalled graphic compression manager in your desktop or wherever you like. All the uncompressed files are contained in a directory named qemu-8.2.0-rc

Before compiling we need to download some debian packages, if you have not already installed them for other purposes. We'll use a script, in order to make our job simple and easy.

First of all, you need a compiler. I usually use gcc, to get it let's download and install the build-essential package using the first instruction in our script.

Open a terminal and write:

cd qemu-8.2.0-rc0

Now that you are within your qemu directory you will create a bash script to add some packages and procede to initial configuration:

nano pre-qemu.sh

Let's fill in the new created script with the following lines, one after another:

sudo apt install build-essential libusb-1.0-0-dev libgtk-3-dev \
       libpulse-dev libgbm-dev libepoxy-dev libspice-server-dev libglib2.0-dev \
       libfdt-dev libpixman-1-dev zlib1g-dev ninja-build libasound2-dev \
       libsdl2-* libslirp-dev libvirglrenderer-dev libpipewire-0.3-dev


./configure --target-list=x86_64-softmmu --enable-opengl --enable-sdl --enable-gtk \
       --enable-kvm --enable-guest-agent --enable-spice --enable-pipewire --audio-drv-list="alsa, default, \
       oss, pa, sdl" --enable-libusb --enable-slirp --enable-virglrenderer

save and exit your script with ctrl-o and ctrl-x

The first group of lines add some system packages, the second one provides an initial configuration that the compiler will use to enrich the availability of options in QEMU

make the script executable:

chmod +x pre-qemu.sh

Now, from within your qemu directory, you can procede to the compilation:

./pre-qemu.sh
make -j8

The number after j depends on the actual number of cores and threads in your processor, adjust it according with your needs. You can verify the number of available cores from the command line with:

nproc

or

lscpu

or

cat /proc/cpuinfo

After some time the compilation will end. Move the compiled libraries into your system dirs:

sudo make install

Now you can check if qemu works using the following command:

qemu-system-x86_64 --version

It shoud show the following message:

QEMU emulator version 8.1.2
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers

I have compiled only qemu for x86_64 as you can see from the pre-qemu script, but qemu can be compiled against a number of different architectures, namely i386, arm, aarch64, sparc, mips and so on. I'm not interested in these alternatives, as they are given for other systems emulation, so I don't bother with them.

Ok, now we are ready to create a working virtual machine.


You can download the Arch distro iso from the official website. I personally prefer to use a graphical installation with Calamares. The iso I use is this one. The references to the iso, in case you prefer one of your choice, must be updated in the installation script you're going to create.

Now it's to time create a working directory, in your desktop if you like, or elsewhere. Name it, let's say, Arch Let's copy your freshly downloaded iso inside.

Let's create a suitable container for our virtual machine

Open a terminal in the newly created Arch directory and write:

qemu-img create -f qcow2 arch.qcow2 256G

This command creates a qcow2 container for our virtual machine, it's a growing system up to 256G. Modify the capacity as you like.

Let's install ovmf, it's Open Virtual Machine Firmware, it's used to enable UEFI support for virtual machines:

sudo apt install ovmf

and the new pipewire audio server for debian bookworm, testing and unstable (Ubuntu users shoud follow the specific instructions given for that platform, see the related wiki).

sudo su 
goes into administrator mode, it requires your root password
apt install wireplumber pipewire-media-session- exit
back to user mode
systemctl --user --now enable wireplumber.service sudo apt install pipewire-pulse
to convert calls to pulseaudio to pipewire

Reboot your system

Check the effectiveness of last operation:

LANG=C aplay -L | grep -A 1 default

It shoud read:

default
    Playback/recording through the PulseAudio sound server

or something like that. It's a major improvement for your host system and I'm sure you will find extremely useful if you need to work with audio.

Now we can go ahead with a new script for Arch installation.



Arch installation

Let's create, in our Arch directory, an installation script.

cd into your Arch directory, open here a terminal and write:

nano install.sh

And that's it. Now we can write an installation script.

copy and paste all the following lines:

qemu-system-x86_64 \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-m 8192 \
-M q35 -enable-kvm \
-cpu host \
-smp 2 \
-cdrom Calam-Arch-Installer-2023-11.iso \
-hda arch.qcow2 \

ctrl-o ctrl-x and make the script executable.

Two words of explanation: the call to qemu is followed by a number of options:

  • use UEFI for your virtual machine
  • give the emulated ram memory a capacity of 8Gb
  • use an advanced emulated machine and enable near native acceleration
  • align emulated cpu to the host one
  • give the processor two cores
  • load the iso in a simulated cdrom
  • make the arch.qcow2 the first hard disk of your vm

The subsequent events are more or less the same as a physical installation, so it's up to you to check the installation. The script is low profile, some better options are given in the next script. In case you see crashes during Arch installation using Calamares, it's probably related to a weak partitioning scheme. Maybe you want to manually provide a basic partitioning before installing Arch, it's how I managed to successfully complete the installation.



Launch the virtual Arch machine

As before, create a new script:

nano launch.sh

Inside of it write the following lines:

qemu-system-x86_64 \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-device virtio-vga-gl \
-display sdl,gl=on \
-m 8192 \
-M q35,accel=kvm,kernel-irqchip=split \
-cpu Skylake-Server-v4 \
-smp 4 \
-device intel-iommu,intremap=on,caching-mode=on \
-boot c \
-drive file=arch.qcow2,media=disk \
-nic user \
-usb -device usb-mouse -device usb-kbd  \
-parallel none -nodefaults \
-audiodev pipewire,id=audio0 \
-device intel-hda -device ac97,audiodev=audio0 \

You'll note that I have added a few options

  • changed emulated cpu to Intel (not necessary)
  • given the cpu 4 cores
  • configured video output to virtio driver and sdl with an opengl option
  • enabled iommu for virtualization
  • enabled pipewire for audio

for some options I simple made copy and paste, I'm not sure about the possible alternatives. It simply works, feel free to change each option (even by trials and errors, refer to the qemu manual for better comprehension)

As before, ctrl-o ctrl-x and make the script executable the usual way

When you launch the script, the Arch vm will appear in all its shining beauty, you can update packages, modify your desktop, do all what you would normally do with a real machine. The call to UEFI firmware, in the boot menu, allows you to change, among other options, the virtual machine resolution to a more defined one.

Try to install a graphic game, I usually use supertuxkart to check the availability of a fast graphic server. You'll be surprised by the results.

If all goes well, let me know in the comments. See you next time.

No comments:

Post a Comment

How to create a virtual linux machine with qemu under Debian or Ubuntu with near native graphics performance

It's been a long time since my latest post. I know, I'm lazy. But every now and then I like to publish something that other people c...