Using Qemu to emulate absent hardware

At the end of one of my training courses recently we got into a discussion about how to continue working with the code and configurations developed during the course after everybody had gone home and they no longer had a target board. I said, you could use qemu to emulate an ARM target that is rather similar to the one we actually use. Thinking about it a bit more, I realise that the situation is general and common enough to be useful to many people (or so I hope) and so I have written this tutorial.

The objective, then, is to use qemu [1] to create an arm926 environment that can run a typical embedded distribution (we use the Ångström distribution [2]), using an NFS root mount to a file system on the host PC.

Installing qemu

Qemu can emulate a wide range of processor types, including arm, cris, m68k, microblaze, mips, ppc and sh4. Each one is a separate executable: qemu-system-arm and qemu-system-mips for example. For each processor type, there are emulations of a number of hardware platforms. For arm, we have the ARM Integrator, RealView and Versatile development boards, the Nokia N800/810 and various others. I have chosen to use the Versatile board with an ARM926E core.

I have tested these instructions with qemu version 0.12.3 which comes with Ubuntu 10.04, so begin with

sudo apt-get install qemu-kvm-extras

This package includes emulators for all processor types as you can see by listing /usr/bin/qemu-system-*.

Compiling the kernel

Next you will need a kernel configuration to match the board. Get a copy of Linux from kernel.org - I am using 2.6.27 here - and create a fresh directory to keep everything in one place.
NOTE: for this you will need a toolchain (e.g. Ångström) and to have set the ARCH and CROSS_COMPILE shell variables.

mkdir ~/qemu
cd ~/qemu
tar xjf linux-2.6.27.tar.bz2
cd linux-2.6.27
make versatile_defconfig
make menuconfig

Enable these features
"Kernel Features->Use the ARM EABI to compile the kernel"
"File systems->Inotify file change notification support"
"File systems->Pseudo filesystems->Virtual memory file system support (former shm fs)"
Finally,

make zImage
cp arch/arm/boot/zImage ~/qemu

Or, you can download a pre-built copy of zImage.

Get the root file system

Here is a copy of the root file system. Download it, if you don't have it already, create a directory such as ~/rootdir and extract it there. You will have to make one small change because the Digi CCW9 target board we use for training has the serial console device as ttyS1 whereas on the Versatile it is ttyAMA0. Edit /etc/inittab and change the reference to ttyS1 to ttyAMA0. That's all.

Configuring the network

You need to configure a network interface so that you can communicate with the emulated target just as if it was a real board. The technique used here is to create a TUN/TAP network device and connect it to the qemu process, with the host PC tap interface being 192.168.1.1 and the target address being 192.168.1.101.
NOTE: Choose a pair of address on a different sub-net to any real network the PC is attached to otherwise the IP routing is going to get mixed up.

Install the uml-utilities package to get the tunctl command

sudo apt-get install uml-utilities

Then configure device tap1

sudo tunctl -u $(whoami) -t tap1
sudo ifconfig tap1 192.168.1.1
sudo route add -net 192.168.1.0 netmask 255.255.255.0 dev tap1
sudo sh -c "echo  1 > /proc/sys/net/ipv4/ip_forward"

Running qemu

Now at last, you can run qemu with this command (all on one line):

qemu-system-arm -m 64M -nographic -M versatilepb -kernel zImage
-append "console=ttyAMA0 root=/dev/nfs rw nfsroot=192.168.1.1:/home/ubuntu/rootdir ip=192.168.1.101"
-net nic -net tap,ifname=tap1,script=no

Lets dissect that a bit:

    -m 64M              Create a virtual machine with 64 MiB of RAM
    -nographic          Don't emulate a frame buffer device
    -M versatilebp      The board to emulate
    -kernel zImage      The kernel to use
    -append “...”       The kernel command line
    -net nic -net tap,ifname=tap1,script=no
                        Connect the emulated network adapter to device tap1 and do not
                        run the default script, /etc/qemu-ifup.

Now you should have a fully working emulated target. To exit qemu, type Ctrl-A x. Also, Ctrl-A h gives a brief help screen.

References

[1] QEMU Emulator User Documentation http://wiki.qemu.org/download/qemu-doc.html
[2] The Ångström Distribution http://www.angstrom-distribution.org/
Chris Simmonds

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

installation problem

Hi Chris!
i tried to install qemu on my system. I encounterd few problems

here is the error log when i try to do------ make versatile_defconfig

rajesh@UbuntuPC:~/qemu/linux-2.6.27$ sudo make versatile_defconfig
HOSTCC scripts/basic/fixdep
scripts/basic/fixdep.c: In function ‘traps’:
scripts/basic/fixdep.c:377: warning: dereferencing type-punned pointer will break strict-aliasing rules
scripts/basic/fixdep.c:379: warning: dereferencing type-punned pointer will break strict-aliasing rules
HOSTCC scripts/basic/docproc
HOSTCC scripts/kconfig/conf.o
scripts/kconfig/conf.c: In function ‘conf_askvalue’:
scripts/kconfig/conf.c:104: warning: ignoring return value of ‘fgets’, declared with attribute warn_unused_result
scripts/kconfig/conf.c: In function ‘conf_choice’:
scripts/kconfig/conf.c:306: warning: ignoring return value of ‘fgets’, declared with attribute warn_unused_result
HOSTCC scripts/kconfig/kxgettext.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/lex.zconf.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
***
*** Can't find default configuration "arch/x86/configs/versatile_defconfig"!
***
make[1]: *** [versatile_defconfig] Error 1
make: *** [versatile_defconfig] Error 2
rajesh@UbuntuPC:~/qemu/linux-2.6.27$

I tried sh /media/cdrom/install.sh, edited .profile in the root with cross compile option but still gives error

Can u pls give me step by step process to build a Linux system so that I can start programming. I have tried the steps from the excercises by omitting target side instruction but it doesn't seems to work. I will make a fresh install of Ubuntu 10.04 LTS and start going through your steps.
Thanks,
Rao

Re Installation problem

Rao,
You need to set the ARCH and CROSS_COMPILE shell variables before building the kernel. For an arm Angstrom toolchain you need
export ARCH=arm
export CROSS_COMPILE=arm-angstrom-linux-gnueabi-

You will also need to set the path:
PATH=/usr/local/angstrom/arm/bin:$PATH

Chris.

could not load kernel 'zImage'

Hi Chris!
The idea of setting the path prior to installation worked very well. Everything went fine until the las step
here is the log:

rajesh@UbuntuPC:~$ sudo tunctl -u $(whoami) -t tap1
Set 'tap1' persistent and owned by uid 1000
rajesh@UbuntuPC:~$ sudo ifconfig tap1 192.168.1.1
rajesh@UbuntuPC:~$ sudo route add -net 192.168.1.0 netmask 255.255.255.0 dev tap1
rajesh@UbuntuPC:~$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
rajesh@UbuntuPC:~$ qemu-system-arm -m 64M -nographic -M versatilepb -kernel zImage -append "console=ttyAMA0 root=/dev/nfs rw nfsroot=192.168.1.1:/home/rajesh/rootdir ip=192.168.1.101" -net nic -net tap,ifname=tap1,script=no
zImage: No such file or directory
qemu: could not load kernel 'zImage'

the zImage is created in qemu folder - is it wrong location?
Can we put the last step in to file and run from it (like we did for minicom)?

Thanks,
Rao

Qemu simulator

Hi,
Did any one managed to qemu sucessfully? If can please tell the solution for my error msg "could not load kernel 'zImage' "
Thanks,
Rao.

Cannot open root device "nfs" or unknown-block(2,0)

Hi Chris!

I figured out the previous problem qemu could not load kernel zImage---
we need to change to ~/qemu before running the script

but here comes new problem root=/dev/nfs doesn't exist on the installed root file system
here is the complete log. can u pls find the solution for this ASAP.

rajesh@UbuntuPC:~$ cd /home/rajesh/qemu/
rajesh@UbuntuPC:~/qemu$ sudo qemu-system-arm -m 64M -nographic -M versatilepb -kernel zImage -append "console=ttyAMA0 root=/dev/nfs rw nfsroot=192.168.1.1:/home/rajesh/rootdir ip=192.168.1.101" -net nic -net tap,ifname=tap1,script=no
[sudo] password for rajesh:
Uncompressing Linux......................................................................................... done, booting the kernel.
Linux version 2.6.27 (rajesh@UbuntuPC) (gcc version 4.3.3 (GCC) ) #1 Thu Sep 30 19:28:17 BST 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
Machine: ARM-Versatile PB
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-through cache
CPU0: I cache: 4096 bytes, associativity 4, 32 byte lines, 32 sets
CPU0: D cache: 65536 bytes, associativity 4, 32 byte lines, 512 sets
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyAMA0 root=/dev/nfs rw nfsroot=192.168.1.1:/home/rajesh/rootdir ip=192.168.1.101
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62028KB available (2516K code, 212K data, 108K init)
Calibrating delay loop... 131.48 BogoMIPS (lpj=657408)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 288 bytes
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
msgmni has been set to 121
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
CLCD: unknown LCD panel ID 0x00001000, using VGA
CLCD: Versatile hardware, VGA display
Clock CLCDCLK: setting VCO reg params: S=1 R=99 V=98
Console: switching to colour frame buffer device 80x60
Serial: AMBA PL011 UART driver
dev:f1: ttyAMA0 at MMIO 0x101f1000 (irq = 12) is a AMBA/PL011
console [ttyAMA0] enabled
dev:f2: ttyAMA1 at MMIO 0x101f2000 (irq = 13) is a AMBA/PL011
dev:f3: ttyAMA2 at MMIO 0x101f3000 (irq = 14) is a AMBA/PL011
fpga:09: ttyAMA3 at MMIO 0x10009000 (irq = 38) is a AMBA/PL011
brd: module loaded
smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre
No set_type function for IRQ 25 (VIC)
eth0: SMC91C11xFD (rev 1) at c4866000 IRQ 25 [nowait]
eth0: Ethernet addr: 52:54:00:12:34:56
mice: PS/2 mouse device common for all mice
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
VFP support v0.3: implementor 41 architecture 1 part 10 variant 9 rev 0
input: AT Raw Set 2 keyboard as /class/input/input0
input: ImExPS/2 Generic Explorer Mouse as /class/input/input1
eth0: link up
IP-Config: Guessing netmask 255.255.255.0
IP-Config: Complete:
device=eth0, addr=192.168.1.101, mask=255.255.255.0, gw=255.255.255.255,
host=192.168.1.101, domain=, nis-domain=(none),
bootserver=255.255.255.255, rootserver=192.168.1.1, rootpath=
Looking up port of RPC 100003/2 on 192.168.1.1
Looking up port of RPC 100005/1 on 192.168.1.1
Root-NFS: Server returned error -13 while mounting /home/rajesh/rootdir
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or unknown-block(2,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)

Cannot open root device "nfs" or unknown-block(2,0)

Hi Rao,

I have just seen this comment, and as I did manage to get it working last month, I have had a look, and it looks like you have not configured "device tap1", every time hat you start your computer, you have to run the commands to configure device tap1.
I have put both the commands for device tap1 and the command to start qemu in two shell scripts, so it is easier to start them and less prone to typos, you can even add them as start up programs

I hope this is not too late for you.

Antonio

nfs problem

Hi Antonio,

I do configure the tap device every time i start system
here is the sample of commands and responses i get

rajesh@UbuntuPC:~$ sudo tunctl -u $(whoami) -t tap1
Set 'tap1' persistent and owned by uid 1000
rajesh@UbuntuPC:~$ sudo ifconfig tap1 192.168.1.1
rajesh@UbuntuPC:~$ sudo route add -net 192.168.1.0 netmask 255.255.255.0 dev tap1
rajesh@UbuntuPC:~$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
rajesh@UbuntuPC:~$ qemu-system-arm -m 64M -nographic -M versatilepb -kernel zImage -append "console=ttyAMA0 root=/dev/nfs rw nfsroot=192.168.1.1:/home/rajesh/rootdir ip=192.168.1.101" -net nic -net tap,ifname=tap1,script=no

I there anything wrong with this- and ip address conflicts? i do have wireless lan on 192.168.1.1 but i did disable it before i configure the tap device and i can see the changes on ifconfig. But once i create tap device if i enable wireless it connects to router but cannot open any pages. i have to restart system. Does it sound anything familiar? Mean while i try ur advice putting the commands on shell script
Thanks,
Rao

Same Problem

Rao,
I have the exact same problem working thru the instructions. Did you solve the problem? How?
Thanks
Steve

Qemu MIPS

i have been trying to run qemu on linux to emulate mips architecture and install debian as os on mips, however i am unable to do it. Can you please help me out with commands that are required for proper installation.

Qemu MIPS

i have been trying to run qemu on linux to emulate mips architecture and install debian as os on mips, however i am unable to do it. Can you please help me out with commands that are required for proper installation.

RE: Qemu MIPS

How far have you got? Then we can take it from there.
Chris.

can not boot from NFS

This was not working for me for a long time... for anyone interested..
iptables --flush did the trick for me.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Youtube and Vimeo video links are automatically converted into embedded videos.
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.