Platform emulation with Bochs
Bochs is an x86 PC emulator and debugger licensed under the lesser GNU Public License (GPL). The platform provides emulation of an entire PC platform, including one or more processors and various PC peripherals, such as hard disks, display, CD-ROM drives, and other common peripherals. You can use Bochs to run operating systems targeted for PC platforms, and it's also an ideal application for operating system development (because crashes of the operating system under development can be isolated within the guest in addition to the debugging capabilities that Bochs provides). Bochs accomplishes this through emulation, but it comes at the cost of performance.
Let's take a quick detour and understand the difference between emulation and the more common virtualization methods available today.
Bochs is a platform emulator, which means that it's not actually virtualization in the modern sense but rather a simulation. In virtualization, the hypervisor and virtual machines (VMs) execute on the bare-metal hardware (with the hypervisor creating the environment to share the hardware amongst the VMs, commonly through hardware instructions). This process is commonly called direct execution, because the instructions are executed directly by the host processor. This type of virtualization uses support from modern-day processors (such as Intel Virtualization Technology for x86 [VT-x] or AMD virtualization [AMD-V]). Emulation commonly provides a layer between the VM and the underlying hardware and operating system to create the illusion of the desired platform environment as shown in Figure 1.
Figure 1. Virtualization vs. emulation
Emulation also commonly interprets the instructions of the guest VM (compared to virtualization, where the instruction set architecture of the guests must be the same as the host). This creates an interesting advantage for emulation, where the guest VM platform can be entirely different from the host (for example, running an x86 guest on an IBM® PowerPC® target).
Another interesting advantage of emulation is that there is complete control of the environment, which makes it easy to pause the entire machine to inspect its state as well as introduce any kind of fault into the emulation to test an operating system's error tree. This functionality comes at the cost of performance, but it's a real benefit for this type of environment. In addition, the emulator provides a true isolation of the guest from the host. In this way, emulators can provide complete transparency of the environment.
There are cases where emulation can be used in performance architectures. One example is the code-morphing technology created by Transmeta. Transmeta's processor was a very long instruction word (VLIW) super-scalar architecture that could emulate x86 code sequences. It did so through either emulation or dynamic compilation of code sequences (similar to the capabilities of QEMU). Transmeta opened its doors in 1995, and then closed them in late 2007.
Other examples include Java technology, which is interpreted from
Java bytecodes to the underlying architecture of the host. Java technology
implements just-in-time (JIT) compilation to work around some of the
inefficiencies, similar to Transmeta and numerous other emulation
solutions (including QEMU, another platform emulation solution similar to
Bochs). But Bochs also achieves efficient emulation (up to 100 million
instructions per second [MIPS] on a modern processor) while also being
portable. Bochs was developed purely in the
language for interpreted x86 instruction execution and platform emulation.
Now, let's explore some of the internals of Bochs to understand how it
achieves useful performance in a pure
implementation. This article focuses on two aspects of emulation: the CPU
(instruction set architecture [ISA] emulation) and devices.
Bochs is unique in its method for emulation. Although other solutions offer direct execution or JIT compilation, Bochs implements pure emulation of the CPU ISA (including support for x86 and x86-64 CPU emulation with up to eight CPUs in a symmetric multiprocessing configuration). Bochs provides emulation of a real CPU, even to the level of emulating the CPU's fetch-decode-execute flow.
In the flow stage, Bochs performs permissions checks, and then fetches the opcode. In the decode stage, Bochs decodes the fetched x86 instruction into an internal representation. It also maintains an instruction cache for improved performance by storing the "micro operations" of the original x86 system (which can be fetched later without the overhead of decoding). Finally, in the execute stage, Bochs performs a number of operations around execution of the specific instruction (including calculating effective addresses for operands, and then performing an indirect call to the particular instruction execution method). When the instruction has been executed, any affected registers and flags can be updated (as appropriate). Bochs provides an optimization here called lazy flags update to calculate the arithmetic flags only when they're required (instead of updating at each step).
Outside of the fetch-decode-execute flow, Bochs also manages external events such as device interrupts and other necessary features like byte-swapping and other privileged checks. In addition to the generic x86 CPU, Bochs implements a number of CPU features, such as the Intel Pentium Processor with MMX technology; Intel's Streaming Single Instruction, Multiple Data Extensions 2 (SSE2); and AMD 3DNow! instructions.
Bochs's internal instruction cache provides a nice trade-off to traditional JIT compilation. Although JIT compilation provides some advantages for speeding up execution, it does so at the cost of larger amounts of memory.
Bochs provides an emulation of the PC platform, with the device emulation based on the device type. For example, the keyboard is a physical device shared between the host and guest, but the disk is shared through an emulation, where the guest disk is a file on the host disk's file system.
Bochs provides a useful list of emulated hardware, including memory, an NE2000 Ethernet card, Cirrus Logic video card (PCI or ISA), Intel 440FX PCI chipset, BIOS, USB root hub, Sound Blaster sound card, and disk and floppy controllers. Like the CPU, these devices are emulated as well, which can introduce considerable overhead in the path. For example, when a driver communicates with hardware, it manipulates registers to request some desired operation of the device. In an emulated platform, the registers and memory that represent the device are emulated. When the guest operating system's driver peeks and pokes at the memory and hardware registers, software exists underneath to emulate the device (see Figure 2). Beyond that emulated interface, the device emulation must then perform the desired operation, which implies an emulation of the device and potentially communication with a physical device in the host platform (such as the physical network interface card [NIC] or physical disk).
Figure 2. Device virtualization through emulation
Bochs and its utilities are quite simple to use for emulating a variety of guest operating systems. This example demonstrates the emulation of the Plan 9 from Bell Labs operating system.
First, you must install Bochs if it's not already available on your system.
For my Ubuntu system, I use the
manager to install the necessary packages:
$ sudo apt-get install bochs $ sudo apt-get install bochs-x
This command installs the Bochs IA-32/64 PC emulator and the X-11 emulator for Bochs.
Prepare for a Plan 9 installation
To emulate Plan 9 on Bochs, you need two more things for your virtualized environment: a CD-ROM containing the Plan 9 installation image and a virtual hard disk (VHD) as the target for your installation.
First, get the Plan 9 image from the Bell Labs site, as indicated by the following command line:
$ wget http://plan9.bell-labs.com/plan9/download/plan9.iso.bz2 $ bunzip2 plan9.iso.bz2
plan9 image is an ISO format file that can
be interpreted using the ISO 9660 format (as an emulation of a CD-ROM
drive, which you'll see shortly).
The next step is to create your VHD. Recall that this will be a file on the
host operating system. Bochs provides a special utility to create this
bximage utility is interactive and allows you
to specify a number of options for how the file is created and managed.
Listing 1 provides the session to create the VHD.
bximage, you specify that you
want to create a hard disk image (rather than a floppy image). Bochs can
support a number of image types, but for performance, request flat,
because no run time dynamic growth will be necessary. The Plan 9 operating
system requires a significant amount of space for its installation, so
specify a 700MB disk followed by the name of the hard disk file (c.img).
Listing 1. Creating the VHD image for Bochs using bximage
$ bximage ======================================================================== bximage Disk Image Creation Tool for Bochs $Id: bximage.c,v 1.34 2009/04/14 09:45:22 sshwarts Exp $ ======================================================================== Do you want to create a floppy disk image or a hard disk image? Please type hd or fd. [hd] What kind of image should I create? Please type flat, sparse or growing. [flat] Enter the hard disk size in megabytes, between 1 and 129023  400 I will create a 'flat' hard disk image with cyl=1422 heads=16 sectors per track=63 total sectors=1433376 total size=699.89 megabytes What should I name the image? [c.img] Writing:  Done. I wrote 314302464 bytes to c.img. The following line should appear in your bochsrc: ata0-master: type=disk, path="c.img", mode=flat, cylinders=1422, heads=16, spt=63 $ ls -la c.img -rw-r--r-- 1 mtj mtj 733888512 2010-12-19 14:30 c.img $
Install Plan 9
With your CD-ROM image and hard disk image in hand, the next step is to
create your Bochs configuration file. This file defines how the Bochs
emulation should be performed while specifying where to find key aspects
of the environment (ISO file, hard disk image, and so on). The bochsrc
configuration file is shown in Listing 2. This file
defines an x86 platform with 128MB of RAM, a mouse, default Extended
Graphics Array display, a hard disk (defined as
ata0-master, created through
bximage), a CD-ROM (defined as
ata1-master, pointed to your downloaded
plan9.iso file), a log file for Bochs output (bochsout.txt), and the
default boot device of the CD-ROM.
Listing 2. The bochsrc configuration file
# bochsrc # megs: 128 # mouse: enabled=1 # ata0-master: type=disk, path="c.img", mode=flat, cylinders=609, heads=16, spt=63 ata1-master: type=cdrom, path=./plan9.iso, status=inserted # log: bochsout.txt # boot: cdrom
Bochs provides a large number of options expressible through the configuration file. These options can define which devices are available on the platform or the types of options expressed (for example, individual CPU configurations such as SSE or the Advanced Encryption Standard extension).
To begin the installation of Plan 9 to Bochs, start Bochs with the
-q option (to skip the start menu) in the same
directory as your disk image, ISO image, and bochsrc file:
$ bochs -q
This command creates a new window representing the emulated platform, which is shown in Figure 3. As shown, the emulator has recognized your disk and CD-ROM and has booted the CD to begin Plan 9 operating system installation.
Figure 3. Starting Bochs (installation of the Plan 9 operating system)
As the installation continues, Plan 9 goes through a variety of configuration and installation steps. Figure 4 shows the setup of the disk (for partitioning).
Figure 4. Installing the Plan 9 operating system
The windowing system used in these examples is Plan 9's rio. Rio was an interesting windowing system with some unique attributes. For example, a window in rio was its own private namespace and exported a file system interface to applications running in the operating system (allowing rio to run within a rio window). Rio predated the X windowing system for UNIX and provided a technical foundation for windowing systems that followed it.
When the lengthy installation is complete, the emulation machine is stopped
and the bochsrc file updated to boot from the disk
boot: disk). Note that at the top of the
window (see Figure 5) is the Bochs control showing the elements that are
active (CD-ROM, mouse) and a set of controls on the right (to reset,
suspend, or power off the emulated machine).
Figure 5. Plan 9 running in the context of Bochs
Running other operating systems
One of the joys of emulation is the ability to easily run other operating systems in a quick and simple way. You can find a list of disk images at the Bochs site (see Related topics) to try some other operating systems, such as FreeDOS, DLX Linux (10MB Linux image), OpenBSD, GNU/Hurd, and KNOPPIX. Figure 6 shows the FreeDOS kernel booting on Bochs.
Figure 6. Running FreeDOS on Bochs
FreeDOS is a project that was created after Microsoft announced that it would no longer produce MS-DOS and is used by a number of companies under the GPL.
Other emulation platforms
Although Bochs is a useful application for platform emulation, other solutions provide similar capabilities. QEMU is one of the most popular, as it provides not only PC-compatible platform emulation but a variety of other processor architectures, as well (ARM, PowerPC, and others).
Other specialized platforms include the SPIM (a MIPS processor simulator) and the computer history simulation project, which provides platform emulation of a number of historically significant computing systems (Altair, VAX 11/780, IBM 1130, and more).
Bochs is a great platform emulator for executing older operating systems, but it's also an ideal platform for developing operating systems. Bochs provides efficient platform emulation and debugging capabilities that are not easily provided on raw hardware (including a full-featured graphical debugger). Nothing beats real hardware for software testing, but Bochs can provide a useful development environment that is portable across a variety of x86 and non-x86 hosts.
- Visit the Bochs Web site for the latest version of Bochs as well as news, documentation, sample disk images, and access to the mailing list to resolve any issues you may encounter. You can also enter a bug report at the site.
- Read the paper "Virtualization Without Direct Execution or Jitting: Designing a Portable Virtual Machine Infrastructure," by Darek Mihocka and Stanislav Shwartsman, to get the gory details of Bochs and learn how it provides an efficient platform without direct execution.
- Transmeta Corporation (see the Transmeta page on Wikipedia) developed code morphing technology that translated x86 instructions into the native VLIW for execution. Read more about VLIW architectures and the CPU architectures that use them on the VLIW architectures page on Wikipedia.
- "How To Write a Computer Emulator," by Marat Fayzullin, nicely introduces the topic and also explores how CPU emulation is implemented along with emulation of other aspects, such as memory.
- The Plan 9 operating system was created by Bell Labs in the 1980s as a research operating system and successor to UNIX. Plan 9 represented all system interfaces as files instead of special devices. It continues to be developed for research and in the hobbyist community. Learn more about Plan 9's windowing system, rio, in this presentation from Rob Pike. For those who'd like to experiment with Plan 9's applications on their favorite operating system (like Linux), Plan 9 from User Space provides a user space implementation of many of the significant components.
- In the developerWorks Linux zone, find hundreds of how-to articles and tutorials, as well as downloads, discussion forums, and a wealth of other resources for Linux developers and administrators.
- Evaluate IBM products in the way that suits you best: Download a product trial, try a product online, use a product in a cloud environment.
- Follow developerWorks on Twitter, or subscribe to a feed of Linux tweets on developerWorks.