http://tipc.wiki.sourceforge.net/QEMU+Cheat+Sheet

QEMU Cheat Sheet

  • author: Allan Stephens
  • last updated: 29 August 2008


Installing QEMU on a Linux host



  • Method 2: compile software from source (see NOTE below)
    • get latest stable version
    • (alternatively) get latest development version
    • cd <qemu root directory>
    • ./configure (usually no options are required)
    • (root) make install (seems to do both "make" and "make install")

    • NOTE: you must have GCC version 3 available, as QEMU won't work right under GCC v4
      • if needed, can install GCC v3 as follows:
        • download GCC v3.4 module (Google located compat-gcc-34-3.4.6-4.i386.rpm)
        • rpm -ivh compat-gcc-34-3.4.6-4.i386.rpm (must be root user)

  • (optional) install QEMU accelerator module (see NOTEs below to check if it's worthwhile)
    • download http://fabrice.bellard.free.fr/qemu/kqemu-1.3.0pre11.tar.gz
    • gunzip kqemu-1.3.0pre11.tar.gz
    • tar xf kqemu-1.3.0pre11.tar
    • cd kqemu-1.3.0pre11
    • ./configure (usually no options are required)
    • make (got a warning at the end, but didn't seem to matter …)
    • (root) make install
    • (root) /sbin/modprobe kqemu (can also set up system to do this automatically)

    • NOTE: KQEMU is incompatible with a Linux target built with GCC v4 (gives boot errors!)
    • NOTE: KQEMU source code builds properly with GCC version 4 (unlike QEMU)
    • NOTE: KQEMU may provide significant benefits (when used with a GCC v3 Linux target)
      eg. time to boot system (from start up until login prompt):
      • with no acceleration (invoke QEMU with -no-kqemu option): 36 sec
      • with user mode acceleration (invoke QEMU normally): 25 sec
      • with user mode & kernel acceleration (invoke QEMU with -kernel-kqemu option): 21 sec

Starting up a QEMU Linux guest on a Linux host


  • there is a lengthy User Guide at http://fabrice.bellard.free.fr/qemu/user-doc.html
    • WARNING: this document contains a lot of useful information, but it is more of a reference guide than a tutorial—it's not the easiest thing in the world to learn from!

  • QEMU guest is invoked by: (root) qemu <options>
    • NOTE: you don't always have to be "root" on host, but I found this convenient to avoid running into permission problems when trying to access host system resources from a QEMU guest

  • typical invocation uses the following options:
    • -kernel <bzImage>
      • overrides the default kernel supplied with guest's filesystem (see below)
        • this is handy if you are developing Linux kernel code
        • to create a bzImage file:
          • go to top level Linux source directory
          • make [ARCH=<arch>] menuconfig
          • make [ARCH=<arch>] bzImage
        • output file is stored in arch/<arch>/boot/bzImage
        • NOTE: can omit ARCH if Linux host and target architectures are the same
    • -append "root=/dev/hda console=ttyS0"
      • passes startup options to Linux kernel
        • NOTE: there are additional options—see Linux kernel documentation …
      • "root=" specifies location of Linux filesystem
        • can omit this if not using "-kernel" option
      • "console=" directs console output to guest machine's serial port
        • can omit this if not using "-nographic" option (see below)
    • -hda <filesystem>
      • tells QEMU to make Linux filesystem visible to guest OS as /dev/hda
      • see "How to create or modify a QEMU guest's filesystem" for help on setting this up
    • -snapshot
      • tells QEMU to use COW-file approach for Linux filesystem; COW = "copy on write"
      • QEMU won't modify filesystem unless specifically told to by user
    • -no-kqemu
      • tells QEMU not to use hardware accelerator (even if it is installed)
    • -nographic
      • tells QEMU not to fire up VGA display window
    • -smp <N>
      • tells QEMU how many CPUs to run—only useful when using an SMP-enabled kernel
      • specify 1 CPU unless you have a good reason not to (more CPUs = slower QEMU runs)

  • this will cause your shell to enter the QEMU monitor (see below), and then immediately start up the QEMU guest and display the output of its serial port
    • the serial port will display the start up messages for your Linux guest's console
    • NOTE: you won't be able to log in to your Linux guest unless the guest's filesystem has been configured to support this (see below)

A useful shell script for invoking a QEMU Linux guest on a Linux host


#! /bin/csh -f
 
# Standard script for initializing a QEMU session
#
# - typically invoked from top level directory of Linux kernel source tree
#   for kernel image to be used
# - requires a single argument to identify the session (a digit from 1 to 9);
#   this is used to generate:
#   - unique MAC addresses for Ethernet ports
#   - a unique serial port that can be used to login via telnet
# - define KERNEL below to identify kernel image to use
# - define ROOTFS below to identify Linux filesystem that image uses
# - define ALTFS  below to identify secondary filesystem that image uses
#   [NOTE: can omit 2nd filesystem if not needed]
 
set N = $argv[1]
 
set KERNEL = "./arch/i386/boot/bzImage"
set ROOTFS = "/home/<your userid>/<main filesystem>"
set ALTFS  = "/home/<your userid>/<secondary filesystem>"
 
# System is configured to use:
# - kernel at location specified by KERNEL
# - /dev/hda1 is main Linux filesystem (at location specified by ROOTFS)
# - /dev/hdb1 is secondary filesystem (at location specified by ALTFS)
# - eth0 and eth1 are configured with (hopefully unique) MAC addresses;
#   they communicate with other guests using host UDP multicasting on VLANs
#   (in a UML-compatible manner)
# - ttyS0 is the system console
#   - to get login prompt, enable "getty" for ttyS0 in guest's /etc/inittab
# - ttyS1 is accessed via telnet on host's port 44xx
#   - to connect, enter "telnet localhost 44xx" on host
#   - to get login prompt, enable "getty" for ttyS1 in guest's /etc/inittab
#   - to allow root logins, add ttyS1 to guest's /etc/securetty
 
qemu \
-kernel ${KERNEL} \
-append "root=/dev/hda console=ttyS0" \
-snapshot \
-hda ${ROOTFS} \
-hdb ${ALTFS} \
-net nic,vlan=0,model=rtl8139,macaddr=02:00:${N}:${N}:${N}:02 \
-net socket,vlan=0,mcast=239.192.168.1:1102 \
-net nic,vlan=1,model=rtl8139,macaddr=02:00:${N}:${N}:${N}:03 \
-net socket,vlan=1,mcast=239.192.168.1:1103 \
-serial stdio \
-serial telnet:localhost:4${N}${N}0,server,nowait \
-smp 1 \
-no-kqemu \
-nographic \
 
# OTHER USEFUL OPTIONS
# To enable floppy disk usage:
# -fda /dev/fd0 \
# To activate gdb server:
# -s \
 

Running a QEMU Linux guest


  • QEMU provides 2 window buffers when invoked with "-nographic"
    • the QEMU monitor
      • can use this for various control/debugging operations (see QEMU documentation)
    • the guest's serial port (typically /dev/ttyS0)
      • allows you to log in to QEMU guest, and to see console output
      • NOTE: you won't be able to log in to your Linux guest unless the guest's filesystem has been configured to support this (see below)

  • important key sequences to know:
    • Ctrl-a c
      • switch between serial port and QEMU monitor window buffers
    • Ctrl-a x
      • terminate QEMU
      • alternate method: enter "quit" in the QEMU monitor window buffer
    • Ctrl-a s
      • save disk data back to file (overrides "-snapshot" option)

  • to enable logins via the guest's serial port:
    • ensure the Linux guest's /etc/inittab file has a line like the following:
      • T0:23:respawn:/sbin/getty -L ttyS0 38400 vt100
      • this tells Linux to listen for logins on /dev/ttyS0
    • there was already a line like this in the filesystem I was using, but it was commented out

  • to login to a Linux guest
    • Ubuntu provides default user of "root", with no password (i.e. just hit enter when prompted)
    • NOTE: this process can vary, depending on the Linux distribution your guest's filesystem has

How to create or modify a QEMU guest's filesystem


  • QEMU requires a Linux filesystem image for your QEMU guest to use
    • easiest approach is to get a pre-built filesystem image from another QEMU user!
    • if none is available, http://uml.nagafix.co.uk/ has filesystems for a variety of Linux distributions
      • you can use a filesystem for a different distribution than the one your host uses
        • the Ubuntu Breezy [Badger] distribution worked for me (even though I was running on a Fedora core host), but I had to manually add in developer packages to allow the guest to compile applications
      • download a copy of filesystem to a directory that isn't your kernel source tree
      • use "bunzip2" to decompress filesystem
        • the filesystem file can be very large (eg. 2G file for Ubuntu!)
    • specify the filesystem file as the "-hda" argument when invoking QEMU

  • using QEMU's "-snapshot" option means that any changes made by Linux guest are not written back to the filesystem image on the host, unless requested
    • this allows multiple guests to share a single filesystem image
      • a guest sees any changes it makes while running, but not changes made by other guests
      • when a guest terminates, all of its changes are lost
    • guest changes can be forceably written back to filesystem image via QEMU monitor commands
      • i.e. "Ctrl-a s" in non-graphical mode, or "commit hda" in graphical mode
      • IMPORTANT: don't do this if multiple guests are sharing the filesystem image!

  • if desired, you can make changes to the filesystem image from your host
    • IMPORTANT: QEMU guest won't pick up filesystem changes that are made after it starts up
      • best policy is terminate QEMU guests before making any changes
    • IMPORTANT: you need administrator privileges to do this
    • typical steps:
      • mkdir <mount_dir>
        • creates a mount point for host to mount the filesystem on
      • (root) mount <filesystem_image> <mount_dir> -o loop
        • alternate form: mount -oloop=/dev/loop0 <filesystem_image> <mount_dir>
      • cd <mount_dir>
        • can now look at/manipulate files in filesystem
      • (root) umount <mount_dir>
        • now safe to start up QEMU guest(s)

  • VERY IMPORTANT!!!
    • Linux increments a filesystem's "mount count" each time it is mounted (either by the host or a guest); after a certain number of mounts Linux checks if the filesystem has become corrupted
    • if a QEMU guest reports a problem with the integrity of its filesystem, terminate the guest and fix the filesystem image on the host
      • (root) losetup /dev/loop0 <filesystem_image>
      • (root) fsck /dev/loop0
        • this checks the filesystem; you may be asked to OK the fixes it wants to make
        • you might want to backup the filesystem image before checking it, just to be safe
      • (root) losetup -d /dev/loop0

Using a secondary filesystem with a QEMU guest


  • it is sometime desirable to supply a Linux guest with a second filesystem
    • eg. allow guest to use tipc-config, TIPC test suite, or other standard applications
    • eg. allow multiple guests to share main filesystem in read-only manner, but have their own writeable files (or vice versa)

  • invoke QEMU with "-hdb <disk_image>" option
    • this maps <disk_image> file on host to target's /dev/hdb
  • tell QEMU to mount disk image
    • (qemu) mkdir host_fs
    • (qemu) mount /dev/hdb1 host_fs
    • (qemu) ls host_fs [this should display files that are present in the disk image]

  • how to create a disk image from scratch
    • info taken from: http://www.osdev.org/osfaq2/index.php/Disk%20Images%20Under%20Linux
    • IMPORTANT! you need administrator privileges to do this
    • create a 500MB disk image file called "disk.img"
      • (root) dd if=/dev/zero of=disk.img bs=516096c count=1000
      • (root) losetup /dev/loop0 disk.img
      • (root) fdisk -u -C1000 -S63 -H16 /dev/loop0
        • [command prompts for disk formatting commands—ignore errors/warnings]
        • o (create empty partition table)
        • n (create a new partition, called #1)
          • enter "p", then "1"
        • w (write out results & exit)
      • (root) losetup -d /dev/loop0
    • convert disk image into a Linux ext2 filesystem
      • (root) losetup -o32256 /dev/loop0 disk.img
      • (root) mke2fs -b1024 /dev/loop0 503968
    • add files to disk image
      • (root) mkdir <mount directory>
      • (root) mount -text2 /dev/loop0 <mount directory>
      • (root) cd <mount directory>
      • … add files …
      • (root) umount /dev/loop0
      • (root) losetup -d /dev/loop0
    • subsequent host updates to disk image can be done in a simpler manner
      • (root) mount -text2 -oloop=/dev/loop0,offset=32256 disk.img <mount directory>
      • … play with files …
      • (root) umount disk.img

  • IMPORTANT!
    • any changes to disk image by guest OS are lost unless they are written back to disk image
      • (qemu) umount hostfs
      • (qemu monitor) commit hdb

Using a floppy drive with a QEMU guest


  • in some case it may be desirable to allow a Linux guest to access a floppy drive (either real or simulated)
    • eg. allow a running Linux guest to get new files from host system

  • IMPORTANT!
    you need administrator privileges to do this
  • when invoking QEMU use "-fda /dev/fd0" option
    • this maps host's /dev/fd0 to target's /dev/fda
  • once QEMU is running mount /dev/fda
    • (qemu) mkdir floppy
    • (qemu) mount /dev/fda floppy
  • IMPORTANT!
    you need to use QEMU Monitor to tell QEMU when floppy disk is inserted/ejected/changed
    • (qemu monitor) change fda /dev/fd0
      • QEMU should now access disk contents
  • you should now be able to access files on floppy drive
    • (qemu) ls floppy
      • should see list of files on host's floppy drive
  • CAUTION!
    QEMU changes contents of floppy disk even when running with "-snapshot" option!
    • I'm not sure if this is true if you do "-fda <floppy image file>", but you can change a real disk if you specify "-fda /dev/fd0"

Setting up networking for a QEMU guest


  • can easily set up simple multicast-based networking (à la UML)
    • this form of networking allows your QEMU and UML guests to communicate with each other, but not with your host and/or the Internet
    • "real" networking is possible, but isn't (yet) documented here—see QEMU documentation …

  • specify both of the following options when invoking QEMU:
    -net nic[,vlan=<N>][,model=<type>][,macaddr=xx:xx:xx:xx:xx:xx]
    -net socket,mcast=239.192.1681.1:1102
    • the first option specifies the NIC to use
      • the optional "vlan" field let you to have multiple NICs, if desired; the default <N> is 0
        • NOTE: it's unclear if you can have multiple NICs on the same VLAN or not; this might conceivably work if you use different multicast ports (eg. 1103, 1104, etc.); I'm also unsure how to tell UML which VLAN to use …
    • the second option indicates that UDP multicasting is used as transport

  • IMPORTANT!
    make sure your target kernel supports the model of Ethernet card you are using
    • specifying a model of "rtl8139" gives an RTL 8139-based card, whose driver is included in the default Linux kernel configuration
    • omitting the model info gives an NE2000-based card, whose driver isn't included in the default Linux kernel configuration; you can include the driver by following the menuconfig path:
  • >> device drivers --> network device support --> Ethernet (10 or 100Mbit) --> PCI NE2000 and clone support

Running QEMU in graphical mode


  • if desired, you can run QEMU in graphical mode, which emulates a VGA display
    • this is handy for people who want to run Windows on a Linux host (or vice versa)
    • not particularly useful for a typical developer who is making changes to the Linux kernel

  • to obtain graphical mode
    • ensure QEMU has been built with graphical capabilities (which is the default)
      • NOTE: host must support SDL development library
    • invoke QEMU without "-nographic" option
      • QEMU should pop up a virtual console window when it is invoked
    • you should probably remove the "console=ttyS0" part of the "-append" option, too
      • ensures the Linux guest's startup messages appear in main virtual console window,
  • >> >>> rather than the (initially hidden) serial port window

  • QEMU's virtual console provides 3 window buffers:
    • main window buffer is the target's virtual console
      • provides simulated VGA display and keyboard
      • use CTL-ALT-1 to select this window
      • use SHIFT-PageUp/PageDown to scroll back and forth in this window
    • secondary window buffer is the QEMU Monitor
      • can use this for various control/debugging operations (see QEMU documentation)
      • use CTL-ALT-2 to select this window
      • use CTL-Up/Down/PageUp/PageDown to scroll back and forth in this window
    • third window buffer is the target's serial port (typically /dev/ttyS0)
      • use CTL-ALT-3 to select this window
      • use CTL-Up/Down/PageUp/PageDown to scroll back and forth in this window
    • fourth window buffer is the target's parallel port
      • use CTL-ALT-4 to select this window
        • if serial port has been redirected, use CTL-ALT-3 instead …
      • use CTL-Up/Down/PageUp/PageDown to scroll back and forth in this window

  • use CTL-ALT to toggle mouse/keyboard focus out of virtual console
    • allows you to access other windows on host in normal manner

Debugging with QEMU on Linux host


  • can use GDB to debug target (in the same way as with UML)
    • NOTE: I haven't figured out how to debug an SMP target with more than 1 CPU using GDB; how does GDB know which CPU it's talking to/about?; hopefully, when UML support for SMP is added it will be possible to simply attach GDB to the process representing each CPU …
  • IMPORTANT!
    make sure you compile target kernel with debugging symbols enabled
    • symbols aren't included in the default Linux kernel configuration; to include them, follow the menuconfig path:
  • >> Kernel hacking --> Compile the kernel with debugging info
  • start QEMU with "-s" option
    • this tells QEMU to listen for gdb on port 1234 when it tries to connect later on
    • you can also use QEMU Monitor to do this if you didn't do it at startup
      • (qemu monitor) gdbserver
  • start GDB
    • (host) gdb vmlinux
    • (gdb) … [set breakpoints, etc.]
    • (gdb) target remote localhost:1234
    • (gdb) c [to continue execution of QEMU]

  • IMPORTANT!
    • I encountered problems in getting QEMU to resume from a breakpoint on my first host (although things seemed to work properly on a different host that uses a later kernel)
    • I'm not sure if there was a problem with the host system or with the target kernel being tested— there was an error message from the target about NMI not working properly that may relate to this …
    • only known workaround was to disable breakpoint, continue execution to next breakpoint, then re-enable the disabled breakpoint—this is tiresome, but it works (note: couldn't use "step" and "next", since they didn't work either)


Redirecting console output with QEMU on a Linux host


  • this may be useful if you need to capture "oops" information or boot time messages when running QEMU in graphical mode
    • to simply read the info, use SHIFT-PageUp/PageDown in the main virtual console window
    • there may be some way to get the host's windowing system to cut-n-paste info in the main virtual console window, but I haven't found it …

  • tell QEMU to redirect console output to /dev/ttyS0, rather than the main virtual console window
    • add "console=ttyS0" to the -append option when invoking QEMU
    • IMPORTANT!
  • >> you won't see most normal boot messages displayed in the virtual console anymore,
  • >> but if you wait long enough you should eventually see the normal login prompt
  • to see redirected console output, switch to virtual console's serial port "window" via CTL-ALT-3
    • can now see console output
    • can scroll up using CTL-Up and CTL-PageUp, etc., as described in documentation
    • toggle back to main virtual console window via CTL-ALT-1 when done
  • to capture console output, must also redirect QEMU's serial port output to a Telnet session
    • add "console=ttyS0" to the -append option, as described above
    • add "-serial tcp::1235,server" option
      • tells QEMU to wait for connection on host port 1235 before booting up
      • can use a different port number, if desired
    • once QEMU begins booting it will stop and wait for you to connect to serial port
    • connect to target's serial port from another window
      • telnet localhost 1235
      • QEMU should now continue booting
      • telnet window will display console output
    • can use this window's scroll bar to see previous out; can cut & paste to save output; etc.

  • QEMU provides a variety of other ways of capturing console output, such as saving it to a file, etc.
    • see QEMU documentation for further details


QEMU Internals


  • QEMU uses the following physical memory map for i386 guests
    • physical address 0000 0000: RAM (ram_size = 128MB)
    • physical address 0800 0000: VGA RAM (vga_ram_size = 8MB)
    • physical address 0880 0000: BIOS (bios_size = 320KB)

  • QEMU uses a 4KB page size for physical memory, plus a 2-stage page table
    • upper 10 bits of physical address = array index in L1 paging array
      • each array entry is a pointer to a L2 paging array
    • next 10 bits of physical address = array index in L2 paging array
      • L2 paging arrays are dynamically allocated; only created if QEMU registers some use of that memory region
      • each array entry specifies offset of page from start of physical memory array in upper 20 bits; lower 12 bits are 0 for normal physical memory, but non-zero for I/O memory—this allows QEMU to recognize when it is accessing memory associated with an I/O device (in which case it invokes the callback routine for the associated device to handle the read or write operation, rather than simply reading or storing the data in the physical memory array)
    • low 12 bits of physical address = offset within a 4096 byte page of physical memory array
    • physical memory array is dynamically allocated
      • phys_ram_size = 128MB + 8MB + 320KB, by default


Installing QEMU on a Windows host



  • obtain QEMU pre-compiled software from http://www1.interq.or.jp/~t-takeda/qemu/
    • download qemu-0.9.0-windows.zip file
    • unzip file to create qemu-0.9.0-windows folder
    • that's it! (no need to run an installer)
  • to test installation, double click "qemu-win.bat" file
    • should boot up a very basic Linux installation using supplied "linux.img" filesystem
    • to exit, type "CTL-ALT-2" to enter QEMU Monitor, then enter "quit"

  • to install the optional QEMU accelerator module, do the following:
    • get software from http://fabrice.bellard.free.fr/qemu/download.html
    • decompress & untar the software
    • in Windows Explorer, right click on "kqemu.inf" and select "Install"
      • you can uninstall it using the normal Add/Remove softwre control panel
    • open a DOS command window and enter "net start kqemu"
      • NOTE: I'm not sure if you need to restart this if you reboot your Windows host, or whether it will restart automatically …
      • you can also stop it via "net stop kqemu"
    • add the "-kernel-kqemu" when invoking QEMU (see below)
      • if things don't seem to work properly try adding the "-no-acpi" option as well
    • NOTE: when I tried this, QEMU didn't seem to enable the accelerator properly—it's unclear if the precompiled Windows code has the accelerator capability enabled; the accelerator documentation says you don't get much improvement when running Linux 2.6 targets anyway (although maybe this only applies to Linux hosts?), so I haven't bothered pursuing things further

Running QEMU Linux target on a Windows host


  • create shortcut for "qemu.exe", then modify start up properties so that "Target" is:
    "<QEMU folder>\qemu.exe" -L . -kernel <bzImage> -append "root=/dev/hda" -snapshot -hda <filesystem>
    • -L option tells QEMU to look for BIOS file in main QEMU folder
    • -kernel <bzImage> allows you to replace default kernel supplied with Linux filesystem
      • to create a bzImage file:
        • go to top level Linux source directory
        • make [ARCH=<arch>] menuconfig
        • make [ARCH=<arch>] bzImage
      • output file is stored in arch/<arch>/boot/bzImage
      • note: I built Linux kernels on my Linux host, then copied them to my Windows host; since both machines are 386-based, there was no need to specify ARCH when building
    • -append option tells QEMU where to find root of filesystem
      • do this if using -kernel option
    • -hda option tells QEMU where to find Linux's filesystem
      • can use same filesystem as with UML (eg. a Ubuntu-based one)
    • -snapshot tells QEMU to use COW-file approach for Linux filesystem
      • i.e. don't modify original filesystem—safest approach to take
  • example:
    • copy bzImage file to QEMU folder
    • copy Ubuntu_buildtools_fs to QEMU folder
    • create shortcut with properties:
  • >> "C:\Documents and Settings\astephen\Desktop\qemu-0.9.0-windows\qemu.exe" -L . -kernel bzImage -append "root=/dev/hda" -snapshot -hda Ubuntu_buildtools_fs

Running QEMU in SMP mode on Windows host


  • ensure that you have built an SMP-enabled kernel
  • when invoking QEMU use "-smp <N>" option to specify # of CPUs to start up
    • note: you may be able to get a faster startup by adding something like "lpj=10000000" to the -append option string; this tells QEMU how many "loops per jiffy" the host executes, so it doesn't have to run a test to figure this out for itself
  • WARNING: currently seem to be able to bring up at most 2 CPUs
    • may be caused by use of hyperthreading on Windows host—need to disable this to confirm …

Accessing filesystem on Windows host


  • ensure Linux kernel has support for Windows filesystem
    • in my case, needed to add support for NTFS filesystem
  • >> (Linux support for this is somewhat rudimentary—probably best to use in read-only fashion)
  • add "-hdb" to -append option when invoking QEMU
    • this maps C: drive (on my Windows PC) to /dev/hdb
  • once QEMU is running, mount /dev/hdb1 (note: the extra '1' at the end is required)
    • (qemu) mkdir hostfs
    • (qemu) mount /dev/hdb1 hostfs
    • (qemu) ls hostfs
      • should see list of files on C: drive
  • CAUTION: QEMU seems to cache its view of the filesystem when it is mounted, so if you add files to the C: drive you won't be able to see them until you unmount and remount things (ugh!)



Reply via email to