Author: Mugabi Siro

Category: qemu

Summary:

This entry presents a few examples illustrating QEMU Human Monitor Interface (HMI) usage. Originally tested on QEMU v1.x. Includes a few updates for v2.x. QEMU version compatibility issues noted where applicable.

Tags: qemu linux

Table Of Contents

Overview

The QEMU Human Monitor Interface (HMI) console provides an interface that allows user interaction with a live QEMU instance. Among other things, it allows (guest virtual and VM physical) memory dumps, taking screenshots and performing audio grabs. In addition it allows viewing QEMU machine "trees" for memory objects, device/bus hierarchies, and QEMU Object Model (QOM) composition. This entry covers a few interesting examples.

Accessing the HMI

By default, the QEMU machine uses SDL to display its video output. This mode is referred to as Graphical Mode. It is also possible to run QEMU as a simple commandline application. This mode is called Nographic and is effected by the -nographic commandline option which completely disables graphical output.

Depending on the mode, different commandline options and key combinations are used to control access to the HMI.

The -monitor DEV commandline option controls redirection of the HMI console. In graphical mode, DEV takes the value vc, by default. This means that the HMI console is on a QEMU Virtual Console (VC) on the SDL window. In nographic mode, DEV takes the default value of stdio.

DEV can take several other values, besides vc and stdio. Legal DEV values are the same as those listed for the -serial option in the qemu(1) manpage. It is therefore possible to redirect the HMI to other host terminal interfaces such as different xterm(1) interfaces, Net Consoles and even on a true remote terminal via ssh(1). Check Redirecting QEMU Serial Line Terminals for examples of non-standard configurations for HMI console redirection.

Graphical Mode

  • Monitor on QEMU Virtual Console

    This is the default setting i.e. when no -monitor DEV option is included in the QEMU commandline. Type CTRL+ATL+N (where N is 2, 3, ..., depending on your particular settings) to switch to the HMI SDL virtual console. The QEMU SDL window should present an interface similar to:

  • Monitor on stdio

    Alternatively, the HMI console may be redirected to stdio by including the -monitor stdio option in the commandline. For example, the following boot against a disk image1:

    $ qemu-system-x86_64 brdisk-img.raw -monitor stdio
    

    resulted in:

  • Multiplexing QEMU Monitor and Guest Serial Port System Console on stdio

    Doing this in graphical mode will require the use of the -serial mon:stdio option. See QEMU Serial port system console for an example of multiplexing the QEMU monitor and the guest serial port system console on stdio.

    Also note that since the HMI console is now being multiplexed with the guest serial port system console on stdio, the key-combinations to switch to between these two interfaces will be the same as those described in the QEMU nographic mode in section Nographic Mode below.

Nographic Mode

Running QEMU with -nographic completely disables any graphical output (QEMU machine video). In this mode, the HMI console is available on stdio by default. The virtual serial port is also redirected to stdio by default. Correspondingly, guest systems will typically be configured to use the virtual serial port as the system console. See QEMU Serial port system console for details on configuring a QEMU/Linux system for system console on serial port.

For example, the following command line:

$ qemu-system-x86_64 -kernel bzImage -hda brdisk-img.raw -append "root=/dev/sda2  rw console=ttyS0" -nographic

resulted in the nographic mode boot instance below:

Typing CTRL+a then c (and then RETURN) switched to the monitor console:

and re-typing CTRL+a then c (and then RETURN) toggled back to the Buildroot login prompt on the guest serial port system console:

Quiting and Exiting

On the HMI console, entering

(qemu) quit

will immediately terminate the QEMU instance.

In nographic mode or if the monitor is being multiplexed with the guest system console on serial port via -serial mon:stdio in graphic mode:

  • Assuming that the HMI console is the current QEMU interface, typing CTRL+a then c will exit "HMI mode" and toggle to the guest serial port system console.

  • Typing CTRL+a then x on the HMI console will immediately kill the QEMU instance.

Available HMI commands

A keyboard TAB against the (qemu) command prompt of the HMI console will display the available commands:

(qemu) info version 
2.6.94 (v2.7.0-rc4-4-ge00da55-dirty)
(qemu) 
?                                acl_add                          
acl_policy                       acl_remove                       
acl_reset                        acl_show                         
...
change                           chardev-add                      
chardev-remove                   client_migrate_info              
closefd                          commit                           
cont                             cpu                              
cpu-add                          delvm                            
device_add                       device_del                       
drive_add                        drive_backup                     
drive_del                        drive_mirror                     
...

For a more verbose output:

(qemu) ?
acl_add aclname match allow|deny [index] -- add a match rule to the access control list
(...)
device_add driver[,prop=value][,...] -- add device, like -device on the command line
device_del device -- remove device
(...)
screendump filename -- save screen into PPM image 'filename'
sendkey keys [hold_ms] -- send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)
(...)
wavcapture path [frequency [bits [channels]]] -- capture audio to a wave file (default frequency=44100 bits=16 channels=2)
x /fmt addr -- virtual memory dump starting at 'addr'
xp /fmt addr -- physical memory dump starting at 'addr'

Obtaining Info about the VM

The info <OPTION> command can be used to obtain information about the VM. To view available <OPTION>s, run info with no argument.

(qemu) info
info balloon  -- show balloon information
info block [-v] [device] -- show info of one block device or all block devices (and details of images with -v option)
info block-jobs  -- show progress of ongoing block device operations
info blockstats  -- show block device statistics
info capture  -- show capture information
info chardev  -- show the character devices
info cpus  -- show infos for each CPU
[...]

A few examples are presented below.

Detecting KVM

For instance, the QEMU launch commandline in section Nographic Mode did not include the -enable-kvm switch, hence:

(qemu) info kvm
kvm support: disabled

Viewing QEMU Machine "Trees"

  • qtree

    The qtree HMI command can be used to display the QEMU bus "tree". For example, on one qemu-system-x86_64 instance:

    (qemu) info qtree
    bus: main-system-bus
        type System
        [...]
        dev: i440FX-pcihost, id ""
            pci-hole64-size = 2.000G
            irq 0
            bus: pci.0
                type PCI
                dev: PIIX4_PM, id ""
                    [...]
                    addr = 01.3
                    [...]
                    class Bridge, addr 00:01.3, pci id 8086:7113 (sub 1af4:1100)
                    bus: i2c
                        type i2c-bus
                        dev: smbus-eeprom, id ""
                            address = 87
                            [...]
                dev: e1000, id ""
                    mac = 52:54:00:12:34:56
                    vlan = 0
                    [...]
                    addr = 03.0
                    romfile = "efi-e1000.rom"
                    [...]
                    class Ethernet controller, addr 00:03.0, pci id 8086:100e (sub 1af4:1100)
                    bar 0: mem at 0xfebc0000 [0xfebdffff]
                    bar 1: i/o at 0xc000 [0xc03f]
                    bar 6: mem at 0xffffffffffffffff [0x3fffe]
                    [...]
    
  • qom-tree

    Displays the QOM device composition tree. NOTE: This command is available only since v2.3 (or thereabouts).

    (qemu) info qom-tree 
    /machine (pc-i440fx-2.7-machine)
      /fw_cfg (fw_cfg_io)
      ...
      /peripheral (container)
        /ivshmem (ivshmem)
      ...
      /unattached (container)
        ...
        /device[14] (isa-parallel)
          /parallel[0] (qemu:memory-region)
        /device[22] (e1000)
          /e1000-mmio[0] (qemu:memory-region)
              ...
      /i440fx (i440FX-pcihost)
        /pam-pci[19] (qemu:memory-region)
        /pam-rom[1] (qemu:memory-region)
          ...
      /peripheral-anon (container)
        /device[0] (virtio-blk-pci)
        ...
    
  • mtree

    The QEMU machine framework implements a memory API to model ordinary system RAM, as well as the I/O Ports and Memory-Mapped I/O (MMIO) regions for its virtual devices. Memory is modeled as an acyclic graph of MemoryRegion objects. Sinks (or leaves) are RAM and MMIO regions, while other nodes represent buses, memory controllers, and memory regions that have been re-routed. See docs/memory.txt of the QEMU sources for a detailed description.

    For illustration, consider the following QEMU commandline:

    $ qemu-system-x86_64 -enable-kvm -m 1G [...] -device ivshmem,shm=ivshmem,size=1
    

    which resulted in the following placement of the ivshmem PCI device's MMIO regions in the QEMU machine memory model:

    (qemu) info mtree
    memory
    0000000000000000-ffffffffffffffff (prio 0, RW): system
        0000000000000000-000000003fffffff (prio 0, RW): alias ram-below-4g @pc.ram 0000000000000000-000000003fffffff
        0000000000000000-ffffffffffffffff (prio -1, RW): pci
        [...]                                                                                                    
            00000000fe000000-00000000fe0fffff (prio 1, RW): ivshmem-bar2-container
                00000000fe000000-00000000fe0fffff (prio 0, RW): ivshmem.bar2
        [...]                                                                                                           
            00000000febf1000-00000000febf10ff (prio 1, RW): ivshmem-mmio
        [...]
    

    where:

    • The ivshmem-mmio is a MMIO sub-region in the QEMU memory range allocated for the PCI memory container. Its range, i.e. 00000000febf1000-00000000febf10ff, maps to the device's MMIO region pointed to by PCI BAR0 (Base Address Register).

    • In a similar fashion, ivshmem-bar2-container is a "pseudo-container" that is overlapped by the ivshmem.bar2 sub-region of the same size, i.e. 00000000fe000000-00000000fe0fffff. The latter is visible to the guest as the device's MMIO region mapped by PCI BAR2.

    The ivshmem device, and other QEMU devices for that matter, implement callbacks which get invoked whenever the virtual CPU accesses memory regions that QEMU has assigned to the device's I/O ports or MMIO mappings. For example, check QEMU MMIO Memory Regions for an illustration.

QOM Property Info

NOTE: qom-tree command available since around v2.3; ivshmem-plain device available since after v2.5 (or thereabouts).

Now, consider the following boot instance:

$ qemu-system-x86_64 ... \
    -object memory-backend-file,id=mb1,size=1M,share,mem-path=/dev/shm/ivshmem \
    -device ivshmem-plain,id=ivshm-plain,memdev=mb1
  • To view the QOM properties for the "ivshmem-plain" device:

    (qemu) info qom-tree
    /machine (pc-i440fx-2.7-machine)
      ...
        /peripheral (container)
        /ivshm-plain (ivshmem-plain)
    
    (qemu) qom-list ivshm-plain
    bus master[0] (child<qemu:memory-region>)
    rombar (uint32)
    hotpluggable (bool)
    ivshmem-mmio[0] (child<qemu:memory-region>)
    ...
    realized (bool)
    
  • Setting QOM properties can be done via qom-set. Note that most QOM properties are locked once the device is realized, or once a user creatable object's property has been set. For example:

    (qemu) qom-list /objects/mb1
    ...
    share (bool)
    size (int)
    \x2fobjects\x2fmb1[0] (child<qemu:memory-region>)
    mem-path (string)
    ...
    
    (qemu) help qom-set
    qom-set path property value -- set QOM property
    
    (qemu) qom-set /objects/mb1 size 2
    cannot change property value
    

    where the -object command line switch adds the user creatable object instance as a child of the /objects root object in the QOM composition tree. With the QEMU version used here (v2.7.0-rc4), info qom-tree did not display the /objects canonical paths in the QOM composition tree. QOM and Device Relationships might be of interest.

Block Info

$ qemu-system-x86_64 -drive file=/usr/local/qemu/derivd0.img,cache=writeback ...

(qemu) info block
ide0-hd0 (#blockNNN): /usr/local/qemu/derivd0.img (qcow2)
    Cache mode:       writeback
    Backing file:     /usr/local/qemu/prestine.img (chain depth: 1)
    ...

(qemu) info block -v ide0-hd0
ide0-hd0 (#block118): /usr/local/qemu/derivd0.img (qcow2)
    Cache mode:       writeback
    Backing file:     /usr/local/qemu/prestine.img (chain depth: 1)

Images:
image: /usr/local/qemu/derivd0.img
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 5.8G
backing file: /usr/local/qemu/prestine.img
...
image: /usr/local/qemu/prestine.img
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 4.7G
...

Network Info

$ qemu-system-x86_64 ... \ 
   -netdev bridge,ifname=tap2,br=br1,id=ndev,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper \
   -device e1000,mac=DE:AD:BE:EF:B1:AB,id=nic0,netdev=ndev

(qemu) info network 
nic0: index=0,type=nic,model=e1000,macaddr=de:ad:be:ef:b1:ab
 \ ndev: index=0,type=tap,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper,br=br1

Hotplugging Devices

Some buses support device "hotplugging", i.e. adding/deleting devices to/from a live QEMU instance. Examples include PCI, USB and Virtio. In QOM lingo, device add and delete implies device "realize" and "unrealize", respectively. A device can be realized and unrealized several times during the lifetime of a QEMU instance.

Hotplugging a device via the HMI interface is done with the device_add (adding) and device_del (deleting) commands. Hotplugging a device may also require addition/deletion of the corresponding backend, e.g.:

  • a character device backend (sockets, terminal, pipe, file, etc). The chardev-add and chardev-remove commands are used for addition/deletion, respectively.

  • The object_add and object_del commands are available for addition and deletion, respectively, of a QOM user creatable object backend.

  • The netdev_add and netdev_del command are available for addition and deletion of a netdev backend for a network device.

  • etc.

Generally, the HMI *add commands listed above accept the very same options as their -device, -chardev, -object and -netdev QEMU command line counterparts. On the other hand, the HMI *del commands generally expect the $ID value of the id=$ID parameter that was specified in the corresponding *add command. Commands such as device_del and object_del alternatively accept the canonical path for the device/object in the QOM composition tree. In fact, the $ID value (if specified in the *add command) is used by QOM as the path component name for the device/object. If no id=$ID parameter was specified, QOM dynamically assigns an "array" name for the device/object. See QOM and Device Relationships for an introduction to device composition.

Presented below are a few examples of hotplugging devices and their corresponding backends. For purposes of illustration, consider the minimal QEMU boot commandline and instance below (tested on qemu-system-x86_64):

$ qemu-system-$ARCH -kernel $KERNEL -initrd $INITRD -drive file=$IMG[,OPTS] \
     [-enable-kvm] [-smp $N] [-m $SIZE] [-nographic]

device_add and device_del

Consider the following simple example:

(qemu) device_add pci-testdev,id=pcitestdev
(qemu) info pci
...     
  Bus  0, device   5, function 0:
    Class 0255: PCI device 1b36:0005
      BAR0: 32 bit memory at 0xffffffffffffffff [0x00000ffe].
      BAR1: I/O at 0xffffffffffffffff [0x00fe].
      id "pcitestdev"

For QEMU versions that support the info qom-tree command:

(qemu) info qom-tree
/machine (pc-i440fx-2.7-machine)
  ...
  /peripheral (container)
    /pcitestdev (pci-testdev)
      /pci-testdev-portio[0] (qemu:memory-region)
      /pci-testdev-mmio[0] (qemu:memory-region)
      /bus master[0] (qemu:memory-region)

Delete the device:

(qemu) device_del pcitestdev

and run info pci (and info qom-tree) to verify that the device has indeed been deleted.

Recall that hotplugging is a property of the underlying bus. Some buses do not support hotplugging. For instance, the "intel-hda" audio controller resides on the PCI bus and supports a private HDA bus for its audio codecs, namely "hda-output", "hda-duplex", and "hda-micro". Now, since the PCI bus supports hotplugging and the HDA bus does not:

(qemu) device_add intel-hda,id=hdactlr
(qemu) device_add hda-duplex,id=hdacdc
Bus 'hdactlr.0' does not support hotplugging
(qemu) device_del hdactlr

QEMU Audio discusses usage of QEMU audio devices.

object_add and object_del

  • TYPE_MEMORY_BACKEND_RAM: Examples of Hotplugging System RAM

    Check docs/memory-hotplug.txt out.

  • TYPE_MEMORY_BACKEND_FILE: Example with ivshmem

    NOTE: The example below with the "ivshmem-plain" device was performed with a post-v2.5 QEMU (v2.7.0-rc4). This device was not available with pre-v2.5 QEMU. See docs/specs/ivshmem-spec.txt or Linux PCI Device Driver Tutorial for an introduction to the ivshmem device/framework.

    The following command adds a TYPE_MEMORY_BACKEND_FILE Host Memory Backend (HMB) object to the QEMU instance:

    (qemu) object_add memory-backend-file,id=mb1,size=1M,share,mem-path=/dev/shm/ivshmem
    (qemu) info memdev 
    memory backend: 0
      size:  1048576
      merge: true
      dump: true
      prealloc: false
      policy: default
      host nodes: 128
    

    where:

    • id parameter is a unique ID that will be used to reference this (host POSIX SHM backing store) RAM memory region.
    • size property specifies the size of the RAM memory region.
    • share is a boolean property that determines how QEMU performs the mmap(2) memory mapping. If unspecified, the mapping will be MAP_PRIVATE (private to the QEMU instance's virtual address space). Otherwise, the mapping will be MAP_SHARED (visible to an external process).
    • mem-path specifies the path to the POSIX SHM file on the host.

    See -object in qemu(1) for more.

    This "memory-backend-file" backend instance should create the following POSIX SHM file on the host:

    $ ls /dev/shm/ivshmem
    /dev/shm/ivshmem
    

    Hotplug the "ivshmem-plain" device for use with this HMB.

    (qemu) device_add ivshmem-plain,id=ivshm-plain,memdev=mb1
    

    where the id=ivshm-plain specifies the path component of the QOM composition tree for the "ivshmem-plain" device. At this juncture, run info pci (and info qom-tree) to verify the device add.

    To hot-unplug:

    (qemu) device_del ivshm-plain
    (qemu) object_del mb1
    

    Devices and QEMU RAM Memory Regions might be of interest.

chardev-add and chardev-remove

  • Psuedo-Terminal Backend: Example with USB Serial

    See Guest System Console over USB-serial for a detailed discussion of using this device. Below are the steps for adding/deleting the device and the corresponding host tty backend:

    (qemu) chardev-add tty,path=/dev/pts/7,id=pts7
    (qemu) info chardev 
    pts7: filename=serial
    ...
    
    (qemu) device_add piix3-usb-uhci,id=uhci
    (qemu) info pci
    ...
    Bus  0, device   4, function 0:
      USB controller: PCI device 8086:7020
        IRQ 0.
        BAR4: I/O at 0x1000 [0x101f].
        id "uhci"
    
    (qemu) device_add usb-serial,id=usbserial,chardev=pts7
    (qemu) info usb
      Device 0.2, Port 1, Speed 12 Mb/s, Product QEMU USB Serial, ID: usbserial
    
    (qemu) device_del usbserial
    (qemu) device_del uhci
    (qemu) chardev-remove pts7
    
  • UNIX Domain Socket Backend: Example with virtio-serial

    See Guest I/O via Virtio-Serial for background info on using virtio-serial. Below is an example of adding the device and the socket backend:

    On the host:

    $ mkdir /tmp/virtserial
    

    then on the HMI, adding the following backend:

    (qemu) chardev-add socket,path=/tmp/virtserial/test0,server,nowait,id=test0
    (qemu) info chardev 
    test0: filename=unix:/tmp/virtserial/test0,server
    

    results in creation of the following UNIX domain socket on the host:

    $ ls -F /tmp/virtserial/
    test0=
    

    Add a virtconsole device to the virtio-serial PCI bus abstraction/proxy. Associate the virtconsole frontend with the UNIX domain socket backend:

    (qemu) device_add virtio-serial,id=virtserial-bus
    (qemu) info pci
      Bus  0, device   4, function 0:
        Class 1920: PCI device 1af4:1003
          IRQ 0.
          BAR0: I/O at 0x1000 [0x101f].
          BAR1: 32 bit memory at 0x40800000 [0x40800fff].
          BAR4: 64 bit prefetchable memory at 0x40000000 [0x407fffff].
          id "virtserial-bus"
    
    (qemu) device_add virtconsole,chardev=test0,name=console.0,id=virtconsole-dev
    (qemu) info qom-tree
    /machine (pc-i440fx-2.7-machine)
      ...
      /peripheral (container)
        /virtconsole-dev (virtconsole)
        /virtserial-bus (virtio-serial-pci)
    

    NOTE: qom-tree command available only since around v2.3.

    In the guest:

    root@vm:~# ls /dev/virtio-ports/
    console.0
    

    Deleting the devices and the UNIX domain socket backend:

    (qemu) device_del virtconsole-dev 
    (qemu) device_del virtserial-bus
    (qemu) chardev-remove test0
    
  • UNIX Domain Socket Backend: Example with ivshmem

    See Linux PCI Device Driver for background info of using the ivshmem device with the ivshmem server. NOTE: These steps were performed with a post-v2.5 QEMU (v2.7.0-rc4). The ivshmem-server is of the contrib/ivshmem-server sources of the QEMU tree.

    Launch the ivshmem-server on one xterm(1):

    $ rm /tmp/ivshmem_socket 2>/dev/null
    $ ivshmem-server -F -v
    *** Example code, do not use in production ***
    Using POSIX shared memory: ivshmem
    create & bind socket /tmp/ivshmem_socket
    

    On the HMI, adding the following character device backend for a UNIX domain socket:

    (qemu) chardev-add socket,path=/tmp/ivshmem_socket,id=ivshmemid
    

    should result in the following connection message on the ivshmem-server terminal:

    accept()=5
    new peer id = 0
    peer->sock_fd=5
    

    then adding the (legacy) ivshmem device:

    • with id=$ID specified:

      (qemu) device_add ivshmem,chardev=ivshmemid,size=1,msi=off,id=ivshm
      ivshmem is deprecated, please use ivshmem-plain or ivshmem-doorbell instead
      

      presented the following canonical path in the QOM composition tree:

      (qemu) info qom-tree
      /machine (pc-i440fx-2.7-machine)
        ...
        /peripheral (container)
          /ivshm (ivshmem)
          ...
      
    • with id=$ID omitted:

      (qemu) device_add ivshmem,chardev=ivshmemid,size=1,msi=off
      ivshmem is deprecated, please use ivshmem-plain or ivshmem-doorbell instead
      

      resulted in the following canonical path:

      (qemu) info qom-tree
        /machine (pc-i440fx-2.7-machine)
          ...
          /peripheral-anon (container)
            /device[1] (ivshmem)
      

      where device[1] is a dynamically assigned "array" name for the path component (or child<> property) representing the "ivshmem" device in the composition tree. QOM and Device Relationships might be of interest.

    To delete (or "hot-unplug") this device:

    • if the id=ivshm option was specified:

      (qemu) device_del ivshm
      
    • if no id=ivshm option was specified.

      (qemu) device_del /machine/peripheral-anon/device[1]
      

    To delete the UNIX domain socket backend:

    (qemu) info chardev 
    ivshmemid: filename=unix:
    ...
    (qemu) chardev-remove ivshmemid
    

    which should cause the ivshmem-server instance to emit a disconnection message similar to:

    peer->sock_fd=5
    free peer 0
    

netdev_add and netdev_del

The netdev configuration described here relies on the libexec/qemu-bridge-helper program discussed in A QEMU TAP Networking Setup to allow adding/deleting a TAP interface to a qemu instance running without root privileges.

Consider the minimal qemu-system-x86_64 boot command line described above. Even with no networking command line options, QEMU still assigns a default user-mode networking config that resembles:

(qemu) info network
hub 0
 \ hub0port1: user.0: index=0,type=user,net=10.0.2.0,restrict=off
 \ hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56

and

(qemu) info pci
...
Bus  0, device   3, function 0:
  Ethernet controller: PCI device 8086:100e
    IRQ 11.
    BAR0: 32 bit memory at 0xfebc0000 [0xfebdffff].
    BAR1: I/O at 0xc000 [0xc03f].
    BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe].
    id ""

and in the guest environment (ps: should be using ip(8) rather than ifconfig(8), route(8), but hey ...):

you@vm$ lspci | grep -i net
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)

you@vm$ lspci -s 00:03.0 -n
00:03.0 0200: 8086:100e (rev 03)

you@vm$ /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56  
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
...
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0

you@vm$ /sbin/route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0

To keep illustration simple, a new TAP networking configuration and network device will be added to the QEMU instance; the default user-mode networking settings will be left untouched/unused.

Now, add the netdev backend. Note that libexec/qemu-bridge-helper should be owned by root with a setuid attribute as described in A QEMU TAP Networking Setup:

(qemu) netdev_add bridge,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper,id=hn0,name=tap0,br=br0
(qemu) info network 
hub 0
 \ hub0port1: user.0: index=0,type=user,net=10.0.2.0,restrict=off
 \ hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56
hn0: index=0,type=tap,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper,br=br0

Then add a virtual NIC and attach it to the netdev backend:

(qemu) device_add rtl8139,netdev=hn0,id=nic0
(qemu) info network 
hub 0
 \ hub0port1: user.0: index=0,type=user,net=10.0.2.0,restrict=off
 \ hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56
nic0: index=0,type=nic,model=rtl8139,macaddr=52:54:00:12:34:57
 \ hn0: index=0,type=tap,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper,br=br0

(qemu) info pci
...
Bus  0, device   3, function 0:
  Ethernet controller: PCI device 8086:100e
  ...
Bus  0, device   4, function 0:
  Ethernet controller: PCI device 10ec:8139
    IRQ 0.
    BAR0: I/O at 0x1000 [0x10ff].
    BAR1: 32 bit memory at 0x40040000 [0x400400ff].
    BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe].
    id "nic0"

In the guest environment:

you@vm$ lspci | grep -i net
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
00:04.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (rev 20)

you@vm$ lspci -s 00:04.0 -n
00:04.0 0200: 10ec:8139 (rev 20)

you@vm$ /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56  
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
...
eth1      Link encap:Ethernet  HWaddr 52:54:00:12:34:57  
          inet6 addr: fe80::5054:ff:fe12:3457/64 Scope:Link

On the host:

host$ /sbin/ifconfig tap0
tap0      Link encap:Ethernet  HWaddr fe:6f:dc:05:1b:ad 
...

host$ sudo brctl showmacs br0
port no  mac addr            is local?   ageing timer
 ...
  2      52:54:00:12:34:57   no          4.07
  2      fe:6f:dc:05:1b:ad   yes         0.00

At this juncture, a guest network configuration can be done for the new VM network interface. For example, assuming that the host br0 was assigned IP address 192.168.2.5, and was connected to an external network via a gateway at 192.168.2.1, i.e:

host$ /sbin/ifconfig br0
br0       Link encap:Ethernet  HWaddr 76:5d:2f:aa:bb:dd  
          inet addr:192.168.2.5  Bcast:192.168.2.255  Mask:255.255.255.0
...
host$ /sbin/route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 br0
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 br0

then in the guest:

you@vm$ sudo ifconfig eth1 192.168.2.4
you@vm$ sudo route add default gw 192.168.2.1 eth1
you@vm$ /sbin/route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1

you@vm$ ping -c 4 192.168.2.5 
PING 192.168.2.5 (192.168.2.5) 56(84) bytes of data.
64 bytes from 192.168.2.5: icmp_seq=1 ttl=64 time=1.02 ms
64 bytes from 192.168.2.5: icmp_seq=2 ttl=64 time=0.632 ms
...

Ping the host's gateway (in this case @ 192.168.2.1). If the gateway is connected to the Internet, and if properly configured (e.g., as described in A QEMU TAP Networking Setup), then the guest should also be able to reach the net.

To hot-unplug the device:

(qemu) device_del nic0
(qemu) info network 
hub 0
 \ hub0port1: user.0: index=0,type=user,net=10.0.2.0,restrict=off
 \ hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56
hn0: index=0,type=tap,helper=${QEMU_INSTALL}/libexec/qemu-bridge-helper,br=br0

Run /sbin/ifconfig and lspci in the guest to verify that the device has indeed been unplugged. Then delete the netdev backend:

(qemu) netdev_del hn0
(qemu) info network
hub 0
 \ hub0port1: user.0: index=0,type=user,net=10.0.2.0,restrict=off
 \ hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56

Obtaining VM memory dumps

QEMU supports dumping VM memory, both physical and virtual, to a disk file on the VM host, or as output on the HMI console interface.

Dumping Memory to a file on the Host

  • Example Dumping Guest Virtual Memory

    The:

    memsave ADDR SIZE FILENAME
    

    command obtains a dump of the guest's virtual memory starting at ADDR of size SIZE to the file FILENAME.

    The following account on obtaining the virtual memory dump of the log buffer of a Linux guest boot instance is based on this link. The vmlinux image used below is the raw, uncompressed ELF image corresponding to the bootable bzImage used with the QEMU instance:

    • Obtain the virtual memory address and size of the logbuffer from vmlinux:

      $ readelf -a vmlinux | grep __log_buf
          1971: c18920d8 0x20000 OBJECT  LOCAL  DEFAULT   40 __log_buf
      
    • Boot against the corresonding bzImage and dump the logbuffer.

      [root@buildroot ~]# uname -r
      3.5.1
      
      (qemu) memsave 0xc18920d8 0x20000 dumpmem.log #  or "memsave 0xc18920d8 131072 dumpmem.log"
      
    • At this point, the dumpmem.log file should be present in the current working directory. However, it may contain some junk and will require some processing in order to be read properly via a text editor:

      $ file dumpmem.log 
      dumpmem.log: data
      

      This utility, logbuf-reader.c, can be used to process and format the file2:

      $ gcc -Wall logbuf-reader.c -o logbuf-reader
      
      $ cat dumpmem.log | ./logbuf-reader > memdump.txt
      
      $ file memdump.txt 
      memdump.txt: ASCII assembler program text
      
      $ cat memdump.txt
      Initializing cgroup subsys cpuset
      Initializing cgroup subsys cpu
      Linux version 3.5.1 (lumumba@lumumba) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #4 PREEMPT 
      KERNEL supported cpus:
       (...)
      Kernel command line: root=/dev/sda2 fbcon=map:-1 rw console=ttyS0
      PID hash table entries: 512 (order: -1, 2048 bytes)
       (...)
      Memory: 120112k/131064k available (5703k kernel code, 10500k reserved, 2578k data, 460k init, 0k highmem)
      virtual kernel memory layout:
              fixmap  : 0xfffe5000 - 0xfffff000   ( 104 kB)
              vmalloc : 0xc87fe000 - 0xfffe3000   ( 887 MB)
              lowmem  : 0xc0000000 - 0xc7ffe000   ( 127 MB)
                  .init : 0xc1817000 - 0xc188a000   ( 460 kB)
                  .data : 0xc1591c06 - 0xc1816520   (2578 kB)
                  .text : 0xc1000000 - 0xc1591c06   (5703 kB)
      (...)
      EXT3-fs (sda2): mounted filesystem with ordered data mode
      VFS: Mounted root (ext3 filesystem) on device 8:2.
      devtmpfs: mounted
      Freeing unused kernel memory: 460k freed
      Write protecting the kernel text: 5704k
      Write protecting the kernel read-only data: 2104k
      
  • Example Dumping VM Physical Memory

    The:

    (qemu) pmemsave ADDR SIZE FILENAME
    

    command obtains a physical memory dump of the VM starting at ADDR of size SIZE to the file FILENAME.

    Consider the case study presented in the mmap and /dev/mem, An Example entry. The example uses /dev/mem change the system's hostname by writing a string directly to the physical location (reserved for the kernel's data segment) that holds the nodename field of struct new_utsname.

    From a QEMU machine instance e.g:

    $ qemu-system-x86_64 -enable-kvm -kernel bzImage-x86_64 -drive file=brdisk-i686-img.raw \
        -append "root=/dev/sda2 rw console=ttyS0" -nographic
    (...)
    [root@buildroot ~]# insmod ne_devmem_hostname_krn.ko 
    [  122.771544] nodename: buildroot, phys addr: 0x1c102c5
    
    [root@buildroot ~]# less /proc/iomem 
    ...
    00100000-07fdffff : System RAM
        01000000-0179fc8c : Kernel code
        0179fc8d-01ccc53f : Kernel data
        01ddb000-01f22fff : Kernel bss
    ...
    
    [root@buildroot ~]# ./ne_devmem_hostname_usr -l 0x1c102c5
    main:143:: Patching paddr. 0x1c102c5, vaddr. 0xf777a2c5 (nodename "buildroot")
    main:145:: with string "simsima"
    
    [root@buildroot ~]# hostname
    simsima
    
    (qemu) pmemsave 0x1c102c5 0x41 hostname
    

    Now, from a terminal on the VM host - in the current working directory:

    $ file hostname 
    hostname: ASCII text, with no line terminators
    
    $ hd hostname 
    00000000  73 69 6d 73 69 6d 61 00  00 00 00 00 00 00 00 00  |simsima.........|
    00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    00000041
    

Dumping Memory on the HMI

Contents of the virtual machine's memory may also be output on the HMI console via:

  • X /CountFormatSize addr

    Output virtual memory dump starting at addr

  • xp /CountFormatSize addr

    Output physical memory dump starting at addr

where:

  • Count is the number of items to be dumped
  • Format may be x (hex), d(signed decimal), u (unsigned decimal), o (octal), c (char), or i (assembly instruction).
  • Size may be b (8-bits), h (16-bits), w (32-bits), or g (64-bits)

For illustration, and continuing with the /dev/mem example above:

[root@buildroot ~]# ./ne_devmem_hostname_usr -l 0x1c102c5 -s chapu-chapu
main:143:: Patching paddr. 0x1c102c5, vaddr. 0xf779f2c5 (nodename "simsima")
main:145:: with string "chapu-chapu"

[root@buildroot ~]# hostname
chapu-chapu

(qemu) xp /11cb 0x1c102c5
0000000001c102c5: 'c' 'h' 'a' 'p' 'u' '-' 'c' 'h'
0000000001c102cd: 'a' 'p' 'u'

Obtaining Screendumps

Consider the following case where the guest system contained a DirectFB installation. Firing up a df_neo instance:

[root@buildroot ~]# df_neo

and then switching to the HMI console and running:

(qemu) screendump df_neo

produced the following file in the current working directory:

$ file df_neo 
df_neo: Netpbm PPM "rawbits" image data

This file can be viewed by almost any image viewer e.g. eog(1), the GNOME Image Viewer:

$ eog df_neo

Another utility such as the GNU Image Manipulation Program (GIMP) can be used to convert the image into another format such as JPEG, PNG, EPS, etc.

Keyboard Control

The sendkeys command accepts a number of options to emulate keyboard input. Type sendkeys then TAB to view available options that command accepts to emulate keyboard action.

For example, the following command:

(qemu) sendkey ctrl-alt-f1

has the same effect as typing CTRL+ALT+F1 to switch between virtual terminals on a physical machine.

Resources

  • qemu(1)
  • QEMU wiki
  • http://www.wiki.xilinx.com/QEMU-Linux+Kernel+logbuf+Extraction

Footnotes

1. Check out Making a QEMU disk image bootable with GRUB for info on booting disk images with GRUB. [go back]

2. You may include <unistd.h> in logbuf-reader.c if gcc complains with warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration] [go back]