Using QEMU for cross-platform development

Multi-platform development on one computer


An advantage of virtualization is extending the utility of computing hardware, enabling a single computer (the host) to fulfill several roles by running multiple guest operating systems. Many of today's popular virtualization tools, however, are still architecturally limited—they enable you to run multiple operating systems for the same architecture, such as multiple x86-64 operating systems on a single x86-64 computer. QEMU can do this, but it can also run operating systems in a cross-platform manner. This capability can help you test the platform-specific features of your program without adding more computers to your desk!

To use QEMU for cross-platform development, you must first set it up and install guest operating systems on it. You may need to jump through some extra hoops to do this for cross-platform development. With the emulator up and running, you can investigate some QEMU features that can help you manage your cross-platform development efforts, such as enabling file transfers or file sharing between the emulator and its host.

Installing QEMU

You may be able to install QEMU easily through a package manager, but you may need to dig a little deeper if you plan to use the program for cross-platform software development. For example, you should understand your options for QEMU installation as well as installation of necessary support files such as firmware. You should also understand the difference between system emulation and user-space emulation, because each requires its own additional software installation.

Obtaining QEMU packages and support software

As with most Linux software packages, you can install QEMU in either of two main ways: using your distribution's package manager or compiling the software from source code. Commands such as apt-get install qemu (on Debian or Ubuntu), yum install qemu (on Red Hat or Fedora), or emerge qemu (on Gentoo) install the main QEMU package on common distributions. (Check your distribution's documentation for details.)

Distribution-provided QEMU packages work well, but they tend to lag behind the latest releases and may be missing important files, such as firmware for non-x86 systems. Thus, you may need to install the software from source code, which you can obtain from the QEMU Web site (see Related topics for a link). Typing ./configure --help in the source directory produces a list of configuration options so you can customize QEMU to your needs. After this, the usual make and make install commands compile and install the software.

As I write, the latest stable version of QEMU is 0.11.1, but a 0.12 release candidate version is also available. I use 0.11.1 as the reference for this article.

If you're using QEMU on an x86 or x86-64 computer to emulate the same, you may be interested in KQEMU. This is a Linux kernel module that provides accelerated CPU virtualization, similar to that provided by Xen or Kernel-based Virtual Machine (KVM). KQEMU is not part of the standard Linux kernel, though; you must download it from the QEMU Web site or install it in a separate package. Be sure to match the versions of QEMU and KQEMU; use KQEMU 1.3 with QEMU 0.9.1 and earlier, and KQEMU 1.4 with more recent versions of QEMU.

The main QEMU site includes several ready-made QEMU disk image files. These include bare-bones installations of Linux on various platforms, FreeBSD, and FreeDOS. You can download these files to test your basic installation. When the system is working, you can either expand the provided systems or install a new one from scratch.

The 0.11.1 QEMU package ships with firmware for x86, x86-64, PowerPC, SPARC 32, and SPARC 64 platforms, along with separate firmware files for the emulated video card, Preboot Execution Environment (PXE) booting, and other options. See the pc-bios subdirectory of the main package, or /usr/share/qemu on an installed system, for the specific files.

Sometimes the firmware provided with QEMU is inadequate. For instance, the firmware for x86 and x86-64 systems is a traditional basic input/output system (BIOS). If you want to develop or test software that relies on the newer Extensible Firmware Interface (EFI) or more exotic firmware, you may need to find it elsewhere. An EFI image is provided on the QEMU site, so that particular condition is easy to satisfy. Others can be more difficult. You may need to do a Web search on relevant key terms if you need to run a specific type of firmware.

System vs. user-space emulation

QEMU provides two modes of emulation. The first, system emulation, sets up a complete virtual machine. Software running in this system sees a computer that can be quite different from the host system—for instance, you can run a PowerPC Debian system atop a real x86-64 openSUSE computer. User-mode emulation is less complete. In this approach, you apply the QEMU emulation libraries to individual binaries, which then see the host computer as their own, so a PowerPC binary might see the hosting x86-64 openSUSE system's /etc directory and other configuration files. User-mode emulation can simplify access to local resources, networks, and so on.

Each emulation approach has its own setup requirements. For system emulation, you must install a client operating system just as if you were setting up a separate physical computer. (Downloading and using a preconfigured disk image is an alternative approach.) For user-space emulation, you needn't set up an entire system, but you may need to set up all the support libraries required by the software in question. You may also need to configure a cross-compiler to generate the binaries you intend to test.

Because the point of this article is using QEMU to develop and test cross-platform software, which may entail subtle hardware interactions, I emphasize system emulation. If you decide that user-space emulation is adequate for your needs, you can investigate it further.

Installing guest operating systems

Before you can use QEMU in system emulation mode, you must install a guest operating system. As mentioned earlier, you can either use a pre-installed disk image or prepare a disk image for a fresh installation. In the latter case, you must first prepare a disk image for the installation, but the installation process itself is similar to that of installing on a regular computer. In any event, you should be aware of important QEMU launch options that affect installation and use of the system.

Preparing disk images

Ordinarily, you employ disk files as stand-ins for hard disks when using QEMU. Alternatively, you can set aside partitions or use network mounts for some or all storage; however, disk files are convenient and flexible, so I emphasize their use. QEMU supports several different file formats for its emulated disks, the most useful being raw disk images, VMware 3/4 format, and QEMU's native Copy-On-Write versions 1 (QCOW) and 2 (QCOW2) formats.

The qemu-img command creates disk images. This command takes many options, but its basic use is fairly simple: Pass it the create parameter, the -f fmt parameter to set the format, the filename, and the size of the image. Raw images (-f raw) are useful for exchanging data with other emulators; however, QCOW2 (-f qcow2) supports compression, enabling you to create seemingly large disks in relatively small spaces.

As an example, the following command creates a 200GB disk image file. Initially, this file consumes little disk space on the host (just 256KB); however, it grows in size as it's used:

qemu-img create -f qcow2 linuxppc.qcow2 200G

In addition to creating your hard disk image, you may need to create an image file containing your installation medium. You can either point QEMU at your real optical drive or specify a file that contains an optical disc image, such as one you've downloaded from the Internet or created from a physical disc.

QEMU launch options

To begin installing or using QEMU, you must launch the program with appropriate options to enable use of the emulator. The QEMU documentation provides information on many obscure options, but you may be able to get by with just a few. In particular, you must specify your hard disk image or images and your installation medium or image. Options also exist to select different firmware files, set various hardware features, and so on. You may want to begin simply and then work up to more complex configurations.

A full QEMU installation includes several binaries, each of which emulates a different CPU architecture. The binary filenames take the form qemu-system-arch, where arch is an architecture code, such as ppc for PowerPC or x86_64 for x86-64. An exception is x86 systems, which are emulated via the qemu binary. Binaries with names of the form qemu-arch provide user-mode emulation for their respective architectures.

To specify hard disks, use -hda, -hdb, -hdc, and -hdd to refer to Parallel ATA (PATA) hard disks, and -cdrom to identify a CD or DVD image file or device. All of these options take a filename as a parameter. The optical drive takes the place of -hdc, so you cannot use both options simultaneously.

Another important QEMU launch option is -boot, which specifies the boot device. Using -boot c boots from the first hard disk, and -boot d boots from the CD-ROM device.

By default, QEMU provides the guest operating system just 128MB of RAM. Chances are you'll want to increase the available memory with the -m option, which takes a value in megabytes.

Putting these options together, installing Debian's PowerPC system using QEMU might look like this:

qemu-system-ppc -hda linuxppc.qcow2 -cdrom debian-ppc.iso -boot d -m 512

This example assumes that the debian-ppc.iso file contains a copy of the Debian PowerPC install disc, and that it's bootable using the default firmware. These options work for me using QEMU 0.11.1 and Debian 5.02a; however, QEMU can be finicky, so you may need to find a workaround to a problem. When the system is installed, you can use a nearly identical command to launch the working system—just change -boot d to -boot c.

Caveats, gotchas, and workarounds

One common stumbling block, particularly if you're trying to boot an unfamiliar architecture, is that the installation disc may not be bootable. One way around this problem is to specify a different firmware file with the -bios option, which takes a firmware filename as an option. Try perusing the firmware files in /usr/local/share/qemu (or a similar directory in /usr/share if you installed using a distribution package). You may also be able to find other firmware options via a Web search.

A similar workaround is to use the -M option to specify an architecture sub-type. Type qemu-system-arch -M ? to learn what the legal values are for your architecture.

Another alternative is to use the -kernel option; pass it the name of a Linux kernel file for the guest platform on the host disk, and QEMU loads and executes it, bypassing whatever platform-specific boot loaders or firmware features might be giving you problems.

Because QEMU emulates the target platform's CPU, it can be quite sluggish, so you should be prepared to spend longer than usual installing your guest operating system. If possible, you should stick to the minimum installation requirements and avoid the X Window System.

With QEMU up and running, it runs in text mode or in graphics mode in a window on your local system. Figure 1 shows a desktop with three QEMU sessions, running Windows XP under x86 emulation, FreeBSD under x86-64 emulation, and Debian Linux under PowerPC emulation.

Figure 1. QEMU enables you to run multiple operating systems on multiple emulated platforms
Imge of a desktop                 with three QEMU sessions, running Windows XP under x86 emulation, FreeBSD                 under x86-64 emulation, and Debian Linux under PowerPC emulation
Imge of a desktop with three QEMU sessions, running Windows XP under x86 emulation, FreeBSD under x86-64 emulation, and Debian Linux under PowerPC emulation

Using QEMU effectively

After you install your guest operating system, you can begin using it for software development or testing. You need to be able to transfer files between the guest and the host. There are several ways to accomplish this task, but using an emulated network is usually the most flexible approach. You should also consider the capabilities and limitations of QEMU's emulation with respect to software development to take best advantage of the emulator.

Managing file transfers

QEMU provides several networking options. The default is user-mode networking, which is similar to a network address translation (NAT) configuration: The guest operating system can use network clients to contact other computers, including both the host operating system and other network servers, but other systems can't contact the guest operating system without special configuration. QEMU provides its own Dynamic Host Configuration Protocol (DHCP) and Domain Name System (DNS) servers for the benefit of the guest operating system alone. To the guest operating system, it appears that the host is a gateway system.

This default configuration is adequate if you plan to use Network File System (NFS), Server Message Block (SMB)/Common Internet File System (CIFS), Secure Shell (SSH), or other clients from the guest to transfer files to and from the host. However, you must run an appropriate server on the host. If you want to initiate connections in the other direction, you must use the -redir option to redirect a port on the host system to the guest operating system. For instance, the following command redirects the host's port 2222 to the guest's port 22:

qemu-system-ppc -hda linuxppc.qcow2 -boot c -m 512 -redir tcp:2222::22

The result of issuing this command is that you can use SSH to log into the guest from the host by typing ssh localhost -p 2222. You can also access the guest from other computers on your network, so you may want to set up new firewall rules. Of course, you need to have an SSH server running on the guest operating system. You can redirect NFS, SMB/CIFS, or other ports in a similar manner.

Software development tips

With QEMU set up and running a guest operating system, you can now begin your software development. You may use either a native compiler running under the emulator or a cross-compiler on your host. For large development projects in which you repeatedly compile and test the software on the guest operating system, a cross-compiler is quicker, but setting up such a configuration is beyond the scope of this article. A compiler running under the emulator should be adequate for smaller projects or if you don't compile the software frequently.

To your software, the computer appears to be a genuine example of the target platform for most practical purposes. Features such as endianness, CPU identification, and other hardware basics work just as they do on a genuine computer. I have used both a genuine PowerPC Apple iMac and a QEMU-based PowerPC system to develop and test the PowerPC version of my globally unique identifier (GUID) partition table (GPT) fdisk program, which needs to know about the CPU's endianness. For my purposes, the QEMU-based system is indistinguishable from the real iMac, aside from the fact that the QEMU system is a bit slower.

That said, there are differences if you dig deep enough. For instance, QEMU's emulated hard disks return a model string of "QEMU HARDDISK" rather than a real hard disk manufacturer and model. QEMU's virtual hardware is also, by and large, a bit dated; disks all appear to be PATA or Small Computer System Interface (SCSI) devices, depending on platform, and the video hardware is ancient. You can find details about the virtual hardware in the QEMU documentation. Note that these details vary from one guest platform to another.

Under Linux, QEMU sessions consume little CPU time except when the guest operating system is doing work. QEMU sessions do consume the amount of RAM you give them, though. Thus, as a practical matter, you may need lots of memory on your host system, particularly if you plan to run more than one or two QEMU sessions simultaneously.

Going further

QEMU is a big package with many options, many of which may be interesting to at least some developers. For instance, you can change the model of the emulated network card, give the guest machine a separate Internet Protocol (IP) address on your real network, redirect various hardware ports to the guest operating system, and tweak a wide variety of hardware options. If such features are important to you, the QEMU documentation will prove invaluable.

Downloadable resources

Related topics


Sign in or register to add and subscribe to comments.

Zone=Linux, Open source
ArticleTitle=Using QEMU for cross-platform development