Debian ARM Linux on Qemu
Qemu now emulates a few ARM cpus and it is possible to use qemu to boot an ARM kernel and a Debian system using a network boot. This page contains instructions and downloads to do that. The base system is "Sargebook" from OpenPsion, and my interest here is the extent to which this emulation can help with development of linux on the Psion PDA's.
Why is this useful? This is an instant cross-compiler, for one, except it is a native compiler. Compile a kernel or applications natively in the qemu emulator. But the system can be maintained as an ordinary Debian system. So install all the Debian development packages you want with apt-get! This system can be used instead of scratchbox for cross-compiling, but it will likely be slower (scratchbox uses qemu, in any case). I can report that I have used this system to compile firefox version 18.104.22.168 for the SA1100 cpu; it took about 12 hrs on a 2 GHz athlon 64 (giving ca. 430 bogomips for the emulated system).
I don't claim to be an expert here - by all means feel free to drop me an email with comments, corrections or suggestions. dushaw AT apl.washington.edu
With only minor adjustments, the psion netBook's (or Psion 5MX) system on compactflash can be booted directly by qemu NFS boot. Mount the compactflash system on your desktop and export it for NFS. Then boot up qemu and aim it at the netBook's CF system!
September 15, 2006
Much of this page seems to have become outdated in the past couple of months. See the link Debian on an emulated ARM machine for a step-by-step account for how to install Debian onto an ARM system using an emulated SCSI disk. However, some people, me included, were not able to get these procedures to work. My install following these procedures, at least, would hang while the disk was being partitioned. But this system shows that a hard disk emulation will work, and the author also reports that the mouse works "out of the box" so he didn't have to mess with the serial port mouse, as I've described at the bottom of this page. The author also obtains a larger screen size - I suspect that some of these successes must lie in how the kernel is configured. But the material here will still likely be useful to people. I am a believer in making (large) tarballs of complete systems available, so that everyone doesn't have to work through the lengthy install process.
November 11, 2006
Get qemu version 0.8.1 or later (although 0.8.0 might work). You can either install the binary tarball that is available there for linux-i386, or compile and install qemu yourself. You will not need the kqemu kernel module for acceleration because that is for x86 guests+hosts only.
Hints for compiling the kqemu.ko module and qemu with SUSE linux: If you have a Suse linux installation, you will have noted that qemu has to be compiled with a 3.X version of gcc and that while Suse linux comes with qemu, it does not come with the kqemu kernel module or a 3.X version of gcc. To obtain the kqemu.ko kernel module to use with Suse's qemu, it is not necessary to compile 3.X gcc and qemu, however. The module kqemu will compile with 4.X gcc just fine with this trick: configure qemu with the "--disable-gcc-check" option; but don't compile qemu. Then go to the kqemu directory and execute "make", which will make the kqemu module without any trouble. Copy kqemu.ko to the /lib/modules/2.6.BLAH/misc/ directory directory and execute "depmod -a", and you should be good to go. Really, you just need to edit the "qemu-BLAH/kqemu-BLAH/config-host.mak" file to set the right directory for "KERNEL_PATH=/lib/modules/2.6.BLAH/build" for the kqemu.ko module to compile. You'll have to recompile kqemu.ko every time you update your kernel. (That said, compiling 3.X gcc and qemu is not that big a deal. Qemu with kqemu kernel module support.)
An ARM kernel binary you can use is linux-2.6.16.bdd, which is configured for an integratorcp1026 cpu and was compiled on the qemu system (the kernel I used to get started was compiled in scratchbox). The kernel compile took about 1.5 hrs to complete. The kernel is configured for networking and nfs boot, but is otherwise minimal. No modules. This kernel is not configured for VGA graphics card or LCD - it seems these elements are not emulated in qemu for the integratorcp1026 cpu qemu option, and trying to include the elements will just cause the kernel to fail to boot. The kernel .config file. The system output from dmesg.
I managed to get the LCD+framebuffer to work using a different kernel (use the "-M versatilepb" option for qemu). The LCD+framebuffer seems to work only for the Versatile/PB or Versatile/AB qemu options. The kernel has to be compiled for these cpu's (enabling ARM926T cpu), and the ARM's graphics option has to be enabled under framebuffer. Even X windows will start and you can use a serial mouse (see below). The framebuffer resolution might be set with the kernel option "vga=301" (640x480, 256 colors) or "vga=303" (800x600, 256 colors); but this may not work. The 0.8.2 version of qemu gives 640x480 resolution by default; older version gave 320x240. There was a peculiar issue with getting the keyboard to work in the framebuffer; another special kernel option had to be enabled for the keyboard to work in the virtual terminal. With this framebuffer option, use "console=tty1" as the option for console when starting qemu, rather than ttyAMA0 as given below. Figuring this out is something of an adventure game...
Root File System
The system disk I use is: qemusarge.tgz which is a slightly modified version of Sargebook-lite, with a number of development packages installed. This Debian "sarge" system was used to compile firefox 22.214.171.124. The package size is a 85 MB tarball, and 245 MB unpacked. Unpack this to a suitable location and then export that location for NFS. I've installed gcc and other development packages on it using apt-get in qemu, and the system includes X windows and WindowMaker.
You may want to edit the /etc/resolv.conf file for your own situation. Edit the /etc/fstab file to set the NFS mount point, although the system will work without that. Also edit the /etc/apt/sources.list to aim at your favorite Debian mirror (it aims at the Oregon State mirror now.)
With only minimal adjustment, a Psion 5MX system disk or netbook system disk (or other PDA system disk) could be used as the NFS system here. This would allow major installation or maintenance of a system far more easily than using the 5MX or netbook. The qemusarge.tgz tarball for download here is cleaned up a bit to avoid several cosmetic complaints on boot up.
Install, configure, and startup NFS server on your desktop. Nothing special here, but use the kernel NFS server, rather than the user NFS server. The latter did not work for me. Add this entry to /etc/exports:
to export /system/directory for NFS. (If you've unpacked the system tarball to /system/directory.) Don't forget to restart NFS or exportfs.
If you are using TCP wrappers, put
portmap: 192.168.7.2 lockd: 192.168.7.2 rquotad: 192.168.7.2 mountd: 192.168.7.2 statd: 192.168.7.2
in your /etc/hosts.allow file. And beware the firewall... for debugging purposes, you might temporarily turn off your firewall.
Since this is an NFS filesystem, you can move things back and forth between the emulator and the host system easily. Or, just ssh over the 192.168.7.x network.
SUSE linux Firewall configuration: (...what a pain...) I got this to work, but I am not an expert in internet security! To open the SUSE Firewall for the qemu internal network, first make a file "/etc/sysconfig/network/ifcfg-tap0" with the entries:
BOOTPROTO='static' BROADCAST='' ETHTOOL_OPTIONS='' IPADDR='192.168.7.1' MTU='' NAME='Qemu' NETMASK='255.255.255.0' NETWORK='' REMOTE_IPADDR='' STARTMODE='auto' UNIQUE='' USERCONTROL='no'
Then, in the Yast firewall configuration, set a custom interface "tap0" to be in the internal zone (and also select "Masquerade" while you are there). Finally, add "/etc/init.d/SuSEfirewall2_setup restart" to the bottom of your qemu-ifup file. Worked for me, maybe...
The boot up script that worked for me is (a single long line):
qemu-system-arm -M integratorcp1026 -kernel linux-2.6.16.bdd -append "root=/dev/nfs \ nfsroot=192.168.7.1:/mnt/openpsion,rsize=32768,wsize=32768,timeo=14,nfsvers=3 rw \ ip=192.168.7.2::192.168.7.1:255.255.255.0 console=ttyAMA0" -net nic,vlan=0 \ -net tap,vlan=0,ifname=tap0,script=./qemu-ifup -nographic
I put my system disk in the directory /mnt/openpsion.
The rsize=32768,wsize=32768 are NFS options that greatly increase the throughput over NFS. The option "nfsvers=3" I suspect enables NFS version 3, which is supposed to be better than NFS version 2. These, with the async option in the /etc/exports file on the host system, greatly increase the response of the filesystem.
The "-nographic" option boots qemu in the terminal. Leaving this option off causes qemu to boot using its separate graphical window. Hit <Ctrl><Alt><3> to toggle to the console. <Ctrl><Alt><2> gets to back to the qemu control panel, where a "quit" will exit qemu. <Ctrl><Alt><1> gives the graphics (LCD) console (which doesn't seem to work for integrator kernels, but will give a small 320×240 framebuffer screen for versatile kernels with ARM LCD enabled). Just <Ctrl><Alt> will free up the mouse. The graphic option is nice in that the console is in color.
With the "-m" option you can tell the system how much memory it should have; 128 MB is the default.
I run qemu as root to avoid complications, e.g., a normal user doesn't have access to the "tap0" device, apparently. The emulated system boots with the serial port /dev/ttyAMA0 as the system console.
The short script qemu-ifup is needed as well to bring up the hosting network:
#!/bin/sh /sbin/ifconfig tap0 192.168.7.1
You can add any firewall or masquerade setup commands to the end of this script.
To quit qemu, you should first do a normal "shutdown -h now" in the emulated system to be sure everything is shutdown properly.
When using the "-nographic" option, after you shut the emulated system down, you may have to "killall qemu-system-arm", and execute "reset" to get your terminal to work properly again.
To allow your new emulated system access to the web so that you can install Debian packages with apt-get, as root on the host system do:
echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -s 192.168.7.0/24 -o eth0 -j MASQUERADE
Replace "eth0" with "wlan0" if you are using wireless (or I use "ra0" for my ralink wireless card). Once this is done, and your DNS is sorted out (see /etc/resolv.conf and try a "/etc/init.d/network restart"), apt-get can be used to obtain and install packages.
These steps are not needed if you've selected "Masquerade" in the SUSE Yast Firewall configuration tool (maybe).
X Windows and Serial Mouse
One can get a mouse to work! Use an old serial mouse in the desktop's serial port, and start qemu with the option "-serial /dev/ttyS0". This connects /dev/ttyS0 of the host to /dev/ttyAMA0 of the guest ARM system. I had to execute this stty command to get the host and guest serial ports to 1200 baud:
stty -F /dev/ttyS0 \ 4:0:8e9:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
Curiously, you may have to run this twice - it might complain about not being able to carry out the instructions the first time. Run this on both the host computer /dev/ttyS0 and the guest computer /dev/ttyAMA0.
In the emulated system, you should be able to cat /dev/ttyAMA0 at this point and see the scramble of binary from the mouse in the host system., Then, start X with the mouse configured to /dev/ttyAMA0 and the appropriate mouse protocol (I used "Mouseman" with my Logitech serial mouse). My /etc/X11/XF86Config-4 configuration file.
If you are having mouse problems, two hints are (a) to turn off the system console to the serial port /dev/ttyAMA0 (kernel configuration/kernel option) and (b) to turn off the getty on the serial port /dev/ttyAMA0 (in the /etc/inittab file, followed by executing init q). The use of minicom on host and guest machines can also be helpful in figuring out what's going on. It can take a bit of fiddling to get to work.
When you are finished, the serial ports can be reset to 115200 baud with
stty -F /dev/ttyS0 \ 1:0:800018b2:0:3:1c:7f:15:4:5:1:0:11:13:1a:0:12:f:17:16:0:0:2f:0:0:0:0:0:0:0:0:0:0:0:0:0