Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 79

Inspecting Machine State and Memory with QEMU Monitor

Recommended resources

Introduction

Welcome back. In our last lesson, we explored how vhost-net and vhost-scsi dramatically improve I/O performance by offloading the data plane from the QEMU userspace process directly into the host kernel. This leaves QEMU to manage the control plane—a critical but less frequent task.

This lesson shifts our focus from performance optimization to interactive control and introspection. We will explore one of the most powerful tools in your QEMU arsenal: the QEMU monitor. Your learning goal for this lesson is to use QEMU's monitor (HMP/QMP) to inspect machine state and memory mappings. This interactive console allows you to pause a running VM, examine its CPU registers, dump memory, check device status, and much more. Mastering the monitor is essential for low-level debugging and understanding the inner workings of your virtual machine.


1. The Two Faces of the Monitor: HMP and QMP

The QEMU monitor isn't a single entity but rather a system with two distinct interfaces, or protocols, designed for different use cases:

  • HMP (Human Monitor Protocol): A command-line interface with human-readable commands and output. It's designed for interactive use, allowing you to manually type commands and read the results. This is the interface we will focus on for hands-on debugging.
  • QMP (QEMU Machine Protocol): A JSON-based protocol designed for programmatic control. Tools like libvirt use QMP to start, stop, migrate, and manage VMs automatically. While we won't write QMP scripts, it's crucial to know it exists as the foundation for most virtualization management tools.

The following image illustrates the conceptual difference between the two.

QEMU HMP and QMP Protocol Principles
This diagram shows the two monitor protocols. On the left, HMP (Human Monitor Protocol) involves a human user typing string commands and receiving formatted text. On the right, QMP (QEMU Machine Protocol) involves an external application sending structured JSON commands and receiving JSON responses, suitable for automation.

2. Accessing the QEMU Monitor

To use the monitor, you must first expose it when launching QEMU. There are two common methods.

Method 1: Standard I/O (-monitor stdio)

This is the simplest method. It attaches the monitor directly to the terminal where you launched QEMU.

qemu-system-x86_64 -m 1G -hda my_image.qcow2 -monitor stdio

After launching, your terminal will show the QEMU monitor prompt, ready for commands.

QEMU Monitor Initialization and Guest Boot Process
An example of launching QEMU with the monitor on standard I/O. The left terminal shows the `(qemu)` prompt, while the right window shows the guest's boot output. Notice how guest output can mix with monitor commands in this mode.

The main disadvantage of this method is that the monitor's input/output is mixed with the guest's serial console output, which can be confusing.

Method 2: TCP Socket (Recommended)

A cleaner approach is to expose the monitor on a TCP port. This separates the monitor interface from the QEMU process's main terminal.

qemu-system-x86_64 -m 1G -hda my_image.qcow2 -monitor tcp::4444,server,nowait
  • tcp::4444: Expose the monitor on TCP port 4444.
  • server: Tells QEMU to act as a server and wait for a connection.
  • nowait: Tells QEMU not to wait for a client to connect before starting the VM.

You can then connect to the monitor from another terminal using tools like telnet or netcat:

telnet localhost 4444



# or
nc localhost 4444

This provides a dedicated, clean terminal for monitor commands, which is the preferred setup for development and debugging.


3. Inspecting Machine State with HMP

Once connected to the HMP, you can issue commands to inspect and control the VM. A crucial first step for inspection is to pause the VM to get a consistent state snapshot.

  • stop: Pauses the guest execution.
  • cont (or c): Resumes guest execution.

With the VM paused, you can use various info commands to probe its state. The official QEMU documentation provides a comprehensive command reference.

QEMU Monitor

The official QEMU documentation is the definitive source for monitor commands. We'll consult it to understand the syntax for memory inspection and address translation.

Skim the list of info subcommands to get a feel for the breadth of information available. Also, read the short section on 'Integer expressions' at the end, which explains how to use register values like $rip in commands.

Here are some of the most essential commands for inspecting the machine state:

  • CPU State:
    • info cpus: Lists all vCPUs and shows their current state (e.g., running, halted).
    • info registers: Dumps the general-purpose registers for the current vCPU. This is invaluable for seeing the exact state of the CPU when it was stopped.
  • System Tables:
    • info gdt, info idt: Show the Global Descriptor Table and Interrupt Descriptor Table. Your experience with low-level systems means you know how critical these are for debugging protection faults and exceptions.
  • Interrupt Controllers:
    • info pic, info lapic, info ioapic: Inspect the state of the legacy and modern interrupt controllers. This can help debug issues where interrupts are not being delivered or handled correctly.

4. Inspecting Memory and Mappings

Beyond the CPU state, the monitor provides powerful tools for examining memory, which is fundamental to debugging device drivers and memory management issues.

Dumping Memory Contents

Two commands are essential for reading memory: x for virtual addresses and xp for physical addresses.

QEMU Monitor

Let's look at the syntax for the memory dumping commands in the official documentation.

Read the documentation for the x/fmt addr and xp/fmt addr commands. Pay close attention to the format specifiers ({count}{format}{size}) as they give you precise control over the output.

The format /{count}{format}{size} is key:

  • count: Number of items to dump.
  • format: x (hex), d (decimal), i (instruction), c (char).
  • size: b (byte), h (half-word, 16-bit), w (word, 32-bit), g (giant-word, 64-bit).

Examples:

  • Disassemble 10 instructions at the current instruction pointer (a guest virtual address):
    (qemu) x/10i $rip
  • Dump 32 bytes in hex from a physical address (common for MMIO registers):
    (qemu) xp/32xb 0xfebf0040

Understanding the Memory Map

Dumping raw memory is useful, but understanding the memory layout is even more important.

  • info mem: Shows the active virtual memory mappings from the guest's perspective (similar to /proc/self/maps in Linux).
  • info mtree: Displays the QEMU memory hierarchy. This is one of the most important commands. It shows you which physical memory ranges are mapped to RAM, which are MMIO regions for specific devices, and which are unused. This is essential for verifying your device's MMIO region is correctly registered.

Translating Addresses

When debugging virtualization, you often need to trace an address through multiple layers of translation. The monitor provides utilities for this.

QEMU Monitor

The ability to translate addresses between different domains (guest virtual, guest physical, host virtual) is a superpower for debugging. Let's look at the commands for this in the QEMU documentation.

Read the descriptions for gva2gpa, gpa2hva, and gpa2hpa. Understand what each one does.

  • gva2gpa <addr>: Translates a Guest Virtual Address to a Guest Physical Address using the guest's current page tables.
  • gpa2hva <addr>: Translates a Guest Physical Address to a Host Virtual Address (i.e., the address within the QEMU process's memory space).
  • gpa2hpa <addr>: Translates a Guest Physical Address to a Host Physical Address.

This chain, GVA -> GPA -> HVA, is the complete path from a guest application's pointer to the actual byte in the QEMU process's memory.


Interview Scenario

An interviewer poses the following problem:

"You've written a driver for a virtual device in a guest Linux OS. The driver writes the value 0xdeadbeef to a 32-bit MMIO control register located at guest physical address 0x90000000. However, the device doesn't respond. The driver reports no errors. How would you use the QEMU monitor to diagnose whether the write from the guest ever reached the physical memory location that QEMU manages?"

Click to see a model response

My diagnostic process using the QEMU monitor would be as follows:

  1. Launch and Connect: I would start the VM with the monitor exposed on a TCP port (-monitor tcp::4444,server,nowait) and connect to it with telnet localhost 4444.

  2. Run the Test and Pause: I'd let the guest OS boot and then run the command that loads my driver and triggers the MMIO write. Immediately after, I would issue the stop command in the monitor to freeze the VM's state.

  3. Verify Memory Mapping: My first step is to confirm that QEMU knows about this MMIO region. I would use info mtree. I'd examine the output to ensure that the physical address 0x90000000 falls within a range that is mapped to my emulated device, not to system RAM or another device. If it's not mapped correctly, the problem is in my device's initialization code in QEMU.

  4. Inspect the Physical Memory: Assuming the mapping is correct, my next step is to check if the value is actually there. I would use the physical memory dump command:

    (qemu) xp/w 0x90000000
    
    • If the output shows 0xdeadbeef, it confirms the write from the guest was successful at the hardware level. The problem is likely in my device's logic that should have reacted to the write.
    • If the output shows 0x00000000 or some other value, it means the write never made it. This could point to a problem in the guest driver (e.g., caching issues, writing to the wrong virtual address that doesn't map here) or a deeper issue in the memory subsystem.
  5. Translate Addresses (If Needed): If the write failed, I might suspect an issue with the guest's virtual-to-physical mapping. I would use GDB on the guest to find the virtual address the driver is using and then use gva2gpa <virtual_addr> in the monitor to see if the guest's page tables are correctly translating it to 0x90000000. A mismatch would indicate a bug in the guest driver's memory mapping.

This methodical approach allows me to isolate the problem layer by layer: from the QEMU memory map, to the physical memory content, and finally to the guest's own page table mappings.


Conclusion

In this lesson, you've learned how to leverage the QEMU monitor as a powerful, interactive debugging tool. It gives you a direct window into the state of the emulated hardware, bypassing the guest OS entirely.

Key Takeaways:

  • The QEMU monitor has two modes: HMP for interactive human use and QMP for programmatic automation.
  • Exposing the monitor via a TCP socket is the recommended method for a clean debugging workflow.
  • You can inspect CPU state (info registers), system tables (info gdt), and the overall device memory map (info mtree).
  • The x (virtual) and xp (physical) commands are essential for dumping memory contents, while commands like gva2gpa help you trace address translations.
  • The monitor is a first-line tool for debugging device emulation issues, allowing you to quickly verify MMIO writes and inspect hardware state.

Preview of the Next Lesson:

The monitor is excellent for inspecting static state, but it doesn't show you the flow of execution over time. For that, we need more dynamic tools. In our next lesson, we will learn to use QEMU's built-in tracing system and connect GDB to debug an emulated device, allowing you to step through the C code of your device model as it executes.