I recently decided to try using the x86 emulator bochs for some of my architecture research, as bochs seems to have a well-structured code base highly amenable to hacking. I also considered using qemu, but qemu’s design was ultimately not a great fit for the do-1-insn-at-a-time model of an architecture simulator. Instead, qemu is designed to run a bunch of instructions (really fast) instead of stopping precisely after each one. For the record, I was using bochs from CVS as of 2 Feb 2010 (bochs 2.4.2 was the latest release at the time) and qemu 0.12.2.
Next came the supposedly easy part: create a disk image with Linux on it (I wanted to use Ubuntu Karmic Server) and start simulating.
It turns out that running the Ubuntu installer in bochs is a real pain. Not only is it slow, but I encountered an assertion failure (in bochs) during the disk partition step of the installation. It turned out that this was due to some funkiness in the bochs plugin system (which is based on dynamically-linked libraries); switching to static linking finally got me past the assertion failure. After that adventure I had some kind of boot loader corruption that caused the virtual machine to fail to boot. Don’t even ask about getting networking to work (it still doesn’t), or why the terminal occasionally looks like the picture below.
Ultimately, I found some success when configuring bochs with the command listed below (everything should be on 1 line):
./configure --enable-sb16 \ --enable-ne2000 \ --enable-all-optimizations \ --enable-cpu-level=6 \ --enable-x86-64 \ --enable-sse=2 \ --enable-pci \ --enable-acpi \ --enable-usb \ --enable-usb-ohci \ --enable-show-ips \ --enable-clgd54xx \ --enable-pci \ --enable-smp \ --enable-debugger \ --enable-disasm
An alternative approach is to use
debootstrap to setup a chroot Linux installation, and then copy that installation onto the virtual hard disk, as outlined here. However, this is a pretty involved procedure, debootstrap with Ubuntu didn’t install any kernels for me, and installing the boot loader also seemed tricky.
Contrast these circuitous approaches with qemu, which is very fast (even without using KVM acceleration) and installed Ubuntu without a hitch on the first try. With networking. And a nice virtual monitor via VNC. All straight out of the box. qemu+kvm might even be fast enough to compile code inside the VM, which would ensure that the right headers, libraries, etc are used (otherwise you can always just mount the virtual drive as a regular filesystem and use
cp from the host machine). qemu is everything I could ask for — if only its codebase was more in tune with what I wanted to do!
The Best of Both Worlds
It took me a while to realize that I could have my bochs and qemu it, too, as both emulators can read and write a common virtual disk format: it’s called “raw” for qemu and “flat” for bochs. Essentially, it just uses a single regular file as the virtual disk. The only trick is that you have to create the virtual disk using bochs’
bximage program; if it’s created with qemu’s corresponding
qemu-img program then bochs won’t recognize the virtual disk for some reason.
With this hybrid approach, I can boot the disk using qemu for installing the OS, interactively setting things up via the commandline, downloading packages from the internet and so on, and then reboot into bochs to run simulations. It gives me the excellent speed and hardware emulation of qemu, with the more-natural-for-simulation interface of bochs.