QEMU for Dummies (Me)

Introduction

I’ve always been afraid of QEMU, since it has a million options you can configure and break. However, it dawned on me (at my job) that you can do stuff on QEMU that you can’t do with other things. In fact, at times, you can ONLY use QEMU. Therefore, I finally decided to face my fears, learn a bit of QEMU, and make sure that you don’t have to go through 50 million lines of documentation like I had to. This is a very simple guide for very simple people.

QEMU has two options: user mode emulation and full system emulation. I’ll be focusing on the full system emulation, which is what we mean by “creating a VM”. It allows us to start full-blown operating systems with our devices, configs, and a whole bunch of other stuff.

To start, we need to create an image. Thankfully, we already have a wonderful utility that does just that. Do this:

qemu-img create -f qcow2 <name>.img <size>

qcow2 is the native format for QEMU images. We’ll install an OS into this image later and do stuff inside it, so set the size accordingly. For starters, 10G could work, which allocates 10 gigabytes for the image. To install an OS, keep your preferred distribution’s ISO file ready.

Now comes the hard part: invoking QEMU. There are thousands of configurations you can do, of which I’ll discuss some just to get you started. The general syntax for QEMU commands is given below. In the real world, you’ll probably want to write a shell script for this, since you can’t type in very long commands every time.

# Basic usage
qemu-system-x86_64 [options] [disk_image]

# Expanded options
qemu-system-x86_64 [machine opts] \
                   [cpu opts] \
                   [accelerator opts] \
                   [device opts] \
                   [backend opts] \
                   [interface opts] \
                   [boot opts]

For example, you could do something like this:

qemu-system-x86_64 -enable-kvm -cdrom <iso_file> -boot menu=on -drive file=<image>.img -m <memory_size>

Let’s break this command down:

  • qemu-system-x86_64 launches a QEMU instance with a base architecture of 64-bits.
  • -enable-kvm uses the KVM accelerator which gives us much better emulation.
  • -cdrom <iso_file> tells QEMU to use the cdrom to load an image file, which is our desired OS that we want to install.
  • -boot menu=on tells QEMU to display a boot menu which we can use to select where we want to boot from. We’ll select the cdrom, and consequently, the ISO image.
  • -drive file=<image>.img allows us to specify the qcow2 image we created as the drive for persistent storage. We’ll install the OS here.
  • -m <memory_size> allows us to specify the amount of RAM available to the VM.

NOTE: We can remove the cdrom flag after we install the OS on our qcow2 image file.


You’ll probably forget how to use each flag. If that happens, use this to access help for any give flag, or just run QEMU with the help command to access it’s documentation:

# access general help
qemu-system-x86_64 -help

# access help for a specific flag
qemu-system-x86_64 -<flag> help

Here’s what the different options available to us in QEMU are, I’ve taken them from the documentation. This will go inside the [options] part in the command structure. Not all options require you to define a disk image. In fact, I rarely do.

Option Explanation
Machine Define the machine type, amount of memory etc
CPU Type and number/topology of vCPUs. Most accelerators offer a host cpu option which simply passes through your host CPU configuration without filtering out any features.
Accelerator This will depend on the hypervisor you run. Note that the default is TCG, which is purely emulated, so you must specify an accelerator type to take advantage of hardware virtualization.
Devices Additional devices that are not defined by default with the machine type.
Backends Backends are how QEMU deals with the guest’s data, for example how a block device is stored, how network devices see the network or how a serial device is directed to the outside world.
Interfaces How the system is displayed, how it is managed and controlled or debugged.
Boot How the system boots, via firmware or direct kernel boot.

Standard Options

-h

Displays help

-version

Displays version information for your QEMU installation

Special Options

These are technically not called special options in the documentation. There, you’ll find them under standard options, but since these options vary according to the user’s needs, I decided to group them differently.

Machine

-machine <machine_name>

Specifies what machine type to use. Use the help param after this flag to list all the available machines. In my case, I’m using pc-q35-7.0.

Props

To declare a prop, we use the following syntax:

-machine [type=]name[,prop=value[,...]]

In other words, write your props after a comma placed after <machine_name>. Don’t give a space after the comma.

accel=<accelerator>

This allows us to specify an accelerator for our VM. QEMU uses tcg by default, which sucks a bit. I usually use kvm. For example: -machine pc-q35-7.0,accel=kvm. For kvm, you get vmport prop on by default as well.

CPU, vCPUs, & RAM

-cpu <type>

This allows us to define as CPU. Use the help param to get a list of CPUs avaliable to you. I’ll discuss two of them: host and max.

The host option simply uses our native CPU configuration and passes it as it is to the VM. It gives us all the features that our native CPU has. The max option gives us all of the features our QEMU version (x86_64 in my case) is capable of emulating, which are support by the accelerator in the current host.

-smp [n][,maxcpus=maxcpus]

Adds n CPUs to our VM in a simulated SMP system. We can additionally provide a maxcpus prop if our host supports hot-plugging, to declare how many more CPUs we can plug into our VM. If either n or maxcpus is omitted, the omitted value is set to the declared value. There are some other props to this flag which allow you to define your own CPU topology, which you can check in the man page.

-m [size=]mem

Sets the VM’s memory. You can add a ‘G’ or an ‘M’ after mem to signify gigabytes or megabytes.

Acceleration

-accel name[,prop=value[,...]]

Allows us to choose an accelerator. As mentioned before, I used kvm.

Devices

-device driver[,prop[=value][,...]]

We can add device drivers to a VM and set relevant properties for the driver. As always, you can type in help for both the device and its driver. For example, I am using intel-iommu device, which is only available for q35 machines.

Boot

-boot [order=drives][,menu=on|off]

This allows us to specify a boot order by specifying a string of letters, each letter representing a drive. For example: a, b are for floppy 1 and 2, c for the first hard disk, d for the first CD-ROM, and n-p for Etherboot from network adapters 1-4. Hard disk boot is the default. Use the menu prop to show a boot loader on startup for interactive boot. It is not enabled by default.

Conclusion

This should give you some basic working knowledge of what QEMU is and how to make VMs with it. I’ve tried to condense it down to basic information only, and have left out several key features that QEMU offers. Hopefully, I’ll get to cover them in a later article. Meanwhile, don’t forget to checkout the manual pages for QEMU and play around on your own.

Sadeem Sajid