QMP
QEMU's machine protocol, by its command and event names. Every command of QEMU 11.1's schema for aarch64 is known; this page lists what each does here.
QMP is QEMU's JSON protocol for controlling a machine. WEMU speaks it by QEMU's names: every command of QEMU 11.1's aarch64 schema is known, and what this machine has no counterpart for is answered as QEMU answers on a machine without it.
vm.qmp() runs a command and resolves with its return value; errors reject with a QmpError. vm.qmpJson() takes and returns JSON text, and vm.on() delivers events. No negotiation is needed.
await vm.qmp("stop");
const { status } = await vm.qmp("query-status"); // "paused"
vm.on("RESUME", () => console.log("running again"));
await vm.qmp("cont");
Start wemu-system-aarch64 with a QMP server and connect any QMP client, such as QEMU's qmp-shell or socat:
wemu-system-aarch64 -m 1G -kernel vmlinuz-virt -initrd initramfs-virt -nographic \
-qmp unix:/tmp/wemu.sock,server,nowait
socat - UNIX-CONNECT:/tmp/wemu.sock
{"QMP": {"version": {"wemu": {"major": 11, "minor": 1, "micro": 50}, "package": "warm64 0.1.0"}, "capabilities": ["oob"]}}
{"execute": "qmp_capabilities"}
{"return": {}}
{"execute": "query-status", "id": 1}
{"return": {"status": "running", "singlestep": false, "running": true}, "id": 1}
- The server sends a greeting; the client answers with
qmp_capabilities before anything else. Until then every command is refused with CommandNotFound. - Requests may span lines. Replies are one line each, echoing the request's
id. - Events go to every client that has negotiated.
exec-oob is accepted and runs as an ordinary command.- Several clients may connect at once, and
-qmp may be given more than once. See -qmp for the endpoints.
An error reply has QEMU's shape: {"error": {"class": "...", "desc": "..."}}. The classes are GenericError, CommandNotFound, DeviceNotFound and DeviceNotActive.
| Situation | Error |
|---|
| Unknown command | CommandNotFound: The command NAME has not been found |
| Missing argument | GenericError: Parameter 'NAME' is missing |
| Unknown device or node | DeviceNotFound: Device 'ID' not found |
| Adding or removing devices while running | hot-plug is not available on this machine: name the device on the command line |
Writing a file on a host without writeFile | the host cannot write files here |
| Command | Arguments | Description |
|---|
query-status | | {status, running, singlestep}. See run states. |
stop | | Pauses the machine. Emits STOP. |
cont | | Resumes it. Emits RESUME. Refused after a guest power-off with -no-shutdown (Resetting the Virtual Machine is required) and before migrate-incoming. |
system_reset | | Resets the machine. Emits RESET. A kernel boot reloads its kernel and initrd. |
system_powerdown | | Presses the power button: the guest shuts down cleanly. Emits POWERDOWN. |
quit | | Stops and releases the machine. Emits SHUTDOWN. |
set-action | shutdown, reboot, panic | As -action. |
| Command | Returns |
|---|
query-version | {"wemu": {"major": 11, "minor": 1, "micro": 50}, "package": "warm64 0.1.0"} |
query-name, query-uuid | The -name and -uuid. |
query-target | {"arch": "aarch64"} |
query-machines | The virt board, cpu-max 8. |
query-kvm | {"enabled": false, "present": false} |
query-accelerators | {"enabled": "tcg", "present": ["tcg"]} |
query-cpus-fast, query-hotpluggable-cpus | One entry per core. |
query-cpu-definitions | The CPU models -cpu accepts. |
query-cpu-model-expansion | A model's pauth, sve and mte settings. |
query-gic-capabilities | GIC versions 2 and 3, emulated. |
query-memory-size-summary | {"base-memory": BYTES, "plugged-memory": 0} |
query-commands, query-events, query-qmp-schema | What this machine knows. |
x-accel-stats | Instructions run, and how many ran in compiled code. |
x-query-jit | The JIT's counters. |
human-monitor-command | Runs a monitor command (command-line) and returns its text. |
| Command | Arguments | Description |
|---|
memsave | val, size, filename | Saves guest virtual memory, as core 0 sees it, to a file. |
pmemsave | val, size, filename | Saves guest physical memory (RAM) to a file. |
dump-guest-memory | protocol: "file:PATH", format | Writes an ELF core of the guest's RAM and core 0's registers. format is elf (the default; others are refused), and paging dumps are refused. Emits DUMP_COMPLETED. |
query-dump | | The last dump's progress. |
dumpdtb | filename | Writes the device tree the guest booted with. |
| Command | Arguments | Description |
|---|
query-block | | Every virtio disk: its file, whether it's read-only, and its size. |
query-blockstats | | Per-disk counters. |
query-named-block-nodes | | The block nodes. |
Disks are fixed while the machine runs: block_resize, eject, change and the other removable-media commands are refused (Device 'ID' is not removable), and so are backing chains, block jobs, NBD and I/O throttling, in QEMU's words for a raw image.
The refused commands still look up the disk they name first, so a name that isn't a disk gets QMP's DeviceNotFound (Device 'ID' not found) rather than the refusal. A disk's name is its drive id (virtio0, drive0… when none is given). They read it from:
| Commands | Argument |
|---|
block_resize | device or node-name |
eject, blockdev-open-tray, blockdev-close-tray, blockdev-remove-medium, blockdev-insert-medium, blockdev-change-medium | device or id |
block-commit, block-stream, blockdev-backup, blockdev-create, blockdev-mirror, blockdev-reopen, blockdev-snapshot, blockdev-snapshot-sync, blockdev-snapshot-internal-sync, blockdev-snapshot-delete-internal-sync, change-backing-file, drive-backup, drive-mirror, x-blockdev-amend, x-blockdev-change | device, else node-name, else job-id |
block-dirty-bitmap-add, block-dirty-bitmap-remove, block-dirty-bitmap-clear, block-dirty-bitmap-enable, block-dirty-bitmap-disable, block-dirty-bitmap-merge, x-debug-block-dirty-bitmap-sha256 | node; the refusal names the bitmap from name, else target |
block-set-write-threshold | node-name (then returns {}) |
block-latency-histogram-set | id (then returns {}) |
block_set_io_throttle | device or id |
| Command | Arguments | Description |
|---|
snapshot-save | job-id, tag | Saves the whole machine under tag, as a job. Emits JOB_STATUS_CHANGE. |
snapshot-load | job-id, tag | Restores a snapshot. |
snapshot-delete | job-id, tag | Deletes one. |
query-jobs | | The jobs above. A job's failure is in its error. |
job-dismiss, job-finalize | id | job-dismiss removes a concluded job from query-jobs; job-finalize returns {}. An unknown id is Job not found. |
migrate | uri: "file:PATH", or channels | Writes the machine's state to a file and leaves it paused (postmigrate). Instead of uri, channels may give one {"addr": {"transport": "file", "filename": PATH}}. Emits MIGRATION. |
migrate-incoming | uri: "file:PATH" | Loads a state into a machine started with -incoming defer. |
query-migrate | | The last migration's status. |
migrate-set-capabilities | capabilities: [{capability, state}] | Stored, and shown by query-migrate-capabilities. An unknown capability is Invalid parameter 'capability'. |
migrate-set-parameters | | Accepted and stored. |
Only migration to and from a file exists. See Snapshots.
| Command | Arguments | Description |
|---|
query-chardev, query-chardev-backends | | The character devices. |
ringbuf-write | device, data, format (utf8 or base64) | Sends data to the guest through a serial port bound to a ring buffer. |
ringbuf-read | device, size, format | Reads and removes what the guest wrote, oldest first. |
chardev-send-break | id | Sends a serial break (on serial0). |
A console a script drives without a terminal:
wemu-system-aarch64 ... -chardev ringbuf,id=con,size=1M -serial chardev:con -display none
await vm.qmp("ringbuf-write", { device: "con", data: "uname -a\n" });
const text = await vm.qmp("ringbuf-read", { device: "con", size: 65536 });
| Command | Arguments | Description |
|---|
send-key | keys, hold-time (ms, default 100) | Presses the keys in order, holds them, and releases them in reverse. Keys are {"type": "qcode", "data": "ctrl"}. |
input-send-event | events | Key presses, buttons, and pointer moves: key, btn (left, right, middle, wheel-up, wheel-down), abs (x or y, 0 to 32767) and rel. |
query-mice | | The pointing devices. |
The pointer is an absolute tablet; rel moves are applied to it. Input needs a keyboard and tablet on the command line, such as -device virtio-keyboard-pci. See Display and input.
await vm.qmp("send-key", { keys: [{ type: "qcode", data: "ctrl" }, { type: "qcode", data: "alt" }, { type: "qcode", data: "f2" }] });
await vm.qmp("input-send-event", { events: [
{ type: "abs", data: { axis: "x", value: 16384 } },
{ type: "abs", data: { axis: "y", value: 16384 } },
{ type: "btn", data: { down: true, button: "left" } },
{ type: "btn", data: { down: false, button: "left" } },
] });
| Command | Arguments | Description |
|---|
screendump | filename, format (ppm or png) | Saves the screen. Needs a display device. |
query-display-options | | The display type. |
| Command | Arguments | Description |
|---|
set_link | name, up | Takes a network card's link down or up. name is the device's id. |
query-rx-filter | | Each network card's receive filter. |
announce-self | | Accepted. |
| Command | Arguments | Description |
|---|
query-pci | | The PCI functions, when the machine uses PCI. |
qom-list | path | The children of /, /machine or /machine/peripheral (the devices given an id). /objects, /chardevs, /machine/peripheral-anon and /machine/unattached are empty; any other path is DeviceNotFound. |
qom-get | path, property | type, gic-version and virtualization of /machine, and type of /. Anything else is DeviceNotFound. |
qom-list-types | implements | The device drivers, the machine and the CPU models. implements: "machine" or "device" narrows the list; other values don't. |
qom-list-get | paths | One empty property list per path. |
device-list-properties | typename | [] for a driver this machine has; Device 'NAME' not found otherwise. |
Properties can't be changed while the machine runs: qom-set is refused.
| Event | Data | Emitted when |
|---|
STOP | | The machine pauses: stop, migrate, a snapshot, a guest panic. |
RESUME | | It resumes after a pause. |
RESET | guest, reason | system_reset or a guest reboot. |
POWERDOWN | | system_powerdown. |
SHUTDOWN | guest, reason | The guest powers off, or the machine quits. |
GUEST_PANICKED | action (pause, poweroff or run), info | The guest stops in a way it can't recover from. info is {"type": "hyper-v", "arg1": 0, "arg2": 0, "arg3": 0, "arg4": 0, "arg5": 0, "desc": TEXT}: the five arguments are always 0, and desc says what stopped it. |
MIGRATION | status | A migration changes state. |
JOB_STATUS_CHANGE | id, status | A snapshot job moves on. |
DUMP_COMPLETED | result: {status, completed, total} | dump-guest-memory finishes. completed and total are bytes, both the RAM size. |
Every command of QEMU 11.1's aarch64 schema is known. Those not in the tables above fall into these groups.
| Command | Returns |
|---|
query-current-machine | {"wakeup-suspend-support": false} |
query-audiodevs | Each -audiodev: {id, driver}. |
query-dump-guest-memory-capability | {"formats": ["elf"]} |
query-migrate-capabilities, query-migrate-parameters | The values stored by the matching set commands. |
query-replay | {"mode": "none", "icount": -1} |
query-dirty-rate | {"status": "unstarted", ...} |
query-colo-status | {"mode": "none", "last-mode": "none", "reason": "none"} |
query-xen-replication-status | {"error": false} |
query-vnc, query-spice | {"enabled": false, ...} |
qom-list-properties, qom-list-get | Empty property lists. |
x-query-interrupt-controllers, x-query-irq, x-query-network, x-query-numa, x-query-ramblock, x-query-roms, x-query-usb, x-query-usernet, x-query-virtio | Text or lists describing the machine, as info prints them. |
x-debug-query-block-graph | The disks as block nodes. |
These return [], the answer for a machine with none of the thing asked about: query-acpi-ospm-status, query-block-exports, query-block-jobs, query-command-line-options, query-cryptodev, query-fdsets, query-iothreads, query-memdev, query-memory-devices, query-pr-managers, query-rocker-ports, query-stats, query-stats-schemas, query-tpm, query-tpm-models, query-tpm-types, query-vcpu-dirty-limit, query-vnc-servers, query-yank, trace-event-get-state.
These return {}: announce-self, block-latency-histogram-set, block-set-write-threshold, blockdev-set-active, calc-dirty-rate, migrate_cancel, migrate-set-capabilities, migrate-set-parameters (both stored), nbd-server-stop, transaction (with no actions), watchdog-set-action, yank (with no instances).
| Commands | Answer |
|---|
device_add, device_del, blockdev-add, blockdev-del, netdev_add, netdev_del, chardev-add, object-add | hot-plug is not available on this machine: name the device on the command line |
object-del | object 'ID' not found |
chardev-change, chardev-remove | Chardev 'ID' is busy for a chardev that exists (by id), Chardev 'ID' not found otherwise. |
eject, blockdev-open-tray, blockdev-close-tray, blockdev-remove-medium, blockdev-insert-medium, blockdev-change-medium | Device 'ID' is not removable |
block_resize | Cannot resize: the virtio disk's capacity is fixed while the machine runs |
blockdev-snapshot-sync, blockdev-snapshot, blockdev-snapshot-internal-sync, blockdev-snapshot-delete-internal-sync, change-backing-file, block-commit, block-stream, drive-backup, blockdev-backup, drive-mirror, blockdev-mirror, blockdev-reopen, blockdev-create, x-blockdev-amend, x-blockdev-change | Raw images have no backing chains, internal snapshots or jobs; savevm and snapshot-save keep the whole machine. |
block-dirty-bitmap-add, block-dirty-bitmap-remove, block-dirty-bitmap-clear, block-dirty-bitmap-enable, block-dirty-bitmap-disable, block-dirty-bitmap-merge, x-debug-block-dirty-bitmap-sha256 | Dirty bitmap 'NAME' not found |
block-job-set-speed, block-job-cancel, block-job-pause, block-job-resume, block-job-complete, block-job-dismiss, block-job-finalize, block-job-change | Block job 'ID' not found |
job-pause, job-resume, job-cancel, job-complete | For the job named by id: Job 'ID' in state 'concluded' cannot accept command verb 'VERB', since a snapshot job has concluded when its command returns. An unknown id is Job not found. |
block_set_io_throttle | I/O throttling is not available on this machine's disks |
x-blockdev-set-iothread | IOThreads are not available here |
x-wemu-io, x-qemu-io | wemu-io is not available here (the disks are the host's images) |
nbd-server-start, nbd-server-add, nbd-server-remove, block-export-add, block-export-del | NBD server not running |
migrate-start-postcopy, migrate-continue, migrate-recover, migrate-pause | Postcopy migration isn't available. |
set-vcpu-dirty-limit, cancel-vcpu-dirty-limit | dirty page limit not supported (it needs KVM's dirty ring) |
system_wakeup | wake-up from suspend is not supported by this guest |
inject-nmi | machine does not provide NMIs |
inject-ghes-v2-error | GHES is not enabled on this machine (it boots with a device tree, not ACPI) |
set-numa-node, x-exit-preconfig | The command is permitted only in 'preconfig' state |
query-balloon, balloon | No balloon device has been activated |
query-hv-balloon-status-report | no Hyper-V dynamic memory device present |
query-vm-generation-id | VM Generation ID device not found |
query-firmware-log | firmware log buffer not found |
query-cpu-model-comparison, query-cpu-model-baseline | Not supported on this target. |
getfd, add-fd | No file descriptor supplied via SCM_RIGHTS |
closefd, remove-fd | The file descriptor isn't found. |
add_client | Protocol 'NAME' is invalid |
set_password, expire_password, change-vnc-password | There's no VNC or SPICE server to set a password on. |
client_migrate_info | spice is not enabled |
display-reload, display-update | The display has nothing to reload or update. |
request-ebpf | RSS eBPF program is not available here |
device-sync-config | Not supported for the device. |
qom-set | Property 'NAME' is read-only on this machine |
trace-event-set-state | No trace events found matching 'NAME' |
replay-break, replay-delete-break, replay-seek | replay is disabled |
query-rocker, query-rocker-of-dpa-flows, query-rocker-of-dpa-groups | rocker NAME not found |
x-query-virtio-status, x-query-virtio-queue-status, x-query-virtio-vhost-queue-status, x-query-virtio-queue-element | Path PATH is not a VirtIODevice |
cxl-add-dynamic-capacity, cxl-release-dynamic-capacity, cxl-inject-poison, cxl-inject-general-media-event, cxl-inject-dram-event, cxl-inject-memory-module-event, cxl-inject-correctable-error, cxl-inject-uncorrectable-errors | Unable to resolve path: PATH (there's no CXL) |
dump-skeys | dump-skeys is only for s390x guests |
x-colo-lost-heartbeat | VM is not in COLO mode |
xen-save-devices-state, xen-load-devices-state, xen-set-global-dirty-log, xen-set-replication, xen-colo-do-checkpoint | this command is only supported with Xen |