Compiling Qemu with KQemu to Run Windows 98 on Debian Sid

For those of you who don’t already know qemu is a fast and free emulator comparable with VMWare. Of course there are Debian packages available which you could just install as usual but they do not include the closed source kernel module (kqemu) which provides major performance enhancements. So we will compile qemu from source.

Compiling qemu from source

Fetch the qemu source code from the webpage and compile it according to the documentation.

Adjust the configure flag as you like, for example I basically just need support for i386 and since Debian Sid is now using GCC 4.x but qemu doesn’t yet compile with it. I had to point it to an older version as follows:

cd /tmp
tar zxvf qemu-0.7.2.tar.gz
cd qemu-0.7.2
tar zxvf /tmp/kqemu-0.7.2.tar.gz
./configure --cc=/usr/bin/gcc-3.3 --target-list=i386-softmmu
make

# and as root
make install

To meet a few dependencies I had to further install the two following packages.

apt-get  install libsdl1.2-dev
apt-get install zlib1g-dev

Per default qemu will be installed in /usr/local, a new device node /dev/kqemu should automatically be created. If this is not the case you should do it manually.

mknod --mode=0666 /dev/kqemu c 250 0

Preparing the kernel for network support via tun/tap devices

If you want your virtual machine connected to the host there are two different ways to accomplish this. One is with the -user-net command line switch which will set up a DHCP server for you (refer to the documentation for further information), the other is to use tun/tap devices. For the latter you obviously need tun/tap support activated in your kernel, below are the relevant settings.

 Symbol: TUN [=y]
 Prompt: Universal TUN/TAP device driver support
   Defined at drivers/net/Kconfig:85
   Depends on: NETDEVICES
   Location:
     -> Device Drivers
       -> Network device support
         -> Network device support (NETDEVICES [=y])
   Selects: CRC32

Afterwards you may have to set appropriate permissions for your /dev/net/tun device.

chgrp users /dev/net/tun
chmod 660 /dev/net/tun

Creating a virtual disk image

Qemu uses a file to represent the content of the virtual hard disk which can be created as follows.

qemu-img create -f raw win98.img 1000M

The file will grow as more software gets installed to the system.

Installing Windows 98 from a bootable CD

To install Windows you can either boot from the CD or use a boot floppy if you don’t have one download one from here.

Then run qemu with the floppy drive and virtual disk image connected and let it boot from floopy (-boot a).

Make sure that you launch the newly compiled qemu which per default is located in /usr/local/bin.

qemu -hda win98.img -fda /dev/fd0 -boot a

With slightly different options qemu boots from CD.

qemu -hda win98.img -cdrom /dev/hdc -boot d

Additionally you can add an option for your keyboard layout for example

-k de-ch

take a look in /usr/locale/share/qemu/keymaps for valid values.

When Windows first boots up go to the command line by pressing Shift+F5 and create an empty primary partition on the hard disk with fdisk, then reboot and proceed with the installation from CD-ROM as you would do it on a normal computer.

I would recommend to keep the cdrom drive connected to the VM until you successfully logged in the system for the first time, because Windows will need various drivers from it.

When the installation is completed you can boot your image with the command below.

qemu -hda win98.img -boot c

You will probably notice that with Windows 98 as guest the CPU load is very high even if you do nothing special in your VM, this is a known problem and here is the solution.

Qemu monitor

If you want to change the cdrom while your VM is running then switch to the QEMU monitor by pressing Ctrl+Alt+2 and issue the following command.

eject cdrom
change cdrom /dev/cdrom

you can see the changes with

info block

to switch back to the VM use Ctrl+Alt+1

Set up networking for the virual machine

My network looks like this.

+-------------------------+                 +----------------------+
| host pc with debian/sid | ==============> | Router with NAT/DHCP |
|  eth0: 192.168.1.2/24   |                 |   192.168.1.1/24     |
|  tun0: 192.168.2.1/24   |                 +----------------------+
|  gw:   192.168.1.1/24   |                            ||
|  dns:  192.168.1.1/24   |                            ||
+-------------------------+                            /
            /                                    +----------+
            ||                                    | Internet |
            ||                                    +----------+
+-------------------------+
| qemu with windows 98    |
|  eth0: 192.168.2.2/24   |
|  gw:   192.168.2.1/24   |
|  dns:  192.168.1.1/24   |
+-------------------------+

So I had to set up a iptables rule to translate the 192.168.2.x IPs so that the internet is accessible from the Windows box.

Qemu will try to execute /etc/qemu-ifup on startup to configure the tun device. The commands in there need root privileges so I created another file called /etc/qemu-net-config containing the following.

#!/bin/sh
# $1 => tun0

/sbin/ifconfig $1 192.168.2.1 up
echo "1" >/proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Then I configured sudo to allow the user to execute this file without prompting for a password. Therefore my /etc/qemu-ifup (which gets executed by qemu) look like this.

#!/bin/sh

sudo /etc/qemu-net-config $1

As a last step, I had to configure the network in Windows IP: 192.168.2.2, gateway: 192.168.2.1 and finally DNS: 192.168.1.1.

With this setup everything worked as expected. After the initial configuration of your VM I would recommend to make a copy of your disk image so you can always switch back to a clean install.

Hope you get it to work too. As a last point I would like to mention the free OS zoo which provides various ready-to-run qemu images.

Marc