aboutsummaryrefslogtreecommitdiffstats
path: root/qapi
diff options
context:
space:
mode:
Diffstat (limited to 'qapi')
-rw-r--r--qapi/acpi.json141
-rw-r--r--qapi/audio.json421
-rw-r--r--qapi/authz.json112
-rw-r--r--qapi/block-core.json5572
-rw-r--r--qapi/block-export.json399
-rw-r--r--qapi/block.json572
-rw-r--r--qapi/char.json742
-rw-r--r--qapi/common.json210
-rw-r--r--qapi/compat.json61
-rw-r--r--qapi/control.json215
-rw-r--r--qapi/crypto.json542
-rw-r--r--qapi/dump.json201
-rw-r--r--qapi/error.json30
-rw-r--r--qapi/introspect.json319
-rw-r--r--qapi/job.json266
-rw-r--r--qapi/machine-target.json343
-rw-r--r--qapi/machine.json1559
-rw-r--r--qapi/meson.build150
-rw-r--r--qapi/migration.json2023
-rw-r--r--qapi/misc-target.json399
-rw-r--r--qapi/misc.json529
-rw-r--r--qapi/net.json698
-rw-r--r--qapi/opts-visitor.c586
-rw-r--r--qapi/pci.json316
-rw-r--r--qapi/pragma.json64
-rw-r--r--qapi/qapi-clone-visitor.c204
-rw-r--r--qapi/qapi-dealloc-visitor.c143
-rw-r--r--qapi/qapi-forward-visitor.c328
-rw-r--r--qapi/qapi-schema.json95
-rw-r--r--qapi/qapi-type-helpers.c23
-rw-r--r--qapi/qapi-util.c154
-rw-r--r--qapi/qapi-visit-core.c444
-rw-r--r--qapi/qdev.json158
-rw-r--r--qapi/qmp-dispatch.c275
-rw-r--r--qapi/qmp-event.c45
-rw-r--r--qapi/qmp-registry.c95
-rw-r--r--qapi/qobject-input-visitor.c776
-rw-r--r--qapi/qobject-output-visitor.c280
-rw-r--r--qapi/qom.json951
-rw-r--r--qapi/rdma.json39
-rw-r--r--qapi/replay.json121
-rw-r--r--qapi/rocker.json342
-rw-r--r--qapi/run-state.json640
-rw-r--r--qapi/sockets.json202
-rw-r--r--qapi/string-input-visitor.c414
-rw-r--r--qapi/string-output-visitor.c374
-rw-r--r--qapi/tpm.json185
-rw-r--r--qapi/trace-events38
-rw-r--r--qapi/trace.h1
-rw-r--r--qapi/trace.json108
-rw-r--r--qapi/transaction.json258
-rw-r--r--qapi/ui.json1306
-rw-r--r--qapi/yank.json119
53 files changed, 24588 insertions, 0 deletions
diff --git a/qapi/acpi.json b/qapi/acpi.json
new file mode 100644
index 000000000..51f0d55db
--- /dev/null
+++ b/qapi/acpi.json
@@ -0,0 +1,141 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+##
+# = ACPI
+##
+
+##
+# @AcpiTableOptions:
+#
+# Specify an ACPI table on the command line to load.
+#
+# At most one of @file and @data can be specified. The list of files specified
+# by any one of them is loaded and concatenated in order. If both are omitted,
+# @data is implied.
+#
+# Other fields / optargs can be used to override fields of the generic ACPI
+# table header; refer to the ACPI specification 5.0, section 5.2.6 System
+# Description Table Header. If a header field is not overridden, then the
+# corresponding value from the concatenated blob is used (in case of @file), or
+# it is filled in with a hard-coded value (in case of @data).
+#
+# String fields are copied into the matching ACPI member from lowest address
+# upwards, and silently truncated / NUL-padded to length.
+#
+# @sig: table signature / identifier (4 bytes)
+#
+# @rev: table revision number (dependent on signature, 1 byte)
+#
+# @oem_id: OEM identifier (6 bytes)
+#
+# @oem_table_id: OEM table identifier (8 bytes)
+#
+# @oem_rev: OEM-supplied revision number (4 bytes)
+#
+# @asl_compiler_id: identifier of the utility that created the table
+# (4 bytes)
+#
+# @asl_compiler_rev: revision number of the utility that created the
+# table (4 bytes)
+#
+# @file: colon (:) separated list of pathnames to load and
+# concatenate as table data. The resultant binary blob is expected to
+# have an ACPI table header. At least one file is required. This field
+# excludes @data.
+#
+# @data: colon (:) separated list of pathnames to load and
+# concatenate as table data. The resultant binary blob must not have an
+# ACPI table header. At least one file is required. This field excludes
+# @file.
+#
+# Since: 1.5
+##
+{ 'struct': 'AcpiTableOptions',
+ 'data': {
+ '*sig': 'str',
+ '*rev': 'uint8',
+ '*oem_id': 'str',
+ '*oem_table_id': 'str',
+ '*oem_rev': 'uint32',
+ '*asl_compiler_id': 'str',
+ '*asl_compiler_rev': 'uint32',
+ '*file': 'str',
+ '*data': 'str' }}
+
+##
+# @ACPISlotType:
+#
+# @DIMM: memory slot
+# @CPU: logical CPU slot (since 2.7)
+##
+{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] }
+
+##
+# @ACPIOSTInfo:
+#
+# OSPM Status Indication for a device
+# For description of possible values of @source and @status fields
+# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec.
+#
+# @device: device ID associated with slot
+#
+# @slot: slot ID, unique per slot of a given @slot-type
+#
+# @slot-type: type of the slot
+#
+# @source: an integer containing the source event
+#
+# @status: an integer containing the status code
+#
+# Since: 2.1
+##
+{ 'struct': 'ACPIOSTInfo',
+ 'data' : { '*device': 'str',
+ 'slot': 'str',
+ 'slot-type': 'ACPISlotType',
+ 'source': 'int',
+ 'status': 'int' } }
+
+##
+# @query-acpi-ospm-status:
+#
+# Return a list of ACPIOSTInfo for devices that support status
+# reporting via ACPI _OST method.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-acpi-ospm-status" }
+# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0},
+# { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0},
+# { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0},
+# { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0}
+# ]}
+#
+##
+{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] }
+
+##
+# @ACPI_DEVICE_OST:
+#
+# Emitted when guest executes ACPI _OST method.
+#
+# @info: OSPM Status Indication
+#
+# Since: 2.1
+#
+# Example:
+#
+# <- { "event": "ACPI_DEVICE_OST",
+# "data": { "device": "d1", "slot": "0",
+# "slot-type": "DIMM", "source": 1, "status": 0 } }
+#
+##
+{ 'event': 'ACPI_DEVICE_OST',
+ 'data': { 'info': 'ACPIOSTInfo' } }
diff --git a/qapi/audio.json b/qapi/audio.json
new file mode 100644
index 000000000..9cba0df8a
--- /dev/null
+++ b/qapi/audio.json
@@ -0,0 +1,421 @@
+# -*- mode: python -*-
+#
+# Copyright (C) 2015-2019 Zoltán Kővágó <DirtY.iCE.hu@gmail.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Audio
+##
+
+##
+# @AudiodevPerDirectionOptions:
+#
+# General audio backend options that are used for both playback and
+# recording.
+#
+# @mixing-engine: use QEMU's mixing engine to mix all streams inside QEMU and
+# convert audio formats when not supported by the backend. When
+# set to off, fixed-settings must be also off (default on,
+# since 4.2)
+#
+# @fixed-settings: use fixed settings for host input/output. When off,
+# frequency, channels and format must not be
+# specified (default true)
+#
+# @frequency: frequency to use when using fixed settings
+# (default 44100)
+#
+# @channels: number of channels when using fixed settings (default 2)
+#
+# @voices: number of voices to use (default 1)
+#
+# @format: sample format to use when using fixed settings
+# (default s16)
+#
+# @buffer-length: the buffer length in microseconds
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*mixing-engine': 'bool',
+ '*fixed-settings': 'bool',
+ '*frequency': 'uint32',
+ '*channels': 'uint32',
+ '*voices': 'uint32',
+ '*format': 'AudioFormat',
+ '*buffer-length': 'uint32' } }
+
+##
+# @AudiodevGenericOptions:
+#
+# Generic driver-specific options.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevGenericOptions',
+ 'data': {
+ '*in': 'AudiodevPerDirectionOptions',
+ '*out': 'AudiodevPerDirectionOptions' } }
+
+##
+# @AudiodevAlsaPerDirectionOptions:
+#
+# Options of the ALSA backend that are used for both playback and
+# recording.
+#
+# @dev: the name of the ALSA device to use (default 'default')
+#
+# @period-length: the period length in microseconds
+#
+# @try-poll: attempt to use poll mode, falling back to non-polling
+# access on failure (default true)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevAlsaPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*dev': 'str',
+ '*period-length': 'uint32',
+ '*try-poll': 'bool' } }
+
+##
+# @AudiodevAlsaOptions:
+#
+# Options of the ALSA audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# @threshold: set the threshold (in microseconds) when playback starts
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevAlsaOptions',
+ 'data': {
+ '*in': 'AudiodevAlsaPerDirectionOptions',
+ '*out': 'AudiodevAlsaPerDirectionOptions',
+ '*threshold': 'uint32' } }
+
+##
+# @AudiodevCoreaudioPerDirectionOptions:
+#
+# Options of the Core Audio backend that are used for both playback and
+# recording.
+#
+# @buffer-count: number of buffers
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevCoreaudioPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*buffer-count': 'uint32' } }
+
+##
+# @AudiodevCoreaudioOptions:
+#
+# Options of the coreaudio audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevCoreaudioOptions',
+ 'data': {
+ '*in': 'AudiodevCoreaudioPerDirectionOptions',
+ '*out': 'AudiodevCoreaudioPerDirectionOptions' } }
+
+##
+# @AudiodevDsoundOptions:
+#
+# Options of the DirectSound audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# @latency: add extra latency to playback in microseconds
+# (default 10000)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevDsoundOptions',
+ 'data': {
+ '*in': 'AudiodevPerDirectionOptions',
+ '*out': 'AudiodevPerDirectionOptions',
+ '*latency': 'uint32' } }
+
+##
+# @AudiodevJackPerDirectionOptions:
+#
+# Options of the JACK backend that are used for both playback and
+# recording.
+#
+# @server-name: select from among several possible concurrent server instances
+# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default")
+#
+# @client-name: the client name to use. The server will modify this name to
+# create a unique variant, if needed unless @exact-name is true (default: the
+# guest's name)
+#
+# @connect-ports: if set, a regular expression of JACK client port name(s) to
+# monitor for and automatically connect to
+#
+# @start-server: start a jack server process if one is not already present
+# (default: false)
+#
+# @exact-name: use the exact name requested otherwise JACK automatically
+# generates a unique one, if needed (default: false)
+#
+# Since: 5.1
+##
+{ 'struct': 'AudiodevJackPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*server-name': 'str',
+ '*client-name': 'str',
+ '*connect-ports': 'str',
+ '*start-server': 'bool',
+ '*exact-name': 'bool' } }
+
+##
+# @AudiodevJackOptions:
+#
+# Options of the JACK audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# Since: 5.1
+##
+{ 'struct': 'AudiodevJackOptions',
+ 'data': {
+ '*in': 'AudiodevJackPerDirectionOptions',
+ '*out': 'AudiodevJackPerDirectionOptions' } }
+
+##
+# @AudiodevOssPerDirectionOptions:
+#
+# Options of the OSS backend that are used for both playback and
+# recording.
+#
+# @dev: file name of the OSS device (default '/dev/dsp')
+#
+# @buffer-count: number of buffers
+#
+# @try-poll: attempt to use poll mode, falling back to non-polling
+# access on failure (default true)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevOssPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*dev': 'str',
+ '*buffer-count': 'uint32',
+ '*try-poll': 'bool' } }
+
+##
+# @AudiodevOssOptions:
+#
+# Options of the OSS audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# @try-mmap: try using memory-mapped access, falling back to
+# non-memory-mapped access on failure (default true)
+#
+# @exclusive: open device in exclusive mode (vmix won't work)
+# (default false)
+#
+# @dsp-policy: set the timing policy of the device (between 0 and 10,
+# where smaller number means smaller latency but higher
+# CPU usage) or -1 to use fragment mode (option ignored
+# on some platforms) (default 5)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevOssOptions',
+ 'data': {
+ '*in': 'AudiodevOssPerDirectionOptions',
+ '*out': 'AudiodevOssPerDirectionOptions',
+ '*try-mmap': 'bool',
+ '*exclusive': 'bool',
+ '*dsp-policy': 'uint32' } }
+
+##
+# @AudiodevPaPerDirectionOptions:
+#
+# Options of the Pulseaudio backend that are used for both playback and
+# recording.
+#
+# @name: name of the sink/source to use
+#
+# @stream-name: name of the PulseAudio stream created by qemu. Can be
+# used to identify the stream in PulseAudio when you
+# create multiple PulseAudio devices or run multiple qemu
+# instances (default: audiodev's id, since 4.2)
+#
+# @latency: latency you want PulseAudio to achieve in microseconds
+# (default 15000)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevPaPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*name': 'str',
+ '*stream-name': 'str',
+ '*latency': 'uint32' } }
+
+##
+# @AudiodevPaOptions:
+#
+# Options of the PulseAudio audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# @server: PulseAudio server address (default: let PulseAudio choose)
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevPaOptions',
+ 'data': {
+ '*in': 'AudiodevPaPerDirectionOptions',
+ '*out': 'AudiodevPaPerDirectionOptions',
+ '*server': 'str' } }
+
+##
+# @AudiodevSdlPerDirectionOptions:
+#
+# Options of the SDL audio backend that are used for both playback and
+# recording.
+#
+# @buffer-count: number of buffers (default 4)
+#
+# Since: 6.0
+##
+{ 'struct': 'AudiodevSdlPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*buffer-count': 'uint32' } }
+
+##
+# @AudiodevSdlOptions:
+#
+# Options of the SDL audio backend.
+#
+# @in: options of the recording stream
+#
+# @out: options of the playback stream
+#
+# Since: 6.0
+##
+{ 'struct': 'AudiodevSdlOptions',
+ 'data': {
+ '*in': 'AudiodevSdlPerDirectionOptions',
+ '*out': 'AudiodevSdlPerDirectionOptions' } }
+
+##
+# @AudiodevWavOptions:
+#
+# Options of the wav audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# @path: name of the wav file to record (default 'qemu.wav')
+#
+# Since: 4.0
+##
+{ 'struct': 'AudiodevWavOptions',
+ 'data': {
+ '*in': 'AudiodevPerDirectionOptions',
+ '*out': 'AudiodevPerDirectionOptions',
+ '*path': 'str' } }
+
+
+##
+# @AudioFormat:
+#
+# An enumeration of possible audio formats.
+#
+# @u8: unsigned 8 bit integer
+#
+# @s8: signed 8 bit integer
+#
+# @u16: unsigned 16 bit integer
+#
+# @s16: signed 16 bit integer
+#
+# @u32: unsigned 32 bit integer
+#
+# @s32: signed 32 bit integer
+#
+# @f32: single precision floating-point (since 5.0)
+#
+# Since: 4.0
+##
+{ 'enum': 'AudioFormat',
+ 'data': [ 'u8', 's8', 'u16', 's16', 'u32', 's32', 'f32' ] }
+
+##
+# @AudiodevDriver:
+#
+# An enumeration of possible audio backend drivers.
+#
+# @jack: JACK audio backend (since 5.1)
+#
+# Since: 4.0
+##
+{ 'enum': 'AudiodevDriver',
+ 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa',
+ 'sdl', 'spice', 'wav' ] }
+
+##
+# @Audiodev:
+#
+# Options of an audio backend.
+#
+# @id: identifier of the backend
+#
+# @driver: the backend driver to use
+#
+# @timer-period: timer period (in microseconds, 0: use lowest possible)
+#
+# Since: 4.0
+##
+{ 'union': 'Audiodev',
+ 'base': {
+ 'id': 'str',
+ 'driver': 'AudiodevDriver',
+ '*timer-period': 'uint32' },
+ 'discriminator': 'driver',
+ 'data': {
+ 'none': 'AudiodevGenericOptions',
+ 'alsa': 'AudiodevAlsaOptions',
+ 'coreaudio': 'AudiodevCoreaudioOptions',
+ 'dsound': 'AudiodevDsoundOptions',
+ 'jack': 'AudiodevJackOptions',
+ 'oss': 'AudiodevOssOptions',
+ 'pa': 'AudiodevPaOptions',
+ 'sdl': 'AudiodevSdlOptions',
+ 'spice': 'AudiodevGenericOptions',
+ 'wav': 'AudiodevWavOptions' } }
diff --git a/qapi/authz.json b/qapi/authz.json
new file mode 100644
index 000000000..51845e37c
--- /dev/null
+++ b/qapi/authz.json
@@ -0,0 +1,112 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = User authorization
+##
+
+##
+# @QAuthZListPolicy:
+#
+# The authorization policy result
+#
+# @deny: deny access
+# @allow: allow access
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListPolicy',
+ 'prefix': 'QAUTHZ_LIST_POLICY',
+ 'data': ['deny', 'allow']}
+
+##
+# @QAuthZListFormat:
+#
+# The authorization policy match format
+#
+# @exact: an exact string match
+# @glob: string with ? and * shell wildcard support
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListFormat',
+ 'prefix': 'QAUTHZ_LIST_FORMAT',
+ 'data': ['exact', 'glob']}
+
+##
+# @QAuthZListRule:
+#
+# A single authorization rule.
+#
+# @match: a string or glob to match against a user identity
+# @policy: the result to return if @match evaluates to true
+# @format: the format of the @match rule (default 'exact')
+#
+# Since: 4.0
+##
+{ 'struct': 'QAuthZListRule',
+ 'data': {'match': 'str',
+ 'policy': 'QAuthZListPolicy',
+ '*format': 'QAuthZListFormat'}}
+
+##
+# @AuthZListProperties:
+#
+# Properties for authz-list objects.
+#
+# @policy: Default policy to apply when no rule matches (default: deny)
+#
+# @rules: Authorization rules based on matching user
+#
+# Since: 4.0
+##
+{ 'struct': 'AuthZListProperties',
+ 'data': { '*policy': 'QAuthZListPolicy',
+ '*rules': ['QAuthZListRule'] } }
+
+##
+# @AuthZListFileProperties:
+#
+# Properties for authz-listfile objects.
+#
+# @filename: File name to load the configuration from. The file must
+# contain valid JSON for AuthZListProperties.
+#
+# @refresh: If true, inotify is used to monitor the file, automatically
+# reloading changes. If an error occurs during reloading, all
+# authorizations will fail until the file is next successfully
+# loaded. (default: true if the binary was built with
+# CONFIG_INOTIFY1, false otherwise)
+#
+# Since: 4.0
+##
+{ 'struct': 'AuthZListFileProperties',
+ 'data': { 'filename': 'str',
+ '*refresh': 'bool' } }
+
+##
+# @AuthZPAMProperties:
+#
+# Properties for authz-pam objects.
+#
+# @service: PAM service name to use for authorization
+#
+# Since: 4.0
+##
+{ 'struct': 'AuthZPAMProperties',
+ 'data': { 'service': 'str' } }
+
+##
+# @AuthZSimpleProperties:
+#
+# Properties for authz-simple objects.
+#
+# @identity: Identifies the allowed user. Its format depends on the network
+# service that authorization object is associated with. For
+# authorizing based on TLS x509 certificates, the identity must be
+# the x509 distinguished name.
+#
+# Since: 4.0
+##
+{ 'struct': 'AuthZSimpleProperties',
+ 'data': { 'identity': 'str' } }
diff --git a/qapi/block-core.json b/qapi/block-core.json
new file mode 100644
index 000000000..1d3dd9cb4
--- /dev/null
+++ b/qapi/block-core.json
@@ -0,0 +1,5572 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# == Block core (VM unrelated)
+##
+
+{ 'include': 'common.json' }
+{ 'include': 'crypto.json' }
+{ 'include': 'job.json' }
+{ 'include': 'sockets.json' }
+
+##
+# @SnapshotInfo:
+#
+# @id: unique snapshot id
+#
+# @name: user chosen name
+#
+# @vm-state-size: size of the VM state
+#
+# @date-sec: UTC date of the snapshot in seconds
+#
+# @date-nsec: fractional part in nano seconds to be used with date-sec
+#
+# @vm-clock-sec: VM clock relative to boot in seconds
+#
+# @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec
+#
+# @icount: Current instruction count. Appears when execution record/replay
+# is enabled. Used for "time-traveling" to match the moment
+# in the recorded execution with the snapshots. This counter may
+# be obtained through @query-replay command (since 5.2)
+#
+# Since: 1.3
+#
+##
+{ 'struct': 'SnapshotInfo',
+ 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',
+ 'date-sec': 'int', 'date-nsec': 'int',
+ 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int',
+ '*icount': 'int' } }
+
+##
+# @ImageInfoSpecificQCow2EncryptionBase:
+#
+# @format: The encryption format
+#
+# Since: 2.10
+##
+{ 'struct': 'ImageInfoSpecificQCow2EncryptionBase',
+ 'data': { 'format': 'BlockdevQcow2EncryptionFormat'}}
+
+##
+# @ImageInfoSpecificQCow2Encryption:
+#
+# Since: 2.10
+##
+{ 'union': 'ImageInfoSpecificQCow2Encryption',
+ 'base': 'ImageInfoSpecificQCow2EncryptionBase',
+ 'discriminator': 'format',
+ 'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
+
+##
+# @ImageInfoSpecificQCow2:
+#
+# @compat: compatibility level
+#
+# @data-file: the filename of the external data file that is stored in the
+# image and used as a default for opening the image (since: 4.0)
+#
+# @data-file-raw: True if the external data file must stay valid as a
+# standalone (read-only) raw image without looking at qcow2
+# metadata (since: 4.0)
+#
+# @extended-l2: true if the image has extended L2 entries; only valid for
+# compat >= 1.1 (since 5.2)
+#
+# @lazy-refcounts: on or off; only valid for compat >= 1.1
+#
+# @corrupt: true if the image has been marked corrupt; only valid for
+# compat >= 1.1 (since 2.2)
+#
+# @refcount-bits: width of a refcount entry in bits (since 2.3)
+#
+# @encrypt: details about encryption parameters; only set if image
+# is encrypted (since 2.10)
+#
+# @bitmaps: A list of qcow2 bitmap details (since 4.0)
+#
+# @compression-type: the image cluster compression method (since 5.1)
+#
+# Since: 1.7
+##
+{ 'struct': 'ImageInfoSpecificQCow2',
+ 'data': {
+ 'compat': 'str',
+ '*data-file': 'str',
+ '*data-file-raw': 'bool',
+ '*extended-l2': 'bool',
+ '*lazy-refcounts': 'bool',
+ '*corrupt': 'bool',
+ 'refcount-bits': 'int',
+ '*encrypt': 'ImageInfoSpecificQCow2Encryption',
+ '*bitmaps': ['Qcow2BitmapInfo'],
+ 'compression-type': 'Qcow2CompressionType'
+ } }
+
+##
+# @ImageInfoSpecificVmdk:
+#
+# @create-type: The create type of VMDK image
+#
+# @cid: Content id of image
+#
+# @parent-cid: Parent VMDK image's cid
+#
+# @extents: List of extent files
+#
+# Since: 1.7
+##
+{ 'struct': 'ImageInfoSpecificVmdk',
+ 'data': {
+ 'create-type': 'str',
+ 'cid': 'int',
+ 'parent-cid': 'int',
+ 'extents': ['ImageInfo']
+ } }
+
+##
+# @ImageInfoSpecificRbd:
+#
+# @encryption-format: Image encryption format
+#
+# Since: 6.1
+##
+{ 'struct': 'ImageInfoSpecificRbd',
+ 'data': {
+ '*encryption-format': 'RbdImageEncryptionFormat'
+ } }
+
+##
+# @ImageInfoSpecificKind:
+#
+# @luks: Since 2.7
+# @rbd: Since 6.1
+#
+# Since: 1.7
+##
+{ 'enum': 'ImageInfoSpecificKind',
+ 'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] }
+
+##
+# @ImageInfoSpecificQCow2Wrapper:
+#
+# Since: 1.7
+##
+{ 'struct': 'ImageInfoSpecificQCow2Wrapper',
+ 'data': { 'data': 'ImageInfoSpecificQCow2' } }
+
+##
+# @ImageInfoSpecificVmdkWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ImageInfoSpecificVmdkWrapper',
+ 'data': { 'data': 'ImageInfoSpecificVmdk' } }
+
+##
+# @ImageInfoSpecificLUKSWrapper:
+#
+# Since: 2.7
+##
+{ 'struct': 'ImageInfoSpecificLUKSWrapper',
+ 'data': { 'data': 'QCryptoBlockInfoLUKS' } }
+# If we need to add block driver specific parameters for
+# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
+# to define a ImageInfoSpecificLUKS
+
+##
+# @ImageInfoSpecificRbdWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ImageInfoSpecificRbdWrapper',
+ 'data': { 'data': 'ImageInfoSpecificRbd' } }
+
+##
+# @ImageInfoSpecific:
+#
+# A discriminated record of image format specific information structures.
+#
+# Since: 1.7
+##
+{ 'union': 'ImageInfoSpecific',
+ 'base': { 'type': 'ImageInfoSpecificKind' },
+ 'discriminator': 'type',
+ 'data': {
+ 'qcow2': 'ImageInfoSpecificQCow2Wrapper',
+ 'vmdk': 'ImageInfoSpecificVmdkWrapper',
+ 'luks': 'ImageInfoSpecificLUKSWrapper',
+ 'rbd': 'ImageInfoSpecificRbdWrapper'
+ } }
+
+##
+# @ImageInfo:
+#
+# Information about a QEMU image file
+#
+# @filename: name of the image file
+#
+# @format: format of the image file
+#
+# @virtual-size: maximum capacity in bytes of the image
+#
+# @actual-size: actual size on disk in bytes of the image
+#
+# @dirty-flag: true if image is not cleanly closed
+#
+# @cluster-size: size of a cluster in bytes
+#
+# @encrypted: true if the image is encrypted
+#
+# @compressed: true if the image is compressed (Since 1.7)
+#
+# @backing-filename: name of the backing file
+#
+# @full-backing-filename: full path of the backing file
+#
+# @backing-filename-format: the format of the backing file
+#
+# @snapshots: list of VM snapshots
+#
+# @backing-image: info of the backing image (since 1.6)
+#
+# @format-specific: structure supplying additional format-specific
+# information (since 1.7)
+#
+# Since: 1.3
+#
+##
+{ 'struct': 'ImageInfo',
+ 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
+ '*actual-size': 'int', 'virtual-size': 'int',
+ '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
+ '*backing-filename': 'str', '*full-backing-filename': 'str',
+ '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
+ '*backing-image': 'ImageInfo',
+ '*format-specific': 'ImageInfoSpecific' } }
+
+##
+# @ImageCheck:
+#
+# Information about a QEMU image file check
+#
+# @filename: name of the image file checked
+#
+# @format: format of the image file checked
+#
+# @check-errors: number of unexpected errors occurred during check
+#
+# @image-end-offset: offset (in bytes) where the image ends, this
+# field is present if the driver for the image format
+# supports it
+#
+# @corruptions: number of corruptions found during the check if any
+#
+# @leaks: number of leaks found during the check if any
+#
+# @corruptions-fixed: number of corruptions fixed during the check
+# if any
+#
+# @leaks-fixed: number of leaks fixed during the check if any
+#
+# @total-clusters: total number of clusters, this field is present
+# if the driver for the image format supports it
+#
+# @allocated-clusters: total number of allocated clusters, this
+# field is present if the driver for the image format
+# supports it
+#
+# @fragmented-clusters: total number of fragmented clusters, this
+# field is present if the driver for the image format
+# supports it
+#
+# @compressed-clusters: total number of compressed clusters, this
+# field is present if the driver for the image format
+# supports it
+#
+# Since: 1.4
+#
+##
+{ 'struct': 'ImageCheck',
+ 'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int',
+ '*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int',
+ '*corruptions-fixed': 'int', '*leaks-fixed': 'int',
+ '*total-clusters': 'int', '*allocated-clusters': 'int',
+ '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } }
+
+##
+# @MapEntry:
+#
+# Mapping information from a virtual block range to a host file range
+#
+# @start: virtual (guest) offset of the first byte described by this
+# entry
+#
+# @length: the number of bytes of the mapped virtual range
+#
+# @data: reading the image will actually read data from a file (in
+# particular, if @offset is present this means that the sectors
+# are not simply preallocated, but contain actual data in raw
+# format)
+#
+# @zero: whether the virtual blocks read as zeroes
+#
+# @depth: number of layers (0 = top image, 1 = top image's backing
+# file, ..., n - 1 = bottom image (where n is the number of
+# images in the chain)) before reaching one for which the
+# range is allocated
+#
+# @present: true if this layer provides the data, false if adding a backing
+# layer could impact this region (since 6.1)
+#
+# @offset: if present, the image file stores the data for this range
+# in raw format at the given (host) offset
+#
+# @filename: filename that is referred to by @offset
+#
+# Since: 2.6
+#
+##
+{ 'struct': 'MapEntry',
+ 'data': {'start': 'int', 'length': 'int', 'data': 'bool',
+ 'zero': 'bool', 'depth': 'int', 'present': 'bool',
+ '*offset': 'int', '*filename': 'str' } }
+
+##
+# @BlockdevCacheInfo:
+#
+# Cache mode information for a block device
+#
+# @writeback: true if writeback mode is enabled
+# @direct: true if the host page cache is bypassed (O_DIRECT)
+# @no-flush: true if flush requests are ignored for the device
+#
+# Since: 2.3
+##
+{ 'struct': 'BlockdevCacheInfo',
+ 'data': { 'writeback': 'bool',
+ 'direct': 'bool',
+ 'no-flush': 'bool' } }
+
+##
+# @BlockDeviceInfo:
+#
+# Information about the backing device for a block device.
+#
+# @file: the filename of the backing device
+#
+# @node-name: the name of the block driver node (Since 2.0)
+#
+# @ro: true if the backing device was open read-only
+#
+# @drv: the name of the block format used to open the backing device. As of
+# 0.14 this can be: 'blkdebug', 'bochs', 'cloop', 'cow', 'dmg',
+# 'file', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
+# 'http', 'https', 'luks', 'nbd', 'parallels', 'qcow',
+# 'qcow2', 'raw', 'vdi', 'vmdk', 'vpc', 'vvfat'
+# 2.2: 'archipelago' added, 'cow' dropped
+# 2.3: 'host_floppy' deprecated
+# 2.5: 'host_floppy' dropped
+# 2.6: 'luks' added
+# 2.8: 'replication' added, 'tftp' dropped
+# 2.9: 'archipelago' dropped
+#
+# @backing_file: the name of the backing file (for copy-on-write)
+#
+# @backing_file_depth: number of files in the backing file chain (since: 1.2)
+#
+# @encrypted: true if the backing device is encrypted
+#
+# @detect_zeroes: detect and optimize zero writes (Since 2.1)
+#
+# @bps: total throughput limit in bytes per second is specified
+#
+# @bps_rd: read throughput limit in bytes per second is specified
+#
+# @bps_wr: write throughput limit in bytes per second is specified
+#
+# @iops: total I/O operations per second is specified
+#
+# @iops_rd: read I/O operations per second is specified
+#
+# @iops_wr: write I/O operations per second is specified
+#
+# @image: the info of image used (since: 1.6)
+#
+# @bps_max: total throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_rd_max: read throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_wr_max: write throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_max: total I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_rd_max: read I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_wr_max: write I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_max_length: maximum length of the @bps_max burst
+# period, in seconds. (Since 2.6)
+#
+# @bps_rd_max_length: maximum length of the @bps_rd_max
+# burst period, in seconds. (Since 2.6)
+#
+# @bps_wr_max_length: maximum length of the @bps_wr_max
+# burst period, in seconds. (Since 2.6)
+#
+# @iops_max_length: maximum length of the @iops burst
+# period, in seconds. (Since 2.6)
+#
+# @iops_rd_max_length: maximum length of the @iops_rd_max
+# burst period, in seconds. (Since 2.6)
+#
+# @iops_wr_max_length: maximum length of the @iops_wr_max
+# burst period, in seconds. (Since 2.6)
+#
+# @iops_size: an I/O size in bytes (Since 1.7)
+#
+# @group: throttle group name (Since 2.4)
+#
+# @cache: the cache mode used for the block device (since: 2.3)
+#
+# @write_threshold: configured write threshold for the device.
+# 0 if disabled. (Since 2.3)
+#
+# @dirty-bitmaps: dirty bitmaps information (only present if node
+# has one or more dirty bitmaps) (Since 4.2)
+#
+# Since: 0.14
+#
+##
+{ 'struct': 'BlockDeviceInfo',
+ 'data': { 'file': 'str', '*node-name': 'str', 'ro': 'bool', 'drv': 'str',
+ '*backing_file': 'str', 'backing_file_depth': 'int',
+ 'encrypted': 'bool',
+ 'detect_zeroes': 'BlockdevDetectZeroesOptions',
+ 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
+ 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+ 'image': 'ImageInfo',
+ '*bps_max': 'int', '*bps_rd_max': 'int',
+ '*bps_wr_max': 'int', '*iops_max': 'int',
+ '*iops_rd_max': 'int', '*iops_wr_max': 'int',
+ '*bps_max_length': 'int', '*bps_rd_max_length': 'int',
+ '*bps_wr_max_length': 'int', '*iops_max_length': 'int',
+ '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int',
+ '*iops_size': 'int', '*group': 'str', 'cache': 'BlockdevCacheInfo',
+ 'write_threshold': 'int', '*dirty-bitmaps': ['BlockDirtyInfo'] } }
+
+##
+# @BlockDeviceIoStatus:
+#
+# An enumeration of block device I/O status.
+#
+# @ok: The last I/O operation has succeeded
+#
+# @failed: The last I/O operation has failed
+#
+# @nospace: The last I/O operation has failed due to a no-space condition
+#
+# Since: 1.0
+##
+{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] }
+
+##
+# @BlockDirtyInfo:
+#
+# Block dirty bitmap information.
+#
+# @name: the name of the dirty bitmap (Since 2.4)
+#
+# @count: number of dirty bytes according to the dirty bitmap
+#
+# @granularity: granularity of the dirty bitmap in bytes (since 1.4)
+#
+# @recording: true if the bitmap is recording new writes from the guest.
+# Replaces ``active`` and ``disabled`` statuses. (since 4.0)
+#
+# @busy: true if the bitmap is in-use by some operation (NBD or jobs)
+# and cannot be modified via QMP or used by another operation.
+# Replaces ``locked`` and ``frozen`` statuses. (since 4.0)
+#
+# @persistent: true if the bitmap was stored on disk, is scheduled to be stored
+# on disk, or both. (since 4.0)
+#
+# @inconsistent: true if this is a persistent bitmap that was improperly
+# stored. Implies @persistent to be true; @recording and
+# @busy to be false. This bitmap cannot be used. To remove
+# it, use @block-dirty-bitmap-remove. (Since 4.0)
+#
+# Since: 1.3
+##
+{ 'struct': 'BlockDirtyInfo',
+ 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32',
+ 'recording': 'bool', 'busy': 'bool',
+ 'persistent': 'bool', '*inconsistent': 'bool' } }
+
+##
+# @Qcow2BitmapInfoFlags:
+#
+# An enumeration of flags that a bitmap can report to the user.
+#
+# @in-use: This flag is set by any process actively modifying the qcow2 file,
+# and cleared when the updated bitmap is flushed to the qcow2 image.
+# The presence of this flag in an offline image means that the bitmap
+# was not saved correctly after its last usage, and may contain
+# inconsistent data.
+#
+# @auto: The bitmap must reflect all changes of the virtual disk by any
+# application that would write to this qcow2 file.
+#
+# Since: 4.0
+##
+{ 'enum': 'Qcow2BitmapInfoFlags',
+ 'data': ['in-use', 'auto'] }
+
+##
+# @Qcow2BitmapInfo:
+#
+# Qcow2 bitmap information.
+#
+# @name: the name of the bitmap
+#
+# @granularity: granularity of the bitmap in bytes
+#
+# @flags: flags of the bitmap
+#
+# Since: 4.0
+##
+{ 'struct': 'Qcow2BitmapInfo',
+ 'data': {'name': 'str', 'granularity': 'uint32',
+ 'flags': ['Qcow2BitmapInfoFlags'] } }
+
+##
+# @BlockLatencyHistogramInfo:
+#
+# Block latency histogram.
+#
+# @boundaries: list of interval boundary values in nanoseconds, all greater
+# than zero and in ascending order.
+# For example, the list [10, 50, 100] produces the following
+# histogram intervals: [0, 10), [10, 50), [50, 100), [100, +inf).
+#
+# @bins: list of io request counts corresponding to histogram intervals.
+# len(@bins) = len(@boundaries) + 1
+# For the example above, @bins may be something like [3, 1, 5, 2],
+# and corresponding histogram looks like:
+#
+# ::
+#
+# 5| *
+# 4| *
+# 3| * *
+# 2| * * *
+# 1| * * * *
+# +------------------
+# 10 50 100
+#
+# Since: 4.0
+##
+{ 'struct': 'BlockLatencyHistogramInfo',
+ 'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
+
+##
+# @BlockInfo:
+#
+# Block device information. This structure describes a virtual device and
+# the backing device associated with it.
+#
+# @device: The device name associated with the virtual device.
+#
+# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block
+# device. (since 2.10)
+#
+# @type: This field is returned only for compatibility reasons, it should
+# not be used (always returns 'unknown')
+#
+# @removable: True if the device supports removable media.
+#
+# @locked: True if the guest has locked this device from having its media
+# removed
+#
+# @tray_open: True if the device's tray is open
+# (only present if it has a tray)
+#
+# @io-status: @BlockDeviceIoStatus. Only present if the device
+# supports it and the VM is configured to stop on errors
+# (supported device models: virtio-blk, IDE, SCSI except
+# scsi-generic)
+#
+# @inserted: @BlockDeviceInfo describing the device if media is
+# present
+#
+# Since: 0.14
+##
+{ 'struct': 'BlockInfo',
+ 'data': {'device': 'str', '*qdev': 'str', 'type': 'str', 'removable': 'bool',
+ 'locked': 'bool', '*inserted': 'BlockDeviceInfo',
+ '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus' } }
+
+##
+# @BlockMeasureInfo:
+#
+# Image file size calculation information. This structure describes the size
+# requirements for creating a new image file.
+#
+# The size requirements depend on the new image file format. File size always
+# equals virtual disk size for the 'raw' format, even for sparse POSIX files.
+# Compact formats such as 'qcow2' represent unallocated and zero regions
+# efficiently so file size may be smaller than virtual disk size.
+#
+# The values are upper bounds that are guaranteed to fit the new image file.
+# Subsequent modification, such as internal snapshot or further bitmap
+# creation, may require additional space and is not covered here.
+#
+# @required: Size required for a new image file, in bytes, when copying just
+# allocated guest-visible contents.
+#
+# @fully-allocated: Image file size, in bytes, once data has been written
+# to all sectors, when copying just guest-visible contents.
+#
+# @bitmaps: Additional size required if all the top-level bitmap metadata
+# in the source image were to be copied to the destination,
+# present only when source and destination both support
+# persistent bitmaps. (since 5.1)
+#
+# Since: 2.10
+##
+{ 'struct': 'BlockMeasureInfo',
+ 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} }
+
+##
+# @query-block:
+#
+# Get a list of BlockInfo for all virtual block devices.
+#
+# Returns: a list of @BlockInfo describing each virtual block device. Filter
+# nodes that were created implicitly are skipped over.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-block" }
+# <- {
+# "return":[
+# {
+# "io-status": "ok",
+# "device":"ide0-hd0",
+# "locked":false,
+# "removable":false,
+# "inserted":{
+# "ro":false,
+# "drv":"qcow2",
+# "encrypted":false,
+# "file":"disks/test.qcow2",
+# "backing_file_depth":1,
+# "bps":1000000,
+# "bps_rd":0,
+# "bps_wr":0,
+# "iops":1000000,
+# "iops_rd":0,
+# "iops_wr":0,
+# "bps_max": 8000000,
+# "bps_rd_max": 0,
+# "bps_wr_max": 0,
+# "iops_max": 0,
+# "iops_rd_max": 0,
+# "iops_wr_max": 0,
+# "iops_size": 0,
+# "detect_zeroes": "on",
+# "write_threshold": 0,
+# "image":{
+# "filename":"disks/test.qcow2",
+# "format":"qcow2",
+# "virtual-size":2048000,
+# "backing_file":"base.qcow2",
+# "full-backing-filename":"disks/base.qcow2",
+# "backing-filename-format":"qcow2",
+# "snapshots":[
+# {
+# "id": "1",
+# "name": "snapshot1",
+# "vm-state-size": 0,
+# "date-sec": 10000200,
+# "date-nsec": 12,
+# "vm-clock-sec": 206,
+# "vm-clock-nsec": 30
+# }
+# ],
+# "backing-image":{
+# "filename":"disks/base.qcow2",
+# "format":"qcow2",
+# "virtual-size":2048000
+# }
+# }
+# },
+# "qdev": "ide_disk",
+# "type":"unknown"
+# },
+# {
+# "io-status": "ok",
+# "device":"ide1-cd0",
+# "locked":false,
+# "removable":true,
+# "qdev": "/machine/unattached/device[23]",
+# "tray_open": false,
+# "type":"unknown"
+# },
+# {
+# "device":"floppy0",
+# "locked":false,
+# "removable":true,
+# "qdev": "/machine/unattached/device[20]",
+# "type":"unknown"
+# },
+# {
+# "device":"sd0",
+# "locked":false,
+# "removable":true,
+# "type":"unknown"
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-block', 'returns': ['BlockInfo'] }
+
+
+##
+# @BlockDeviceTimedStats:
+#
+# Statistics of a block device during a given interval of time.
+#
+# @interval_length: Interval used for calculating the statistics,
+# in seconds.
+#
+# @min_rd_latency_ns: Minimum latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @min_wr_latency_ns: Minimum latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @min_flush_latency_ns: Minimum latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @max_rd_latency_ns: Maximum latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @max_wr_latency_ns: Maximum latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @max_flush_latency_ns: Maximum latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_rd_latency_ns: Average latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_wr_latency_ns: Average latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_flush_latency_ns: Average latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_rd_queue_depth: Average number of pending read operations
+# in the defined interval.
+#
+# @avg_wr_queue_depth: Average number of pending write operations
+# in the defined interval.
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockDeviceTimedStats',
+ 'data': { 'interval_length': 'int', 'min_rd_latency_ns': 'int',
+ 'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int',
+ 'min_wr_latency_ns': 'int', 'max_wr_latency_ns': 'int',
+ 'avg_wr_latency_ns': 'int', 'min_flush_latency_ns': 'int',
+ 'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int',
+ 'avg_rd_queue_depth': 'number', 'avg_wr_queue_depth': 'number' } }
+
+##
+# @BlockDeviceStats:
+#
+# Statistics of a virtual block device or a block backing device.
+#
+# @rd_bytes: The number of bytes read by the device.
+#
+# @wr_bytes: The number of bytes written by the device.
+#
+# @unmap_bytes: The number of bytes unmapped by the device (Since 4.2)
+#
+# @rd_operations: The number of read operations performed by the device.
+#
+# @wr_operations: The number of write operations performed by the device.
+#
+# @flush_operations: The number of cache flush operations performed by the
+# device (since 0.15)
+#
+# @unmap_operations: The number of unmap operations performed by the device
+# (Since 4.2)
+#
+# @rd_total_time_ns: Total time spent on reads in nanoseconds (since 0.15).
+#
+# @wr_total_time_ns: Total time spent on writes in nanoseconds (since 0.15).
+#
+# @flush_total_time_ns: Total time spent on cache flushes in nanoseconds
+# (since 0.15).
+#
+# @unmap_total_time_ns: Total time spent on unmap operations in nanoseconds
+# (Since 4.2)
+#
+# @wr_highest_offset: The offset after the greatest byte written to the
+# device. The intended use of this information is for
+# growable sparse files (like qcow2) that are used on top
+# of a physical device.
+#
+# @rd_merged: Number of read requests that have been merged into another
+# request (Since 2.3).
+#
+# @wr_merged: Number of write requests that have been merged into another
+# request (Since 2.3).
+#
+# @unmap_merged: Number of unmap requests that have been merged into another
+# request (Since 4.2)
+#
+# @idle_time_ns: Time since the last I/O operation, in
+# nanoseconds. If the field is absent it means that
+# there haven't been any operations yet (Since 2.5).
+#
+# @failed_rd_operations: The number of failed read operations
+# performed by the device (Since 2.5)
+#
+# @failed_wr_operations: The number of failed write operations
+# performed by the device (Since 2.5)
+#
+# @failed_flush_operations: The number of failed flush operations
+# performed by the device (Since 2.5)
+#
+# @failed_unmap_operations: The number of failed unmap operations performed
+# by the device (Since 4.2)
+#
+# @invalid_rd_operations: The number of invalid read operations
+# performed by the device (Since 2.5)
+#
+# @invalid_wr_operations: The number of invalid write operations
+# performed by the device (Since 2.5)
+#
+# @invalid_flush_operations: The number of invalid flush operations
+# performed by the device (Since 2.5)
+#
+# @invalid_unmap_operations: The number of invalid unmap operations performed
+# by the device (Since 4.2)
+#
+# @account_invalid: Whether invalid operations are included in the
+# last access statistics (Since 2.5)
+#
+# @account_failed: Whether failed operations are included in the
+# latency and last access statistics (Since 2.5)
+#
+# @timed_stats: Statistics specific to the set of previously defined
+# intervals of time (Since 2.5)
+#
+# @rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
+#
+# @wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
+#
+# @flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
+#
+# Since: 0.14
+##
+{ 'struct': 'BlockDeviceStats',
+ 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'unmap_bytes' : 'int',
+ 'rd_operations': 'int', 'wr_operations': 'int',
+ 'flush_operations': 'int', 'unmap_operations': 'int',
+ 'rd_total_time_ns': 'int', 'wr_total_time_ns': 'int',
+ 'flush_total_time_ns': 'int', 'unmap_total_time_ns': 'int',
+ 'wr_highest_offset': 'int',
+ 'rd_merged': 'int', 'wr_merged': 'int', 'unmap_merged': 'int',
+ '*idle_time_ns': 'int',
+ 'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
+ 'failed_flush_operations': 'int', 'failed_unmap_operations': 'int',
+ 'invalid_rd_operations': 'int', 'invalid_wr_operations': 'int',
+ 'invalid_flush_operations': 'int', 'invalid_unmap_operations': 'int',
+ 'account_invalid': 'bool', 'account_failed': 'bool',
+ 'timed_stats': ['BlockDeviceTimedStats'],
+ '*rd_latency_histogram': 'BlockLatencyHistogramInfo',
+ '*wr_latency_histogram': 'BlockLatencyHistogramInfo',
+ '*flush_latency_histogram': 'BlockLatencyHistogramInfo' } }
+
+##
+# @BlockStatsSpecificFile:
+#
+# File driver statistics
+#
+# @discard-nb-ok: The number of successful discard operations performed by
+# the driver.
+#
+# @discard-nb-failed: The number of failed discard operations performed by
+# the driver.
+#
+# @discard-bytes-ok: The number of bytes discarded by the driver.
+#
+# Since: 4.2
+##
+{ 'struct': 'BlockStatsSpecificFile',
+ 'data': {
+ 'discard-nb-ok': 'uint64',
+ 'discard-nb-failed': 'uint64',
+ 'discard-bytes-ok': 'uint64' } }
+
+##
+# @BlockStatsSpecificNvme:
+#
+# NVMe driver statistics
+#
+# @completion-errors: The number of completion errors.
+#
+# @aligned-accesses: The number of aligned accesses performed by
+# the driver.
+#
+# @unaligned-accesses: The number of unaligned accesses performed by
+# the driver.
+#
+# Since: 5.2
+##
+{ 'struct': 'BlockStatsSpecificNvme',
+ 'data': {
+ 'completion-errors': 'uint64',
+ 'aligned-accesses': 'uint64',
+ 'unaligned-accesses': 'uint64' } }
+
+##
+# @BlockStatsSpecific:
+#
+# Block driver specific statistics
+#
+# Since: 4.2
+##
+{ 'union': 'BlockStatsSpecific',
+ 'base': { 'driver': 'BlockdevDriver' },
+ 'discriminator': 'driver',
+ 'data': {
+ 'file': 'BlockStatsSpecificFile',
+ 'host_device': { 'type': 'BlockStatsSpecificFile',
+ 'if': 'HAVE_HOST_BLOCK_DEVICE' },
+ 'nvme': 'BlockStatsSpecificNvme' } }
+
+##
+# @BlockStats:
+#
+# Statistics of a virtual block device or a block backing device.
+#
+# @device: If the stats are for a virtual block device, the name
+# corresponding to the virtual block device.
+#
+# @node-name: The node name of the device. (Since 2.3)
+#
+# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block
+# device. (since 3.0)
+#
+# @stats: A @BlockDeviceStats for the device.
+#
+# @driver-specific: Optional driver-specific stats. (Since 4.2)
+#
+# @parent: This describes the file block device if it has one.
+# Contains recursively the statistics of the underlying
+# protocol (e.g. the host file for a qcow2 image). If there is
+# no underlying protocol, this field is omitted
+#
+# @backing: This describes the backing block device if it has one.
+# (Since 2.0)
+#
+# Since: 0.14
+##
+{ 'struct': 'BlockStats',
+ 'data': {'*device': 'str', '*qdev': 'str', '*node-name': 'str',
+ 'stats': 'BlockDeviceStats',
+ '*driver-specific': 'BlockStatsSpecific',
+ '*parent': 'BlockStats',
+ '*backing': 'BlockStats'} }
+
+##
+# @query-blockstats:
+#
+# Query the @BlockStats for all virtual block devices.
+#
+# @query-nodes: If true, the command will query all the block nodes
+# that have a node name, in a list which will include "parent"
+# information, but not "backing".
+# If false or omitted, the behavior is as before - query all the
+# device backends, recursively including their "parent" and
+# "backing". Filter nodes that were created implicitly are
+# skipped over in this mode. (Since 2.3)
+#
+# Returns: A list of @BlockStats for each virtual block devices.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-blockstats" }
+# <- {
+# "return":[
+# {
+# "device":"ide0-hd0",
+# "parent":{
+# "stats":{
+# "wr_highest_offset":3686448128,
+# "wr_bytes":9786368,
+# "wr_operations":751,
+# "rd_bytes":122567168,
+# "rd_operations":36772
+# "wr_total_times_ns":313253456
+# "rd_total_times_ns":3465673657
+# "flush_total_times_ns":49653
+# "flush_operations":61,
+# "rd_merged":0,
+# "wr_merged":0,
+# "idle_time_ns":2953431879,
+# "account_invalid":true,
+# "account_failed":false
+# }
+# },
+# "stats":{
+# "wr_highest_offset":2821110784,
+# "wr_bytes":9786368,
+# "wr_operations":692,
+# "rd_bytes":122739200,
+# "rd_operations":36604
+# "flush_operations":51,
+# "wr_total_times_ns":313253456
+# "rd_total_times_ns":3465673657
+# "flush_total_times_ns":49653,
+# "rd_merged":0,
+# "wr_merged":0,
+# "idle_time_ns":2953431879,
+# "account_invalid":true,
+# "account_failed":false
+# },
+# "qdev": "/machine/unattached/device[23]"
+# },
+# {
+# "device":"ide1-cd0",
+# "stats":{
+# "wr_highest_offset":0,
+# "wr_bytes":0,
+# "wr_operations":0,
+# "rd_bytes":0,
+# "rd_operations":0
+# "flush_operations":0,
+# "wr_total_times_ns":0
+# "rd_total_times_ns":0
+# "flush_total_times_ns":0,
+# "rd_merged":0,
+# "wr_merged":0,
+# "account_invalid":false,
+# "account_failed":false
+# },
+# "qdev": "/machine/unattached/device[24]"
+# },
+# {
+# "device":"floppy0",
+# "stats":{
+# "wr_highest_offset":0,
+# "wr_bytes":0,
+# "wr_operations":0,
+# "rd_bytes":0,
+# "rd_operations":0
+# "flush_operations":0,
+# "wr_total_times_ns":0
+# "rd_total_times_ns":0
+# "flush_total_times_ns":0,
+# "rd_merged":0,
+# "wr_merged":0,
+# "account_invalid":false,
+# "account_failed":false
+# },
+# "qdev": "/machine/unattached/device[16]"
+# },
+# {
+# "device":"sd0",
+# "stats":{
+# "wr_highest_offset":0,
+# "wr_bytes":0,
+# "wr_operations":0,
+# "rd_bytes":0,
+# "rd_operations":0
+# "flush_operations":0,
+# "wr_total_times_ns":0
+# "rd_total_times_ns":0
+# "flush_total_times_ns":0,
+# "rd_merged":0,
+# "wr_merged":0,
+# "account_invalid":false,
+# "account_failed":false
+# }
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-blockstats',
+ 'data': { '*query-nodes': 'bool' },
+ 'returns': ['BlockStats'] }
+
+##
+# @BlockdevOnError:
+#
+# An enumeration of possible behaviors for errors on I/O operations.
+# The exact meaning depends on whether the I/O was initiated by a guest
+# or by a block job
+#
+# @report: for guest operations, report the error to the guest;
+# for jobs, cancel the job
+#
+# @ignore: ignore the error, only report a QMP event (BLOCK_IO_ERROR
+# or BLOCK_JOB_ERROR). The backup, mirror and commit block jobs retry
+# the failing request later and may still complete successfully. The
+# stream block job continues to stream and will complete with an
+# error.
+#
+# @enospc: same as @stop on ENOSPC, same as @report otherwise.
+#
+# @stop: for guest operations, stop the virtual machine;
+# for jobs, pause the job
+#
+# @auto: inherit the error handling policy of the backend (since: 2.7)
+#
+# Since: 1.3
+##
+{ 'enum': 'BlockdevOnError',
+ 'data': ['report', 'ignore', 'enospc', 'stop', 'auto'] }
+
+##
+# @MirrorSyncMode:
+#
+# An enumeration of possible behaviors for the initial synchronization
+# phase of storage mirroring.
+#
+# @top: copies data in the topmost image to the destination
+#
+# @full: copies data from all images to the destination
+#
+# @none: only copy data written from now on
+#
+# @incremental: only copy data described by the dirty bitmap. (since: 2.4)
+#
+# @bitmap: only copy data described by the dirty bitmap. (since: 4.2)
+# Behavior on completion is determined by the BitmapSyncMode.
+#
+# Since: 1.3
+##
+{ 'enum': 'MirrorSyncMode',
+ 'data': ['top', 'full', 'none', 'incremental', 'bitmap'] }
+
+##
+# @BitmapSyncMode:
+#
+# An enumeration of possible behaviors for the synchronization of a bitmap
+# when used for data copy operations.
+#
+# @on-success: The bitmap is only synced when the operation is successful.
+# This is the behavior always used for 'INCREMENTAL' backups.
+#
+# @never: The bitmap is never synchronized with the operation, and is
+# treated solely as a read-only manifest of blocks to copy.
+#
+# @always: The bitmap is always synchronized with the operation,
+# regardless of whether or not the operation was successful.
+#
+# Since: 4.2
+##
+{ 'enum': 'BitmapSyncMode',
+ 'data': ['on-success', 'never', 'always'] }
+
+##
+# @MirrorCopyMode:
+#
+# An enumeration whose values tell the mirror block job when to
+# trigger writes to the target.
+#
+# @background: copy data in background only.
+#
+# @write-blocking: when data is written to the source, write it
+# (synchronously) to the target as well. In
+# addition, data is copied in background just like in
+# @background mode.
+#
+# Since: 3.0
+##
+{ 'enum': 'MirrorCopyMode',
+ 'data': ['background', 'write-blocking'] }
+
+##
+# @BlockJobInfo:
+#
+# Information about a long-running block device operation.
+#
+# @type: the job type ('stream' for image streaming)
+#
+# @device: The job identifier. Originally the device name but other
+# values are allowed since QEMU 2.7
+#
+# @len: Estimated @offset value at the completion of the job. This value can
+# arbitrarily change while the job is running, in both directions.
+#
+# @offset: Progress made until now. The unit is arbitrary and the value can
+# only meaningfully be used for the ratio of @offset to @len. The
+# value is monotonically increasing.
+#
+# @busy: false if the job is known to be in a quiescent state, with
+# no pending I/O. Since 1.3.
+#
+# @paused: whether the job is paused or, if @busy is true, will
+# pause itself as soon as possible. Since 1.3.
+#
+# @speed: the rate limit, bytes per second
+#
+# @io-status: the status of the job (since 1.3)
+#
+# @ready: true if the job may be completed (since 2.2)
+#
+# @status: Current job state/status (since 2.12)
+#
+# @auto-finalize: Job will finalize itself when PENDING, moving to
+# the CONCLUDED state. (since 2.12)
+#
+# @auto-dismiss: Job will dismiss itself when CONCLUDED, moving to the NULL
+# state and disappearing from the query list. (since 2.12)
+#
+# @error: Error information if the job did not complete successfully.
+# Not set if the job completed successfully. (since 2.12.1)
+#
+# Since: 1.1
+##
+{ 'struct': 'BlockJobInfo',
+ 'data': {'type': 'str', 'device': 'str', 'len': 'int',
+ 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int',
+ 'io-status': 'BlockDeviceIoStatus', 'ready': 'bool',
+ 'status': 'JobStatus',
+ 'auto-finalize': 'bool', 'auto-dismiss': 'bool',
+ '*error': 'str' } }
+
+##
+# @query-block-jobs:
+#
+# Return information about long-running block device operations.
+#
+# Returns: a list of @BlockJobInfo for each active block job
+#
+# Since: 1.1
+##
+{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }
+
+##
+# @block_resize:
+#
+# Resize a block image while a guest is running.
+#
+# Either @device or @node-name must be set but not both.
+#
+# @device: the name of the device to get the image resized
+#
+# @node-name: graph node name to get the image resized (Since 2.0)
+#
+# @size: new image size in bytes
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, DeviceNotFound
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "block_resize",
+# "arguments": { "device": "scratch", "size": 1073741824 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block_resize',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'size': 'int' },
+ 'coroutine': true }
+
+##
+# @NewImageMode:
+#
+# An enumeration that tells QEMU how to set the backing file path in
+# a new image file.
+#
+# @existing: QEMU should look for an existing image file.
+#
+# @absolute-paths: QEMU should create a new image with absolute paths
+# for the backing file. If there is no backing file available, the new
+# image will not be backed either.
+#
+# Since: 1.1
+##
+{ 'enum': 'NewImageMode',
+ 'data': [ 'existing', 'absolute-paths' ] }
+
+##
+# @BlockdevSnapshotSync:
+#
+# Either @device or @node-name must be set but not both.
+#
+# @device: the name of the device to take a snapshot of.
+#
+# @node-name: graph node name to generate the snapshot from (Since 2.0)
+#
+# @snapshot-file: the target of the new overlay image. If the file
+# exists, or if it is a device, the overlay will be created in the
+# existing file/device. Otherwise, a new file will be created.
+#
+# @snapshot-node-name: the graph node name of the new image (Since 2.0)
+#
+# @format: the format of the overlay image, default is 'qcow2'.
+#
+# @mode: whether and how QEMU should create a new image, default is
+# 'absolute-paths'.
+##
+{ 'struct': 'BlockdevSnapshotSync',
+ 'data': { '*device': 'str', '*node-name': 'str',
+ 'snapshot-file': 'str', '*snapshot-node-name': 'str',
+ '*format': 'str', '*mode': 'NewImageMode' } }
+
+##
+# @BlockdevSnapshot:
+#
+# @node: device or node name that will have a snapshot taken.
+#
+# @overlay: reference to the existing block device that will become
+# the overlay of @node, as part of taking the snapshot.
+# It must not have a current backing file (this can be
+# achieved by passing "backing": null to blockdev-add).
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockdevSnapshot',
+ 'data': { 'node': 'str', 'overlay': 'str' } }
+
+##
+# @BackupPerf:
+#
+# Optional parameters for backup. These parameters don't affect
+# functionality, but may significantly affect performance.
+#
+# @use-copy-range: Use copy offloading. Default false.
+#
+# @max-workers: Maximum number of parallel requests for the sustained background
+# copying process. Doesn't influence copy-before-write operations.
+# Default 64.
+#
+# @max-chunk: Maximum request length for the sustained background copying
+# process. Doesn't influence copy-before-write operations.
+# 0 means unlimited. If max-chunk is non-zero then it should not be
+# less than job cluster size which is calculated as maximum of
+# target image cluster size and 64k. Default 0.
+#
+# Since: 6.0
+##
+{ 'struct': 'BackupPerf',
+ 'data': { '*use-copy-range': 'bool',
+ '*max-workers': 'int', '*max-chunk': 'int64' } }
+
+##
+# @BackupCommon:
+#
+# @job-id: identifier for the newly-created block job. If
+# omitted, the device name will be used. (Since 2.7)
+#
+# @device: the device name or node-name of a root node which should be copied.
+#
+# @sync: what parts of the disk image should be copied to the destination
+# (all the disk, only the sectors allocated in the topmost image, from a
+# dirty bitmap, or only new I/O).
+#
+# @speed: the maximum speed, in bytes per second. The default is 0,
+# for unlimited.
+#
+# @bitmap: The name of a dirty bitmap to use.
+# Must be present if sync is "bitmap" or "incremental".
+# Can be present if sync is "full" or "top".
+# Must not be present otherwise.
+# (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
+#
+# @bitmap-mode: Specifies the type of data the bitmap should contain after
+# the operation concludes.
+# Must be present if a bitmap was provided,
+# Must NOT be present otherwise. (Since 4.2)
+#
+# @compress: true to compress data, if the target format supports it.
+# (default: false) (since 2.8)
+#
+# @on-source-error: the action to take on an error on the source,
+# default 'report'. 'stop' and 'enospc' can only be used
+# if the block device supports io-status (see BlockInfo).
+#
+# @on-target-error: the action to take on an error on the target,
+# default 'report' (no limitations, since this applies to
+# a different block device than @device).
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true. (Since 2.12)
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+# has completely ceased all work, and awaits @block-job-dismiss.
+# When true, this job will automatically disappear from the query
+# list without user intervention.
+# Defaults to true. (Since 2.12)
+#
+# @filter-node-name: the node name that should be assigned to the
+# filter driver that the backup job inserts into the graph
+# above node specified by @drive. If this option is not given,
+# a node name is autogenerated. (Since: 4.2)
+#
+# @x-perf: Performance options. (Since 6.0)
+#
+# Features:
+# @unstable: Member @x-perf is experimental.
+#
+# Note: @on-source-error and @on-target-error only affect background
+# I/O. If an error occurs during a guest write request, the device's
+# rerror/werror actions will be used.
+#
+# Since: 4.2
+##
+{ 'struct': 'BackupCommon',
+ 'data': { '*job-id': 'str', 'device': 'str',
+ 'sync': 'MirrorSyncMode', '*speed': 'int',
+ '*bitmap': 'str', '*bitmap-mode': 'BitmapSyncMode',
+ '*compress': 'bool',
+ '*on-source-error': 'BlockdevOnError',
+ '*on-target-error': 'BlockdevOnError',
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool',
+ '*filter-node-name': 'str',
+ '*x-perf': { 'type': 'BackupPerf',
+ 'features': [ 'unstable' ] } } }
+
+##
+# @DriveBackup:
+#
+# @target: the target of the new image. If the file exists, or if it
+# is a device, the existing file/device will be used as the new
+# destination. If it does not exist, a new file will be created.
+#
+# @format: the format of the new destination, default is to
+# probe if @mode is 'existing', else the format of the source
+#
+# @mode: whether and how QEMU should create a new image, default is
+# 'absolute-paths'.
+#
+# Since: 1.6
+##
+{ 'struct': 'DriveBackup',
+ 'base': 'BackupCommon',
+ 'data': { 'target': 'str',
+ '*format': 'str',
+ '*mode': 'NewImageMode' } }
+
+##
+# @BlockdevBackup:
+#
+# @target: the device name or node-name of the backup target node.
+#
+# Since: 2.3
+##
+{ 'struct': 'BlockdevBackup',
+ 'base': 'BackupCommon',
+ 'data': { 'target': 'str' } }
+
+##
+# @blockdev-snapshot-sync:
+#
+# Takes a synchronous snapshot of a block device.
+#
+# For the arguments, see the documentation of BlockdevSnapshotSync.
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, DeviceNotFound
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "blockdev-snapshot-sync",
+# "arguments": { "device": "ide-hd0",
+# "snapshot-file":
+# "/some/place/my-image",
+# "format": "qcow2" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-snapshot-sync',
+ 'data': 'BlockdevSnapshotSync' }
+
+
+##
+# @blockdev-snapshot:
+#
+# Takes a snapshot of a block device.
+#
+# Take a snapshot, by installing 'node' as the backing image of
+# 'overlay'. Additionally, if 'node' is associated with a block
+# device, the block device changes to using 'overlay' as its new active
+# image.
+#
+# For the arguments, see the documentation of BlockdevSnapshot.
+#
+# Features:
+# @allow-write-only-overlay: If present, the check whether this operation is safe
+# was relaxed so that it can be used to change
+# backing file of a destination of a blockdev-mirror.
+# (since 5.0)
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "blockdev-add",
+# "arguments": { "driver": "qcow2",
+# "node-name": "node1534",
+# "file": { "driver": "file",
+# "filename": "hd1.qcow2" },
+# "backing": null } }
+#
+# <- { "return": {} }
+#
+# -> { "execute": "blockdev-snapshot",
+# "arguments": { "node": "ide-hd0",
+# "overlay": "node1534" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-snapshot',
+ 'data': 'BlockdevSnapshot',
+ 'features': [ 'allow-write-only-overlay' ] }
+
+##
+# @change-backing-file:
+#
+# Change the backing file in the image file metadata. This does not
+# cause QEMU to reopen the image file to reparse the backing filename
+# (it may, however, perform a reopen to change permissions from
+# r/o -> r/w -> r/o, if needed). The new backing file string is written
+# into the image file metadata, and the QEMU internal strings are
+# updated.
+#
+# @image-node-name: The name of the block driver state node of the
+# image to modify. The "device" argument is used
+# to verify "image-node-name" is in the chain
+# described by "device".
+#
+# @device: The device name or node-name of the root node that owns
+# image-node-name.
+#
+# @backing-file: The string to write as the backing file. This
+# string is not validated, so care should be taken
+# when specifying the string or the image chain may
+# not be able to be reopened again.
+#
+# Returns: - Nothing on success
+# - If "device" does not exist or cannot be determined, DeviceNotFound
+#
+# Since: 2.1
+##
+{ 'command': 'change-backing-file',
+ 'data': { 'device': 'str', 'image-node-name': 'str',
+ 'backing-file': 'str' } }
+
+##
+# @block-commit:
+#
+# Live commit of data from overlay image nodes into backing nodes - i.e.,
+# writes data between 'top' and 'base' into 'base'.
+#
+# If top == base, that is an error.
+# If top has no overlays on top of it, or if it is in use by a writer,
+# the job will not be completed by itself. The user needs to complete
+# the job with the block-job-complete command after getting the ready
+# event. (Since 2.0)
+#
+# If the base image is smaller than top, then the base image will be
+# resized to be the same size as top. If top is smaller than the base
+# image, the base will not be truncated. If you want the base image
+# size to match the size of the smaller top, you can safely truncate
+# it yourself once the commit operation successfully completes.
+#
+# @job-id: identifier for the newly-created block job. If
+# omitted, the device name will be used. (Since 2.7)
+#
+# @device: the device name or node-name of a root node
+#
+# @base-node: The node name of the backing image to write data into.
+# If not specified, this is the deepest backing image.
+# (since: 3.1)
+#
+# @base: Same as @base-node, except that it is a file name rather than a node
+# name. This must be the exact filename string that was used to open the
+# node; other strings, even if addressing the same file, are not
+# accepted
+#
+# @top-node: The node name of the backing image within the image chain
+# which contains the topmost data to be committed down. If
+# not specified, this is the active layer. (since: 3.1)
+#
+# @top: Same as @top-node, except that it is a file name rather than a node
+# name. This must be the exact filename string that was used to open the
+# node; other strings, even if addressing the same file, are not
+# accepted
+#
+# @backing-file: The backing file string to write into the overlay
+# image of 'top'. If 'top' does not have an overlay
+# image, or if 'top' is in use by a writer, specifying
+# a backing file string is an error.
+#
+# This filename is not validated. If a pathname string
+# is such that it cannot be resolved by QEMU, that
+# means that subsequent QMP or HMP commands must use
+# node-names for the image in question, as filename
+# lookup methods will fail.
+#
+# If not specified, QEMU will automatically determine
+# the backing file string to use, or error out if
+# there is no obvious choice. Care should be taken
+# when specifying the string, to specify a valid
+# filename or protocol.
+# (Since 2.1)
+#
+# @speed: the maximum speed, in bytes per second
+#
+# @on-error: the action to take on an error. 'ignore' means that the request
+# should be retried. (default: report; Since: 5.0)
+#
+# @filter-node-name: the node name that should be assigned to the
+# filter driver that the commit job inserts into the graph
+# above @top. If this option is not given, a node name is
+# autogenerated. (Since: 2.9)
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true. (Since 3.1)
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+# has completely ceased all work, and awaits @block-job-dismiss.
+# When true, this job will automatically disappear from the query
+# list without user intervention.
+# Defaults to true. (Since 3.1)
+#
+# Features:
+# @deprecated: Members @base and @top are deprecated. Use @base-node
+# and @top-node instead.
+#
+# Returns: - Nothing on success
+# - If @device does not exist, DeviceNotFound
+# - Any other error returns a GenericError.
+#
+# Since: 1.3
+#
+# Example:
+#
+# -> { "execute": "block-commit",
+# "arguments": { "device": "virtio0",
+# "top": "/tmp/snap1.qcow2" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-commit',
+ 'data': { '*job-id': 'str', 'device': 'str', '*base-node': 'str',
+ '*base': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*top-node': 'str',
+ '*top': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*backing-file': 'str', '*speed': 'int',
+ '*on-error': 'BlockdevOnError',
+ '*filter-node-name': 'str',
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+
+##
+# @drive-backup:
+#
+# Start a point-in-time copy of a block device to a new destination. The
+# status of ongoing drive-backup operations can be checked with
+# query-block-jobs where the BlockJobInfo.type field has the value 'backup'.
+# The operation can be stopped before it has completed using the
+# block-job-cancel command.
+#
+# Features:
+# @deprecated: This command is deprecated. Use @blockdev-backup instead.
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, GenericError
+#
+# Since: 1.6
+#
+# Example:
+#
+# -> { "execute": "drive-backup",
+# "arguments": { "device": "drive0",
+# "sync": "full",
+# "target": "backup.img" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'drive-backup', 'boxed': true,
+ 'data': 'DriveBackup', 'features': ['deprecated'] }
+
+##
+# @blockdev-backup:
+#
+# Start a point-in-time copy of a block device to a new destination. The
+# status of ongoing blockdev-backup operations can be checked with
+# query-block-jobs where the BlockJobInfo.type field has the value 'backup'.
+# The operation can be stopped before it has completed using the
+# block-job-cancel command.
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, DeviceNotFound
+#
+# Since: 2.3
+#
+# Example:
+# -> { "execute": "blockdev-backup",
+# "arguments": { "device": "src-id",
+# "sync": "full",
+# "target": "tgt-id" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-backup', 'boxed': true,
+ 'data': 'BlockdevBackup' }
+
+
+##
+# @query-named-block-nodes:
+#
+# Get the named block driver list
+#
+# @flat: Omit the nested data about backing image ("backing-image" key) if true.
+# Default is false (Since 5.0)
+#
+# Returns: the list of BlockDeviceInfo
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-named-block-nodes" }
+# <- { "return": [ { "ro":false,
+# "drv":"qcow2",
+# "encrypted":false,
+# "file":"disks/test.qcow2",
+# "node-name": "my-node",
+# "backing_file_depth":1,
+# "bps":1000000,
+# "bps_rd":0,
+# "bps_wr":0,
+# "iops":1000000,
+# "iops_rd":0,
+# "iops_wr":0,
+# "bps_max": 8000000,
+# "bps_rd_max": 0,
+# "bps_wr_max": 0,
+# "iops_max": 0,
+# "iops_rd_max": 0,
+# "iops_wr_max": 0,
+# "iops_size": 0,
+# "write_threshold": 0,
+# "image":{
+# "filename":"disks/test.qcow2",
+# "format":"qcow2",
+# "virtual-size":2048000,
+# "backing_file":"base.qcow2",
+# "full-backing-filename":"disks/base.qcow2",
+# "backing-filename-format":"qcow2",
+# "snapshots":[
+# {
+# "id": "1",
+# "name": "snapshot1",
+# "vm-state-size": 0,
+# "date-sec": 10000200,
+# "date-nsec": 12,
+# "vm-clock-sec": 206,
+# "vm-clock-nsec": 30
+# }
+# ],
+# "backing-image":{
+# "filename":"disks/base.qcow2",
+# "format":"qcow2",
+# "virtual-size":2048000
+# }
+# } } ] }
+#
+##
+{ 'command': 'query-named-block-nodes',
+ 'returns': [ 'BlockDeviceInfo' ],
+ 'data': { '*flat': 'bool' } }
+
+##
+# @XDbgBlockGraphNodeType:
+#
+# @block-backend: corresponds to BlockBackend
+#
+# @block-job: corresponds to BlockJob
+#
+# @block-driver: corresponds to BlockDriverState
+#
+# Since: 4.0
+##
+{ 'enum': 'XDbgBlockGraphNodeType',
+ 'data': [ 'block-backend', 'block-job', 'block-driver' ] }
+
+##
+# @XDbgBlockGraphNode:
+#
+# @id: Block graph node identifier. This @id is generated only for
+# x-debug-query-block-graph and does not relate to any other identifiers in
+# Qemu.
+#
+# @type: Type of graph node. Can be one of block-backend, block-job or
+# block-driver-state.
+#
+# @name: Human readable name of the node. Corresponds to node-name for
+# block-driver-state nodes; is not guaranteed to be unique in the whole
+# graph (with block-jobs and block-backends).
+#
+# Since: 4.0
+##
+{ 'struct': 'XDbgBlockGraphNode',
+ 'data': { 'id': 'uint64', 'type': 'XDbgBlockGraphNodeType', 'name': 'str' } }
+
+##
+# @BlockPermission:
+#
+# Enum of base block permissions.
+#
+# @consistent-read: A user that has the "permission" of consistent reads is
+# guaranteed that their view of the contents of the block
+# device is complete and self-consistent, representing the
+# contents of a disk at a specific point.
+# For most block devices (including their backing files) this
+# is true, but the property cannot be maintained in a few
+# situations like for intermediate nodes of a commit block
+# job.
+#
+# @write: This permission is required to change the visible disk contents.
+#
+# @write-unchanged: This permission (which is weaker than BLK_PERM_WRITE) is
+# both enough and required for writes to the block node when
+# the caller promises that the visible disk content doesn't
+# change.
+# As the BLK_PERM_WRITE permission is strictly stronger,
+# either is sufficient to perform an unchanging write.
+#
+# @resize: This permission is required to change the size of a block node.
+#
+# @graph-mod: This permission is required to change the node that this
+# BdrvChild points to.
+#
+# Since: 4.0
+##
+{ 'enum': 'BlockPermission',
+ 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize',
+ 'graph-mod' ] }
+##
+# @XDbgBlockGraphEdge:
+#
+# Block Graph edge description for x-debug-query-block-graph.
+#
+# @parent: parent id
+#
+# @child: child id
+#
+# @name: name of the relation (examples are 'file' and 'backing')
+#
+# @perm: granted permissions for the parent operating on the child
+#
+# @shared-perm: permissions that can still be granted to other users of the
+# child while it is still attached to this parent
+#
+# Since: 4.0
+##
+{ 'struct': 'XDbgBlockGraphEdge',
+ 'data': { 'parent': 'uint64', 'child': 'uint64',
+ 'name': 'str', 'perm': [ 'BlockPermission' ],
+ 'shared-perm': [ 'BlockPermission' ] } }
+
+##
+# @XDbgBlockGraph:
+#
+# Block Graph - list of nodes and list of edges.
+#
+# Since: 4.0
+##
+{ 'struct': 'XDbgBlockGraph',
+ 'data': { 'nodes': ['XDbgBlockGraphNode'], 'edges': ['XDbgBlockGraphEdge'] } }
+
+##
+# @x-debug-query-block-graph:
+#
+# Get the block graph.
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Since: 4.0
+##
+{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph',
+ 'features': [ 'unstable' ] }
+
+##
+# @drive-mirror:
+#
+# Start mirroring a block device's writes to a new destination. target
+# specifies the target of the new image. If the file exists, or if it
+# is a device, it will be used as the new destination for writes. If
+# it does not exist, a new file will be created. format specifies the
+# format of the mirror image, default is to probe if mode='existing',
+# else the format of the source.
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, GenericError
+#
+# Since: 1.3
+#
+# Example:
+#
+# -> { "execute": "drive-mirror",
+# "arguments": { "device": "ide-hd0",
+# "target": "/some/place/my-image",
+# "sync": "full",
+# "format": "qcow2" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'drive-mirror', 'boxed': true,
+ 'data': 'DriveMirror' }
+
+##
+# @DriveMirror:
+#
+# A set of parameters describing drive mirror setup.
+#
+# @job-id: identifier for the newly-created block job. If
+# omitted, the device name will be used. (Since 2.7)
+#
+# @device: the device name or node-name of a root node whose writes should be
+# mirrored.
+#
+# @target: the target of the new image. If the file exists, or if it
+# is a device, the existing file/device will be used as the new
+# destination. If it does not exist, a new file will be created.
+#
+# @format: the format of the new destination, default is to
+# probe if @mode is 'existing', else the format of the source
+#
+# @node-name: the new block driver state node name in the graph
+# (Since 2.1)
+#
+# @replaces: with sync=full graph node name to be replaced by the new
+# image when a whole image copy is done. This can be used to repair
+# broken Quorum files. By default, @device is replaced, although
+# implicitly created filters on it are kept. (Since 2.1)
+#
+# @mode: whether and how QEMU should create a new image, default is
+# 'absolute-paths'.
+#
+# @speed: the maximum speed, in bytes per second
+#
+# @sync: what parts of the disk image should be copied to the destination
+# (all the disk, only the sectors allocated in the topmost image, or
+# only new I/O).
+#
+# @granularity: granularity of the dirty bitmap, default is 64K
+# if the image format doesn't have clusters, 4K if the clusters
+# are smaller than that, else the cluster size. Must be a
+# power of 2 between 512 and 64M (since 1.4).
+#
+# @buf-size: maximum amount of data in flight from source to
+# target (since 1.4).
+#
+# @on-source-error: the action to take on an error on the source,
+# default 'report'. 'stop' and 'enospc' can only be used
+# if the block device supports io-status (see BlockInfo).
+#
+# @on-target-error: the action to take on an error on the target,
+# default 'report' (no limitations, since this applies to
+# a different block device than @device).
+# @unmap: Whether to try to unmap target sectors where source has
+# only zero. If true, and target unallocated sectors will read as zero,
+# target image sectors will be unmapped; otherwise, zeroes will be
+# written. Both will result in identical contents.
+# Default is true. (Since 2.4)
+#
+# @copy-mode: when to copy data to the destination; defaults to 'background'
+# (Since: 3.0)
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true. (Since 3.1)
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+# has completely ceased all work, and awaits @block-job-dismiss.
+# When true, this job will automatically disappear from the query
+# list without user intervention.
+# Defaults to true. (Since 3.1)
+# Since: 1.3
+##
+{ 'struct': 'DriveMirror',
+ 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
+ '*format': 'str', '*node-name': 'str', '*replaces': 'str',
+ 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
+ '*speed': 'int', '*granularity': 'uint32',
+ '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
+ '*on-target-error': 'BlockdevOnError',
+ '*unmap': 'bool', '*copy-mode': 'MirrorCopyMode',
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+
+##
+# @BlockDirtyBitmap:
+#
+# @node: name of device/node which the bitmap is tracking
+#
+# @name: name of the dirty bitmap
+#
+# Since: 2.4
+##
+{ 'struct': 'BlockDirtyBitmap',
+ 'data': { 'node': 'str', 'name': 'str' } }
+
+##
+# @BlockDirtyBitmapAdd:
+#
+# @node: name of device/node which the bitmap is tracking
+#
+# @name: name of the dirty bitmap (must be less than 1024 bytes)
+#
+# @granularity: the bitmap granularity, default is 64k for
+# block-dirty-bitmap-add
+#
+# @persistent: the bitmap is persistent, i.e. it will be saved to the
+# corresponding block device image file on its close. For now only
+# Qcow2 disks support persistent bitmaps. Default is false for
+# block-dirty-bitmap-add. (Since: 2.10)
+#
+# @disabled: the bitmap is created in the disabled state, which means that
+# it will not track drive changes. The bitmap may be enabled with
+# block-dirty-bitmap-enable. Default is false. (Since: 4.0)
+#
+# Since: 2.4
+##
+{ 'struct': 'BlockDirtyBitmapAdd',
+ 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
+ '*persistent': 'bool', '*disabled': 'bool' } }
+
+##
+# @BlockDirtyBitmapMergeSource:
+#
+# @local: name of the bitmap, attached to the same node as target bitmap.
+#
+# @external: bitmap with specified node
+#
+# Since: 4.1
+##
+{ 'alternate': 'BlockDirtyBitmapMergeSource',
+ 'data': { 'local': 'str',
+ 'external': 'BlockDirtyBitmap' } }
+
+##
+# @BlockDirtyBitmapMerge:
+#
+# @node: name of device/node which the @target bitmap is tracking
+#
+# @target: name of the destination dirty bitmap
+#
+# @bitmaps: name(s) of the source dirty bitmap(s) at @node and/or fully
+# specified BlockDirtyBitmap elements. The latter are supported
+# since 4.1.
+#
+# Since: 4.0
+##
+{ 'struct': 'BlockDirtyBitmapMerge',
+ 'data': { 'node': 'str', 'target': 'str',
+ 'bitmaps': ['BlockDirtyBitmapMergeSource'] } }
+
+##
+# @block-dirty-bitmap-add:
+#
+# Create a dirty bitmap with a name on the node, and start tracking the writes.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device or node, DeviceNotFound
+# - If @name is already taken, GenericError with an explanation
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-add",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-add',
+ 'data': 'BlockDirtyBitmapAdd' }
+
+##
+# @block-dirty-bitmap-remove:
+#
+# Stop write tracking and remove the dirty bitmap that was created
+# with block-dirty-bitmap-add. If the bitmap is persistent, remove it from its
+# storage too.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device or node, DeviceNotFound
+# - If @name is not found, GenericError with an explanation
+# - if @name is frozen by an operation, GenericError
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-remove",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-remove',
+ 'data': 'BlockDirtyBitmap' }
+
+##
+# @block-dirty-bitmap-clear:
+#
+# Clear (reset) a dirty bitmap on the device, so that an incremental
+# backup from this point in time forward will only backup clusters
+# modified after this clear operation.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device, DeviceNotFound
+# - If @name is not found, GenericError with an explanation
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-clear",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-clear',
+ 'data': 'BlockDirtyBitmap' }
+
+##
+# @block-dirty-bitmap-enable:
+#
+# Enables a dirty bitmap so that it will begin tracking disk changes.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device, DeviceNotFound
+# - If @name is not found, GenericError with an explanation
+#
+# Since: 4.0
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-enable",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-enable',
+ 'data': 'BlockDirtyBitmap' }
+
+##
+# @block-dirty-bitmap-disable:
+#
+# Disables a dirty bitmap so that it will stop tracking disk changes.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device, DeviceNotFound
+# - If @name is not found, GenericError with an explanation
+#
+# Since: 4.0
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-disable",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-disable',
+ 'data': 'BlockDirtyBitmap' }
+
+##
+# @block-dirty-bitmap-merge:
+#
+# Merge dirty bitmaps listed in @bitmaps to the @target dirty bitmap.
+# Dirty bitmaps in @bitmaps will be unchanged, except if it also appears
+# as the @target bitmap. Any bits already set in @target will still be
+# set after the merge, i.e., this operation does not clear the target.
+# On error, @target is unchanged.
+#
+# The resulting bitmap will count as dirty any clusters that were dirty in any
+# of the source bitmaps. This can be used to achieve backup checkpoints, or in
+# simpler usages, to copy bitmaps.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device, DeviceNotFound
+# - If any bitmap in @bitmaps or @target is not found, GenericError
+# - If any of the bitmaps have different sizes or granularities,
+# GenericError
+#
+# Since: 4.0
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-merge",
+# "arguments": { "node": "drive0", "target": "bitmap0",
+# "bitmaps": ["bitmap1"] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-dirty-bitmap-merge',
+ 'data': 'BlockDirtyBitmapMerge' }
+
+##
+# @BlockDirtyBitmapSha256:
+#
+# SHA256 hash of dirty bitmap data
+#
+# @sha256: ASCII representation of SHA256 bitmap hash
+#
+# Since: 2.10
+##
+{ 'struct': 'BlockDirtyBitmapSha256',
+ 'data': {'sha256': 'str'} }
+
+##
+# @x-debug-block-dirty-bitmap-sha256:
+#
+# Get bitmap SHA256.
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: - BlockDirtyBitmapSha256 on success
+# - If @node is not a valid block device, DeviceNotFound
+# - If @name is not found or if hashing has failed, GenericError with an
+# explanation
+#
+# Since: 2.10
+##
+{ 'command': 'x-debug-block-dirty-bitmap-sha256',
+ 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256',
+ 'features': [ 'unstable' ] }
+
+##
+# @blockdev-mirror:
+#
+# Start mirroring a block device's writes to a new destination.
+#
+# @job-id: identifier for the newly-created block job. If
+# omitted, the device name will be used. (Since 2.7)
+#
+# @device: The device name or node-name of a root node whose writes should be
+# mirrored.
+#
+# @target: the id or node-name of the block device to mirror to. This mustn't be
+# attached to guest.
+#
+# @replaces: with sync=full graph node name to be replaced by the new
+# image when a whole image copy is done. This can be used to repair
+# broken Quorum files. By default, @device is replaced, although
+# implicitly created filters on it are kept.
+#
+# @speed: the maximum speed, in bytes per second
+#
+# @sync: what parts of the disk image should be copied to the destination
+# (all the disk, only the sectors allocated in the topmost image, or
+# only new I/O).
+#
+# @granularity: granularity of the dirty bitmap, default is 64K
+# if the image format doesn't have clusters, 4K if the clusters
+# are smaller than that, else the cluster size. Must be a
+# power of 2 between 512 and 64M
+#
+# @buf-size: maximum amount of data in flight from source to
+# target
+#
+# @on-source-error: the action to take on an error on the source,
+# default 'report'. 'stop' and 'enospc' can only be used
+# if the block device supports io-status (see BlockInfo).
+#
+# @on-target-error: the action to take on an error on the target,
+# default 'report' (no limitations, since this applies to
+# a different block device than @device).
+#
+# @filter-node-name: the node name that should be assigned to the
+# filter driver that the mirror job inserts into the graph
+# above @device. If this option is not given, a node name is
+# autogenerated. (Since: 2.9)
+#
+# @copy-mode: when to copy data to the destination; defaults to 'background'
+# (Since: 3.0)
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true. (Since 3.1)
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+# has completely ceased all work, and awaits @block-job-dismiss.
+# When true, this job will automatically disappear from the query
+# list without user intervention.
+# Defaults to true. (Since 3.1)
+# Returns: nothing on success.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "blockdev-mirror",
+# "arguments": { "device": "ide-hd0",
+# "target": "target0",
+# "sync": "full" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-mirror',
+ 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
+ '*replaces': 'str',
+ 'sync': 'MirrorSyncMode',
+ '*speed': 'int', '*granularity': 'uint32',
+ '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
+ '*on-target-error': 'BlockdevOnError',
+ '*filter-node-name': 'str',
+ '*copy-mode': 'MirrorCopyMode',
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+
+##
+# @BlockIOThrottle:
+#
+# A set of parameters describing block throttling.
+#
+# @device: Block device name
+#
+# @id: The name or QOM path of the guest device (since: 2.8)
+#
+# @bps: total throughput limit in bytes per second
+#
+# @bps_rd: read throughput limit in bytes per second
+#
+# @bps_wr: write throughput limit in bytes per second
+#
+# @iops: total I/O operations per second
+#
+# @iops_rd: read I/O operations per second
+#
+# @iops_wr: write I/O operations per second
+#
+# @bps_max: total throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_rd_max: read throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_wr_max: write throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_max: total I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_rd_max: read I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @iops_wr_max: write I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_max_length: maximum length of the @bps_max burst
+# period, in seconds. It must only
+# be set if @bps_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @bps_rd_max_length: maximum length of the @bps_rd_max
+# burst period, in seconds. It must only
+# be set if @bps_rd_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @bps_wr_max_length: maximum length of the @bps_wr_max
+# burst period, in seconds. It must only
+# be set if @bps_wr_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_max_length: maximum length of the @iops burst
+# period, in seconds. It must only
+# be set if @iops_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_rd_max_length: maximum length of the @iops_rd_max
+# burst period, in seconds. It must only
+# be set if @iops_rd_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_wr_max_length: maximum length of the @iops_wr_max
+# burst period, in seconds. It must only
+# be set if @iops_wr_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_size: an I/O size in bytes (Since 1.7)
+#
+# @group: throttle group name (Since 2.4)
+#
+# Features:
+# @deprecated: Member @device is deprecated. Use @id instead.
+#
+# Since: 1.1
+##
+{ 'struct': 'BlockIOThrottle',
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*id': 'str', 'bps': 'int', 'bps_rd': 'int',
+ 'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+ '*bps_max': 'int', '*bps_rd_max': 'int',
+ '*bps_wr_max': 'int', '*iops_max': 'int',
+ '*iops_rd_max': 'int', '*iops_wr_max': 'int',
+ '*bps_max_length': 'int', '*bps_rd_max_length': 'int',
+ '*bps_wr_max_length': 'int', '*iops_max_length': 'int',
+ '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int',
+ '*iops_size': 'int', '*group': 'str' } }
+
+##
+# @ThrottleLimits:
+#
+# Limit parameters for throttling.
+# Since some limit combinations are illegal, limits should always be set in one
+# transaction. All fields are optional. When setting limits, if a field is
+# missing the current value is not changed.
+#
+# @iops-total: limit total I/O operations per second
+# @iops-total-max: I/O operations burst
+# @iops-total-max-length: length of the iops-total-max burst period, in seconds
+# It must only be set if @iops-total-max is set as well.
+# @iops-read: limit read operations per second
+# @iops-read-max: I/O operations read burst
+# @iops-read-max-length: length of the iops-read-max burst period, in seconds
+# It must only be set if @iops-read-max is set as well.
+# @iops-write: limit write operations per second
+# @iops-write-max: I/O operations write burst
+# @iops-write-max-length: length of the iops-write-max burst period, in seconds
+# It must only be set if @iops-write-max is set as well.
+# @bps-total: limit total bytes per second
+# @bps-total-max: total bytes burst
+# @bps-total-max-length: length of the bps-total-max burst period, in seconds.
+# It must only be set if @bps-total-max is set as well.
+# @bps-read: limit read bytes per second
+# @bps-read-max: total bytes read burst
+# @bps-read-max-length: length of the bps-read-max burst period, in seconds
+# It must only be set if @bps-read-max is set as well.
+# @bps-write: limit write bytes per second
+# @bps-write-max: total bytes write burst
+# @bps-write-max-length: length of the bps-write-max burst period, in seconds
+# It must only be set if @bps-write-max is set as well.
+# @iops-size: when limiting by iops max size of an I/O in bytes
+#
+# Since: 2.11
+##
+{ 'struct': 'ThrottleLimits',
+ 'data': { '*iops-total' : 'int', '*iops-total-max' : 'int',
+ '*iops-total-max-length' : 'int', '*iops-read' : 'int',
+ '*iops-read-max' : 'int', '*iops-read-max-length' : 'int',
+ '*iops-write' : 'int', '*iops-write-max' : 'int',
+ '*iops-write-max-length' : 'int', '*bps-total' : 'int',
+ '*bps-total-max' : 'int', '*bps-total-max-length' : 'int',
+ '*bps-read' : 'int', '*bps-read-max' : 'int',
+ '*bps-read-max-length' : 'int', '*bps-write' : 'int',
+ '*bps-write-max' : 'int', '*bps-write-max-length' : 'int',
+ '*iops-size' : 'int' } }
+
+##
+# @ThrottleGroupProperties:
+#
+# Properties for throttle-group objects.
+#
+# @limits: limits to apply for this throttle group
+#
+# Features:
+# @unstable: All members starting with x- are aliases for the same key
+# without x- in the @limits object. This is not a stable
+# interface and may be removed or changed incompatibly in
+# the future. Use @limits for a supported stable
+# interface.
+#
+# Since: 2.11
+##
+{ 'struct': 'ThrottleGroupProperties',
+ 'data': { '*limits': 'ThrottleLimits',
+ '*x-iops-total': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-total-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-total-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-read': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-read-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-read-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-write': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-write-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-write-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-total': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-total-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-total-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-read': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-read-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-read-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-write': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-write-max': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-bps-write-max-length': { 'type': 'int',
+ 'features': [ 'unstable' ] },
+ '*x-iops-size': { 'type': 'int',
+ 'features': [ 'unstable' ] } } }
+
+##
+# @block-stream:
+#
+# Copy data from a backing file into a block device.
+#
+# The block streaming operation is performed in the background until the entire
+# backing file has been copied. This command returns immediately once streaming
+# has started. The status of ongoing block streaming operations can be checked
+# with query-block-jobs. The operation can be stopped before it has completed
+# using the block-job-cancel command.
+#
+# The node that receives the data is called the top image, can be located in
+# any part of the chain (but always above the base image; see below) and can be
+# specified using its device or node name. Earlier qemu versions only allowed
+# 'device' to name the top level node; presence of the 'base-node' parameter
+# during introspection can be used as a witness of the enhanced semantics
+# of 'device'.
+#
+# If a base file is specified then sectors are not copied from that base file and
+# its backing chain. This can be used to stream a subset of the backing file
+# chain instead of flattening the entire image.
+# When streaming completes the image file will have the base file as its backing
+# file, unless that node was changed while the job was running. In that case,
+# base's parent's backing (or filtered, whichever exists) child (i.e., base at
+# the beginning of the job) will be the new backing file.
+#
+# On successful completion the image file is updated to drop the backing file
+# and the BLOCK_JOB_COMPLETED event is emitted.
+#
+# In case @device is a filter node, block-stream modifies the first non-filter
+# overlay node below it to point to the new backing node instead of modifying
+# @device itself.
+#
+# @job-id: identifier for the newly-created block job. If
+# omitted, the device name will be used. (Since 2.7)
+#
+# @device: the device or node name of the top image
+#
+# @base: the common backing file name.
+# It cannot be set if @base-node or @bottom is also set.
+#
+# @base-node: the node name of the backing file.
+# It cannot be set if @base or @bottom is also set. (Since 2.8)
+#
+# @bottom: the last node in the chain that should be streamed into
+# top. It cannot be set if @base or @base-node is also set.
+# It cannot be filter node. (Since 6.0)
+#
+# @backing-file: The backing file string to write into the top
+# image. This filename is not validated.
+#
+# If a pathname string is such that it cannot be
+# resolved by QEMU, that means that subsequent QMP or
+# HMP commands must use node-names for the image in
+# question, as filename lookup methods will fail.
+#
+# If not specified, QEMU will automatically determine
+# the backing file string to use, or error out if there
+# is no obvious choice. Care should be taken when
+# specifying the string, to specify a valid filename or
+# protocol.
+# (Since 2.1)
+#
+# @speed: the maximum speed, in bytes per second
+#
+# @on-error: the action to take on an error (default report).
+# 'stop' and 'enospc' can only be used if the block device
+# supports io-status (see BlockInfo). Since 1.3.
+#
+# @filter-node-name: the node name that should be assigned to the
+# filter driver that the stream job inserts into the graph
+# above @device. If this option is not given, a node name is
+# autogenerated. (Since: 6.0)
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true. (Since 3.1)
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+# has completely ceased all work, and awaits @block-job-dismiss.
+# When true, this job will automatically disappear from the query
+# list without user intervention.
+# Defaults to true. (Since 3.1)
+#
+# Returns: - Nothing on success.
+# - If @device does not exist, DeviceNotFound.
+#
+# Since: 1.1
+#
+# Example:
+#
+# -> { "execute": "block-stream",
+# "arguments": { "device": "virtio0",
+# "base": "/tmp/master.qcow2" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-stream',
+ 'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
+ '*base-node': 'str', '*backing-file': 'str', '*bottom': 'str',
+ '*speed': 'int', '*on-error': 'BlockdevOnError',
+ '*filter-node-name': 'str',
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
+
+##
+# @block-job-set-speed:
+#
+# Set maximum speed for a background block operation.
+#
+# This command can only be issued when there is an active block job.
+#
+# Throttling can be disabled by setting the speed to 0.
+#
+# @device: The job identifier. This used to be a device name (hence
+# the name of the parameter), but since QEMU 2.7 it can have
+# other values.
+#
+# @speed: the maximum speed, in bytes per second, or 0 for unlimited.
+# Defaults to 0.
+#
+# Returns: - Nothing on success
+# - If no background operation is active on this device, DeviceNotActive
+#
+# Since: 1.1
+##
+{ 'command': 'block-job-set-speed',
+ 'data': { 'device': 'str', 'speed': 'int' } }
+
+##
+# @block-job-cancel:
+#
+# Stop an active background block operation.
+#
+# This command returns immediately after marking the active background block
+# operation for cancellation. It is an error to call this command if no
+# operation is in progress.
+#
+# The operation will cancel as soon as possible and then emit the
+# BLOCK_JOB_CANCELLED event. Before that happens the job is still visible when
+# enumerated using query-block-jobs.
+#
+# Note that if you issue 'block-job-cancel' after 'drive-mirror' has indicated
+# (via the event BLOCK_JOB_READY) that the source and destination are
+# synchronized, then the event triggered by this command changes to
+# BLOCK_JOB_COMPLETED, to indicate that the mirroring has ended and the
+# destination now has a point-in-time copy tied to the time of the cancellation.
+#
+# For streaming, the image file retains its backing file unless the streaming
+# operation happens to complete just as it is being cancelled. A new streaming
+# operation can be started at a later time to finish copying all data from the
+# backing file.
+#
+# @device: The job identifier. This used to be a device name (hence
+# the name of the parameter), but since QEMU 2.7 it can have
+# other values.
+#
+# @force: If true, and the job has already emitted the event BLOCK_JOB_READY,
+# abandon the job immediately (even if it is paused) instead of waiting
+# for the destination to complete its final synchronization (since 1.3)
+#
+# Returns: - Nothing on success
+# - If no background operation is active on this device, DeviceNotActive
+#
+# Since: 1.1
+##
+{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }
+
+##
+# @block-job-pause:
+#
+# Pause an active background block operation.
+#
+# This command returns immediately after marking the active background block
+# operation for pausing. It is an error to call this command if no
+# operation is in progress or if the job is already paused.
+#
+# The operation will pause as soon as possible. No event is emitted when
+# the operation is actually paused. Cancelling a paused job automatically
+# resumes it.
+#
+# @device: The job identifier. This used to be a device name (hence
+# the name of the parameter), but since QEMU 2.7 it can have
+# other values.
+#
+# Returns: - Nothing on success
+# - If no background operation is active on this device, DeviceNotActive
+#
+# Since: 1.3
+##
+{ 'command': 'block-job-pause', 'data': { 'device': 'str' } }
+
+##
+# @block-job-resume:
+#
+# Resume an active background block operation.
+#
+# This command returns immediately after resuming a paused background block
+# operation. It is an error to call this command if no operation is in
+# progress or if the job is not paused.
+#
+# This command also clears the error status of the job.
+#
+# @device: The job identifier. This used to be a device name (hence
+# the name of the parameter), but since QEMU 2.7 it can have
+# other values.
+#
+# Returns: - Nothing on success
+# - If no background operation is active on this device, DeviceNotActive
+#
+# Since: 1.3
+##
+{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }
+
+##
+# @block-job-complete:
+#
+# Manually trigger completion of an active background block operation. This
+# is supported for drive mirroring, where it also switches the device to
+# write to the target path only. The ability to complete is signaled with
+# a BLOCK_JOB_READY event.
+#
+# This command completes an active background block operation synchronously.
+# The ordering of this command's return with the BLOCK_JOB_COMPLETED event
+# is not defined. Note that if an I/O error occurs during the processing of
+# this command: 1) the command itself will fail; 2) the error will be processed
+# according to the rerror/werror arguments that were specified when starting
+# the operation.
+#
+# A cancelled or paused job cannot be completed.
+#
+# @device: The job identifier. This used to be a device name (hence
+# the name of the parameter), but since QEMU 2.7 it can have
+# other values.
+#
+# Returns: - Nothing on success
+# - If no background operation is active on this device, DeviceNotActive
+#
+# Since: 1.3
+##
+{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }
+
+##
+# @block-job-dismiss:
+#
+# For jobs that have already concluded, remove them from the block-job-query
+# list. This command only needs to be run for jobs which were started with
+# QEMU 2.12+ job lifetime management semantics.
+#
+# This command will refuse to operate on any job that has not yet reached
+# its terminal state, JOB_STATUS_CONCLUDED. For jobs that make use of the
+# BLOCK_JOB_READY event, block-job-cancel or block-job-complete will still need
+# to be used as appropriate.
+#
+# @id: The job identifier.
+#
+# Returns: Nothing on success
+#
+# Since: 2.12
+##
+{ 'command': 'block-job-dismiss', 'data': { 'id': 'str' } }
+
+##
+# @block-job-finalize:
+#
+# Once a job that has manual=true reaches the pending state, it can be
+# instructed to finalize any graph changes and do any necessary cleanup
+# via this command.
+# For jobs in a transaction, instructing one job to finalize will force
+# ALL jobs in the transaction to finalize, so it is only necessary to instruct
+# a single member job to finalize.
+#
+# @id: The job identifier.
+#
+# Returns: Nothing on success
+#
+# Since: 2.12
+##
+{ 'command': 'block-job-finalize', 'data': { 'id': 'str' } }
+
+##
+# @BlockdevDiscardOptions:
+#
+# Determines how to handle discard requests.
+#
+# @ignore: Ignore the request
+# @unmap: Forward as an unmap request
+#
+# Since: 2.9
+##
+{ 'enum': 'BlockdevDiscardOptions',
+ 'data': [ 'ignore', 'unmap' ] }
+
+##
+# @BlockdevDetectZeroesOptions:
+#
+# Describes the operation mode for the automatic conversion of plain
+# zero writes by the OS to driver specific optimized zero write commands.
+#
+# @off: Disabled (default)
+# @on: Enabled
+# @unmap: Enabled and even try to unmap blocks if possible. This requires
+# also that @BlockdevDiscardOptions is set to unmap for this device.
+#
+# Since: 2.1
+##
+{ 'enum': 'BlockdevDetectZeroesOptions',
+ 'data': [ 'off', 'on', 'unmap' ] }
+
+##
+# @BlockdevAioOptions:
+#
+# Selects the AIO backend to handle I/O requests
+#
+# @threads: Use qemu's thread pool
+# @native: Use native AIO backend (only Linux and Windows)
+# @io_uring: Use linux io_uring (since 5.0)
+#
+# Since: 2.9
+##
+{ 'enum': 'BlockdevAioOptions',
+ 'data': [ 'threads', 'native',
+ { 'name': 'io_uring', 'if': 'CONFIG_LINUX_IO_URING' } ] }
+
+##
+# @BlockdevCacheOptions:
+#
+# Includes cache-related options for block devices
+#
+# @direct: enables use of O_DIRECT (bypass the host page cache;
+# default: false)
+# @no-flush: ignore any flush requests for the device (default:
+# false)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevCacheOptions',
+ 'data': { '*direct': 'bool',
+ '*no-flush': 'bool' } }
+
+##
+# @BlockdevDriver:
+#
+# Drivers that are supported in block device operations.
+#
+# @throttle: Since 2.11
+# @nvme: Since 2.12
+# @copy-on-read: Since 3.0
+# @blklogwrites: Since 3.0
+# @blkreplay: Since 4.2
+# @compress: Since 5.0
+# @copy-before-write: Since 6.2
+#
+# Since: 2.9
+##
+{ 'enum': 'BlockdevDriver',
+ 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
+ 'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg',
+ 'file', 'ftp', 'ftps', 'gluster',
+ {'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
+ {'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
+ 'http', 'https', 'iscsi',
+ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
+ 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ { 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
+ 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
+
+##
+# @BlockdevOptionsFile:
+#
+# Driver specific block device options for the file backend.
+#
+# @filename: path to the image file
+# @pr-manager: the id for the object that will handle persistent reservations
+# for this device (default: none, forward the commands via SG_IO;
+# since 2.11)
+# @aio: AIO backend (default: threads) (since: 2.8)
+# @aio-max-batch: maximum number of requests to batch together into a single
+# submission in the AIO backend. The smallest value between
+# this and the aio-max-batch value of the IOThread object is
+# chosen.
+# 0 means that the AIO backend will handle it automatically.
+# (default: 0, since 6.2)
+# @locking: whether to enable file locking. If set to 'auto', only enable
+# when Open File Descriptor (OFD) locking API is available
+# (default: auto, since 2.10)
+# @drop-cache: invalidate page cache during live migration. This prevents
+# stale data on the migration destination with cache.direct=off.
+# Currently only supported on Linux hosts.
+# (default: on, since: 4.0)
+# @x-check-cache-dropped: whether to check that page cache was dropped on live
+# migration. May cause noticeable delays if the image
+# file is large, do not use in production.
+# (default: off) (since: 3.0)
+#
+# Features:
+# @dynamic-auto-read-only: If present, enabled auto-read-only means that the
+# driver will open the image read-only at first,
+# dynamically reopen the image file read-write when
+# the first writer is attached to the node and reopen
+# read-only when the last writer is detached. This
+# allows giving QEMU write permissions only on demand
+# when an operation actually needs write access.
+# @unstable: Member x-check-cache-dropped is meant for debugging.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsFile',
+ 'data': { 'filename': 'str',
+ '*pr-manager': 'str',
+ '*locking': 'OnOffAuto',
+ '*aio': 'BlockdevAioOptions',
+ '*aio-max-batch': 'int',
+ '*drop-cache': {'type': 'bool',
+ 'if': 'CONFIG_LINUX'},
+ '*x-check-cache-dropped': { 'type': 'bool',
+ 'features': [ 'unstable' ] } },
+ 'features': [ { 'name': 'dynamic-auto-read-only',
+ 'if': 'CONFIG_POSIX' } ] }
+
+##
+# @BlockdevOptionsNull:
+#
+# Driver specific block device options for the null backend.
+#
+# @size: size of the device in bytes.
+# @latency-ns: emulated latency (in nanoseconds) in processing
+# requests. Default to zero which completes requests immediately.
+# (Since 2.4)
+# @read-zeroes: if true, reads from the device produce zeroes; if false, the
+# buffer is left unchanged. (default: false; since: 4.1)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsNull',
+ 'data': { '*size': 'int', '*latency-ns': 'uint64', '*read-zeroes': 'bool' } }
+
+##
+# @BlockdevOptionsNVMe:
+#
+# Driver specific block device options for the NVMe backend.
+#
+# @device: PCI controller address of the NVMe device in
+# format hhhh:bb:ss.f (host:bus:slot.function)
+# @namespace: namespace number of the device, starting from 1.
+#
+# Note that the PCI @device must have been unbound from any host
+# kernel driver before instructing QEMU to add the blockdev.
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevOptionsNVMe',
+ 'data': { 'device': 'str', 'namespace': 'int' } }
+
+##
+# @BlockdevOptionsVVFAT:
+#
+# Driver specific block device options for the vvfat protocol.
+#
+# @dir: directory to be exported as FAT image
+# @fat-type: FAT type: 12, 16 or 32
+# @floppy: whether to export a floppy image (true) or
+# partitioned hard disk (false; default)
+# @label: set the volume label, limited to 11 bytes. FAT16 and
+# FAT32 traditionally have some restrictions on labels, which are
+# ignored by most operating systems. Defaults to "QEMU VVFAT".
+# (since 2.4)
+# @rw: whether to allow write operations (default: false)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsVVFAT',
+ 'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool',
+ '*label': 'str', '*rw': 'bool' } }
+
+##
+# @BlockdevOptionsGenericFormat:
+#
+# Driver specific block device options for image format that have no option
+# besides their data source.
+#
+# @file: reference to or definition of the data source block device
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsGenericFormat',
+ 'data': { 'file': 'BlockdevRef' } }
+
+##
+# @BlockdevOptionsLUKS:
+#
+# Driver specific block device options for LUKS.
+#
+# @key-secret: the ID of a QCryptoSecret object providing
+# the decryption key (since 2.6). Mandatory except when
+# doing a metadata-only probe of the image.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsLUKS',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*key-secret': 'str' } }
+
+
+##
+# @BlockdevOptionsGenericCOWFormat:
+#
+# Driver specific block device options for image format that have no option
+# besides their data source and an optional backing file.
+#
+# @backing: reference to or definition of the backing file block
+# device, null disables the backing file entirely.
+# Defaults to the backing file stored the image file.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsGenericCOWFormat',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*backing': 'BlockdevRefOrNull' } }
+
+##
+# @Qcow2OverlapCheckMode:
+#
+# General overlap check modes.
+#
+# @none: Do not perform any checks
+#
+# @constant: Perform only checks which can be done in constant time and
+# without reading anything from disk
+#
+# @cached: Perform only checks which can be done without reading anything
+# from disk
+#
+# @all: Perform all available overlap checks
+#
+# Since: 2.9
+##
+{ 'enum': 'Qcow2OverlapCheckMode',
+ 'data': [ 'none', 'constant', 'cached', 'all' ] }
+
+##
+# @Qcow2OverlapCheckFlags:
+#
+# Structure of flags for each metadata structure. Setting a field to 'true'
+# makes qemu guard that structure against unintended overwriting. The default
+# value is chosen according to the template given.
+#
+# @template: Specifies a template mode which can be adjusted using the other
+# flags, defaults to 'cached'
+#
+# @bitmap-directory: since 3.0
+#
+# Since: 2.9
+##
+{ 'struct': 'Qcow2OverlapCheckFlags',
+ 'data': { '*template': 'Qcow2OverlapCheckMode',
+ '*main-header': 'bool',
+ '*active-l1': 'bool',
+ '*active-l2': 'bool',
+ '*refcount-table': 'bool',
+ '*refcount-block': 'bool',
+ '*snapshot-table': 'bool',
+ '*inactive-l1': 'bool',
+ '*inactive-l2': 'bool',
+ '*bitmap-directory': 'bool' } }
+
+##
+# @Qcow2OverlapChecks:
+#
+# Specifies which metadata structures should be guarded against unintended
+# overwriting.
+#
+# @flags: set of flags for separate specification of each metadata structure
+# type
+#
+# @mode: named mode which chooses a specific set of flags
+#
+# Since: 2.9
+##
+{ 'alternate': 'Qcow2OverlapChecks',
+ 'data': { 'flags': 'Qcow2OverlapCheckFlags',
+ 'mode': 'Qcow2OverlapCheckMode' } }
+
+##
+# @BlockdevQcowEncryptionFormat:
+#
+# @aes: AES-CBC with plain64 initialization vectors
+#
+# Since: 2.10
+##
+{ 'enum': 'BlockdevQcowEncryptionFormat',
+ 'data': [ 'aes' ] }
+
+##
+# @BlockdevQcowEncryption:
+#
+# Since: 2.10
+##
+{ 'union': 'BlockdevQcowEncryption',
+ 'base': { 'format': 'BlockdevQcowEncryptionFormat' },
+ 'discriminator': 'format',
+ 'data': { 'aes': 'QCryptoBlockOptionsQCow' } }
+
+##
+# @BlockdevOptionsQcow:
+#
+# Driver specific block device options for qcow.
+#
+# @encrypt: Image decryption options. Mandatory for
+# encrypted images, except when doing a metadata-only
+# probe of the image.
+#
+# Since: 2.10
+##
+{ 'struct': 'BlockdevOptionsQcow',
+ 'base': 'BlockdevOptionsGenericCOWFormat',
+ 'data': { '*encrypt': 'BlockdevQcowEncryption' } }
+
+
+
+##
+# @BlockdevQcow2EncryptionFormat:
+#
+# @aes: AES-CBC with plain64 initialization vectors
+#
+# Since: 2.10
+##
+{ 'enum': 'BlockdevQcow2EncryptionFormat',
+ 'data': [ 'aes', 'luks' ] }
+
+##
+# @BlockdevQcow2Encryption:
+#
+# Since: 2.10
+##
+{ 'union': 'BlockdevQcow2Encryption',
+ 'base': { 'format': 'BlockdevQcow2EncryptionFormat' },
+ 'discriminator': 'format',
+ 'data': { 'aes': 'QCryptoBlockOptionsQCow',
+ 'luks': 'QCryptoBlockOptionsLUKS'} }
+
+##
+# @BlockdevOptionsPreallocate:
+#
+# Filter driver intended to be inserted between format and protocol node
+# and do preallocation in protocol node on write.
+#
+# @prealloc-align: on preallocation, align file length to this number,
+# default 1048576 (1M)
+#
+# @prealloc-size: how much to preallocate, default 134217728 (128M)
+#
+# Since: 6.0
+##
+{ 'struct': 'BlockdevOptionsPreallocate',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*prealloc-align': 'int', '*prealloc-size': 'int' } }
+
+##
+# @BlockdevOptionsQcow2:
+#
+# Driver specific block device options for qcow2.
+#
+# @lazy-refcounts: whether to enable the lazy refcounts
+# feature (default is taken from the image file)
+#
+# @pass-discard-request: whether discard requests to the qcow2
+# device should be forwarded to the data source
+#
+# @pass-discard-snapshot: whether discard requests for the data source
+# should be issued when a snapshot operation (e.g.
+# deleting a snapshot) frees clusters in the qcow2 file
+#
+# @pass-discard-other: whether discard requests for the data source
+# should be issued on other occasions where a cluster
+# gets freed
+#
+# @overlap-check: which overlap checks to perform for writes
+# to the image, defaults to 'cached' (since 2.2)
+#
+# @cache-size: the maximum total size of the L2 table and
+# refcount block caches in bytes (since 2.2)
+#
+# @l2-cache-size: the maximum size of the L2 table cache in
+# bytes (since 2.2)
+#
+# @l2-cache-entry-size: the size of each entry in the L2 cache in
+# bytes. It must be a power of two between 512
+# and the cluster size. The default value is
+# the cluster size (since 2.12)
+#
+# @refcount-cache-size: the maximum size of the refcount block cache
+# in bytes (since 2.2)
+#
+# @cache-clean-interval: clean unused entries in the L2 and refcount
+# caches. The interval is in seconds. The default value
+# is 600 on supporting platforms, and 0 on other
+# platforms. 0 disables this feature. (since 2.5)
+#
+# @encrypt: Image decryption options. Mandatory for
+# encrypted images, except when doing a metadata-only
+# probe of the image. (since 2.10)
+#
+# @data-file: reference to or definition of the external data file.
+# This may only be specified for images that require an
+# external data file. If it is not specified for such
+# an image, the data file name is loaded from the image
+# file. (since 4.0)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsQcow2',
+ 'base': 'BlockdevOptionsGenericCOWFormat',
+ 'data': { '*lazy-refcounts': 'bool',
+ '*pass-discard-request': 'bool',
+ '*pass-discard-snapshot': 'bool',
+ '*pass-discard-other': 'bool',
+ '*overlap-check': 'Qcow2OverlapChecks',
+ '*cache-size': 'int',
+ '*l2-cache-size': 'int',
+ '*l2-cache-entry-size': 'int',
+ '*refcount-cache-size': 'int',
+ '*cache-clean-interval': 'int',
+ '*encrypt': 'BlockdevQcow2Encryption',
+ '*data-file': 'BlockdevRef' } }
+
+##
+# @SshHostKeyCheckMode:
+#
+# @none: Don't check the host key at all
+# @hash: Compare the host key with a given hash
+# @known_hosts: Check the host key against the known_hosts file
+#
+# Since: 2.12
+##
+{ 'enum': 'SshHostKeyCheckMode',
+ 'data': [ 'none', 'hash', 'known_hosts' ] }
+
+##
+# @SshHostKeyCheckHashType:
+#
+# @md5: The given hash is an md5 hash
+# @sha1: The given hash is an sha1 hash
+# @sha256: The given hash is an sha256 hash
+#
+# Since: 2.12
+##
+{ 'enum': 'SshHostKeyCheckHashType',
+ 'data': [ 'md5', 'sha1', 'sha256' ] }
+
+##
+# @SshHostKeyHash:
+#
+# @type: The hash algorithm used for the hash
+# @hash: The expected hash value
+#
+# Since: 2.12
+##
+{ 'struct': 'SshHostKeyHash',
+ 'data': { 'type': 'SshHostKeyCheckHashType',
+ 'hash': 'str' }}
+
+##
+# @SshHostKeyCheck:
+#
+# Since: 2.12
+##
+{ 'union': 'SshHostKeyCheck',
+ 'base': { 'mode': 'SshHostKeyCheckMode' },
+ 'discriminator': 'mode',
+ 'data': { 'hash': 'SshHostKeyHash' } }
+
+##
+# @BlockdevOptionsSsh:
+#
+# @server: host address
+#
+# @path: path to the image on the host
+#
+# @user: user as which to connect, defaults to current
+# local user name
+#
+# @host-key-check: Defines how and what to check the host key against
+# (default: known_hosts)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsSsh',
+ 'data': { 'server': 'InetSocketAddress',
+ 'path': 'str',
+ '*user': 'str',
+ '*host-key-check': 'SshHostKeyCheck' } }
+
+
+##
+# @BlkdebugEvent:
+#
+# Trigger events supported by blkdebug.
+#
+# @l1_shrink_write_table: write zeros to the l1 table to shrink image.
+# (since 2.11)
+#
+# @l1_shrink_free_l2_clusters: discard the l2 tables. (since 2.11)
+#
+# @cor_write: a write due to copy-on-read (since 2.11)
+#
+# @cluster_alloc_space: an allocation of file space for a cluster (since 4.1)
+#
+# @none: triggers once at creation of the blkdebug node (since 4.1)
+#
+# Since: 2.9
+##
+{ 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG',
+ 'data': [ 'l1_update', 'l1_grow_alloc_table', 'l1_grow_write_table',
+ 'l1_grow_activate_table', 'l2_load', 'l2_update',
+ 'l2_update_compressed', 'l2_alloc_cow_read', 'l2_alloc_write',
+ 'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
+ 'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
+ 'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
+ 'refblock_load', 'refblock_update', 'refblock_update_part',
+ 'refblock_alloc', 'refblock_alloc_hookup', 'refblock_alloc_write',
+ 'refblock_alloc_write_blocks', 'refblock_alloc_write_table',
+ 'refblock_alloc_switch_table', 'cluster_alloc',
+ 'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
+ 'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head',
+ 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev',
+ 'pwritev_zero', 'pwritev_done', 'empty_image_prepare',
+ 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters',
+ 'cor_write', 'cluster_alloc_space', 'none'] }
+
+##
+# @BlkdebugIOType:
+#
+# Kinds of I/O that blkdebug can inject errors in.
+#
+# @read: .bdrv_co_preadv()
+#
+# @write: .bdrv_co_pwritev()
+#
+# @write-zeroes: .bdrv_co_pwrite_zeroes()
+#
+# @discard: .bdrv_co_pdiscard()
+#
+# @flush: .bdrv_co_flush_to_disk()
+#
+# @block-status: .bdrv_co_block_status()
+#
+# Since: 4.1
+##
+{ 'enum': 'BlkdebugIOType', 'prefix': 'BLKDEBUG_IO_TYPE',
+ 'data': [ 'read', 'write', 'write-zeroes', 'discard', 'flush',
+ 'block-status' ] }
+
+##
+# @BlkdebugInjectErrorOptions:
+#
+# Describes a single error injection for blkdebug.
+#
+# @event: trigger event
+#
+# @state: the state identifier blkdebug needs to be in to
+# actually trigger the event; defaults to "any"
+#
+# @iotype: the type of I/O operations on which this error should
+# be injected; defaults to "all read, write,
+# write-zeroes, discard, and flush operations"
+# (since: 4.1)
+#
+# @errno: error identifier (errno) to be returned; defaults to
+# EIO
+#
+# @sector: specifies the sector index which has to be affected
+# in order to actually trigger the event; defaults to "any
+# sector"
+#
+# @once: disables further events after this one has been
+# triggered; defaults to false
+#
+# @immediately: fail immediately; defaults to false
+#
+# Since: 2.9
+##
+{ 'struct': 'BlkdebugInjectErrorOptions',
+ 'data': { 'event': 'BlkdebugEvent',
+ '*state': 'int',
+ '*iotype': 'BlkdebugIOType',
+ '*errno': 'int',
+ '*sector': 'int',
+ '*once': 'bool',
+ '*immediately': 'bool' } }
+
+##
+# @BlkdebugSetStateOptions:
+#
+# Describes a single state-change event for blkdebug.
+#
+# @event: trigger event
+#
+# @state: the current state identifier blkdebug needs to be in;
+# defaults to "any"
+#
+# @new_state: the state identifier blkdebug is supposed to assume if
+# this event is triggered
+#
+# Since: 2.9
+##
+{ 'struct': 'BlkdebugSetStateOptions',
+ 'data': { 'event': 'BlkdebugEvent',
+ '*state': 'int',
+ 'new_state': 'int' } }
+
+##
+# @BlockdevOptionsBlkdebug:
+#
+# Driver specific block device options for blkdebug.
+#
+# @image: underlying raw block device (or image file)
+#
+# @config: filename of the configuration file
+#
+# @align: required alignment for requests in bytes, must be
+# positive power of 2, or 0 for default
+#
+# @max-transfer: maximum size for I/O transfers in bytes, must be
+# positive multiple of @align and of the underlying
+# file's request alignment (but need not be a power of
+# 2), or 0 for default (since 2.10)
+#
+# @opt-write-zero: preferred alignment for write zero requests in bytes,
+# must be positive multiple of @align and of the
+# underlying file's request alignment (but need not be a
+# power of 2), or 0 for default (since 2.10)
+#
+# @max-write-zero: maximum size for write zero requests in bytes, must be
+# positive multiple of @align, of @opt-write-zero, and of
+# the underlying file's request alignment (but need not
+# be a power of 2), or 0 for default (since 2.10)
+#
+# @opt-discard: preferred alignment for discard requests in bytes, must
+# be positive multiple of @align and of the underlying
+# file's request alignment (but need not be a power of
+# 2), or 0 for default (since 2.10)
+#
+# @max-discard: maximum size for discard requests in bytes, must be
+# positive multiple of @align, of @opt-discard, and of
+# the underlying file's request alignment (but need not
+# be a power of 2), or 0 for default (since 2.10)
+#
+# @inject-error: array of error injection descriptions
+#
+# @set-state: array of state-change descriptions
+#
+# @take-child-perms: Permissions to take on @image in addition to what
+# is necessary anyway (which depends on how the
+# blkdebug node is used). Defaults to none.
+# (since 5.0)
+#
+# @unshare-child-perms: Permissions not to share on @image in addition
+# to what cannot be shared anyway (which depends
+# on how the blkdebug node is used). Defaults
+# to none. (since 5.0)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsBlkdebug',
+ 'data': { 'image': 'BlockdevRef',
+ '*config': 'str',
+ '*align': 'int', '*max-transfer': 'int32',
+ '*opt-write-zero': 'int32', '*max-write-zero': 'int32',
+ '*opt-discard': 'int32', '*max-discard': 'int32',
+ '*inject-error': ['BlkdebugInjectErrorOptions'],
+ '*set-state': ['BlkdebugSetStateOptions'],
+ '*take-child-perms': ['BlockPermission'],
+ '*unshare-child-perms': ['BlockPermission'] } }
+
+##
+# @BlockdevOptionsBlklogwrites:
+#
+# Driver specific block device options for blklogwrites.
+#
+# @file: block device
+#
+# @log: block device used to log writes to @file
+#
+# @log-sector-size: sector size used in logging writes to @file, determines
+# granularity of offsets and sizes of writes (default: 512)
+#
+# @log-append: append to an existing log (default: false)
+#
+# @log-super-update-interval: interval of write requests after which the log
+# super block is updated to disk (default: 4096)
+#
+# Since: 3.0
+##
+{ 'struct': 'BlockdevOptionsBlklogwrites',
+ 'data': { 'file': 'BlockdevRef',
+ 'log': 'BlockdevRef',
+ '*log-sector-size': 'uint32',
+ '*log-append': 'bool',
+ '*log-super-update-interval': 'uint64' } }
+
+##
+# @BlockdevOptionsBlkverify:
+#
+# Driver specific block device options for blkverify.
+#
+# @test: block device to be tested
+#
+# @raw: raw image used for verification
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsBlkverify',
+ 'data': { 'test': 'BlockdevRef',
+ 'raw': 'BlockdevRef' } }
+
+##
+# @BlockdevOptionsBlkreplay:
+#
+# Driver specific block device options for blkreplay.
+#
+# @image: disk image which should be controlled with blkreplay
+#
+# Since: 4.2
+##
+{ 'struct': 'BlockdevOptionsBlkreplay',
+ 'data': { 'image': 'BlockdevRef' } }
+
+##
+# @QuorumReadPattern:
+#
+# An enumeration of quorum read patterns.
+#
+# @quorum: read all the children and do a quorum vote on reads
+#
+# @fifo: read only from the first child that has not failed
+#
+# Since: 2.9
+##
+{ 'enum': 'QuorumReadPattern', 'data': [ 'quorum', 'fifo' ] }
+
+##
+# @BlockdevOptionsQuorum:
+#
+# Driver specific block device options for Quorum
+#
+# @blkverify: true if the driver must print content mismatch
+# set to false by default
+#
+# @children: the children block devices to use
+#
+# @vote-threshold: the vote limit under which a read will fail
+#
+# @rewrite-corrupted: rewrite corrupted data when quorum is reached
+# (Since 2.1)
+#
+# @read-pattern: choose read pattern and set to quorum by default
+# (Since 2.2)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsQuorum',
+ 'data': { '*blkverify': 'bool',
+ 'children': [ 'BlockdevRef' ],
+ 'vote-threshold': 'int',
+ '*rewrite-corrupted': 'bool',
+ '*read-pattern': 'QuorumReadPattern' } }
+
+##
+# @BlockdevOptionsGluster:
+#
+# Driver specific block device options for Gluster
+#
+# @volume: name of gluster volume where VM image resides
+#
+# @path: absolute path to image file in gluster volume
+#
+# @server: gluster servers description
+#
+# @debug: libgfapi log level (default '4' which is Error)
+# (Since 2.8)
+#
+# @logfile: libgfapi log file (default /dev/stderr) (Since 2.8)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsGluster',
+ 'data': { 'volume': 'str',
+ 'path': 'str',
+ 'server': ['SocketAddress'],
+ '*debug': 'int',
+ '*logfile': 'str' } }
+
+##
+# @IscsiTransport:
+#
+# An enumeration of libiscsi transport types
+#
+# Since: 2.9
+##
+{ 'enum': 'IscsiTransport',
+ 'data': [ 'tcp', 'iser' ] }
+
+##
+# @IscsiHeaderDigest:
+#
+# An enumeration of header digests supported by libiscsi
+#
+# Since: 2.9
+##
+{ 'enum': 'IscsiHeaderDigest',
+ 'prefix': 'QAPI_ISCSI_HEADER_DIGEST',
+ 'data': [ 'crc32c', 'none', 'crc32c-none', 'none-crc32c' ] }
+
+##
+# @BlockdevOptionsIscsi:
+#
+# @transport: The iscsi transport type
+#
+# @portal: The address of the iscsi portal
+#
+# @target: The target iqn name
+#
+# @lun: LUN to connect to. Defaults to 0.
+#
+# @user: User name to log in with. If omitted, no CHAP
+# authentication is performed.
+#
+# @password-secret: The ID of a QCryptoSecret object providing
+# the password for the login. This option is required if
+# @user is specified.
+#
+# @initiator-name: The iqn name we want to identify to the target
+# as. If this option is not specified, an initiator name is
+# generated automatically.
+#
+# @header-digest: The desired header digest. Defaults to
+# none-crc32c.
+#
+# @timeout: Timeout in seconds after which a request will
+# timeout. 0 means no timeout and is the default.
+#
+# Driver specific block device options for iscsi
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsIscsi',
+ 'data': { 'transport': 'IscsiTransport',
+ 'portal': 'str',
+ 'target': 'str',
+ '*lun': 'int',
+ '*user': 'str',
+ '*password-secret': 'str',
+ '*initiator-name': 'str',
+ '*header-digest': 'IscsiHeaderDigest',
+ '*timeout': 'int' } }
+
+
+##
+# @RbdAuthMode:
+#
+# Since: 3.0
+##
+{ 'enum': 'RbdAuthMode',
+ 'data': [ 'cephx', 'none' ] }
+
+##
+# @RbdImageEncryptionFormat:
+#
+# Since: 6.1
+##
+{ 'enum': 'RbdImageEncryptionFormat',
+ 'data': [ 'luks', 'luks2' ] }
+
+##
+# @RbdEncryptionOptionsLUKSBase:
+#
+# @key-secret: ID of a QCryptoSecret object providing a passphrase
+# for unlocking the encryption
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionOptionsLUKSBase',
+ 'data': { 'key-secret': 'str' } }
+
+##
+# @RbdEncryptionCreateOptionsLUKSBase:
+#
+# @cipher-alg: The encryption algorithm
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionCreateOptionsLUKSBase',
+ 'base': 'RbdEncryptionOptionsLUKSBase',
+ 'data': { '*cipher-alg': 'QCryptoCipherAlgorithm' } }
+
+##
+# @RbdEncryptionOptionsLUKS:
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionOptionsLUKS',
+ 'base': 'RbdEncryptionOptionsLUKSBase',
+ 'data': { } }
+
+##
+# @RbdEncryptionOptionsLUKS2:
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionOptionsLUKS2',
+ 'base': 'RbdEncryptionOptionsLUKSBase',
+ 'data': { } }
+
+##
+# @RbdEncryptionCreateOptionsLUKS:
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionCreateOptionsLUKS',
+ 'base': 'RbdEncryptionCreateOptionsLUKSBase',
+ 'data': { } }
+
+##
+# @RbdEncryptionCreateOptionsLUKS2:
+#
+# Since: 6.1
+##
+{ 'struct': 'RbdEncryptionCreateOptionsLUKS2',
+ 'base': 'RbdEncryptionCreateOptionsLUKSBase',
+ 'data': { } }
+
+##
+# @RbdEncryptionOptions:
+#
+# Since: 6.1
+##
+{ 'union': 'RbdEncryptionOptions',
+ 'base': { 'format': 'RbdImageEncryptionFormat' },
+ 'discriminator': 'format',
+ 'data': { 'luks': 'RbdEncryptionOptionsLUKS',
+ 'luks2': 'RbdEncryptionOptionsLUKS2' } }
+
+##
+# @RbdEncryptionCreateOptions:
+#
+# Since: 6.1
+##
+{ 'union': 'RbdEncryptionCreateOptions',
+ 'base': { 'format': 'RbdImageEncryptionFormat' },
+ 'discriminator': 'format',
+ 'data': { 'luks': 'RbdEncryptionCreateOptionsLUKS',
+ 'luks2': 'RbdEncryptionCreateOptionsLUKS2' } }
+
+##
+# @BlockdevOptionsRbd:
+#
+# @pool: Ceph pool name.
+#
+# @namespace: Rados namespace name in the Ceph pool. (Since 5.0)
+#
+# @image: Image name in the Ceph pool.
+#
+# @conf: path to Ceph configuration file. Values
+# in the configuration file will be overridden by
+# options specified via QAPI.
+#
+# @snapshot: Ceph snapshot name.
+#
+# @encrypt: Image encryption options. (Since 6.1)
+#
+# @user: Ceph id name.
+#
+# @auth-client-required: Acceptable authentication modes.
+# This maps to Ceph configuration option
+# "auth_client_required". (Since 3.0)
+#
+# @key-secret: ID of a QCryptoSecret object providing a key
+# for cephx authentication.
+# This maps to Ceph configuration option
+# "key". (Since 3.0)
+#
+# @server: Monitor host address and port. This maps
+# to the "mon_host" Ceph option.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsRbd',
+ 'data': { 'pool': 'str',
+ '*namespace': 'str',
+ 'image': 'str',
+ '*conf': 'str',
+ '*snapshot': 'str',
+ '*encrypt': 'RbdEncryptionOptions',
+ '*user': 'str',
+ '*auth-client-required': ['RbdAuthMode'],
+ '*key-secret': 'str',
+ '*server': ['InetSocketAddressBase'] } }
+
+##
+# @ReplicationMode:
+#
+# An enumeration of replication modes.
+#
+# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
+#
+# @secondary: Secondary mode, receive the vm's state from primary QEMU.
+#
+# Since: 2.9
+##
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @BlockdevOptionsReplication:
+#
+# Driver specific block device options for replication
+#
+# @mode: the replication mode
+#
+# @top-id: In secondary mode, node name or device ID of the root
+# node who owns the replication node chain. Must not be given in
+# primary mode.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsReplication',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { 'mode': 'ReplicationMode',
+ '*top-id': 'str' },
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @NFSTransport:
+#
+# An enumeration of NFS transport types
+#
+# @inet: TCP transport
+#
+# Since: 2.9
+##
+{ 'enum': 'NFSTransport',
+ 'data': [ 'inet' ] }
+
+##
+# @NFSServer:
+#
+# Captures the address of the socket
+#
+# @type: transport type used for NFS (only TCP supported)
+#
+# @host: host address for NFS server
+#
+# Since: 2.9
+##
+{ 'struct': 'NFSServer',
+ 'data': { 'type': 'NFSTransport',
+ 'host': 'str' } }
+
+##
+# @BlockdevOptionsNfs:
+#
+# Driver specific block device option for NFS
+#
+# @server: host address
+#
+# @path: path of the image on the host
+#
+# @user: UID value to use when talking to the
+# server (defaults to 65534 on Windows and getuid()
+# on unix)
+#
+# @group: GID value to use when talking to the
+# server (defaults to 65534 on Windows and getgid()
+# in unix)
+#
+# @tcp-syn-count: number of SYNs during the session
+# establishment (defaults to libnfs default)
+#
+# @readahead-size: set the readahead size in bytes (defaults
+# to libnfs default)
+#
+# @page-cache-size: set the pagecache size in bytes (defaults
+# to libnfs default)
+#
+# @debug: set the NFS debug level (max 2) (defaults
+# to libnfs default)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsNfs',
+ 'data': { 'server': 'NFSServer',
+ 'path': 'str',
+ '*user': 'int',
+ '*group': 'int',
+ '*tcp-syn-count': 'int',
+ '*readahead-size': 'int',
+ '*page-cache-size': 'int',
+ '*debug': 'int' } }
+
+##
+# @BlockdevOptionsCurlBase:
+#
+# Driver specific block device options shared by all protocols supported by the
+# curl backend.
+#
+# @url: URL of the image file
+#
+# @readahead: Size of the read-ahead cache; must be a multiple of
+# 512 (defaults to 256 kB)
+#
+# @timeout: Timeout for connections, in seconds (defaults to 5)
+#
+# @username: Username for authentication (defaults to none)
+#
+# @password-secret: ID of a QCryptoSecret object providing a password
+# for authentication (defaults to no password)
+#
+# @proxy-username: Username for proxy authentication (defaults to none)
+#
+# @proxy-password-secret: ID of a QCryptoSecret object providing a password
+# for proxy authentication (defaults to no password)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsCurlBase',
+ 'data': { 'url': 'str',
+ '*readahead': 'int',
+ '*timeout': 'int',
+ '*username': 'str',
+ '*password-secret': 'str',
+ '*proxy-username': 'str',
+ '*proxy-password-secret': 'str' } }
+
+##
+# @BlockdevOptionsCurlHttp:
+#
+# Driver specific block device options for HTTP connections over the curl
+# backend. URLs must start with "http://".
+#
+# @cookie: List of cookies to set; format is
+# "name1=content1; name2=content2;" as explained by
+# CURLOPT_COOKIE(3). Defaults to no cookies.
+#
+# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a
+# secure way. See @cookie for the format. (since 2.10)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsCurlHttp',
+ 'base': 'BlockdevOptionsCurlBase',
+ 'data': { '*cookie': 'str',
+ '*cookie-secret': 'str'} }
+
+##
+# @BlockdevOptionsCurlHttps:
+#
+# Driver specific block device options for HTTPS connections over the curl
+# backend. URLs must start with "https://".
+#
+# @cookie: List of cookies to set; format is
+# "name1=content1; name2=content2;" as explained by
+# CURLOPT_COOKIE(3). Defaults to no cookies.
+#
+# @sslverify: Whether to verify the SSL certificate's validity (defaults to
+# true)
+#
+# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a
+# secure way. See @cookie for the format. (since 2.10)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsCurlHttps',
+ 'base': 'BlockdevOptionsCurlBase',
+ 'data': { '*cookie': 'str',
+ '*sslverify': 'bool',
+ '*cookie-secret': 'str'} }
+
+##
+# @BlockdevOptionsCurlFtp:
+#
+# Driver specific block device options for FTP connections over the curl
+# backend. URLs must start with "ftp://".
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsCurlFtp',
+ 'base': 'BlockdevOptionsCurlBase',
+ 'data': { } }
+
+##
+# @BlockdevOptionsCurlFtps:
+#
+# Driver specific block device options for FTPS connections over the curl
+# backend. URLs must start with "ftps://".
+#
+# @sslverify: Whether to verify the SSL certificate's validity (defaults to
+# true)
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsCurlFtps',
+ 'base': 'BlockdevOptionsCurlBase',
+ 'data': { '*sslverify': 'bool' } }
+
+##
+# @BlockdevOptionsNbd:
+#
+# Driver specific block device options for NBD.
+#
+# @server: NBD server address
+#
+# @export: export name
+#
+# @tls-creds: TLS credentials ID
+#
+# @x-dirty-bitmap: A metadata context name such as "qemu:dirty-bitmap:NAME"
+# or "qemu:allocation-depth" to query in place of the
+# traditional "base:allocation" block status (see
+# NBD_OPT_LIST_META_CONTEXT in the NBD protocol; and
+# yes, naming this option x-context would have made
+# more sense) (since 3.0)
+#
+# @reconnect-delay: On an unexpected disconnect, the nbd client tries to
+# connect again until succeeding or encountering a serious
+# error. During the first @reconnect-delay seconds, all
+# requests are paused and will be rerun on a successful
+# reconnect. After that time, any delayed requests and all
+# future requests before a successful reconnect will
+# immediately fail. Default 0 (Since 4.2)
+#
+# Features:
+# @unstable: Member @x-dirty-bitmap is experimental.
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsNbd',
+ 'data': { 'server': 'SocketAddress',
+ '*export': 'str',
+ '*tls-creds': 'str',
+ '*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] },
+ '*reconnect-delay': 'uint32' } }
+
+##
+# @BlockdevOptionsRaw:
+#
+# Driver specific block device options for the raw driver.
+#
+# @offset: position where the block device starts
+# @size: the assumed size of the device
+#
+# Since: 2.9
+##
+{ 'struct': 'BlockdevOptionsRaw',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*offset': 'int', '*size': 'int' } }
+
+##
+# @BlockdevOptionsThrottle:
+#
+# Driver specific block device options for the throttle driver
+#
+# @throttle-group: the name of the throttle-group object to use. It
+# must already exist.
+# @file: reference to or definition of the data source block device
+# Since: 2.11
+##
+{ 'struct': 'BlockdevOptionsThrottle',
+ 'data': { 'throttle-group': 'str',
+ 'file' : 'BlockdevRef'
+ } }
+
+##
+# @BlockdevOptionsCor:
+#
+# Driver specific block device options for the copy-on-read driver.
+#
+# @bottom: The name of a non-filter node (allocation-bearing layer) that
+# limits the COR operations in the backing chain (inclusive), so
+# that no data below this node will be copied by this filter.
+# If option is absent, the limit is not applied, so that data
+# from all backing layers may be copied.
+#
+# Since: 6.0
+##
+{ 'struct': 'BlockdevOptionsCor',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*bottom': 'str' } }
+
+##
+# @BlockdevOptionsCbw:
+#
+# Driver specific block device options for the copy-before-write driver,
+# which does so called copy-before-write operations: when data is
+# written to the filter, the filter first reads corresponding blocks
+# from its file child and copies them to @target child. After successfully
+# copying, the write request is propagated to file child. If copying
+# fails, the original write request is failed too and no data is written
+# to file child.
+#
+# @target: The target for copy-before-write operations.
+#
+# Since: 6.2
+##
+{ 'struct': 'BlockdevOptionsCbw',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { 'target': 'BlockdevRef' } }
+
+##
+# @BlockdevOptions:
+#
+# Options for creating a block device. Many options are available for all
+# block devices, independent of the block driver:
+#
+# @driver: block driver name
+# @node-name: the node name of the new node (Since 2.0).
+# This option is required on the top level of blockdev-add.
+# Valid node names start with an alphabetic character and may
+# contain only alphanumeric characters, '-', '.' and '_'. Their
+# maximum length is 31 characters.
+# @discard: discard-related options (default: ignore)
+# @cache: cache-related options
+# @read-only: whether the block device should be read-only (default: false).
+# Note that some block drivers support only read-only access,
+# either generally or in certain configurations. In this case,
+# the default value does not work and the option must be
+# specified explicitly.
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
+# decide not to open the image read-write as requested, but
+# fall back to read-only instead (and switch between the modes
+# later), e.g. depending on whether the image file is writable
+# or whether a writing user is attached to the node
+# (default: false, since 3.1)
+# @detect-zeroes: detect and optimize zero writes (Since 2.1)
+# (default: off)
+# @force-share: force share all permission on added nodes.
+# Requires read-only=true. (Since 2.10)
+#
+# Remaining options are determined by the block driver.
+#
+# Since: 2.9
+##
+{ 'union': 'BlockdevOptions',
+ 'base': { 'driver': 'BlockdevDriver',
+ '*node-name': 'str',
+ '*discard': 'BlockdevDiscardOptions',
+ '*cache': 'BlockdevCacheOptions',
+ '*read-only': 'bool',
+ '*auto-read-only': 'bool',
+ '*force-share': 'bool',
+ '*detect-zeroes': 'BlockdevDetectZeroesOptions' },
+ 'discriminator': 'driver',
+ 'data': {
+ 'blkdebug': 'BlockdevOptionsBlkdebug',
+ 'blklogwrites':'BlockdevOptionsBlklogwrites',
+ 'blkverify': 'BlockdevOptionsBlkverify',
+ 'blkreplay': 'BlockdevOptionsBlkreplay',
+ 'bochs': 'BlockdevOptionsGenericFormat',
+ 'cloop': 'BlockdevOptionsGenericFormat',
+ 'compress': 'BlockdevOptionsGenericFormat',
+ 'copy-before-write':'BlockdevOptionsCbw',
+ 'copy-on-read':'BlockdevOptionsCor',
+ 'dmg': 'BlockdevOptionsGenericFormat',
+ 'file': 'BlockdevOptionsFile',
+ 'ftp': 'BlockdevOptionsCurlFtp',
+ 'ftps': 'BlockdevOptionsCurlFtps',
+ 'gluster': 'BlockdevOptionsGluster',
+ 'host_cdrom': { 'type': 'BlockdevOptionsFile',
+ 'if': 'HAVE_HOST_BLOCK_DEVICE' },
+ 'host_device': { 'type': 'BlockdevOptionsFile',
+ 'if': 'HAVE_HOST_BLOCK_DEVICE' },
+ 'http': 'BlockdevOptionsCurlHttp',
+ 'https': 'BlockdevOptionsCurlHttps',
+ 'iscsi': 'BlockdevOptionsIscsi',
+ 'luks': 'BlockdevOptionsLUKS',
+ 'nbd': 'BlockdevOptionsNbd',
+ 'nfs': 'BlockdevOptionsNfs',
+ 'null-aio': 'BlockdevOptionsNull',
+ 'null-co': 'BlockdevOptionsNull',
+ 'nvme': 'BlockdevOptionsNVMe',
+ 'parallels': 'BlockdevOptionsGenericFormat',
+ 'preallocate':'BlockdevOptionsPreallocate',
+ 'qcow2': 'BlockdevOptionsQcow2',
+ 'qcow': 'BlockdevOptionsQcow',
+ 'qed': 'BlockdevOptionsGenericCOWFormat',
+ 'quorum': 'BlockdevOptionsQuorum',
+ 'raw': 'BlockdevOptionsRaw',
+ 'rbd': 'BlockdevOptionsRbd',
+ 'replication': { 'type': 'BlockdevOptionsReplication',
+ 'if': 'CONFIG_REPLICATION' },
+ 'ssh': 'BlockdevOptionsSsh',
+ 'throttle': 'BlockdevOptionsThrottle',
+ 'vdi': 'BlockdevOptionsGenericFormat',
+ 'vhdx': 'BlockdevOptionsGenericFormat',
+ 'vmdk': 'BlockdevOptionsGenericCOWFormat',
+ 'vpc': 'BlockdevOptionsGenericFormat',
+ 'vvfat': 'BlockdevOptionsVVFAT'
+ } }
+
+##
+# @BlockdevRef:
+#
+# Reference to a block device.
+#
+# @definition: defines a new block device inline
+# @reference: references the ID of an existing block device
+#
+# Since: 2.9
+##
+{ 'alternate': 'BlockdevRef',
+ 'data': { 'definition': 'BlockdevOptions',
+ 'reference': 'str' } }
+
+##
+# @BlockdevRefOrNull:
+#
+# Reference to a block device.
+#
+# @definition: defines a new block device inline
+# @reference: references the ID of an existing block device.
+# An empty string means that no block device should
+# be referenced. Deprecated; use null instead.
+# @null: No block device should be referenced (since 2.10)
+#
+# Since: 2.9
+##
+{ 'alternate': 'BlockdevRefOrNull',
+ 'data': { 'definition': 'BlockdevOptions',
+ 'reference': 'str',
+ 'null': 'null' } }
+
+##
+# @blockdev-add:
+#
+# Creates a new block device.
+#
+# Since: 2.9
+#
+# Example:
+#
+# 1.
+# -> { "execute": "blockdev-add",
+# "arguments": {
+# "driver": "qcow2",
+# "node-name": "test1",
+# "file": {
+# "driver": "file",
+# "filename": "test.qcow2"
+# }
+# }
+# }
+# <- { "return": {} }
+#
+# 2.
+# -> { "execute": "blockdev-add",
+# "arguments": {
+# "driver": "qcow2",
+# "node-name": "node0",
+# "discard": "unmap",
+# "cache": {
+# "direct": true
+# },
+# "file": {
+# "driver": "file",
+# "filename": "/tmp/test.qcow2"
+# },
+# "backing": {
+# "driver": "raw",
+# "file": {
+# "driver": "file",
+# "filename": "/dev/fdset/4"
+# }
+# }
+# }
+# }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true }
+
+##
+# @blockdev-reopen:
+#
+# Reopens one or more block devices using the given set of options.
+# Any option not specified will be reset to its default value regardless
+# of its previous status. If an option cannot be changed or a particular
+# driver does not support reopening then the command will return an
+# error. All devices in the list are reopened in one transaction, so
+# if one of them fails then the whole transaction is cancelled.
+#
+# The command receives a list of block devices to reopen. For each one
+# of them, the top-level @node-name option (from BlockdevOptions) must be
+# specified and is used to select the block device to be reopened.
+# Other @node-name options must be either omitted or set to the
+# current name of the appropriate node. This command won't change any
+# node name and any attempt to do it will result in an error.
+#
+# In the case of options that refer to child nodes, the behavior of
+# this command depends on the value:
+#
+# 1) A set of options (BlockdevOptions): the child is reopened with
+# the specified set of options.
+#
+# 2) A reference to the current child: the child is reopened using
+# its existing set of options.
+#
+# 3) A reference to a different node: the current child is replaced
+# with the specified one.
+#
+# 4) NULL: the current child (if any) is detached.
+#
+# Options (1) and (2) are supported in all cases. Option (3) is
+# supported for @file and @backing, and option (4) for @backing only.
+#
+# Unlike with blockdev-add, the @backing option must always be present
+# unless the node being reopened does not have a backing file and its
+# image does not have a default backing file name as part of its
+# metadata.
+#
+# Since: 6.1
+##
+{ 'command': 'blockdev-reopen',
+ 'data': { 'options': ['BlockdevOptions'] } }
+
+##
+# @blockdev-del:
+#
+# Deletes a block device that has been added using blockdev-add.
+# The command will fail if the node is attached to a device or is
+# otherwise being used.
+#
+# @node-name: Name of the graph node to delete.
+#
+# Since: 2.9
+#
+# Example:
+#
+# -> { "execute": "blockdev-add",
+# "arguments": {
+# "driver": "qcow2",
+# "node-name": "node0",
+# "file": {
+# "driver": "file",
+# "filename": "test.qcow2"
+# }
+# }
+# }
+# <- { "return": {} }
+#
+# -> { "execute": "blockdev-del",
+# "arguments": { "node-name": "node0" }
+# }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
+
+##
+# @BlockdevCreateOptionsFile:
+#
+# Driver specific image creation options for file.
+#
+# @filename: Filename for the new image file
+# @size: Size of the virtual disk in bytes
+# @preallocation: Preallocation mode for the new image (default: off;
+# allowed values: off,
+# falloc (if CONFIG_POSIX_FALLOCATE),
+# full (if CONFIG_POSIX))
+# @nocow: Turn off copy-on-write (valid only on btrfs; default: off)
+# @extent-size-hint: Extent size hint to add to the image file; 0 for not
+# adding an extent size hint (default: 1 MB, since 5.1)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsFile',
+ 'data': { 'filename': 'str',
+ 'size': 'size',
+ '*preallocation': 'PreallocMode',
+ '*nocow': 'bool',
+ '*extent-size-hint': 'size'} }
+
+##
+# @BlockdevCreateOptionsGluster:
+#
+# Driver specific image creation options for gluster.
+#
+# @location: Where to store the new image file
+# @size: Size of the virtual disk in bytes
+# @preallocation: Preallocation mode for the new image (default: off;
+# allowed values: off,
+# falloc (if CONFIG_GLUSTERFS_FALLOCATE),
+# full (if CONFIG_GLUSTERFS_ZEROFILL))
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsGluster',
+ 'data': { 'location': 'BlockdevOptionsGluster',
+ 'size': 'size',
+ '*preallocation': 'PreallocMode' } }
+
+##
+# @BlockdevCreateOptionsLUKS:
+#
+# Driver specific image creation options for LUKS.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @preallocation: Preallocation mode for the new image
+# (since: 4.2)
+# (default: off; allowed values: off, metadata, falloc, full)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsLUKS',
+ 'base': 'QCryptoBlockCreateOptionsLUKS',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*preallocation': 'PreallocMode' } }
+
+##
+# @BlockdevCreateOptionsNfs:
+#
+# Driver specific image creation options for NFS.
+#
+# @location: Where to store the new image file
+# @size: Size of the virtual disk in bytes
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsNfs',
+ 'data': { 'location': 'BlockdevOptionsNfs',
+ 'size': 'size' } }
+
+##
+# @BlockdevCreateOptionsParallels:
+#
+# Driver specific image creation options for parallels.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @cluster-size: Cluster size in bytes (default: 1 MB)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsParallels',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*cluster-size': 'size' } }
+
+##
+# @BlockdevCreateOptionsQcow:
+#
+# Driver specific image creation options for qcow.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @backing-file: File name of the backing file if a backing file
+# should be used
+# @encrypt: Encryption options if the image should be encrypted
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsQcow',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*backing-file': 'str',
+ '*encrypt': 'QCryptoBlockCreateOptions' } }
+
+##
+# @BlockdevQcow2Version:
+#
+# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2)
+# @v3: The extended QCOW2 format as introduced in qemu 1.1 (version 3)
+#
+# Since: 2.12
+##
+{ 'enum': 'BlockdevQcow2Version',
+ 'data': [ 'v2', 'v3' ] }
+
+
+##
+# @Qcow2CompressionType:
+#
+# Compression type used in qcow2 image file
+#
+# @zlib: zlib compression, see <http://zlib.net/>
+# @zstd: zstd compression, see <http://github.com/facebook/zstd>
+#
+# Since: 5.1
+##
+{ 'enum': 'Qcow2CompressionType',
+ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
+
+##
+# @BlockdevCreateOptionsQcow2:
+#
+# Driver specific image creation options for qcow2.
+#
+# @file: Node to create the image format on
+# @data-file: Node to use as an external data file in which all guest
+# data is stored so that only metadata remains in the qcow2
+# file (since: 4.0)
+# @data-file-raw: True if the external data file must stay valid as a
+# standalone (read-only) raw image without looking at qcow2
+# metadata (default: false; since: 4.0)
+# @extended-l2: True to make the image have extended L2 entries
+# (default: false; since 5.2)
+# @size: Size of the virtual disk in bytes
+# @version: Compatibility level (default: v3)
+# @backing-file: File name of the backing file if a backing file
+# should be used
+# @backing-fmt: Name of the block driver to use for the backing file
+# @encrypt: Encryption options if the image should be encrypted
+# @cluster-size: qcow2 cluster size in bytes (default: 65536)
+# @preallocation: Preallocation mode for the new image (default: off;
+# allowed values: off, falloc, full, metadata)
+# @lazy-refcounts: True if refcounts may be updated lazily (default: off)
+# @refcount-bits: Width of reference counts in bits (default: 16)
+# @compression-type: The image cluster compression method
+# (default: zlib, since 5.1)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsQcow2',
+ 'data': { 'file': 'BlockdevRef',
+ '*data-file': 'BlockdevRef',
+ '*data-file-raw': 'bool',
+ '*extended-l2': 'bool',
+ 'size': 'size',
+ '*version': 'BlockdevQcow2Version',
+ '*backing-file': 'str',
+ '*backing-fmt': 'BlockdevDriver',
+ '*encrypt': 'QCryptoBlockCreateOptions',
+ '*cluster-size': 'size',
+ '*preallocation': 'PreallocMode',
+ '*lazy-refcounts': 'bool',
+ '*refcount-bits': 'int',
+ '*compression-type':'Qcow2CompressionType' } }
+
+##
+# @BlockdevCreateOptionsQed:
+#
+# Driver specific image creation options for qed.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @backing-file: File name of the backing file if a backing file
+# should be used
+# @backing-fmt: Name of the block driver to use for the backing file
+# @cluster-size: Cluster size in bytes (default: 65536)
+# @table-size: L1/L2 table size (in clusters)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsQed',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*backing-file': 'str',
+ '*backing-fmt': 'BlockdevDriver',
+ '*cluster-size': 'size',
+ '*table-size': 'int' } }
+
+##
+# @BlockdevCreateOptionsRbd:
+#
+# Driver specific image creation options for rbd/Ceph.
+#
+# @location: Where to store the new image file. This location cannot
+# point to a snapshot.
+# @size: Size of the virtual disk in bytes
+# @cluster-size: RBD object size
+# @encrypt: Image encryption options. (Since 6.1)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsRbd',
+ 'data': { 'location': 'BlockdevOptionsRbd',
+ 'size': 'size',
+ '*cluster-size' : 'size',
+ '*encrypt' : 'RbdEncryptionCreateOptions' } }
+
+##
+# @BlockdevVmdkSubformat:
+#
+# Subformat options for VMDK images
+#
+# @monolithicSparse: Single file image with sparse cluster allocation
+#
+# @monolithicFlat: Single flat data image and a descriptor file
+#
+# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse extent
+# files, in addition to a descriptor file
+#
+# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat extent
+# files, in addition to a descriptor file
+#
+# @streamOptimized: Single file image sparse cluster allocation, optimized
+# for streaming over network.
+#
+# Since: 4.0
+##
+{ 'enum': 'BlockdevVmdkSubformat',
+ 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse',
+ 'twoGbMaxExtentFlat', 'streamOptimized'] }
+
+##
+# @BlockdevVmdkAdapterType:
+#
+# Adapter type info for VMDK images
+#
+# Since: 4.0
+##
+{ 'enum': 'BlockdevVmdkAdapterType',
+ 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] }
+
+##
+# @BlockdevCreateOptionsVmdk:
+#
+# Driver specific image creation options for VMDK.
+#
+# @file: Where to store the new image file. This refers to the image
+# file for monolithcSparse and streamOptimized format, or the
+# descriptor file for other formats.
+# @size: Size of the virtual disk in bytes
+# @extents: Where to store the data extents. Required for monolithcFlat,
+# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For
+# monolithicFlat, only one entry is required; for
+# twoGbMaxExtent* formats, the number of entries required is
+# calculated as extent_number = virtual_size / 2GB. Providing
+# more extents than will be used is an error.
+# @subformat: The subformat of the VMDK image. Default: "monolithicSparse".
+# @backing-file: The path of backing file. Default: no backing file is used.
+# @adapter-type: The adapter type used to fill in the descriptor. Default: ide.
+# @hwversion: Hardware version. The meaningful options are "4" or "6".
+# Default: "4".
+# @toolsversion: VMware guest tools version.
+# Default: "2147483647" (Since 6.2)
+# @zeroed-grain: Whether to enable zeroed-grain feature for sparse subformats.
+# Default: false.
+#
+# Since: 4.0
+##
+{ 'struct': 'BlockdevCreateOptionsVmdk',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*extents': ['BlockdevRef'],
+ '*subformat': 'BlockdevVmdkSubformat',
+ '*backing-file': 'str',
+ '*adapter-type': 'BlockdevVmdkAdapterType',
+ '*hwversion': 'str',
+ '*toolsversion': 'str',
+ '*zeroed-grain': 'bool' } }
+
+
+##
+# @BlockdevCreateOptionsSsh:
+#
+# Driver specific image creation options for SSH.
+#
+# @location: Where to store the new image file
+# @size: Size of the virtual disk in bytes
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsSsh',
+ 'data': { 'location': 'BlockdevOptionsSsh',
+ 'size': 'size' } }
+
+##
+# @BlockdevCreateOptionsVdi:
+#
+# Driver specific image creation options for VDI.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @preallocation: Preallocation mode for the new image (default: off;
+# allowed values: off, metadata)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsVdi',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*preallocation': 'PreallocMode' } }
+
+##
+# @BlockdevVhdxSubformat:
+#
+# @dynamic: Growing image file
+# @fixed: Preallocated fixed-size image file
+#
+# Since: 2.12
+##
+{ 'enum': 'BlockdevVhdxSubformat',
+ 'data': [ 'dynamic', 'fixed' ] }
+
+##
+# @BlockdevCreateOptionsVhdx:
+#
+# Driver specific image creation options for vhdx.
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @log-size: Log size in bytes, must be a multiple of 1 MB
+# (default: 1 MB)
+# @block-size: Block size in bytes, must be a multiple of 1 MB and not
+# larger than 256 MB (default: automatically choose a block
+# size depending on the image size)
+# @subformat: vhdx subformat (default: dynamic)
+# @block-state-zero: Force use of payload blocks of type 'ZERO'. Non-standard,
+# but default. Do not set to 'off' when using 'qemu-img
+# convert' with subformat=dynamic.
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsVhdx',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*log-size': 'size',
+ '*block-size': 'size',
+ '*subformat': 'BlockdevVhdxSubformat',
+ '*block-state-zero': 'bool' } }
+
+##
+# @BlockdevVpcSubformat:
+#
+# @dynamic: Growing image file
+# @fixed: Preallocated fixed-size image file
+#
+# Since: 2.12
+##
+{ 'enum': 'BlockdevVpcSubformat',
+ 'data': [ 'dynamic', 'fixed' ] }
+
+##
+# @BlockdevCreateOptionsVpc:
+#
+# Driver specific image creation options for vpc (VHD).
+#
+# @file: Node to create the image format on
+# @size: Size of the virtual disk in bytes
+# @subformat: vhdx subformat (default: dynamic)
+# @force-size: Force use of the exact byte size instead of rounding to the
+# next size that can be represented in CHS geometry
+# (default: false)
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsVpc',
+ 'data': { 'file': 'BlockdevRef',
+ 'size': 'size',
+ '*subformat': 'BlockdevVpcSubformat',
+ '*force-size': 'bool' } }
+
+##
+# @BlockdevCreateOptions:
+#
+# Options for creating an image format on a given node.
+#
+# @driver: block driver to create the image format
+#
+# Since: 2.12
+##
+{ 'union': 'BlockdevCreateOptions',
+ 'base': {
+ 'driver': 'BlockdevDriver' },
+ 'discriminator': 'driver',
+ 'data': {
+ 'file': 'BlockdevCreateOptionsFile',
+ 'gluster': 'BlockdevCreateOptionsGluster',
+ 'luks': 'BlockdevCreateOptionsLUKS',
+ 'nfs': 'BlockdevCreateOptionsNfs',
+ 'parallels': 'BlockdevCreateOptionsParallels',
+ 'qcow': 'BlockdevCreateOptionsQcow',
+ 'qcow2': 'BlockdevCreateOptionsQcow2',
+ 'qed': 'BlockdevCreateOptionsQed',
+ 'rbd': 'BlockdevCreateOptionsRbd',
+ 'ssh': 'BlockdevCreateOptionsSsh',
+ 'vdi': 'BlockdevCreateOptionsVdi',
+ 'vhdx': 'BlockdevCreateOptionsVhdx',
+ 'vmdk': 'BlockdevCreateOptionsVmdk',
+ 'vpc': 'BlockdevCreateOptionsVpc'
+ } }
+
+##
+# @blockdev-create:
+#
+# Starts a job to create an image format on a given node. The job is
+# automatically finalized, but a manual job-dismiss is required.
+#
+# @job-id: Identifier for the newly created job.
+#
+# @options: Options for the image creation.
+#
+# Since: 3.0
+##
+{ 'command': 'blockdev-create',
+ 'data': { 'job-id': 'str',
+ 'options': 'BlockdevCreateOptions' } }
+
+##
+# @BlockdevAmendOptionsLUKS:
+#
+# Driver specific image amend options for LUKS.
+#
+# Since: 5.1
+##
+{ 'struct': 'BlockdevAmendOptionsLUKS',
+ 'base': 'QCryptoBlockAmendOptionsLUKS',
+ 'data': { }
+}
+
+##
+# @BlockdevAmendOptionsQcow2:
+#
+# Driver specific image amend options for qcow2.
+# For now, only encryption options can be amended
+#
+# @encrypt Encryption options to be amended
+#
+# Since: 5.1
+##
+{ 'struct': 'BlockdevAmendOptionsQcow2',
+ 'data': { '*encrypt': 'QCryptoBlockAmendOptions' } }
+
+##
+# @BlockdevAmendOptions:
+#
+# Options for amending an image format
+#
+# @driver: Block driver of the node to amend.
+#
+# Since: 5.1
+##
+{ 'union': 'BlockdevAmendOptions',
+ 'base': {
+ 'driver': 'BlockdevDriver' },
+ 'discriminator': 'driver',
+ 'data': {
+ 'luks': 'BlockdevAmendOptionsLUKS',
+ 'qcow2': 'BlockdevAmendOptionsQcow2' } }
+
+##
+# @x-blockdev-amend:
+#
+# Starts a job to amend format specific options of an existing open block device
+# The job is automatically finalized, but a manual job-dismiss is required.
+#
+# @job-id: Identifier for the newly created job.
+#
+# @node-name: Name of the block node to work on
+#
+# @options: Options (driver specific)
+#
+# @force: Allow unsafe operations, format specific
+# For luks that allows erase of the last active keyslot
+# (permanent loss of data),
+# and replacement of an active keyslot
+# (possible loss of data if IO error happens)
+#
+# Features:
+# @unstable: This command is experimental.
+#
+# Since: 5.1
+##
+{ 'command': 'x-blockdev-amend',
+ 'data': { 'job-id': 'str',
+ 'node-name': 'str',
+ 'options': 'BlockdevAmendOptions',
+ '*force': 'bool' },
+ 'features': [ 'unstable' ] }
+
+##
+# @BlockErrorAction:
+#
+# An enumeration of action that has been taken when a DISK I/O occurs
+#
+# @ignore: error has been ignored
+#
+# @report: error has been reported to the device
+#
+# @stop: error caused VM to be stopped
+#
+# Since: 2.1
+##
+{ 'enum': 'BlockErrorAction',
+ 'data': [ 'ignore', 'report', 'stop' ] }
+
+
+##
+# @BLOCK_IMAGE_CORRUPTED:
+#
+# Emitted when a disk image is being marked corrupt. The image can be
+# identified by its device or node name. The 'device' field is always
+# present for compatibility reasons, but it can be empty ("") if the
+# image does not have a device name associated.
+#
+# @device: device name. This is always present for compatibility
+# reasons, but it can be empty ("") if the image does not
+# have a device name associated.
+#
+# @node-name: node name (Since: 2.4)
+#
+# @msg: informative message for human consumption, such as the kind of
+# corruption being detected. It should not be parsed by machine as it is
+# not guaranteed to be stable
+#
+# @offset: if the corruption resulted from an image access, this is
+# the host's access offset into the image
+#
+# @size: if the corruption resulted from an image access, this is
+# the access size
+#
+# @fatal: if set, the image is marked corrupt and therefore unusable after this
+# event and must be repaired (Since 2.2; before, every
+# BLOCK_IMAGE_CORRUPTED event was fatal)
+#
+# Note: If action is "stop", a STOP event will eventually follow the
+# BLOCK_IO_ERROR event.
+#
+# Example:
+#
+# <- { "event": "BLOCK_IMAGE_CORRUPTED",
+# "data": { "device": "ide0-hd0", "node-name": "node0",
+# "msg": "Prevented active L1 table overwrite", "offset": 196608,
+# "size": 65536 },
+# "timestamp": { "seconds": 1378126126, "microseconds": 966463 } }
+#
+# Since: 1.7
+##
+{ 'event': 'BLOCK_IMAGE_CORRUPTED',
+ 'data': { 'device' : 'str',
+ '*node-name' : 'str',
+ 'msg' : 'str',
+ '*offset' : 'int',
+ '*size' : 'int',
+ 'fatal' : 'bool' } }
+
+##
+# @BLOCK_IO_ERROR:
+#
+# Emitted when a disk I/O error occurs
+#
+# @device: device name. This is always present for compatibility
+# reasons, but it can be empty ("") if the image does not
+# have a device name associated.
+#
+# @node-name: node name. Note that errors may be reported for the root node
+# that is directly attached to a guest device rather than for the
+# node where the error occurred. The node name is not present if
+# the drive is empty. (Since: 2.8)
+#
+# @operation: I/O operation
+#
+# @action: action that has been taken
+#
+# @nospace: true if I/O error was caused due to a no-space
+# condition. This key is only present if query-block's
+# io-status is present, please see query-block documentation
+# for more information (since: 2.2)
+#
+# @reason: human readable string describing the error cause.
+# (This field is a debugging aid for humans, it should not
+# be parsed by applications) (since: 2.2)
+#
+# Note: If action is "stop", a STOP event will eventually follow the
+# BLOCK_IO_ERROR event
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "BLOCK_IO_ERROR",
+# "data": { "device": "ide0-hd1",
+# "node-name": "#block212",
+# "operation": "write",
+# "action": "stop" },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'BLOCK_IO_ERROR',
+ 'data': { 'device': 'str', '*node-name': 'str',
+ 'operation': 'IoOperationType',
+ 'action': 'BlockErrorAction', '*nospace': 'bool',
+ 'reason': 'str' } }
+
+##
+# @BLOCK_JOB_COMPLETED:
+#
+# Emitted when a block job has completed
+#
+# @type: job type
+#
+# @device: The job identifier. Originally the device name but other
+# values are allowed since QEMU 2.7
+#
+# @len: maximum progress value
+#
+# @offset: current progress value. On success this is equal to len.
+# On failure this is less than len
+#
+# @speed: rate limit, bytes per second
+#
+# @error: error message. Only present on failure. This field
+# contains a human-readable error message. There are no semantics
+# other than that streaming has failed and clients should not try to
+# interpret the error string
+#
+# Since: 1.1
+#
+# Example:
+#
+# <- { "event": "BLOCK_JOB_COMPLETED",
+# "data": { "type": "stream", "device": "virtio-disk0",
+# "len": 10737418240, "offset": 10737418240,
+# "speed": 0 },
+# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
+#
+##
+{ 'event': 'BLOCK_JOB_COMPLETED',
+ 'data': { 'type' : 'JobType',
+ 'device': 'str',
+ 'len' : 'int',
+ 'offset': 'int',
+ 'speed' : 'int',
+ '*error': 'str' } }
+
+##
+# @BLOCK_JOB_CANCELLED:
+#
+# Emitted when a block job has been cancelled
+#
+# @type: job type
+#
+# @device: The job identifier. Originally the device name but other
+# values are allowed since QEMU 2.7
+#
+# @len: maximum progress value
+#
+# @offset: current progress value. On success this is equal to len.
+# On failure this is less than len
+#
+# @speed: rate limit, bytes per second
+#
+# Since: 1.1
+#
+# Example:
+#
+# <- { "event": "BLOCK_JOB_CANCELLED",
+# "data": { "type": "stream", "device": "virtio-disk0",
+# "len": 10737418240, "offset": 134217728,
+# "speed": 0 },
+# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
+#
+##
+{ 'event': 'BLOCK_JOB_CANCELLED',
+ 'data': { 'type' : 'JobType',
+ 'device': 'str',
+ 'len' : 'int',
+ 'offset': 'int',
+ 'speed' : 'int' } }
+
+##
+# @BLOCK_JOB_ERROR:
+#
+# Emitted when a block job encounters an error
+#
+# @device: The job identifier. Originally the device name but other
+# values are allowed since QEMU 2.7
+#
+# @operation: I/O operation
+#
+# @action: action that has been taken
+#
+# Since: 1.3
+#
+# Example:
+#
+# <- { "event": "BLOCK_JOB_ERROR",
+# "data": { "device": "ide0-hd1",
+# "operation": "write",
+# "action": "stop" },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'BLOCK_JOB_ERROR',
+ 'data': { 'device' : 'str',
+ 'operation': 'IoOperationType',
+ 'action' : 'BlockErrorAction' } }
+
+##
+# @BLOCK_JOB_READY:
+#
+# Emitted when a block job is ready to complete
+#
+# @type: job type
+#
+# @device: The job identifier. Originally the device name but other
+# values are allowed since QEMU 2.7
+#
+# @len: maximum progress value
+#
+# @offset: current progress value. On success this is equal to len.
+# On failure this is less than len
+#
+# @speed: rate limit, bytes per second
+#
+# Note: The "ready to complete" status is always reset by a @BLOCK_JOB_ERROR
+# event
+#
+# Since: 1.3
+#
+# Example:
+#
+# <- { "event": "BLOCK_JOB_READY",
+# "data": { "device": "drive0", "type": "mirror", "speed": 0,
+# "len": 2097152, "offset": 2097152 }
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'BLOCK_JOB_READY',
+ 'data': { 'type' : 'JobType',
+ 'device': 'str',
+ 'len' : 'int',
+ 'offset': 'int',
+ 'speed' : 'int' } }
+
+##
+# @BLOCK_JOB_PENDING:
+#
+# Emitted when a block job is awaiting explicit authorization to finalize graph
+# changes via @block-job-finalize. If this job is part of a transaction, it will
+# not emit this event until the transaction has converged first.
+#
+# @type: job type
+#
+# @id: The job identifier.
+#
+# Since: 2.12
+#
+# Example:
+#
+# <- { "event": "BLOCK_JOB_WAITING",
+# "data": { "device": "drive0", "type": "mirror" },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'BLOCK_JOB_PENDING',
+ 'data': { 'type' : 'JobType',
+ 'id' : 'str' } }
+
+##
+# @PreallocMode:
+#
+# Preallocation mode of QEMU image file
+#
+# @off: no preallocation
+# @metadata: preallocate only for metadata
+# @falloc: like @full preallocation but allocate disk space by
+# posix_fallocate() rather than writing data.
+# @full: preallocate all data by writing it to the device to ensure
+# disk space is really available. This data may or may not be
+# zero, depending on the image format and storage.
+# @full preallocation also sets up metadata correctly.
+#
+# Since: 2.2
+##
+{ 'enum': 'PreallocMode',
+ 'data': [ 'off', 'metadata', 'falloc', 'full' ] }
+
+##
+# @BLOCK_WRITE_THRESHOLD:
+#
+# Emitted when writes on block device reaches or exceeds the
+# configured write threshold. For thin-provisioned devices, this
+# means the device should be extended to avoid pausing for
+# disk exhaustion.
+# The event is one shot. Once triggered, it needs to be
+# re-registered with another block-set-write-threshold command.
+#
+# @node-name: graph node name on which the threshold was exceeded.
+#
+# @amount-exceeded: amount of data which exceeded the threshold, in bytes.
+#
+# @write-threshold: last configured threshold, in bytes.
+#
+# Since: 2.3
+##
+{ 'event': 'BLOCK_WRITE_THRESHOLD',
+ 'data': { 'node-name': 'str',
+ 'amount-exceeded': 'uint64',
+ 'write-threshold': 'uint64' } }
+
+##
+# @block-set-write-threshold:
+#
+# Change the write threshold for a block drive. An event will be
+# delivered if a write to this block drive crosses the configured
+# threshold. The threshold is an offset, thus must be
+# non-negative. Default is no write threshold. Setting the threshold
+# to zero disables it.
+#
+# This is useful to transparently resize thin-provisioned drives without
+# the guest OS noticing.
+#
+# @node-name: graph node name on which the threshold must be set.
+#
+# @write-threshold: configured threshold for the block device, bytes.
+# Use 0 to disable the threshold.
+#
+# Since: 2.3
+#
+# Example:
+#
+# -> { "execute": "block-set-write-threshold",
+# "arguments": { "node-name": "mydev",
+# "write-threshold": 17179869184 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'block-set-write-threshold',
+ 'data': { 'node-name': 'str', 'write-threshold': 'uint64' } }
+
+##
+# @x-blockdev-change:
+#
+# Dynamically reconfigure the block driver state graph. It can be used
+# to add, remove, insert or replace a graph node. Currently only the
+# Quorum driver implements this feature to add or remove its child. This
+# is useful to fix a broken quorum child.
+#
+# If @node is specified, it will be inserted under @parent. @child
+# may not be specified in this case. If both @parent and @child are
+# specified but @node is not, @child will be detached from @parent.
+#
+# @parent: the id or name of the parent node.
+#
+# @child: the name of a child under the given parent node.
+#
+# @node: the name of the node that will be added.
+#
+# Features:
+# @unstable: This command is experimental, and its API is not stable. It
+# does not support all kinds of operations, all kinds of
+# children, nor all block drivers.
+#
+# FIXME Removing children from a quorum node means introducing
+# gaps in the child indices. This cannot be represented in the
+# 'children' list of BlockdevOptionsQuorum, as returned by
+# .bdrv_refresh_filename().
+#
+# Warning: The data in a new quorum child MUST be consistent
+# with that of the rest of the array.
+#
+# Since: 2.7
+#
+# Example:
+#
+# 1. Add a new node to a quorum
+# -> { "execute": "blockdev-add",
+# "arguments": {
+# "driver": "raw",
+# "node-name": "new_node",
+# "file": { "driver": "file",
+# "filename": "test.raw" } } }
+# <- { "return": {} }
+# -> { "execute": "x-blockdev-change",
+# "arguments": { "parent": "disk1",
+# "node": "new_node" } }
+# <- { "return": {} }
+#
+# 2. Delete a quorum's node
+# -> { "execute": "x-blockdev-change",
+# "arguments": { "parent": "disk1",
+# "child": "children.1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'x-blockdev-change',
+ 'data' : { 'parent': 'str',
+ '*child': 'str',
+ '*node': 'str' },
+ 'features': [ 'unstable' ] }
+
+##
+# @x-blockdev-set-iothread:
+#
+# Move @node and its children into the @iothread. If @iothread is null then
+# move @node and its children into the main loop.
+#
+# The node must not be attached to a BlockBackend.
+#
+# @node-name: the name of the block driver node
+#
+# @iothread: the name of the IOThread object or null for the main loop
+#
+# @force: true if the node and its children should be moved when a BlockBackend
+# is already attached
+#
+# Features:
+# @unstable: This command is experimental and intended for test cases that
+# need control over IOThreads only.
+#
+# Since: 2.12
+#
+# Example:
+#
+# 1. Move a node into an IOThread
+# -> { "execute": "x-blockdev-set-iothread",
+# "arguments": { "node-name": "disk1",
+# "iothread": "iothread0" } }
+# <- { "return": {} }
+#
+# 2. Move a node into the main loop
+# -> { "execute": "x-blockdev-set-iothread",
+# "arguments": { "node-name": "disk1",
+# "iothread": null } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'x-blockdev-set-iothread',
+ 'data' : { 'node-name': 'str',
+ 'iothread': 'StrOrNull',
+ '*force': 'bool' },
+ 'features': [ 'unstable' ] }
+
+##
+# @QuorumOpType:
+#
+# An enumeration of the quorum operation types
+#
+# @read: read operation
+#
+# @write: write operation
+#
+# @flush: flush operation
+#
+# Since: 2.6
+##
+{ 'enum': 'QuorumOpType',
+ 'data': [ 'read', 'write', 'flush' ] }
+
+##
+# @QUORUM_FAILURE:
+#
+# Emitted by the Quorum block driver if it fails to establish a quorum
+#
+# @reference: device name if defined else node name
+#
+# @sector-num: number of the first sector of the failed read operation
+#
+# @sectors-count: failed read operation sector count
+#
+# Note: This event is rate-limited.
+#
+# Since: 2.0
+#
+# Example:
+#
+# <- { "event": "QUORUM_FAILURE",
+# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
+# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
+#
+##
+{ 'event': 'QUORUM_FAILURE',
+ 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
+
+##
+# @QUORUM_REPORT_BAD:
+#
+# Emitted to report a corruption of a Quorum file
+#
+# @type: quorum operation type (Since 2.6)
+#
+# @error: error message. Only present on failure. This field
+# contains a human-readable error message. There are no semantics other
+# than that the block layer reported an error and clients should not
+# try to interpret the error string.
+#
+# @node-name: the graph node name of the block driver state
+#
+# @sector-num: number of the first sector of the failed read operation
+#
+# @sectors-count: failed read operation sector count
+#
+# Note: This event is rate-limited.
+#
+# Since: 2.0
+#
+# Example:
+#
+# 1. Read operation
+#
+# { "event": "QUORUM_REPORT_BAD",
+# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
+# "type": "read" },
+# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
+#
+# 2. Flush operation
+#
+# { "event": "QUORUM_REPORT_BAD",
+# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
+# "type": "flush", "error": "Broken pipe" },
+# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } }
+#
+##
+{ 'event': 'QUORUM_REPORT_BAD',
+ 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
+ 'sector-num': 'int', 'sectors-count': 'int' } }
+
+##
+# @BlockdevSnapshotInternal:
+#
+# @device: the device name or node-name of a root node to generate the snapshot
+# from
+#
+# @name: the name of the internal snapshot to be created
+#
+# Notes: In transaction, if @name is empty, or any snapshot matching @name
+# exists, the operation will fail. Only some image formats support it,
+# for example, qcow2, and rbd.
+#
+# Since: 1.7
+##
+{ 'struct': 'BlockdevSnapshotInternal',
+ 'data': { 'device': 'str', 'name': 'str' } }
+
+##
+# @blockdev-snapshot-internal-sync:
+#
+# Synchronously take an internal snapshot of a block device, when the
+# format of the image used supports it. If the name is an empty
+# string, or a snapshot with name already exists, the operation will
+# fail.
+#
+# For the arguments, see the documentation of BlockdevSnapshotInternal.
+#
+# Returns: - nothing on success
+# - If @device is not a valid block device, GenericError
+# - If any snapshot matching @name exists, or @name is empty,
+# GenericError
+# - If the format of the image used does not support it,
+# BlockFormatFeatureNotSupported
+#
+# Since: 1.7
+#
+# Example:
+#
+# -> { "execute": "blockdev-snapshot-internal-sync",
+# "arguments": { "device": "ide-hd0",
+# "name": "snapshot0" }
+# }
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-snapshot-internal-sync',
+ 'data': 'BlockdevSnapshotInternal' }
+
+##
+# @blockdev-snapshot-delete-internal-sync:
+#
+# Synchronously delete an internal snapshot of a block device, when the format
+# of the image used support it. The snapshot is identified by name or id or
+# both. One of the name or id is required. Return SnapshotInfo for the
+# successfully deleted snapshot.
+#
+# @device: the device name or node-name of a root node to delete the snapshot
+# from
+#
+# @id: optional the snapshot's ID to be deleted
+#
+# @name: optional the snapshot's name to be deleted
+#
+# Returns: - SnapshotInfo on success
+# - If @device is not a valid block device, GenericError
+# - If snapshot not found, GenericError
+# - If the format of the image used does not support it,
+# BlockFormatFeatureNotSupported
+# - If @id and @name are both not specified, GenericError
+#
+# Since: 1.7
+#
+# Example:
+#
+# -> { "execute": "blockdev-snapshot-delete-internal-sync",
+# "arguments": { "device": "ide-hd0",
+# "name": "snapshot0" }
+# }
+# <- { "return": {
+# "id": "1",
+# "name": "snapshot0",
+# "vm-state-size": 0,
+# "date-sec": 1000012,
+# "date-nsec": 10,
+# "vm-clock-sec": 100,
+# "vm-clock-nsec": 20,
+# "icount": 220414
+# }
+# }
+#
+##
+{ 'command': 'blockdev-snapshot-delete-internal-sync',
+ 'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
+ 'returns': 'SnapshotInfo' }
diff --git a/qapi/block-export.json b/qapi/block-export.json
new file mode 100644
index 000000000..c1b92ce1c
--- /dev/null
+++ b/qapi/block-export.json
@@ -0,0 +1,399 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# == Block device exports
+##
+
+{ 'include': 'sockets.json' }
+
+##
+# @NbdServerOptions:
+#
+# Keep this type consistent with the nbd-server-start arguments. The only
+# intended difference is using SocketAddress instead of SocketAddressLegacy.
+#
+# @addr: Address on which to listen.
+# @tls-creds: ID of the TLS credentials object (since 2.6).
+# @tls-authz: ID of the QAuthZ authorization object used to validate
+# the client's x509 distinguished name. This object is
+# is only resolved at time of use, so can be deleted and
+# recreated on the fly while the NBD server is active.
+# If missing, it will default to denying access (since 4.0).
+# @max-connections: The maximum number of connections to allow at the same
+# time, 0 for unlimited. (since 5.2; default: 0)
+#
+# Since: 4.2
+##
+{ 'struct': 'NbdServerOptions',
+ 'data': { 'addr': 'SocketAddress',
+ '*tls-creds': 'str',
+ '*tls-authz': 'str',
+ '*max-connections': 'uint32' } }
+
+##
+# @nbd-server-start:
+#
+# Start an NBD server listening on the given host and port. Block
+# devices can then be exported using @nbd-server-add. The NBD
+# server will present them as named exports; for example, another
+# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
+#
+# Keep this type consistent with the NbdServerOptions type. The only intended
+# difference is using SocketAddressLegacy instead of SocketAddress.
+#
+# @addr: Address on which to listen.
+# @tls-creds: ID of the TLS credentials object (since 2.6).
+# @tls-authz: ID of the QAuthZ authorization object used to validate
+# the client's x509 distinguished name. This object is
+# is only resolved at time of use, so can be deleted and
+# recreated on the fly while the NBD server is active.
+# If missing, it will default to denying access (since 4.0).
+# @max-connections: The maximum number of connections to allow at the same
+# time, 0 for unlimited. (since 5.2; default: 0)
+#
+# Returns: error if the server is already running.
+#
+# Since: 1.3
+##
+{ 'command': 'nbd-server-start',
+ 'data': { 'addr': 'SocketAddressLegacy',
+ '*tls-creds': 'str',
+ '*tls-authz': 'str',
+ '*max-connections': 'uint32' } }
+
+##
+# @BlockExportOptionsNbdBase:
+#
+# An NBD block export (common options shared between nbd-server-add and
+# the NBD branch of block-export-add).
+#
+# @name: Export name. If unspecified, the @device parameter is used as the
+# export name. (Since 2.12)
+#
+# @description: Free-form description of the export, up to 4096 bytes.
+# (Since 5.0)
+#
+# Since: 5.0
+##
+{ 'struct': 'BlockExportOptionsNbdBase',
+ 'data': { '*name': 'str', '*description': 'str' } }
+
+##
+# @BlockExportOptionsNbd:
+#
+# An NBD block export (distinct options used in the NBD branch of
+# block-export-add).
+#
+# @bitmaps: Also export each of the named dirty bitmaps reachable from
+# @device, so the NBD client can use NBD_OPT_SET_META_CONTEXT with
+# the metadata context name "qemu:dirty-bitmap:BITMAP" to inspect
+# each bitmap.
+#
+# @allocation-depth: Also export the allocation depth map for @device, so
+# the NBD client can use NBD_OPT_SET_META_CONTEXT with
+# the metadata context name "qemu:allocation-depth" to
+# inspect allocation details. (since 5.2)
+#
+# Since: 5.2
+##
+{ 'struct': 'BlockExportOptionsNbd',
+ 'base': 'BlockExportOptionsNbdBase',
+ 'data': { '*bitmaps': ['str'], '*allocation-depth': 'bool' } }
+
+##
+# @BlockExportOptionsVhostUserBlk:
+#
+# A vhost-user-blk block export.
+#
+# @addr: The vhost-user socket on which to listen. Both 'unix' and 'fd'
+# SocketAddress types are supported. Passed fds must be UNIX domain
+# sockets.
+# @logical-block-size: Logical block size in bytes. Defaults to 512 bytes.
+# @num-queues: Number of request virtqueues. Must be greater than 0. Defaults
+# to 1.
+#
+# Since: 5.2
+##
+{ 'struct': 'BlockExportOptionsVhostUserBlk',
+ 'data': { 'addr': 'SocketAddress',
+ '*logical-block-size': 'size',
+ '*num-queues': 'uint16'} }
+
+##
+# @FuseExportAllowOther:
+#
+# Possible allow_other modes for FUSE exports.
+#
+# @off: Do not pass allow_other as a mount option.
+#
+# @on: Pass allow_other as a mount option.
+#
+# @auto: Try mounting with allow_other first, and if that fails, retry
+# without allow_other.
+#
+# Since: 6.1
+##
+{ 'enum': 'FuseExportAllowOther',
+ 'data': ['off', 'on', 'auto'] }
+
+##
+# @BlockExportOptionsFuse:
+#
+# Options for exporting a block graph node on some (file) mountpoint
+# as a raw image.
+#
+# @mountpoint: Path on which to export the block device via FUSE.
+# This must point to an existing regular file.
+#
+# @growable: Whether writes beyond the EOF should grow the block node
+# accordingly. (default: false)
+#
+# @allow-other: If this is off, only qemu's user is allowed access to
+# this export. That cannot be changed even with chmod or
+# chown.
+# Enabling this option will allow other users access to
+# the export with the FUSE mount option "allow_other".
+# Note that using allow_other as a non-root user requires
+# user_allow_other to be enabled in the global fuse.conf
+# configuration file.
+# In auto mode (the default), the FUSE export driver will
+# first attempt to mount the export with allow_other, and
+# if that fails, try again without.
+# (since 6.1; default: auto)
+#
+# Since: 6.0
+##
+{ 'struct': 'BlockExportOptionsFuse',
+ 'data': { 'mountpoint': 'str',
+ '*growable': 'bool',
+ '*allow-other': 'FuseExportAllowOther' },
+ 'if': 'CONFIG_FUSE' }
+
+##
+# @NbdServerAddOptions:
+#
+# An NBD block export, per legacy nbd-server-add command.
+#
+# @device: The device name or node name of the node to be exported
+#
+# @writable: Whether clients should be able to write to the device via the
+# NBD connection (default false).
+#
+# @bitmap: Also export a single dirty bitmap reachable from @device, so the
+# NBD client can use NBD_OPT_SET_META_CONTEXT with the metadata
+# context name "qemu:dirty-bitmap:BITMAP" to inspect the bitmap
+# (since 4.0).
+#
+# Since: 5.0
+##
+{ 'struct': 'NbdServerAddOptions',
+ 'base': 'BlockExportOptionsNbdBase',
+ 'data': { 'device': 'str',
+ '*writable': 'bool', '*bitmap': 'str' } }
+
+##
+# @nbd-server-add:
+#
+# Export a block node to QEMU's embedded NBD server.
+#
+# The export name will be used as the id for the resulting block export.
+#
+# Features:
+# @deprecated: This command is deprecated. Use @block-export-add instead.
+#
+# Returns: error if the server is not running, or export with the same name
+# already exists.
+#
+# Since: 1.3
+##
+{ 'command': 'nbd-server-add',
+ 'data': 'NbdServerAddOptions', 'boxed': true, 'features': ['deprecated'] }
+
+##
+# @BlockExportRemoveMode:
+#
+# Mode for removing a block export.
+#
+# @safe: Remove export if there are no existing connections, fail otherwise.
+#
+# @hard: Drop all connections immediately and remove export.
+#
+# Potential additional modes to be added in the future:
+#
+# hide: Just hide export from new clients, leave existing connections as is.
+# Remove export after all clients are disconnected.
+#
+# soft: Hide export from new clients, answer with ESHUTDOWN for all further
+# requests from existing clients.
+#
+# Since: 2.12
+##
+{'enum': 'BlockExportRemoveMode', 'data': ['safe', 'hard']}
+
+##
+# @nbd-server-remove:
+#
+# Remove NBD export by name.
+#
+# @name: Block export id.
+#
+# @mode: Mode of command operation. See @BlockExportRemoveMode description.
+# Default is 'safe'.
+#
+# Features:
+# @deprecated: This command is deprecated. Use @block-export-del instead.
+#
+# Returns: error if
+# - the server is not running
+# - export is not found
+# - mode is 'safe' and there are existing connections
+#
+# Since: 2.12
+##
+{ 'command': 'nbd-server-remove',
+ 'data': {'name': 'str', '*mode': 'BlockExportRemoveMode'},
+ 'features': ['deprecated'] }
+
+##
+# @nbd-server-stop:
+#
+# Stop QEMU's embedded NBD server, and unregister all devices previously
+# added via @nbd-server-add.
+#
+# Since: 1.3
+##
+{ 'command': 'nbd-server-stop' }
+
+##
+# @BlockExportType:
+#
+# An enumeration of block export types
+#
+# @nbd: NBD export
+# @vhost-user-blk: vhost-user-blk export (since 5.2)
+# @fuse: FUSE export (since: 6.0)
+#
+# Since: 4.2
+##
+{ 'enum': 'BlockExportType',
+ 'data': [ 'nbd', 'vhost-user-blk',
+ { 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] }
+
+##
+# @BlockExportOptions:
+#
+# Describes a block export, i.e. how single node should be exported on an
+# external interface.
+#
+# @id: A unique identifier for the block export (across all export types)
+#
+# @node-name: The node name of the block node to be exported (since: 5.2)
+#
+# @writable: True if clients should be able to write to the export
+# (default false)
+#
+# @writethrough: If true, caches are flushed after every write request to the
+# export before completion is signalled. (since: 5.2;
+# default: false)
+#
+# @iothread: The name of the iothread object where the export will run. The
+# default is to use the thread currently associated with the
+# block node. (since: 5.2)
+#
+# @fixed-iothread: True prevents the block node from being moved to another
+# thread while the export is active. If true and @iothread is
+# given, export creation fails if the block node cannot be
+# moved to the iothread. The default is false. (since: 5.2)
+#
+# Since: 4.2
+##
+{ 'union': 'BlockExportOptions',
+ 'base': { 'type': 'BlockExportType',
+ 'id': 'str',
+ '*fixed-iothread': 'bool',
+ '*iothread': 'str',
+ 'node-name': 'str',
+ '*writable': 'bool',
+ '*writethrough': 'bool' },
+ 'discriminator': 'type',
+ 'data': {
+ 'nbd': 'BlockExportOptionsNbd',
+ 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk',
+ 'fuse': { 'type': 'BlockExportOptionsFuse',
+ 'if': 'CONFIG_FUSE' }
+ } }
+
+##
+# @block-export-add:
+#
+# Creates a new block export.
+#
+# Since: 5.2
+##
+{ 'command': 'block-export-add',
+ 'data': 'BlockExportOptions', 'boxed': true }
+
+##
+# @block-export-del:
+#
+# Request to remove a block export. This drops the user's reference to the
+# export, but the export may still stay around after this command returns until
+# the shutdown of the export has completed.
+#
+# @id: Block export id.
+#
+# @mode: Mode of command operation. See @BlockExportRemoveMode description.
+# Default is 'safe'.
+#
+# Returns: Error if the export is not found or @mode is 'safe' and the export
+# is still in use (e.g. by existing client connections)
+#
+# Since: 5.2
+##
+{ 'command': 'block-export-del',
+ 'data': { 'id': 'str', '*mode': 'BlockExportRemoveMode' } }
+
+##
+# @BLOCK_EXPORT_DELETED:
+#
+# Emitted when a block export is removed and its id can be reused.
+#
+# @id: Block export id.
+#
+# Since: 5.2
+##
+{ 'event': 'BLOCK_EXPORT_DELETED',
+ 'data': { 'id': 'str' } }
+
+##
+# @BlockExportInfo:
+#
+# Information about a single block export.
+#
+# @id: The unique identifier for the block export
+#
+# @type: The block export type
+#
+# @node-name: The node name of the block node that is exported
+#
+# @shutting-down: True if the export is shutting down (e.g. after a
+# block-export-del command, but before the shutdown has
+# completed)
+#
+# Since: 5.2
+##
+{ 'struct': 'BlockExportInfo',
+ 'data': { 'id': 'str',
+ 'type': 'BlockExportType',
+ 'node-name': 'str',
+ 'shutting-down': 'bool' } }
+
+##
+# @query-block-exports:
+#
+# Returns: A list of BlockExportInfo describing all block exports
+#
+# Since: 5.2
+##
+{ 'command': 'query-block-exports', 'returns': ['BlockExportInfo'] }
diff --git a/qapi/block.json b/qapi/block.json
new file mode 100644
index 000000000..82fcf2c91
--- /dev/null
+++ b/qapi/block.json
@@ -0,0 +1,572 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = Block devices
+##
+
+{ 'include': 'block-core.json' }
+
+##
+# == Additional block stuff (VM related)
+##
+
+##
+# @BiosAtaTranslation:
+#
+# Policy that BIOS should use to interpret cylinder/head/sector
+# addresses. Note that Bochs BIOS and SeaBIOS will not actually
+# translate logical CHS to physical; instead, they will use logical
+# block addressing.
+#
+# @auto: If cylinder/heads/sizes are passed, choose between none and LBA
+# depending on the size of the disk. If they are not passed,
+# choose none if QEMU can guess that the disk had 16 or fewer
+# heads, large if QEMU can guess that the disk had 131072 or
+# fewer tracks across all heads (i.e. cylinders*heads<131072),
+# otherwise LBA.
+#
+# @none: The physical disk geometry is equal to the logical geometry.
+#
+# @lba: Assume 63 sectors per track and one of 16, 32, 64, 128 or 255
+# heads (if fewer than 255 are enough to cover the whole disk
+# with 1024 cylinders/head). The number of cylinders/head is
+# then computed based on the number of sectors and heads.
+#
+# @large: The number of cylinders per head is scaled down to 1024
+# by correspondingly scaling up the number of heads.
+#
+# @rechs: Same as @large, but first convert a 16-head geometry to
+# 15-head, by proportionally scaling up the number of
+# cylinders/head.
+#
+# Since: 2.0
+##
+{ 'enum': 'BiosAtaTranslation',
+ 'data': ['auto', 'none', 'lba', 'large', 'rechs']}
+
+##
+# @FloppyDriveType:
+#
+# Type of Floppy drive to be emulated by the Floppy Disk Controller.
+#
+# @144: 1.44MB 3.5" drive
+# @288: 2.88MB 3.5" drive
+# @120: 1.2MB 5.25" drive
+# @none: No drive connected
+# @auto: Automatically determined by inserted media at boot
+#
+# Since: 2.6
+##
+{ 'enum': 'FloppyDriveType',
+ 'data': ['144', '288', '120', 'none', 'auto']}
+
+##
+# @PRManagerInfo:
+#
+# Information about a persistent reservation manager
+#
+# @id: the identifier of the persistent reservation manager
+#
+# @connected: true if the persistent reservation manager is connected to
+# the underlying storage or helper
+#
+# Since: 3.0
+##
+{ 'struct': 'PRManagerInfo',
+ 'data': {'id': 'str', 'connected': 'bool'} }
+
+##
+# @query-pr-managers:
+#
+# Returns a list of information about each persistent reservation manager.
+#
+# Returns: a list of @PRManagerInfo for each persistent reservation manager
+#
+# Since: 3.0
+##
+{ 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'],
+ 'allow-preconfig': true }
+
+##
+# @eject:
+#
+# Ejects the medium from a removable drive.
+#
+# @device: Block device name
+#
+# @id: The name or QOM path of the guest device (since: 2.8)
+#
+# @force: If true, eject regardless of whether the drive is locked.
+# If not specified, the default value is false.
+#
+# Features:
+# @deprecated: Member @device is deprecated. Use @id instead.
+#
+# Returns: - Nothing on success
+# - If @device is not a valid block device, DeviceNotFound
+# Notes: Ejecting a device with no media results in success
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } }
+# <- { "return": {} }
+##
+{ 'command': 'eject',
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*id': 'str',
+ '*force': 'bool' } }
+
+##
+# @blockdev-open-tray:
+#
+# Opens a block device's tray. If there is a block driver state tree inserted as
+# a medium, it will become inaccessible to the guest (but it will remain
+# associated to the block device, so closing the tray will make it accessible
+# again).
+#
+# If the tray was already open before, this will be a no-op.
+#
+# Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in
+# which no such event will be generated, these include:
+#
+# - if the guest has locked the tray, @force is false and the guest does not
+# respond to the eject request
+# - if the BlockBackend denoted by @device does not have a guest device attached
+# to it
+# - if the guest device does not have an actual tray
+#
+# @device: Block device name
+#
+# @id: The name or QOM path of the guest device (since: 2.8)
+#
+# @force: if false (the default), an eject request will be sent to
+# the guest if it has locked the tray (and the tray will not be opened
+# immediately); if true, the tray will be opened regardless of whether
+# it is locked
+#
+# Features:
+# @deprecated: Member @device is deprecated. Use @id instead.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "blockdev-open-tray",
+# "arguments": { "id": "ide0-1-0" } }
+#
+# <- { "timestamp": { "seconds": 1418751016,
+# "microseconds": 716996 },
+# "event": "DEVICE_TRAY_MOVED",
+# "data": { "device": "ide1-cd0",
+# "id": "ide0-1-0",
+# "tray-open": true } }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-open-tray',
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*id': 'str',
+ '*force': 'bool' } }
+
+##
+# @blockdev-close-tray:
+#
+# Closes a block device's tray. If there is a block driver state tree associated
+# with the block device (which is currently ejected), that tree will be loaded
+# as the medium.
+#
+# If the tray was already closed before, this will be a no-op.
+#
+# @device: Block device name
+#
+# @id: The name or QOM path of the guest device (since: 2.8)
+#
+# Features:
+# @deprecated: Member @device is deprecated. Use @id instead.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "blockdev-close-tray",
+# "arguments": { "id": "ide0-1-0" } }
+#
+# <- { "timestamp": { "seconds": 1418751345,
+# "microseconds": 272147 },
+# "event": "DEVICE_TRAY_MOVED",
+# "data": { "device": "ide1-cd0",
+# "id": "ide0-1-0",
+# "tray-open": false } }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-close-tray',
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*id': 'str' } }
+
+##
+# @blockdev-remove-medium:
+#
+# Removes a medium (a block driver state tree) from a block device. That block
+# device's tray must currently be open (unless there is no attached guest
+# device).
+#
+# If the tray is open and there is no medium inserted, this will be a no-op.
+#
+# @id: The name or QOM path of the guest device
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "blockdev-remove-medium",
+# "arguments": { "id": "ide0-1-0" } }
+#
+# <- { "error": { "class": "GenericError",
+# "desc": "Tray of device 'ide0-1-0' is not open" } }
+#
+# -> { "execute": "blockdev-open-tray",
+# "arguments": { "id": "ide0-1-0" } }
+#
+# <- { "timestamp": { "seconds": 1418751627,
+# "microseconds": 549958 },
+# "event": "DEVICE_TRAY_MOVED",
+# "data": { "device": "ide1-cd0",
+# "id": "ide0-1-0",
+# "tray-open": true } }
+#
+# <- { "return": {} }
+#
+# -> { "execute": "blockdev-remove-medium",
+# "arguments": { "id": "ide0-1-0" } }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-remove-medium',
+ 'data': { 'id': 'str' } }
+
+##
+# @blockdev-insert-medium:
+#
+# Inserts a medium (a block driver state tree) into a block device. That block
+# device's tray must currently be open (unless there is no attached guest
+# device) and there must be no medium inserted already.
+#
+# @id: The name or QOM path of the guest device
+#
+# @node-name: name of a node in the block driver state graph
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "blockdev-add",
+# "arguments": {
+# "node-name": "node0",
+# "driver": "raw",
+# "file": { "driver": "file",
+# "filename": "fedora.iso" } } }
+# <- { "return": {} }
+#
+# -> { "execute": "blockdev-insert-medium",
+# "arguments": { "id": "ide0-1-0",
+# "node-name": "node0" } }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-insert-medium',
+ 'data': { 'id': 'str',
+ 'node-name': 'str'} }
+
+
+##
+# @BlockdevChangeReadOnlyMode:
+#
+# Specifies the new read-only mode of a block device subject to the
+# @blockdev-change-medium command.
+#
+# @retain: Retains the current read-only mode
+#
+# @read-only: Makes the device read-only
+#
+# @read-write: Makes the device writable
+#
+# Since: 2.3
+#
+##
+{ 'enum': 'BlockdevChangeReadOnlyMode',
+ 'data': ['retain', 'read-only', 'read-write'] }
+
+
+##
+# @blockdev-change-medium:
+#
+# Changes the medium inserted into a block device by ejecting the current medium
+# and loading a new image file which is inserted as the new medium (this command
+# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
+# and blockdev-close-tray).
+#
+# @device: Block device name
+#
+# @id: The name or QOM path of the guest device
+# (since: 2.8)
+#
+# @filename: filename of the new image to be loaded
+#
+# @format: format to open the new image with (defaults to
+# the probed format)
+#
+# @read-only-mode: change the read-only mode of the device; defaults
+# to 'retain'
+#
+# Features:
+# @deprecated: Member @device is deprecated. Use @id instead.
+#
+# Since: 2.5
+#
+# Examples:
+#
+# 1. Change a removable medium
+#
+# -> { "execute": "blockdev-change-medium",
+# "arguments": { "id": "ide0-1-0",
+# "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
+# "format": "raw" } }
+# <- { "return": {} }
+#
+# 2. Load a read-only medium into a writable drive
+#
+# -> { "execute": "blockdev-change-medium",
+# "arguments": { "id": "floppyA",
+# "filename": "/srv/images/ro.img",
+# "format": "raw",
+# "read-only-mode": "retain" } }
+#
+# <- { "error":
+# { "class": "GenericError",
+# "desc": "Could not open '/srv/images/ro.img': Permission denied" } }
+#
+# -> { "execute": "blockdev-change-medium",
+# "arguments": { "id": "floppyA",
+# "filename": "/srv/images/ro.img",
+# "format": "raw",
+# "read-only-mode": "read-only" } }
+#
+# <- { "return": {} }
+#
+##
+{ 'command': 'blockdev-change-medium',
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ '*id': 'str',
+ 'filename': 'str',
+ '*format': 'str',
+ '*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
+
+
+##
+# @DEVICE_TRAY_MOVED:
+#
+# Emitted whenever the tray of a removable device is moved by the guest or by
+# HMP/QMP commands
+#
+# @device: Block device name. This is always present for compatibility
+# reasons, but it can be empty ("") if the image does not
+# have a device name associated.
+#
+# @id: The name or QOM path of the guest device (since 2.8)
+#
+# @tray-open: true if the tray has been opened or false if it has been closed
+#
+# Since: 1.1
+#
+# Example:
+#
+# <- { "event": "DEVICE_TRAY_MOVED",
+# "data": { "device": "ide1-cd0",
+# "id": "/machine/unattached/device[22]",
+# "tray-open": true
+# },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'DEVICE_TRAY_MOVED',
+ 'data': { 'device': 'str', 'id': 'str', 'tray-open': 'bool' } }
+
+##
+# @PR_MANAGER_STATUS_CHANGED:
+#
+# Emitted whenever the connected status of a persistent reservation
+# manager changes.
+#
+# @id: The id of the PR manager object
+#
+# @connected: true if the PR manager is connected to a backend
+#
+# Since: 3.0
+#
+# Example:
+#
+# <- { "event": "PR_MANAGER_STATUS_CHANGED",
+# "data": { "id": "pr-helper0",
+# "connected": true
+# },
+# "timestamp": { "seconds": 1519840375, "microseconds": 450486 } }
+#
+##
+{ 'event': 'PR_MANAGER_STATUS_CHANGED',
+ 'data': { 'id': 'str', 'connected': 'bool' } }
+
+##
+# @block_set_io_throttle:
+#
+# Change I/O throttle limits for a block drive.
+#
+# Since QEMU 2.4, each device with I/O limits is member of a throttle
+# group.
+#
+# If two or more devices are members of the same group, the limits
+# will apply to the combined I/O of the whole group in a round-robin
+# fashion. Therefore, setting new I/O limits to a device will affect
+# the whole group.
+#
+# The name of the group can be specified using the 'group' parameter.
+# If the parameter is unset, it is assumed to be the current group of
+# that device. If it's not in any group yet, the name of the device
+# will be used as the name for its group.
+#
+# The 'group' parameter can also be used to move a device to a
+# different group. In this case the limits specified in the parameters
+# will be applied to the new group only.
+#
+# I/O limits can be disabled by setting all of them to 0. In this case
+# the device will be removed from its group and the rest of its
+# members will not be affected. The 'group' parameter is ignored.
+#
+# Returns: - Nothing on success
+# - If @device is not a valid block device, DeviceNotFound
+#
+# Since: 1.1
+#
+# Example:
+#
+# -> { "execute": "block_set_io_throttle",
+# "arguments": { "id": "virtio-blk-pci0/virtio-backend",
+# "bps": 0,
+# "bps_rd": 0,
+# "bps_wr": 0,
+# "iops": 512,
+# "iops_rd": 0,
+# "iops_wr": 0,
+# "bps_max": 0,
+# "bps_rd_max": 0,
+# "bps_wr_max": 0,
+# "iops_max": 0,
+# "iops_rd_max": 0,
+# "iops_wr_max": 0,
+# "bps_max_length": 0,
+# "iops_size": 0 } }
+# <- { "return": {} }
+#
+# -> { "execute": "block_set_io_throttle",
+# "arguments": { "id": "ide0-1-0",
+# "bps": 1000000,
+# "bps_rd": 0,
+# "bps_wr": 0,
+# "iops": 0,
+# "iops_rd": 0,
+# "iops_wr": 0,
+# "bps_max": 8000000,
+# "bps_rd_max": 0,
+# "bps_wr_max": 0,
+# "iops_max": 0,
+# "iops_rd_max": 0,
+# "iops_wr_max": 0,
+# "bps_max_length": 60,
+# "iops_size": 0 } }
+# <- { "return": {} }
+##
+{ 'command': 'block_set_io_throttle', 'boxed': true,
+ 'data': 'BlockIOThrottle' }
+
+##
+# @block-latency-histogram-set:
+#
+# Manage read, write and flush latency histograms for the device.
+#
+# If only @id parameter is specified, remove all present latency histograms
+# for the device. Otherwise, add/reset some of (or all) latency histograms.
+#
+# @id: The name or QOM path of the guest device.
+#
+# @boundaries: list of interval boundary values (see description in
+# BlockLatencyHistogramInfo definition). If specified, all
+# latency histograms are removed, and empty ones created for all
+# io types with intervals corresponding to @boundaries (except for
+# io types, for which specific boundaries are set through the
+# following parameters).
+#
+# @boundaries-read: list of interval boundary values for read latency
+# histogram. If specified, old read latency histogram is
+# removed, and empty one created with intervals
+# corresponding to @boundaries-read. The parameter has higher
+# priority then @boundaries.
+#
+# @boundaries-write: list of interval boundary values for write latency
+# histogram.
+#
+# @boundaries-flush: list of interval boundary values for flush latency
+# histogram.
+#
+# Returns: error if device is not found or any boundary arrays are invalid.
+#
+# Since: 4.0
+#
+# Example:
+# set new histograms for all io types with intervals
+# [0, 10), [10, 50), [50, 100), [100, +inf):
+#
+# -> { "execute": "block-latency-histogram-set",
+# "arguments": { "id": "drive0",
+# "boundaries": [10, 50, 100] } }
+# <- { "return": {} }
+#
+# Example:
+# set new histogram only for write, other histograms will remain
+# not changed (or not created):
+#
+# -> { "execute": "block-latency-histogram-set",
+# "arguments": { "id": "drive0",
+# "boundaries-write": [10, 50, 100] } }
+# <- { "return": {} }
+#
+# Example:
+# set new histograms with the following intervals:
+# read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
+# write: [0, 1000), [1000, 5000), [5000, +inf)
+#
+# -> { "execute": "block-latency-histogram-set",
+# "arguments": { "id": "drive0",
+# "boundaries": [10, 50, 100],
+# "boundaries-write": [1000, 5000] } }
+# <- { "return": {} }
+#
+# Example:
+# remove all latency histograms:
+#
+# -> { "execute": "block-latency-histogram-set",
+# "arguments": { "id": "drive0" } }
+# <- { "return": {} }
+##
+{ 'command': 'block-latency-histogram-set',
+ 'data': {'id': 'str',
+ '*boundaries': ['uint64'],
+ '*boundaries-read': ['uint64'],
+ '*boundaries-write': ['uint64'],
+ '*boundaries-flush': ['uint64'] } }
diff --git a/qapi/char.json b/qapi/char.json
new file mode 100644
index 000000000..f5133a5ee
--- /dev/null
+++ b/qapi/char.json
@@ -0,0 +1,742 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Character devices
+##
+
+{ 'include': 'sockets.json' }
+
+##
+# @ChardevInfo:
+#
+# Information about a character device.
+#
+# @label: the label of the character device
+#
+# @filename: the filename of the character device
+#
+# @frontend-open: shows whether the frontend device attached to this backend
+# (eg. with the chardev=... option) is in open or closed state
+# (since 2.1)
+#
+# Notes: @filename is encoded using the QEMU command line character device
+# encoding. See the QEMU man page for details.
+#
+# Since: 0.14
+##
+{ 'struct': 'ChardevInfo',
+ 'data': { 'label': 'str',
+ 'filename': 'str',
+ 'frontend-open': 'bool' } }
+
+##
+# @query-chardev:
+#
+# Returns information about current character devices.
+#
+# Returns: a list of @ChardevInfo
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-chardev" }
+# <- {
+# "return": [
+# {
+# "label": "charchannel0",
+# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.agent,server=on",
+# "frontend-open": false
+# },
+# {
+# "label": "charmonitor",
+# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.monitor,server=on",
+# "frontend-open": true
+# },
+# {
+# "label": "charserial0",
+# "filename": "pty:/dev/pts/2",
+# "frontend-open": true
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-chardev', 'returns': ['ChardevInfo'],
+ 'allow-preconfig': true }
+
+##
+# @ChardevBackendInfo:
+#
+# Information about a character device backend
+#
+# @name: The backend name
+#
+# Since: 2.0
+##
+{ 'struct': 'ChardevBackendInfo', 'data': {'name': 'str'} }
+
+##
+# @query-chardev-backends:
+#
+# Returns information about character device backends.
+#
+# Returns: a list of @ChardevBackendInfo
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-chardev-backends" }
+# <- {
+# "return":[
+# {
+# "name":"udp"
+# },
+# {
+# "name":"tcp"
+# },
+# {
+# "name":"unix"
+# },
+# {
+# "name":"spiceport"
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] }
+
+##
+# @DataFormat:
+#
+# An enumeration of data format.
+#
+# @utf8: Data is a UTF-8 string (RFC 3629)
+#
+# @base64: Data is Base64 encoded binary (RFC 3548)
+#
+# Since: 1.4
+##
+{ 'enum': 'DataFormat',
+ 'data': [ 'utf8', 'base64' ] }
+
+##
+# @ringbuf-write:
+#
+# Write to a ring buffer character device.
+#
+# @device: the ring buffer character device name
+#
+# @data: data to write
+#
+# @format: data encoding (default 'utf8').
+#
+# - base64: data must be base64 encoded text. Its binary
+# decoding gets written.
+# - utf8: data's UTF-8 encoding is written
+# - data itself is always Unicode regardless of format, like
+# any other string.
+#
+# Returns: Nothing on success
+#
+# Since: 1.4
+#
+# Example:
+#
+# -> { "execute": "ringbuf-write",
+# "arguments": { "device": "foo",
+# "data": "abcdefgh",
+# "format": "utf8" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'ringbuf-write',
+ 'data': { 'device': 'str',
+ 'data': 'str',
+ '*format': 'DataFormat'} }
+
+##
+# @ringbuf-read:
+#
+# Read from a ring buffer character device.
+#
+# @device: the ring buffer character device name
+#
+# @size: how many bytes to read at most
+#
+# @format: data encoding (default 'utf8').
+#
+# - base64: the data read is returned in base64 encoding.
+# - utf8: the data read is interpreted as UTF-8.
+# Bug: can screw up when the buffer contains invalid UTF-8
+# sequences, NUL characters, after the ring buffer lost
+# data, and when reading stops because the size limit is
+# reached.
+# - The return value is always Unicode regardless of format,
+# like any other string.
+#
+# Returns: data read from the device
+#
+# Since: 1.4
+#
+# Example:
+#
+# -> { "execute": "ringbuf-read",
+# "arguments": { "device": "foo",
+# "size": 1000,
+# "format": "utf8" } }
+# <- { "return": "abcdefgh" }
+#
+##
+{ 'command': 'ringbuf-read',
+ 'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
+ 'returns': 'str' }
+
+##
+# @ChardevCommon:
+#
+# Configuration shared across all chardev backends
+#
+# @logfile: The name of a logfile to save output
+# @logappend: true to append instead of truncate
+# (default to false to truncate)
+#
+# Since: 2.6
+##
+{ 'struct': 'ChardevCommon',
+ 'data': { '*logfile': 'str',
+ '*logappend': 'bool' } }
+
+##
+# @ChardevFile:
+#
+# Configuration info for file chardevs.
+#
+# @in: The name of the input file
+# @out: The name of the output file
+# @append: Open the file in append mode (default false to
+# truncate) (Since 2.6)
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevFile',
+ 'data': { '*in': 'str',
+ 'out': 'str',
+ '*append': 'bool' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevHostdev:
+#
+# Configuration info for device and pipe chardevs.
+#
+# @device: The name of the special file for the device,
+# i.e. /dev/ttyS0 on Unix or COM1: on Windows
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevHostdev',
+ 'data': { 'device': 'str' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevSocket:
+#
+# Configuration info for (stream) socket chardevs.
+#
+# @addr: socket address to listen on (server=true)
+# or connect to (server=false)
+# @tls-creds: the ID of the TLS credentials object (since 2.6)
+# @tls-authz: the ID of the QAuthZ authorization object against which
+# the client's x509 distinguished name will be validated. This
+# object is only resolved at time of use, so can be deleted
+# and recreated on the fly while the chardev server is active.
+# If missing, it will default to denying access (since 4.0)
+# @server: create server socket (default: true)
+# @wait: wait for incoming connection on server
+# sockets (default: false).
+# Silently ignored with server: false. This use is deprecated.
+# @nodelay: set TCP_NODELAY socket option (default: false)
+# @telnet: enable telnet protocol on server
+# sockets (default: false)
+# @tn3270: enable tn3270 protocol on server
+# sockets (default: false) (Since: 2.10)
+# @websocket: enable websocket protocol on server
+# sockets (default: false) (Since: 3.1)
+# @reconnect: For a client socket, if a socket is disconnected,
+# then attempt a reconnect after the given number of seconds.
+# Setting this to zero disables this function. (default: 0)
+# (Since: 2.2)
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevSocket',
+ 'data': { 'addr': 'SocketAddressLegacy',
+ '*tls-creds': 'str',
+ '*tls-authz' : 'str',
+ '*server': 'bool',
+ '*wait': 'bool',
+ '*nodelay': 'bool',
+ '*telnet': 'bool',
+ '*tn3270': 'bool',
+ '*websocket': 'bool',
+ '*reconnect': 'int' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevUdp:
+#
+# Configuration info for datagram socket chardevs.
+#
+# @remote: remote address
+# @local: local address
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevUdp',
+ 'data': { 'remote': 'SocketAddressLegacy',
+ '*local': 'SocketAddressLegacy' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevMux:
+#
+# Configuration info for mux chardevs.
+#
+# @chardev: name of the base chardev.
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevMux',
+ 'data': { 'chardev': 'str' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevStdio:
+#
+# Configuration info for stdio chardevs.
+#
+# @signal: Allow signals (such as SIGINT triggered by ^C)
+# be delivered to qemu. Default: true.
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevStdio',
+ 'data': { '*signal': 'bool' },
+ 'base': 'ChardevCommon' }
+
+
+##
+# @ChardevSpiceChannel:
+#
+# Configuration info for spice vm channel chardevs.
+#
+# @type: kind of channel (for example vdagent).
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpiceChannel',
+ 'data': { 'type': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @ChardevSpicePort:
+#
+# Configuration info for spice port chardevs.
+#
+# @fqdn: name of the channel (see docs/spice-port-fqdn.txt)
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpicePort',
+ 'data': { 'fqdn': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @ChardevVC:
+#
+# Configuration info for virtual console chardevs.
+#
+# @width: console width, in pixels
+# @height: console height, in pixels
+# @cols: console width, in chars
+# @rows: console height, in chars
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevVC',
+ 'data': { '*width': 'int',
+ '*height': 'int',
+ '*cols': 'int',
+ '*rows': 'int' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevRingbuf:
+#
+# Configuration info for ring buffer chardevs.
+#
+# @size: ring buffer size, must be power of two, default is 65536
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevRingbuf',
+ 'data': { '*size': 'int' },
+ 'base': 'ChardevCommon' }
+
+##
+# @ChardevQemuVDAgent:
+#
+# Configuration info for qemu vdagent implementation.
+#
+# @mouse: enable/disable mouse, default is enabled.
+# @clipboard: enable/disable clipboard, default is disabled.
+#
+# Since: 6.1
+#
+##
+{ 'struct': 'ChardevQemuVDAgent',
+ 'data': { '*mouse': 'bool',
+ '*clipboard': 'bool' },
+ 'base': 'ChardevCommon',
+ 'if': 'CONFIG_SPICE_PROTOCOL' }
+
+##
+# @ChardevBackendKind:
+#
+# @pipe: Since 1.5
+# @udp: Since 1.5
+# @mux: Since 1.5
+# @msmouse: Since 1.5
+# @wctablet: Since 2.9
+# @braille: Since 1.5
+# @testdev: Since 2.2
+# @stdio: Since 1.5
+# @console: Since 1.5
+# @spicevmc: Since 1.5
+# @spiceport: Since 1.5
+# @qemu-vdagent: Since 6.1
+# @vc: v1.5
+# @ringbuf: Since 1.6
+# @memory: Since 1.5
+#
+# Since: 1.4
+##
+{ 'enum': 'ChardevBackendKind',
+ 'data': [ 'file',
+ 'serial',
+ 'parallel',
+ 'pipe',
+ 'socket',
+ 'udp',
+ 'pty',
+ 'null',
+ 'mux',
+ 'msmouse',
+ 'wctablet',
+ 'braille',
+ 'testdev',
+ 'stdio',
+ 'console',
+ { 'name': 'spicevmc', 'if': 'CONFIG_SPICE' },
+ { 'name': 'spiceport', 'if': 'CONFIG_SPICE' },
+ { 'name': 'qemu-vdagent', 'if': 'CONFIG_SPICE_PROTOCOL' },
+ 'vc',
+ 'ringbuf',
+ # next one is just for compatibility
+ 'memory' ] }
+
+##
+# @ChardevFileWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevFileWrapper',
+ 'data': { 'data': 'ChardevFile' } }
+
+##
+# @ChardevHostdevWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevHostdevWrapper',
+ 'data': { 'data': 'ChardevHostdev' } }
+
+##
+# @ChardevSocketWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevSocketWrapper',
+ 'data': { 'data': 'ChardevSocket' } }
+
+##
+# @ChardevUdpWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevUdpWrapper',
+ 'data': { 'data': 'ChardevUdp' } }
+
+##
+# @ChardevCommonWrapper:
+#
+# Since: 2.6
+##
+{ 'struct': 'ChardevCommonWrapper',
+ 'data': { 'data': 'ChardevCommon' } }
+
+##
+# @ChardevMuxWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevMuxWrapper',
+ 'data': { 'data': 'ChardevMux' } }
+
+##
+# @ChardevStdioWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevStdioWrapper',
+ 'data': { 'data': 'ChardevStdio' } }
+
+##
+# @ChardevSpiceChannelWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpiceChannelWrapper',
+ 'data': { 'data': 'ChardevSpiceChannel' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @ChardevSpicePortWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpicePortWrapper',
+ 'data': { 'data': 'ChardevSpicePort' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @ChardevQemuVDAgentWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ChardevQemuVDAgentWrapper',
+ 'data': { 'data': 'ChardevQemuVDAgent' },
+ 'if': 'CONFIG_SPICE_PROTOCOL' }
+
+##
+# @ChardevVCWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevVCWrapper',
+ 'data': { 'data': 'ChardevVC' } }
+
+##
+# @ChardevRingbufWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevRingbufWrapper',
+ 'data': { 'data': 'ChardevRingbuf' } }
+
+##
+# @ChardevBackend:
+#
+# Configuration info for the new chardev backend.
+#
+# Since: 1.4
+##
+{ 'union': 'ChardevBackend',
+ 'base': { 'type': 'ChardevBackendKind' },
+ 'discriminator': 'type',
+ 'data': { 'file': 'ChardevFileWrapper',
+ 'serial': 'ChardevHostdevWrapper',
+ 'parallel': 'ChardevHostdevWrapper',
+ 'pipe': 'ChardevHostdevWrapper',
+ 'socket': 'ChardevSocketWrapper',
+ 'udp': 'ChardevUdpWrapper',
+ 'pty': 'ChardevCommonWrapper',
+ 'null': 'ChardevCommonWrapper',
+ 'mux': 'ChardevMuxWrapper',
+ 'msmouse': 'ChardevCommonWrapper',
+ 'wctablet': 'ChardevCommonWrapper',
+ 'braille': 'ChardevCommonWrapper',
+ 'testdev': 'ChardevCommonWrapper',
+ 'stdio': 'ChardevStdioWrapper',
+ 'console': 'ChardevCommonWrapper',
+ 'spicevmc': { 'type': 'ChardevSpiceChannelWrapper',
+ 'if': 'CONFIG_SPICE' },
+ 'spiceport': { 'type': 'ChardevSpicePortWrapper',
+ 'if': 'CONFIG_SPICE' },
+ 'qemu-vdagent': { 'type': 'ChardevQemuVDAgentWrapper',
+ 'if': 'CONFIG_SPICE_PROTOCOL' },
+ 'vc': 'ChardevVCWrapper',
+ 'ringbuf': 'ChardevRingbufWrapper',
+ # next one is just for compatibility
+ 'memory': 'ChardevRingbufWrapper' } }
+
+##
+# @ChardevReturn:
+#
+# Return info about the chardev backend just created.
+#
+# @pty: name of the slave pseudoterminal device, present if
+# and only if a chardev of type 'pty' was created
+#
+# Since: 1.4
+##
+{ 'struct' : 'ChardevReturn',
+ 'data': { '*pty': 'str' } }
+
+##
+# @chardev-add:
+#
+# Add a character device backend
+#
+# @id: the chardev's ID, must be unique
+# @backend: backend type and parameters
+#
+# Returns: ChardevReturn.
+#
+# Since: 1.4
+#
+# Example:
+#
+# -> { "execute" : "chardev-add",
+# "arguments" : { "id" : "foo",
+# "backend" : { "type" : "null", "data" : {} } } }
+# <- { "return": {} }
+#
+# -> { "execute" : "chardev-add",
+# "arguments" : { "id" : "bar",
+# "backend" : { "type" : "file",
+# "data" : { "out" : "/tmp/bar.log" } } } }
+# <- { "return": {} }
+#
+# -> { "execute" : "chardev-add",
+# "arguments" : { "id" : "baz",
+# "backend" : { "type" : "pty", "data" : {} } } }
+# <- { "return": { "pty" : "/dev/pty/42" } }
+#
+##
+{ 'command': 'chardev-add',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
+ 'returns': 'ChardevReturn' }
+
+##
+# @chardev-change:
+#
+# Change a character device backend
+#
+# @id: the chardev's ID, must exist
+# @backend: new backend type and parameters
+#
+# Returns: ChardevReturn.
+#
+# Since: 2.10
+#
+# Example:
+#
+# -> { "execute" : "chardev-change",
+# "arguments" : { "id" : "baz",
+# "backend" : { "type" : "pty", "data" : {} } } }
+# <- { "return": { "pty" : "/dev/pty/42" } }
+#
+# -> {"execute" : "chardev-change",
+# "arguments" : {
+# "id" : "charchannel2",
+# "backend" : {
+# "type" : "socket",
+# "data" : {
+# "addr" : {
+# "type" : "unix" ,
+# "data" : {
+# "path" : "/tmp/charchannel2.socket"
+# }
+# },
+# "server" : true,
+# "wait" : false }}}}
+# <- {"return": {}}
+#
+##
+{ 'command': 'chardev-change',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
+ 'returns': 'ChardevReturn' }
+
+##
+# @chardev-remove:
+#
+# Remove a character device backend
+#
+# @id: the chardev's ID, must exist and not be in use
+#
+# Returns: Nothing on success
+#
+# Since: 1.4
+#
+# Example:
+#
+# -> { "execute": "chardev-remove", "arguments": { "id" : "foo" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'chardev-remove',
+ 'data': { 'id': 'str' } }
+
+##
+# @chardev-send-break:
+#
+# Send a break to a character device
+#
+# @id: the chardev's ID, must exist
+#
+# Returns: Nothing on success
+#
+# Since: 2.10
+#
+# Example:
+#
+# -> { "execute": "chardev-send-break", "arguments": { "id" : "foo" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'chardev-send-break',
+ 'data': { 'id': 'str' } }
+
+##
+# @VSERPORT_CHANGE:
+#
+# Emitted when the guest opens or closes a virtio-serial port.
+#
+# @id: device identifier of the virtio-serial port
+#
+# @open: true if the guest has opened the virtio-serial port
+#
+# Note: This event is rate-limited.
+#
+# Since: 2.1
+#
+# Example:
+#
+# <- { "event": "VSERPORT_CHANGE",
+# "data": { "id": "channel0", "open": true },
+# "timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
+#
+##
+{ 'event': 'VSERPORT_CHANGE',
+ 'data': { 'id': 'str',
+ 'open': 'bool' } }
diff --git a/qapi/common.json b/qapi/common.json
new file mode 100644
index 000000000..412cc4f5a
--- /dev/null
+++ b/qapi/common.json
@@ -0,0 +1,210 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = Common data types
+##
+
+##
+# @IoOperationType:
+#
+# An enumeration of the I/O operation types
+#
+# @read: read operation
+#
+# @write: write operation
+#
+# Since: 2.1
+##
+{ 'enum': 'IoOperationType',
+ 'data': [ 'read', 'write' ] }
+
+##
+# @OnOffAuto:
+#
+# An enumeration of three options: on, off, and auto
+#
+# @auto: QEMU selects the value between on and off
+#
+# @on: Enabled
+#
+# @off: Disabled
+#
+# Since: 2.2
+##
+{ 'enum': 'OnOffAuto',
+ 'data': [ 'auto', 'on', 'off' ] }
+
+##
+# @OnOffSplit:
+#
+# An enumeration of three values: on, off, and split
+#
+# @on: Enabled
+#
+# @off: Disabled
+#
+# @split: Mixed
+#
+# Since: 2.6
+##
+{ 'enum': 'OnOffSplit',
+ 'data': [ 'on', 'off', 'split' ] }
+
+##
+# @String:
+#
+# A fat type wrapping 'str', to be embedded in lists.
+#
+# Since: 1.2
+##
+{ 'struct': 'String',
+ 'data': {
+ 'str': 'str' } }
+
+##
+# @StrOrNull:
+#
+# This is a string value or the explicit lack of a string (null
+# pointer in C). Intended for cases when 'optional absent' already
+# has a different meaning.
+#
+# @s: the string value
+# @n: no string value
+#
+# Since: 2.10
+##
+{ 'alternate': 'StrOrNull',
+ 'data': { 's': 'str',
+ 'n': 'null' } }
+
+##
+# @OffAutoPCIBAR:
+#
+# An enumeration of options for specifying a PCI BAR
+#
+# @off: The specified feature is disabled
+#
+# @auto: The PCI BAR for the feature is automatically selected
+#
+# @bar0: PCI BAR0 is used for the feature
+#
+# @bar1: PCI BAR1 is used for the feature
+#
+# @bar2: PCI BAR2 is used for the feature
+#
+# @bar3: PCI BAR3 is used for the feature
+#
+# @bar4: PCI BAR4 is used for the feature
+#
+# @bar5: PCI BAR5 is used for the feature
+#
+# Since: 2.12
+##
+{ 'enum': 'OffAutoPCIBAR',
+ 'data': [ 'off', 'auto', 'bar0', 'bar1', 'bar2', 'bar3', 'bar4', 'bar5' ] }
+
+##
+# @PCIELinkSpeed:
+#
+# An enumeration of PCIe link speeds in units of GT/s
+#
+# @2_5: 2.5GT/s
+#
+# @5: 5.0GT/s
+#
+# @8: 8.0GT/s
+#
+# @16: 16.0GT/s
+#
+# Since: 4.0
+##
+{ 'enum': 'PCIELinkSpeed',
+ 'data': [ '2_5', '5', '8', '16' ] }
+
+##
+# @PCIELinkWidth:
+#
+# An enumeration of PCIe link width
+#
+# @1: x1
+#
+# @2: x2
+#
+# @4: x4
+#
+# @8: x8
+#
+# @12: x12
+#
+# @16: x16
+#
+# @32: x32
+#
+# Since: 4.0
+##
+{ 'enum': 'PCIELinkWidth',
+ 'data': [ '1', '2', '4', '8', '12', '16', '32' ] }
+
+##
+# @HostMemPolicy:
+#
+# Host memory policy types
+#
+# @default: restore default policy, remove any nondefault policy
+#
+# @preferred: set the preferred host nodes for allocation
+#
+# @bind: a strict policy that restricts memory allocation to the
+# host nodes specified
+#
+# @interleave: memory allocations are interleaved across the set
+# of host nodes specified
+#
+# Since: 2.1
+##
+{ 'enum': 'HostMemPolicy',
+ 'data': [ 'default', 'preferred', 'bind', 'interleave' ] }
+
+##
+# @NetFilterDirection:
+#
+# Indicates whether a netfilter is attached to a netdev's transmit queue or
+# receive queue or both.
+#
+# @all: the filter is attached both to the receive and the transmit
+# queue of the netdev (default).
+#
+# @rx: the filter is attached to the receive queue of the netdev,
+# where it will receive packets sent to the netdev.
+#
+# @tx: the filter is attached to the transmit queue of the netdev,
+# where it will receive packets sent by the netdev.
+#
+# Since: 2.5
+##
+{ 'enum': 'NetFilterDirection',
+ 'data': [ 'all', 'rx', 'tx' ] }
+
+##
+# @GrabToggleKeys:
+#
+# Keys to toggle input-linux between host and guest.
+#
+# Since: 4.0
+#
+##
+{ 'enum': 'GrabToggleKeys',
+ 'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock',
+ 'ctrl-scrolllock' ] }
+
+##
+# @HumanReadableText:
+#
+# @human-readable-text: Formatted output intended for humans.
+#
+# Since: 6.2
+#
+##
+{ 'struct': 'HumanReadableText',
+ 'data': { 'human-readable-text': 'str' } }
diff --git a/qapi/compat.json b/qapi/compat.json
new file mode 100644
index 000000000..dd7261ae2
--- /dev/null
+++ b/qapi/compat.json
@@ -0,0 +1,61 @@
+# -*- Mode: Python -*-
+
+##
+# = Compatibility policy
+##
+
+##
+# @CompatPolicyInput:
+#
+# Policy for handling "funny" input.
+#
+# @accept: Accept silently
+# @reject: Reject with an error
+# @crash: abort() the process
+#
+# Since: 6.0
+##
+{ 'enum': 'CompatPolicyInput',
+ 'data': [ 'accept', 'reject', 'crash' ] }
+
+##
+# @CompatPolicyOutput:
+#
+# Policy for handling "funny" output.
+#
+# @accept: Pass on unchanged
+# @hide: Filter out
+#
+# Since: 6.0
+##
+{ 'enum': 'CompatPolicyOutput',
+ 'data': [ 'accept', 'hide' ] }
+
+##
+# @CompatPolicy:
+#
+# Policy for handling deprecated management interfaces.
+#
+# This is intended for testing users of the management interfaces.
+#
+# Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged
+# with feature 'deprecated'. We may want to extend it to cover
+# semantic aspects, CLI, and experimental features.
+#
+# Limitation: deprecated-output policy @hide is not implemented for
+# enumeration values. They behave the same as with policy @accept.
+#
+# @deprecated-input: how to handle deprecated input (default 'accept')
+# @deprecated-output: how to handle deprecated output (default 'accept')
+# @unstable-input: how to handle unstable input (default 'accept')
+# (since 6.2)
+# @unstable-output: how to handle unstable output (default 'accept')
+# (since 6.2)
+#
+# Since: 6.0
+##
+{ 'struct': 'CompatPolicy',
+ 'data': { '*deprecated-input': 'CompatPolicyInput',
+ '*deprecated-output': 'CompatPolicyOutput',
+ '*unstable-input': 'CompatPolicyInput',
+ '*unstable-output': 'CompatPolicyOutput' } }
diff --git a/qapi/control.json b/qapi/control.json
new file mode 100644
index 000000000..71a838d49
--- /dev/null
+++ b/qapi/control.json
@@ -0,0 +1,215 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = QMP monitor control
+##
+
+##
+# @qmp_capabilities:
+#
+# Enable QMP capabilities.
+#
+# Arguments:
+#
+# @enable: An optional list of QMPCapability values to enable. The
+# client must not enable any capability that is not
+# mentioned in the QMP greeting message. If the field is not
+# provided, it means no QMP capabilities will be enabled.
+# (since 2.12)
+#
+# Example:
+#
+# -> { "execute": "qmp_capabilities",
+# "arguments": { "enable": [ "oob" ] } }
+# <- { "return": {} }
+#
+# Notes: This command is valid exactly when first connecting: it must be
+# issued before any other command will be accepted, and will fail once the
+# monitor is accepting other commands. (see qemu docs/interop/qmp-spec.txt)
+#
+# The QMP client needs to explicitly enable QMP capabilities, otherwise
+# all the QMP capabilities will be turned off by default.
+#
+# Since: 0.13
+#
+##
+{ 'command': 'qmp_capabilities',
+ 'data': { '*enable': [ 'QMPCapability' ] },
+ 'allow-preconfig': true }
+
+##
+# @QMPCapability:
+#
+# Enumeration of capabilities to be advertised during initial client
+# connection, used for agreeing on particular QMP extension behaviors.
+#
+# @oob: QMP ability to support out-of-band requests.
+# (Please refer to qmp-spec.txt for more information on OOB)
+#
+# Since: 2.12
+#
+##
+{ 'enum': 'QMPCapability',
+ 'data': [ 'oob' ] }
+
+##
+# @VersionTriple:
+#
+# A three-part version number.
+#
+# @major: The major version number.
+#
+# @minor: The minor version number.
+#
+# @micro: The micro version number.
+#
+# Since: 2.4
+##
+{ 'struct': 'VersionTriple',
+ 'data': {'major': 'int', 'minor': 'int', 'micro': 'int'} }
+
+
+##
+# @VersionInfo:
+#
+# A description of QEMU's version.
+#
+# @qemu: The version of QEMU. By current convention, a micro
+# version of 50 signifies a development branch. A micro version
+# greater than or equal to 90 signifies a release candidate for
+# the next minor version. A micro version of less than 50
+# signifies a stable release.
+#
+# @package: QEMU will always set this field to an empty string. Downstream
+# versions of QEMU should set this to a non-empty string. The
+# exact format depends on the downstream however it highly
+# recommended that a unique name is used.
+#
+# Since: 0.14
+##
+{ 'struct': 'VersionInfo',
+ 'data': {'qemu': 'VersionTriple', 'package': 'str'} }
+
+##
+# @query-version:
+#
+# Returns the current version of QEMU.
+#
+# Returns: A @VersionInfo object describing the current version of QEMU.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-version" }
+# <- {
+# "return":{
+# "qemu":{
+# "major":0,
+# "minor":11,
+# "micro":5
+# },
+# "package":""
+# }
+# }
+#
+##
+{ 'command': 'query-version', 'returns': 'VersionInfo',
+ 'allow-preconfig': true }
+
+##
+# @CommandInfo:
+#
+# Information about a QMP command
+#
+# @name: The command name
+#
+# Since: 0.14
+##
+{ 'struct': 'CommandInfo', 'data': {'name': 'str'} }
+
+##
+# @query-commands:
+#
+# Return a list of supported QMP commands by this server
+#
+# Returns: A list of @CommandInfo for all supported commands
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-commands" }
+# <- {
+# "return":[
+# {
+# "name":"query-balloon"
+# },
+# {
+# "name":"system_powerdown"
+# }
+# ]
+# }
+#
+# Note: This example has been shortened as the real response is too long.
+#
+##
+{ 'command': 'query-commands', 'returns': ['CommandInfo'],
+ 'allow-preconfig': true }
+
+##
+# @quit:
+#
+# This command will cause the QEMU process to exit gracefully. While every
+# attempt is made to send the QMP response before terminating, this is not
+# guaranteed. When using this interface, a premature EOF would not be
+# unexpected.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "quit" }
+# <- { "return": {} }
+##
+{ 'command': 'quit',
+ 'allow-preconfig': true }
+
+##
+# @MonitorMode:
+#
+# An enumeration of monitor modes.
+#
+# @readline: HMP monitor (human-oriented command line interface)
+#
+# @control: QMP monitor (JSON-based machine interface)
+#
+# Since: 5.0
+##
+{ 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] }
+
+##
+# @MonitorOptions:
+#
+# Options to be used for adding a new monitor.
+#
+# @id: Name of the monitor
+#
+# @mode: Selects the monitor mode (default: readline in the system
+# emulator, control in qemu-storage-daemon)
+#
+# @pretty: Enables pretty printing (QMP only)
+#
+# @chardev: Name of a character device to expose the monitor on
+#
+# Since: 5.0
+##
+{ 'struct': 'MonitorOptions',
+ 'data': {
+ '*id': 'str',
+ '*mode': 'MonitorMode',
+ '*pretty': 'bool',
+ 'chardev': 'str'
+ } }
diff --git a/qapi/crypto.json b/qapi/crypto.json
new file mode 100644
index 000000000..1ec54c15c
--- /dev/null
+++ b/qapi/crypto.json
@@ -0,0 +1,542 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Cryptography
+##
+
+##
+# @QCryptoTLSCredsEndpoint:
+#
+# The type of network endpoint that will be using the credentials.
+# Most types of credential require different setup / structures
+# depending on whether they will be used in a server versus a
+# client.
+#
+# @client: the network endpoint is acting as the client
+#
+# @server: the network endpoint is acting as the server
+#
+# Since: 2.5
+##
+{ 'enum': 'QCryptoTLSCredsEndpoint',
+ 'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT',
+ 'data': ['client', 'server']}
+
+
+##
+# @QCryptoSecretFormat:
+#
+# The data format that the secret is provided in
+#
+# @raw: raw bytes. When encoded in JSON only valid UTF-8 sequences can be used
+# @base64: arbitrary base64 encoded binary data
+# Since: 2.6
+##
+{ 'enum': 'QCryptoSecretFormat',
+ 'prefix': 'QCRYPTO_SECRET_FORMAT',
+ 'data': ['raw', 'base64']}
+
+
+##
+# @QCryptoHashAlgorithm:
+#
+# The supported algorithms for computing content digests
+#
+# @md5: MD5. Should not be used in any new code, legacy compat only
+# @sha1: SHA-1. Should not be used in any new code, legacy compat only
+# @sha224: SHA-224. (since 2.7)
+# @sha256: SHA-256. Current recommended strong hash.
+# @sha384: SHA-384. (since 2.7)
+# @sha512: SHA-512. (since 2.7)
+# @ripemd160: RIPEMD-160. (since 2.7)
+# Since: 2.6
+##
+{ 'enum': 'QCryptoHashAlgorithm',
+ 'prefix': 'QCRYPTO_HASH_ALG',
+ 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']}
+
+
+##
+# @QCryptoCipherAlgorithm:
+#
+# The supported algorithms for content encryption ciphers
+#
+# @aes-128: AES with 128 bit / 16 byte keys
+# @aes-192: AES with 192 bit / 24 byte keys
+# @aes-256: AES with 256 bit / 32 byte keys
+# @des: DES with 56 bit / 8 byte keys. Do not use except in VNC. (since 6.1)
+# @3des: 3DES(EDE) with 192 bit / 24 byte keys (since 2.9)
+# @cast5-128: Cast5 with 128 bit / 16 byte keys
+# @serpent-128: Serpent with 128 bit / 16 byte keys
+# @serpent-192: Serpent with 192 bit / 24 byte keys
+# @serpent-256: Serpent with 256 bit / 32 byte keys
+# @twofish-128: Twofish with 128 bit / 16 byte keys
+# @twofish-192: Twofish with 192 bit / 24 byte keys
+# @twofish-256: Twofish with 256 bit / 32 byte keys
+# Since: 2.6
+##
+{ 'enum': 'QCryptoCipherAlgorithm',
+ 'prefix': 'QCRYPTO_CIPHER_ALG',
+ 'data': ['aes-128', 'aes-192', 'aes-256',
+ 'des', '3des',
+ 'cast5-128',
+ 'serpent-128', 'serpent-192', 'serpent-256',
+ 'twofish-128', 'twofish-192', 'twofish-256']}
+
+
+##
+# @QCryptoCipherMode:
+#
+# The supported modes for content encryption ciphers
+#
+# @ecb: Electronic Code Book
+# @cbc: Cipher Block Chaining
+# @xts: XEX with tweaked code book and ciphertext stealing
+# @ctr: Counter (Since 2.8)
+# Since: 2.6
+##
+{ 'enum': 'QCryptoCipherMode',
+ 'prefix': 'QCRYPTO_CIPHER_MODE',
+ 'data': ['ecb', 'cbc', 'xts', 'ctr']}
+
+
+##
+# @QCryptoIVGenAlgorithm:
+#
+# The supported algorithms for generating initialization
+# vectors for full disk encryption. The 'plain' generator
+# should not be used for disks with sector numbers larger
+# than 2^32, except where compatibility with pre-existing
+# Linux dm-crypt volumes is required.
+#
+# @plain: 64-bit sector number truncated to 32-bits
+# @plain64: 64-bit sector number
+# @essiv: 64-bit sector number encrypted with a hash of the encryption key
+# Since: 2.6
+##
+{ 'enum': 'QCryptoIVGenAlgorithm',
+ 'prefix': 'QCRYPTO_IVGEN_ALG',
+ 'data': ['plain', 'plain64', 'essiv']}
+
+##
+# @QCryptoBlockFormat:
+#
+# The supported full disk encryption formats
+#
+# @qcow: QCow/QCow2 built-in AES-CBC encryption. Use only
+# for liberating data from old images.
+# @luks: LUKS encryption format. Recommended for new images
+#
+# Since: 2.6
+##
+{ 'enum': 'QCryptoBlockFormat',
+# 'prefix': 'QCRYPTO_BLOCK_FORMAT',
+ 'data': ['qcow', 'luks']}
+
+##
+# @QCryptoBlockOptionsBase:
+#
+# The common options that apply to all full disk
+# encryption formats
+#
+# @format: the encryption format
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsBase',
+ 'data': { 'format': 'QCryptoBlockFormat' }}
+
+##
+# @QCryptoBlockOptionsQCow:
+#
+# The options that apply to QCow/QCow2 AES-CBC encryption format
+#
+# @key-secret: the ID of a QCryptoSecret object providing the
+# decryption key. Mandatory except when probing image for
+# metadata only.
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsQCow',
+ 'data': { '*key-secret': 'str' }}
+
+##
+# @QCryptoBlockOptionsLUKS:
+#
+# The options that apply to LUKS encryption format
+#
+# @key-secret: the ID of a QCryptoSecret object providing the
+# decryption key. Mandatory except when probing image for
+# metadata only.
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsLUKS',
+ 'data': { '*key-secret': 'str' }}
+
+
+##
+# @QCryptoBlockCreateOptionsLUKS:
+#
+# The options that apply to LUKS encryption format initialization
+#
+# @cipher-alg: the cipher algorithm for data encryption
+# Currently defaults to 'aes-256'.
+# @cipher-mode: the cipher mode for data encryption
+# Currently defaults to 'xts'
+# @ivgen-alg: the initialization vector generator
+# Currently defaults to 'plain64'
+# @ivgen-hash-alg: the initialization vector generator hash
+# Currently defaults to 'sha256'
+# @hash-alg: the master key hash algorithm
+# Currently defaults to 'sha256'
+# @iter-time: number of milliseconds to spend in
+# PBKDF passphrase processing. Currently defaults
+# to 2000. (since 2.8)
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockCreateOptionsLUKS',
+ 'base': 'QCryptoBlockOptionsLUKS',
+ 'data': { '*cipher-alg': 'QCryptoCipherAlgorithm',
+ '*cipher-mode': 'QCryptoCipherMode',
+ '*ivgen-alg': 'QCryptoIVGenAlgorithm',
+ '*ivgen-hash-alg': 'QCryptoHashAlgorithm',
+ '*hash-alg': 'QCryptoHashAlgorithm',
+ '*iter-time': 'int'}}
+
+
+##
+# @QCryptoBlockOpenOptions:
+#
+# The options that are available for all encryption formats
+# when opening an existing volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockOpenOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcow': 'QCryptoBlockOptionsQCow',
+ 'luks': 'QCryptoBlockOptionsLUKS' } }
+
+
+##
+# @QCryptoBlockCreateOptions:
+#
+# The options that are available for all encryption formats
+# when initializing a new volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockCreateOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcow': 'QCryptoBlockOptionsQCow',
+ 'luks': 'QCryptoBlockCreateOptionsLUKS' } }
+
+
+##
+# @QCryptoBlockInfoBase:
+#
+# The common information that applies to all full disk
+# encryption formats
+#
+# @format: the encryption format
+#
+# Since: 2.7
+##
+{ 'struct': 'QCryptoBlockInfoBase',
+ 'data': { 'format': 'QCryptoBlockFormat' }}
+
+
+##
+# @QCryptoBlockInfoLUKSSlot:
+#
+# Information about the LUKS block encryption key
+# slot options
+#
+# @active: whether the key slot is currently in use
+# @key-offset: offset to the key material in bytes
+# @iters: number of PBKDF2 iterations for key material
+# @stripes: number of stripes for splitting key material
+#
+# Since: 2.7
+##
+{ 'struct': 'QCryptoBlockInfoLUKSSlot',
+ 'data': {'active': 'bool',
+ '*iters': 'int',
+ '*stripes': 'int',
+ 'key-offset': 'int' } }
+
+
+##
+# @QCryptoBlockInfoLUKS:
+#
+# Information about the LUKS block encryption options
+#
+# @cipher-alg: the cipher algorithm for data encryption
+# @cipher-mode: the cipher mode for data encryption
+# @ivgen-alg: the initialization vector generator
+# @ivgen-hash-alg: the initialization vector generator hash
+# @hash-alg: the master key hash algorithm
+# @payload-offset: offset to the payload data in bytes
+# @master-key-iters: number of PBKDF2 iterations for key material
+# @uuid: unique identifier for the volume
+# @slots: information about each key slot
+#
+# Since: 2.7
+##
+{ 'struct': 'QCryptoBlockInfoLUKS',
+ 'data': {'cipher-alg': 'QCryptoCipherAlgorithm',
+ 'cipher-mode': 'QCryptoCipherMode',
+ 'ivgen-alg': 'QCryptoIVGenAlgorithm',
+ '*ivgen-hash-alg': 'QCryptoHashAlgorithm',
+ 'hash-alg': 'QCryptoHashAlgorithm',
+ 'payload-offset': 'int',
+ 'master-key-iters': 'int',
+ 'uuid': 'str',
+ 'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }}
+
+##
+# @QCryptoBlockInfo:
+#
+# Information about the block encryption options
+#
+# Since: 2.7
+##
+{ 'union': 'QCryptoBlockInfo',
+ 'base': 'QCryptoBlockInfoBase',
+ 'discriminator': 'format',
+ 'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
+
+##
+# @QCryptoBlockLUKSKeyslotState:
+#
+# Defines state of keyslots that are affected by the update
+#
+# @active: The slots contain the given password and marked as active
+# @inactive: The slots are erased (contain garbage) and marked as inactive
+#
+# Since: 5.1
+##
+{ 'enum': 'QCryptoBlockLUKSKeyslotState',
+ 'data': [ 'active', 'inactive' ] }
+
+
+##
+# @QCryptoBlockAmendOptionsLUKS:
+#
+# This struct defines the update parameters that activate/de-activate set
+# of keyslots
+#
+# @state: the desired state of the keyslots
+#
+# @new-secret: The ID of a QCryptoSecret object providing the password to be
+# written into added active keyslots
+#
+# @old-secret: Optional (for deactivation only)
+# If given will deactivate all keyslots that
+# match password located in QCryptoSecret with this ID
+#
+# @iter-time: Optional (for activation only)
+# Number of milliseconds to spend in
+# PBKDF passphrase processing for the newly activated keyslot.
+# Currently defaults to 2000.
+#
+# @keyslot: Optional. ID of the keyslot to activate/deactivate.
+# For keyslot activation, keyslot should not be active already
+# (this is unsafe to update an active keyslot),
+# but possible if 'force' parameter is given.
+# If keyslot is not given, first free keyslot will be written.
+#
+# For keyslot deactivation, this parameter specifies the exact
+# keyslot to deactivate
+#
+# @secret: Optional. The ID of a QCryptoSecret object providing the
+# password to use to retrieve current master key.
+# Defaults to the same secret that was used to open the image
+#
+#
+# Since 5.1
+##
+{ 'struct': 'QCryptoBlockAmendOptionsLUKS',
+ 'data': { 'state': 'QCryptoBlockLUKSKeyslotState',
+ '*new-secret': 'str',
+ '*old-secret': 'str',
+ '*keyslot': 'int',
+ '*iter-time': 'int',
+ '*secret': 'str' } }
+
+##
+# @QCryptoBlockAmendOptions:
+#
+# The options that are available for all encryption formats
+# when amending encryption settings
+#
+# Since: 5.1
+##
+{ 'union': 'QCryptoBlockAmendOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': {
+ 'luks': 'QCryptoBlockAmendOptionsLUKS' } }
+
+##
+# @SecretCommonProperties:
+#
+# Properties for objects of classes derived from secret-common.
+#
+# @loaded: if true, the secret is loaded immediately when applying this option
+# and will probably fail when processing the next option. Don't use;
+# only provided for compatibility. (default: false)
+#
+# @format: the data format that the secret is provided in (default: raw)
+#
+# @keyid: the name of another secret that should be used to decrypt the
+# provided data. If not present, the data is assumed to be unencrypted.
+#
+# @iv: the random initialization vector used for encryption of this particular
+# secret. Should be a base64 encrypted string of the 16-byte IV. Mandatory
+# if @keyid is given. Ignored if @keyid is absent.
+#
+# Features:
+# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense,
+# and false is already the default.
+#
+# Since: 2.6
+##
+{ 'struct': 'SecretCommonProperties',
+ 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
+ '*format': 'QCryptoSecretFormat',
+ '*keyid': 'str',
+ '*iv': 'str' } }
+
+##
+# @SecretProperties:
+#
+# Properties for secret objects.
+#
+# Either @data or @file must be provided, but not both.
+#
+# @data: the associated with the secret from
+#
+# @file: the filename to load the data associated with the secret from
+#
+# Since: 2.6
+##
+{ 'struct': 'SecretProperties',
+ 'base': 'SecretCommonProperties',
+ 'data': { '*data': 'str',
+ '*file': 'str' } }
+
+##
+# @SecretKeyringProperties:
+#
+# Properties for secret_keyring objects.
+#
+# @serial: serial number that identifies a key to get from the kernel
+#
+# Since: 5.1
+##
+{ 'struct': 'SecretKeyringProperties',
+ 'base': 'SecretCommonProperties',
+ 'data': { 'serial': 'int32' } }
+
+##
+# @TlsCredsProperties:
+#
+# Properties for objects of classes derived from tls-creds.
+#
+# @verify-peer: if true the peer credentials will be verified once the
+# handshake is completed. This is a no-op for anonymous
+# credentials. (default: true)
+#
+# @dir: the path of the directory that contains the credential files
+#
+# @endpoint: whether the QEMU network backend that uses the credentials will be
+# acting as a client or as a server (default: client)
+#
+# @priority: a gnutls priority string as described at
+# https://gnutls.org/manual/html_node/Priority-Strings.html
+#
+# Since: 2.5
+##
+{ 'struct': 'TlsCredsProperties',
+ 'data': { '*verify-peer': 'bool',
+ '*dir': 'str',
+ '*endpoint': 'QCryptoTLSCredsEndpoint',
+ '*priority': 'str' } }
+
+##
+# @TlsCredsAnonProperties:
+#
+# Properties for tls-creds-anon objects.
+#
+# @loaded: if true, the credentials are loaded immediately when applying this
+# option and will ignore options that are processed later. Don't use;
+# only provided for compatibility. (default: false)
+#
+# Features:
+# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense,
+# and false is already the default.
+#
+# Since: 2.5
+##
+{ 'struct': 'TlsCredsAnonProperties',
+ 'base': 'TlsCredsProperties',
+ 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] } } }
+
+##
+# @TlsCredsPskProperties:
+#
+# Properties for tls-creds-psk objects.
+#
+# @loaded: if true, the credentials are loaded immediately when applying this
+# option and will ignore options that are processed later. Don't use;
+# only provided for compatibility. (default: false)
+#
+# @username: the username which will be sent to the server. For clients only.
+# If absent, "qemu" is sent and the property will read back as an
+# empty string.
+#
+# Features:
+# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense,
+# and false is already the default.
+#
+# Since: 3.0
+##
+{ 'struct': 'TlsCredsPskProperties',
+ 'base': 'TlsCredsProperties',
+ 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
+ '*username': 'str' } }
+
+##
+# @TlsCredsX509Properties:
+#
+# Properties for tls-creds-x509 objects.
+#
+# @loaded: if true, the credentials are loaded immediately when applying this
+# option and will ignore options that are processed later. Don't use;
+# only provided for compatibility. (default: false)
+#
+# @sanity-check: if true, perform some sanity checks before using the
+# credentials (default: true)
+#
+# @passwordid: For the server-key.pem and client-key.pem files which contain
+# sensitive private keys, it is possible to use an encrypted
+# version by providing the @passwordid parameter. This provides
+# the ID of a previously created secret object containing the
+# password for decryption.
+#
+# Features:
+# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense,
+# and false is already the default.
+#
+# Since: 2.5
+##
+{ 'struct': 'TlsCredsX509Properties',
+ 'base': 'TlsCredsProperties',
+ 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
+ '*sanity-check': 'bool',
+ '*passwordid': 'str' } }
diff --git a/qapi/dump.json b/qapi/dump.json
new file mode 100644
index 000000000..f7c4267e3
--- /dev/null
+++ b/qapi/dump.json
@@ -0,0 +1,201 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Dump guest memory
+##
+
+##
+# @DumpGuestMemoryFormat:
+#
+# An enumeration of guest-memory-dump's format.
+#
+# @elf: elf format
+#
+# @kdump-zlib: kdump-compressed format with zlib-compressed
+#
+# @kdump-lzo: kdump-compressed format with lzo-compressed
+#
+# @kdump-snappy: kdump-compressed format with snappy-compressed
+#
+# @win-dmp: Windows full crashdump format,
+# can be used instead of ELF converting (since 2.13)
+#
+# Since: 2.0
+##
+{ 'enum': 'DumpGuestMemoryFormat',
+ 'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] }
+
+##
+# @dump-guest-memory:
+#
+# Dump guest's memory to vmcore. It is a synchronous operation that can take
+# very long depending on the amount of guest memory.
+#
+# @paging: if true, do paging to get guest's memory mapping. This allows
+# using gdb to process the core file.
+#
+# IMPORTANT: this option can make QEMU allocate several gigabytes
+# of RAM. This can happen for a large guest, or a
+# malicious guest pretending to be large.
+#
+# Also, paging=true has the following limitations:
+#
+# 1. The guest may be in a catastrophic state or can have corrupted
+# memory, which cannot be trusted
+# 2. The guest can be in real-mode even if paging is enabled. For
+# example, the guest uses ACPI to sleep, and ACPI sleep state
+# goes in real-mode
+# 3. Currently only supported on i386 and x86_64.
+#
+# @protocol: the filename or file descriptor of the vmcore. The supported
+# protocols are:
+#
+# 1. file: the protocol starts with "file:", and the following
+# string is the file's path.
+# 2. fd: the protocol starts with "fd:", and the following string
+# is the fd's name.
+#
+# @detach: if true, QMP will return immediately rather than
+# waiting for the dump to finish. The user can track progress
+# using "query-dump". (since 2.6).
+#
+# @begin: if specified, the starting physical address.
+#
+# @length: if specified, the memory size, in bytes. If you don't
+# want to dump all guest's memory, please specify the start @begin
+# and @length
+#
+# @format: if specified, the format of guest memory dump. But non-elf
+# format is conflict with paging and filter, ie. @paging, @begin and
+# @length is not allowed to be specified with non-elf @format at the
+# same time (since 2.0)
+#
+# Note: All boolean arguments default to false
+#
+# Returns: nothing on success
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "dump-guest-memory",
+# "arguments": { "protocol": "fd:dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-guest-memory',
+ 'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
+ '*begin': 'int', '*length': 'int',
+ '*format': 'DumpGuestMemoryFormat'} }
+
+##
+# @DumpStatus:
+#
+# Describe the status of a long-running background guest memory dump.
+#
+# @none: no dump-guest-memory has started yet.
+#
+# @active: there is one dump running in background.
+#
+# @completed: the last dump has finished successfully.
+#
+# @failed: the last dump has failed.
+#
+# Since: 2.6
+##
+{ 'enum': 'DumpStatus',
+ 'data': [ 'none', 'active', 'completed', 'failed' ] }
+
+##
+# @DumpQueryResult:
+#
+# The result format for 'query-dump'.
+#
+# @status: enum of @DumpStatus, which shows current dump status
+#
+# @completed: bytes written in latest dump (uncompressed)
+#
+# @total: total bytes to be written in latest dump (uncompressed)
+#
+# Since: 2.6
+##
+{ 'struct': 'DumpQueryResult',
+ 'data': { 'status': 'DumpStatus',
+ 'completed': 'int',
+ 'total': 'int' } }
+
+##
+# @query-dump:
+#
+# Query latest dump status.
+#
+# Returns: A @DumpStatus object showing the dump status.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-dump" }
+# <- { "return": { "status": "active", "completed": 1024000,
+# "total": 2048000 } }
+#
+##
+{ 'command': 'query-dump', 'returns': 'DumpQueryResult' }
+
+##
+# @DUMP_COMPLETED:
+#
+# Emitted when background dump has completed
+#
+# @result: final dump status
+#
+# @error: human-readable error string that provides
+# hint on why dump failed. Only presents on failure. The
+# user should not try to interpret the error string.
+#
+# Since: 2.6
+#
+# Example:
+#
+# { "event": "DUMP_COMPLETED",
+# "data": {"result": {"total": 1090650112, "status": "completed",
+# "completed": 1090650112} } }
+#
+##
+{ 'event': 'DUMP_COMPLETED' ,
+ 'data': { 'result': 'DumpQueryResult', '*error': 'str' } }
+
+##
+# @DumpGuestMemoryCapability:
+#
+# A list of the available formats for dump-guest-memory
+#
+# Since: 2.0
+##
+{ 'struct': 'DumpGuestMemoryCapability',
+ 'data': {
+ 'formats': ['DumpGuestMemoryFormat'] } }
+
+##
+# @query-dump-guest-memory-capability:
+#
+# Returns the available formats for dump-guest-memory
+#
+# Returns: A @DumpGuestMemoryCapability object listing available formats for
+# dump-guest-memory
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-dump-guest-memory-capability" }
+# <- { "return": { "formats":
+# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] }
+#
+##
+{ 'command': 'query-dump-guest-memory-capability',
+ 'returns': 'DumpGuestMemoryCapability' }
diff --git a/qapi/error.json b/qapi/error.json
new file mode 100644
index 000000000..94a6502de
--- /dev/null
+++ b/qapi/error.json
@@ -0,0 +1,30 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = QMP errors
+##
+
+##
+# @QapiErrorClass:
+#
+# QEMU error classes
+#
+# @GenericError: this is used for errors that don't require a specific error
+# class. This should be the default case for most errors
+#
+# @CommandNotFound: the requested command has not been found
+#
+# @DeviceNotActive: a device has failed to be become active
+#
+# @DeviceNotFound: the requested device has not been found
+#
+# @KVMMissingCap: the requested operation can't be fulfilled because a
+# required KVM capability is missing
+#
+# Since: 1.2
+##
+{ 'enum': 'QapiErrorClass',
+ # Keep this in sync with ErrorClass in error.h
+ 'data': [ 'GenericError', 'CommandNotFound',
+ 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
diff --git a/qapi/introspect.json b/qapi/introspect.json
new file mode 100644
index 000000000..183148b2e
--- /dev/null
+++ b/qapi/introspect.json
@@ -0,0 +1,319 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# Authors:
+# Markus Armbruster <armbru@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = QMP introspection
+##
+
+##
+# @query-qmp-schema:
+#
+# Command query-qmp-schema exposes the QMP wire ABI as an array of
+# SchemaInfo. This lets QMP clients figure out what commands and
+# events are available in this QEMU, and their parameters and results.
+#
+# However, the SchemaInfo can't reflect all the rules and restrictions
+# that apply to QMP. It's interface introspection (figuring out
+# what's there), not interface specification. The specification is in
+# the QAPI schema.
+#
+# Furthermore, while we strive to keep the QMP wire format
+# backwards-compatible across qemu versions, the introspection output
+# is not guaranteed to have the same stability. For example, one
+# version of qemu may list an object member as an optional
+# non-variant, while another lists the same member only through the
+# object's variants; or the type of a member may change from a generic
+# string into a specific enum or from one specific type into an
+# alternate that includes the original type alongside something else.
+#
+# Returns: array of @SchemaInfo, where each element describes an
+# entity in the ABI: command, event, type, ...
+#
+# The order of the various SchemaInfo is unspecified; however, all
+# names are guaranteed to be unique (no name will be duplicated with
+# different meta-types).
+#
+# Note: the QAPI schema is also used to help define *internal*
+# interfaces, by defining QAPI types. These are not part of the QMP
+# wire ABI, and therefore not returned by this command.
+#
+# Since: 2.5
+##
+{ 'command': 'query-qmp-schema',
+ 'returns': [ 'SchemaInfo' ],
+ 'allow-preconfig': true }
+
+##
+# @SchemaMetaType:
+#
+# This is a @SchemaInfo's meta type, i.e. the kind of entity it
+# describes.
+#
+# @builtin: a predefined type such as 'int' or 'bool'.
+#
+# @enum: an enumeration type
+#
+# @array: an array type
+#
+# @object: an object type (struct or union)
+#
+# @alternate: an alternate type
+#
+# @command: a QMP command
+#
+# @event: a QMP event
+#
+# Since: 2.5
+##
+{ 'enum': 'SchemaMetaType',
+ 'data': [ 'builtin', 'enum', 'array', 'object', 'alternate',
+ 'command', 'event' ] }
+
+##
+# @SchemaInfo:
+#
+# @name: the entity's name, inherited from @base.
+# The SchemaInfo is always referenced by this name.
+# Commands and events have the name defined in the QAPI schema.
+# Unlike command and event names, type names are not part of
+# the wire ABI. Consequently, type names are meaningless
+# strings here, although they are still guaranteed unique
+# regardless of @meta-type.
+#
+# @meta-type: the entity's meta type, inherited from @base.
+#
+# @features: names of features associated with the entity, in no
+# particular order.
+# (since 4.1 for object types, 4.2 for commands, 5.0 for
+# the rest)
+#
+# Additional members depend on the value of @meta-type.
+#
+# Since: 2.5
+##
+{ 'union': 'SchemaInfo',
+ 'base': { 'name': 'str', 'meta-type': 'SchemaMetaType',
+ '*features': [ 'str' ] },
+ 'discriminator': 'meta-type',
+ 'data': {
+ 'builtin': 'SchemaInfoBuiltin',
+ 'enum': 'SchemaInfoEnum',
+ 'array': 'SchemaInfoArray',
+ 'object': 'SchemaInfoObject',
+ 'alternate': 'SchemaInfoAlternate',
+ 'command': 'SchemaInfoCommand',
+ 'event': 'SchemaInfoEvent' } }
+
+##
+# @SchemaInfoBuiltin:
+#
+# Additional SchemaInfo members for meta-type 'builtin'.
+#
+# @json-type: the JSON type used for this type on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoBuiltin',
+ 'data': { 'json-type': 'JSONType' } }
+
+##
+# @JSONType:
+#
+# The four primitive and two structured types according to RFC 8259
+# section 1, plus 'int' (split off 'number'), plus the obvious top
+# type 'value'.
+#
+# Since: 2.5
+##
+{ 'enum': 'JSONType',
+ 'data': [ 'string', 'number', 'int', 'boolean', 'null',
+ 'object', 'array', 'value' ] }
+
+##
+# @SchemaInfoEnum:
+#
+# Additional SchemaInfo members for meta-type 'enum'.
+#
+# @members: the enum type's members, in no particular order
+# (since 6.2).
+#
+# @values: the enumeration type's member names, in no particular order.
+# Redundant with @members. Just for backward compatibility.
+#
+# Features:
+# @deprecated: Member @values is deprecated. Use @members instead.
+#
+# Values of this type are JSON string on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoEnum',
+ 'data': { 'members': [ 'SchemaInfoEnumMember' ],
+ 'values': { 'type': [ 'str' ],
+ 'features': [ 'deprecated' ] } } }
+
+##
+# @SchemaInfoEnumMember:
+#
+# An object member.
+#
+# @name: the member's name, as defined in the QAPI schema.
+#
+# @features: names of features associated with the member, in no
+# particular order.
+#
+# Since: 6.2
+##
+{ 'struct': 'SchemaInfoEnumMember',
+ 'data': { 'name': 'str', '*features': [ 'str' ] } }
+
+##
+# @SchemaInfoArray:
+#
+# Additional SchemaInfo members for meta-type 'array'.
+#
+# @element-type: the array type's element type.
+#
+# Values of this type are JSON array on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoArray',
+ 'data': { 'element-type': 'str' } }
+
+##
+# @SchemaInfoObject:
+#
+# Additional SchemaInfo members for meta-type 'object'.
+#
+# @members: the object type's (non-variant) members, in no particular order.
+#
+# @tag: the name of the member serving as type tag.
+# An element of @members with this name must exist.
+#
+# @variants: variant members, i.e. additional members that
+# depend on the type tag's value. Present exactly when
+# @tag is present. The variants are in no particular order,
+# and may even differ from the order of the values of the
+# enum type of the @tag.
+#
+# Values of this type are JSON object on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObject',
+ 'data': { 'members': [ 'SchemaInfoObjectMember' ],
+ '*tag': 'str',
+ '*variants': [ 'SchemaInfoObjectVariant' ] } }
+
+##
+# @SchemaInfoObjectMember:
+#
+# An object member.
+#
+# @name: the member's name, as defined in the QAPI schema.
+#
+# @type: the name of the member's type.
+#
+# @default: default when used as command parameter.
+# If absent, the parameter is mandatory.
+# If present, the value must be null. The parameter is
+# optional, and behavior when it's missing is not specified
+# here.
+# Future extension: if present and non-null, the parameter
+# is optional, and defaults to this value.
+#
+# @features: names of features associated with the member, in no
+# particular order. (since 5.0)
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObjectMember',
+ 'data': { 'name': 'str', 'type': 'str', '*default': 'any',
+# @default's type must be null or match @type
+ '*features': [ 'str' ] } }
+
+##
+# @SchemaInfoObjectVariant:
+#
+# The variant members for a value of the type tag.
+#
+# @case: a value of the type tag.
+#
+# @type: the name of the object type that provides the variant members
+# when the type tag has value @case.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObjectVariant',
+ 'data': { 'case': 'str', 'type': 'str' } }
+
+##
+# @SchemaInfoAlternate:
+#
+# Additional SchemaInfo members for meta-type 'alternate'.
+#
+# @members: the alternate type's members, in no particular order.
+# The members' wire encoding is distinct, see
+# docs/devel/qapi-code-gen.txt section Alternate types.
+#
+# On the wire, this can be any of the members.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoAlternate',
+ 'data': { 'members': [ 'SchemaInfoAlternateMember' ] } }
+
+##
+# @SchemaInfoAlternateMember:
+#
+# An alternate member.
+#
+# @type: the name of the member's type.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoAlternateMember',
+ 'data': { 'type': 'str' } }
+
+##
+# @SchemaInfoCommand:
+#
+# Additional SchemaInfo members for meta-type 'command'.
+#
+# @arg-type: the name of the object type that provides the command's
+# parameters.
+#
+# @ret-type: the name of the command's result type.
+#
+# @allow-oob: whether the command allows out-of-band execution,
+# defaults to false (Since: 2.12)
+#
+# TODO: @success-response (currently irrelevant, because it's QGA, not QMP)
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoCommand',
+ 'data': { 'arg-type': 'str', 'ret-type': 'str',
+ '*allow-oob': 'bool' } }
+
+##
+# @SchemaInfoEvent:
+#
+# Additional SchemaInfo members for meta-type 'event'.
+#
+# @arg-type: the name of the object type that provides the event's
+# parameters.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoEvent',
+ 'data': { 'arg-type': 'str' } }
diff --git a/qapi/job.json b/qapi/job.json
new file mode 100644
index 000000000..1a6ef0345
--- /dev/null
+++ b/qapi/job.json
@@ -0,0 +1,266 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# == Background jobs
+##
+
+##
+# @JobType:
+#
+# Type of a background job.
+#
+# @commit: block commit job type, see "block-commit"
+#
+# @stream: block stream job type, see "block-stream"
+#
+# @mirror: drive mirror job type, see "drive-mirror"
+#
+# @backup: drive backup job type, see "drive-backup"
+#
+# @create: image creation job type, see "blockdev-create" (since 3.0)
+#
+# @amend: image options amend job type, see "x-blockdev-amend" (since 5.1)
+#
+# @snapshot-load: snapshot load job type, see "snapshot-load" (since 6.0)
+#
+# @snapshot-save: snapshot save job type, see "snapshot-save" (since 6.0)
+#
+# @snapshot-delete: snapshot delete job type, see "snapshot-delete" (since 6.0)
+#
+# Since: 1.7
+##
+{ 'enum': 'JobType',
+ 'data': ['commit', 'stream', 'mirror', 'backup', 'create', 'amend',
+ 'snapshot-load', 'snapshot-save', 'snapshot-delete'] }
+
+##
+# @JobStatus:
+#
+# Indicates the present state of a given job in its lifetime.
+#
+# @undefined: Erroneous, default state. Should not ever be visible.
+#
+# @created: The job has been created, but not yet started.
+#
+# @running: The job is currently running.
+#
+# @paused: The job is running, but paused. The pause may be requested by
+# either the QMP user or by internal processes.
+#
+# @ready: The job is running, but is ready for the user to signal completion.
+# This is used for long-running jobs like mirror that are designed to
+# run indefinitely.
+#
+# @standby: The job is ready, but paused. This is nearly identical to @paused.
+# The job may return to @ready or otherwise be canceled.
+#
+# @waiting: The job is waiting for other jobs in the transaction to converge
+# to the waiting state. This status will likely not be visible for
+# the last job in a transaction.
+#
+# @pending: The job has finished its work, but has finalization steps that it
+# needs to make prior to completing. These changes will require
+# manual intervention via @job-finalize if auto-finalize was set to
+# false. These pending changes may still fail.
+#
+# @aborting: The job is in the process of being aborted, and will finish with
+# an error. The job will afterwards report that it is @concluded.
+# This status may not be visible to the management process.
+#
+# @concluded: The job has finished all work. If auto-dismiss was set to false,
+# the job will remain in the query list until it is dismissed via
+# @job-dismiss.
+#
+# @null: The job is in the process of being dismantled. This state should not
+# ever be visible externally.
+#
+# Since: 2.12
+##
+{ 'enum': 'JobStatus',
+ 'data': ['undefined', 'created', 'running', 'paused', 'ready', 'standby',
+ 'waiting', 'pending', 'aborting', 'concluded', 'null' ] }
+
+##
+# @JobVerb:
+#
+# Represents command verbs that can be applied to a job.
+#
+# @cancel: see @job-cancel
+#
+# @pause: see @job-pause
+#
+# @resume: see @job-resume
+#
+# @set-speed: see @block-job-set-speed
+#
+# @complete: see @job-complete
+#
+# @dismiss: see @job-dismiss
+#
+# @finalize: see @job-finalize
+#
+# Since: 2.12
+##
+{ 'enum': 'JobVerb',
+ 'data': ['cancel', 'pause', 'resume', 'set-speed', 'complete', 'dismiss',
+ 'finalize' ] }
+
+##
+# @JOB_STATUS_CHANGE:
+#
+# Emitted when a job transitions to a different status.
+#
+# @id: The job identifier
+# @status: The new job status
+#
+# Since: 3.0
+##
+{ 'event': 'JOB_STATUS_CHANGE',
+ 'data': { 'id': 'str',
+ 'status': 'JobStatus' } }
+
+##
+# @job-pause:
+#
+# Pause an active job.
+#
+# This command returns immediately after marking the active job for pausing.
+# Pausing an already paused job is an error.
+#
+# The job will pause as soon as possible, which means transitioning into the
+# PAUSED state if it was RUNNING, or into STANDBY if it was READY. The
+# corresponding JOB_STATUS_CHANGE event will be emitted.
+#
+# Cancelling a paused job automatically resumes it.
+#
+# @id: The job identifier.
+#
+# Since: 3.0
+##
+{ 'command': 'job-pause', 'data': { 'id': 'str' } }
+
+##
+# @job-resume:
+#
+# Resume a paused job.
+#
+# This command returns immediately after resuming a paused job. Resuming an
+# already running job is an error.
+#
+# @id : The job identifier.
+#
+# Since: 3.0
+##
+{ 'command': 'job-resume', 'data': { 'id': 'str' } }
+
+##
+# @job-cancel:
+#
+# Instruct an active background job to cancel at the next opportunity.
+# This command returns immediately after marking the active job for
+# cancellation.
+#
+# The job will cancel as soon as possible and then emit a JOB_STATUS_CHANGE
+# event. Usually, the status will change to ABORTING, but it is possible that
+# a job successfully completes (e.g. because it was almost done and there was
+# no opportunity to cancel earlier than completing the job) and transitions to
+# PENDING instead.
+#
+# @id: The job identifier.
+#
+# Since: 3.0
+##
+{ 'command': 'job-cancel', 'data': { 'id': 'str' } }
+
+
+##
+# @job-complete:
+#
+# Manually trigger completion of an active job in the READY state.
+#
+# @id: The job identifier.
+#
+# Since: 3.0
+##
+{ 'command': 'job-complete', 'data': { 'id': 'str' } }
+
+##
+# @job-dismiss:
+#
+# Deletes a job that is in the CONCLUDED state. This command only needs to be
+# run explicitly for jobs that don't have automatic dismiss enabled.
+#
+# This command will refuse to operate on any job that has not yet reached its
+# terminal state, JOB_STATUS_CONCLUDED. For jobs that make use of JOB_READY
+# event, job-cancel or job-complete will still need to be used as appropriate.
+#
+# @id: The job identifier.
+#
+# Since: 3.0
+##
+{ 'command': 'job-dismiss', 'data': { 'id': 'str' } }
+
+##
+# @job-finalize:
+#
+# Instructs all jobs in a transaction (or a single job if it is not part of any
+# transaction) to finalize any graph changes and do any necessary cleanup. This
+# command requires that all involved jobs are in the PENDING state.
+#
+# For jobs in a transaction, instructing one job to finalize will force
+# ALL jobs in the transaction to finalize, so it is only necessary to instruct
+# a single member job to finalize.
+#
+# @id: The identifier of any job in the transaction, or of a job that is not
+# part of any transaction.
+#
+# Since: 3.0
+##
+{ 'command': 'job-finalize', 'data': { 'id': 'str' } }
+
+##
+# @JobInfo:
+#
+# Information about a job.
+#
+# @id: The job identifier
+#
+# @type: The kind of job that is being performed
+#
+# @status: Current job state/status
+#
+# @current-progress: Progress made until now. The unit is arbitrary and the
+# value can only meaningfully be used for the ratio of
+# @current-progress to @total-progress. The value is
+# monotonically increasing.
+#
+# @total-progress: Estimated @current-progress value at the completion of
+# the job. This value can arbitrarily change while the
+# job is running, in both directions.
+#
+# @error: If this field is present, the job failed; if it is
+# still missing in the CONCLUDED state, this indicates
+# successful completion.
+#
+# The value is a human-readable error message to describe
+# the reason for the job failure. It should not be parsed
+# by applications.
+#
+# Since: 3.0
+##
+{ 'struct': 'JobInfo',
+ 'data': { 'id': 'str', 'type': 'JobType', 'status': 'JobStatus',
+ 'current-progress': 'int', 'total-progress': 'int',
+ '*error': 'str' } }
+
+##
+# @query-jobs:
+#
+# Return information about jobs.
+#
+# Returns: a list with a @JobInfo for each active job
+#
+# Since: 3.0
+##
+{ 'command': 'query-jobs', 'returns': ['JobInfo'] }
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
new file mode 100644
index 000000000..f5ec4bc17
--- /dev/null
+++ b/qapi/machine-target.json
@@ -0,0 +1,343 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# @CpuModelInfo:
+#
+# Virtual CPU model.
+#
+# A CPU model consists of the name of a CPU definition, to which
+# delta changes are applied (e.g. features added/removed). Most magic values
+# that an architecture might require should be hidden behind the name.
+# However, if required, architectures can expose relevant properties.
+#
+# @name: the name of the CPU definition the model is based on
+# @props: a dictionary of QOM properties to be applied
+#
+# Since: 2.8
+##
+{ 'struct': 'CpuModelInfo',
+ 'data': { 'name': 'str',
+ '*props': 'any' } }
+
+##
+# @CpuModelExpansionType:
+#
+# An enumeration of CPU model expansion types.
+#
+# @static: Expand to a static CPU model, a combination of a static base
+# model name and property delta changes. As the static base model will
+# never change, the expanded CPU model will be the same, independent of
+# QEMU version, machine type, machine options, and accelerator options.
+# Therefore, the resulting model can be used by tooling without having
+# to specify a compatibility machine - e.g. when displaying the "host"
+# model. The @static CPU models are migration-safe.
+
+# @full: Expand all properties. The produced model is not guaranteed to be
+# migration-safe, but allows tooling to get an insight and work with
+# model details.
+#
+# Note: When a non-migration-safe CPU model is expanded in static mode, some
+# features enabled by the CPU model may be omitted, because they can't be
+# implemented by a static CPU model definition (e.g. cache info passthrough and
+# PMU passthrough in x86). If you need an accurate representation of the
+# features enabled by a non-migration-safe CPU model, use @full. If you need a
+# static representation that will keep ABI compatibility even when changing QEMU
+# version or machine-type, use @static (but keep in mind that some features may
+# be omitted).
+#
+# Since: 2.8
+##
+{ 'enum': 'CpuModelExpansionType',
+ 'data': [ 'static', 'full' ] }
+
+
+##
+# @CpuModelCompareResult:
+#
+# An enumeration of CPU model comparison results. The result is usually
+# calculated using e.g. CPU features or CPU generations.
+#
+# @incompatible: If model A is incompatible to model B, model A is not
+# guaranteed to run where model B runs and the other way around.
+#
+# @identical: If model A is identical to model B, model A is guaranteed to run
+# where model B runs and the other way around.
+#
+# @superset: If model A is a superset of model B, model B is guaranteed to run
+# where model A runs. There are no guarantees about the other way.
+#
+# @subset: If model A is a subset of model B, model A is guaranteed to run
+# where model B runs. There are no guarantees about the other way.
+#
+# Since: 2.8
+##
+{ 'enum': 'CpuModelCompareResult',
+ 'data': [ 'incompatible', 'identical', 'superset', 'subset' ] }
+
+##
+# @CpuModelBaselineInfo:
+#
+# The result of a CPU model baseline.
+#
+# @model: the baselined CpuModelInfo.
+#
+# Since: 2.8
+##
+{ 'struct': 'CpuModelBaselineInfo',
+ 'data': { 'model': 'CpuModelInfo' },
+ 'if': 'TARGET_S390X' }
+
+##
+# @CpuModelCompareInfo:
+#
+# The result of a CPU model comparison.
+#
+# @result: The result of the compare operation.
+# @responsible-properties: List of properties that led to the comparison result
+# not being identical.
+#
+# @responsible-properties is a list of QOM property names that led to
+# both CPUs not being detected as identical. For identical models, this
+# list is empty.
+# If a QOM property is read-only, that means there's no known way to make the
+# CPU models identical. If the special property name "type" is included, the
+# models are by definition not identical and cannot be made identical.
+#
+# Since: 2.8
+##
+{ 'struct': 'CpuModelCompareInfo',
+ 'data': { 'result': 'CpuModelCompareResult',
+ 'responsible-properties': ['str'] },
+ 'if': 'TARGET_S390X' }
+
+##
+# @query-cpu-model-comparison:
+#
+# Compares two CPU models, returning how they compare in a specific
+# configuration. The results indicates how both models compare regarding
+# runnability. This result can be used by tooling to make decisions if a
+# certain CPU model will run in a certain configuration or if a compatible
+# CPU model has to be created by baselining.
+#
+# Usually, a CPU model is compared against the maximum possible CPU model
+# of a certain configuration (e.g. the "host" model for KVM). If that CPU
+# model is identical or a subset, it will run in that configuration.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support comparing CPU models. s390x supports
+# comparing CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
+# not supported, if a model cannot be used, if a model contains
+# an unknown cpu definition name, unknown properties or properties
+# with wrong types.
+#
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
+# Since: 2.8
+##
+{ 'command': 'query-cpu-model-comparison',
+ 'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
+ 'returns': 'CpuModelCompareInfo',
+ 'if': 'TARGET_S390X' }
+
+##
+# @query-cpu-model-baseline:
+#
+# Baseline two CPU models, creating a compatible third model. The created
+# model will always be a static, migration-safe CPU model (see "static"
+# CPU model expansion for details).
+#
+# This interface can be used by tooling to create a compatible CPU model out
+# two CPU models. The created CPU model will be identical to or a subset of
+# both CPU models when comparing them. Therefore, the created CPU model is
+# guaranteed to run where the given CPU models run.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support baselining CPU models. s390x supports
+# baselining CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
+# not supported, if a model cannot be used, if a model contains
+# an unknown cpu definition name, unknown properties or properties
+# with wrong types.
+#
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
+# Since: 2.8
+##
+{ 'command': 'query-cpu-model-baseline',
+ 'data': { 'modela': 'CpuModelInfo',
+ 'modelb': 'CpuModelInfo' },
+ 'returns': 'CpuModelBaselineInfo',
+ 'if': 'TARGET_S390X' }
+
+##
+# @CpuModelExpansionInfo:
+#
+# The result of a cpu model expansion.
+#
+# @model: the expanded CpuModelInfo.
+#
+# Since: 2.8
+##
+{ 'struct': 'CpuModelExpansionInfo',
+ 'data': { 'model': 'CpuModelInfo' },
+ 'if': { 'any': [ 'TARGET_S390X',
+ 'TARGET_I386',
+ 'TARGET_ARM' ] } }
+
+##
+# @query-cpu-model-expansion:
+#
+# Expands a given CPU model (or a combination of CPU model + additional options)
+# to different granularities, allowing tooling to get an understanding what a
+# specific CPU model looks like in QEMU under a certain configuration.
+#
+# This interface can be used to query the "host" CPU model.
+#
+# The data returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support all expansion types. s390x supports
+# "full" and "static". Arm only supports "full".
+#
+# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
+# not supported, if the model cannot be expanded, if the model contains
+# an unknown CPU definition name, unknown properties or properties
+# with a wrong type. Also returns an error if an expansion type is
+# not supported.
+#
+# Since: 2.8
+##
+{ 'command': 'query-cpu-model-expansion',
+ 'data': { 'type': 'CpuModelExpansionType',
+ 'model': 'CpuModelInfo' },
+ 'returns': 'CpuModelExpansionInfo',
+ 'if': { 'any': [ 'TARGET_S390X',
+ 'TARGET_I386',
+ 'TARGET_ARM' ] } }
+
+##
+# @CpuDefinitionInfo:
+#
+# Virtual CPU definition.
+#
+# @name: the name of the CPU definition
+#
+# @migration-safe: whether a CPU definition can be safely used for
+# migration in combination with a QEMU compatibility machine
+# when migrating between different QEMU versions and between
+# hosts with different sets of (hardware or software)
+# capabilities. If not provided, information is not available
+# and callers should not assume the CPU definition to be
+# migration-safe. (since 2.8)
+#
+# @static: whether a CPU definition is static and will not change depending on
+# QEMU version, machine type, machine options and accelerator options.
+# A static model is always migration-safe. (since 2.8)
+#
+# @unavailable-features: List of properties that prevent
+# the CPU model from running in the current
+# host. (since 2.8)
+# @typename: Type name that can be used as argument to @device-list-properties,
+# to introspect properties configurable using -cpu or -global.
+# (since 2.9)
+#
+# @alias-of: Name of CPU model this model is an alias for. The target of the
+# CPU model alias may change depending on the machine type.
+# Management software is supposed to translate CPU model aliases
+# in the VM configuration, because aliases may stop being
+# migration-safe in the future (since 4.1)
+#
+# @deprecated: If true, this CPU model is deprecated and may be removed in
+# in some future version of QEMU according to the QEMU deprecation
+# policy. (since 5.2)
+#
+# @unavailable-features is a list of QOM property names that
+# represent CPU model attributes that prevent the CPU from running.
+# If the QOM property is read-only, that means there's no known
+# way to make the CPU model run in the current host. Implementations
+# that choose not to provide specific information return the
+# property name "type".
+# If the property is read-write, it means that it MAY be possible
+# to run the CPU model in the current host if that property is
+# changed. Management software can use it as hints to suggest or
+# choose an alternative for the user, or just to generate meaningful
+# error messages explaining why the CPU model can't be used.
+# If @unavailable-features is an empty list, the CPU model is
+# runnable using the current host and machine-type.
+# If @unavailable-features is not present, runnability
+# information for the CPU is not available.
+#
+# Since: 1.2
+##
+{ 'struct': 'CpuDefinitionInfo',
+ 'data': { 'name': 'str',
+ '*migration-safe': 'bool',
+ 'static': 'bool',
+ '*unavailable-features': [ 'str' ],
+ 'typename': 'str',
+ '*alias-of' : 'str',
+ 'deprecated' : 'bool' },
+ 'if': { 'any': [ 'TARGET_PPC',
+ 'TARGET_ARM',
+ 'TARGET_I386',
+ 'TARGET_S390X',
+ 'TARGET_MIPS' ] } }
+
+##
+# @query-cpu-definitions:
+#
+# Return a list of supported virtual CPU definitions
+#
+# Returns: a list of CpuDefInfo
+#
+# Since: 1.2
+##
+{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
+ 'if': { 'any': [ 'TARGET_PPC',
+ 'TARGET_ARM',
+ 'TARGET_I386',
+ 'TARGET_S390X',
+ 'TARGET_MIPS' ] } }
diff --git a/qapi/machine.json b/qapi/machine.json
new file mode 100644
index 000000000..067e3f537
--- /dev/null
+++ b/qapi/machine.json
@@ -0,0 +1,1559 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Machines
+##
+
+{ 'include': 'common.json' }
+
+##
+# @SysEmuTarget:
+#
+# The comprehensive enumeration of QEMU system emulation ("softmmu")
+# targets. Run "./configure --help" in the project root directory, and
+# look for the \*-softmmu targets near the "--target-list" option. The
+# individual target constants are not documented here, for the time
+# being.
+#
+# @rx: since 5.0
+# @avr: since 5.1
+#
+# Notes: The resulting QMP strings can be appended to the "qemu-system-"
+# prefix to produce the corresponding QEMU executable name. This
+# is true even for "qemu-system-x86_64".
+#
+# Since: 3.0
+##
+{ 'enum' : 'SysEmuTarget',
+ 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386',
+ 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
+ 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc',
+ 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
+ 'sh4eb', 'sparc', 'sparc64', 'tricore',
+ 'x86_64', 'xtensa', 'xtensaeb' ] }
+
+##
+# @CpuS390State:
+#
+# An enumeration of cpu states that can be assumed by a virtual
+# S390 CPU
+#
+# Since: 2.12
+##
+{ 'enum': 'CpuS390State',
+ 'prefix': 'S390_CPU_STATE',
+ 'data': [ 'uninitialized', 'stopped', 'check-stop', 'operating', 'load' ] }
+
+##
+# @CpuInfoS390:
+#
+# Additional information about a virtual S390 CPU
+#
+# @cpu-state: the virtual CPU's state
+#
+# Since: 2.12
+##
+{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } }
+
+##
+# @CpuInfoFast:
+#
+# Information about a virtual CPU
+#
+# @cpu-index: index of the virtual CPU
+#
+# @qom-path: path to the CPU object in the QOM tree
+#
+# @thread-id: ID of the underlying host thread
+#
+# @props: properties describing to which node/socket/core/thread
+# virtual CPU belongs to, provided if supported by board
+#
+# @target: the QEMU system emulation target, which determines which
+# additional fields will be listed (since 3.0)
+#
+# Since: 2.12
+#
+##
+{ 'union' : 'CpuInfoFast',
+ 'base' : { 'cpu-index' : 'int',
+ 'qom-path' : 'str',
+ 'thread-id' : 'int',
+ '*props' : 'CpuInstanceProperties',
+ 'target' : 'SysEmuTarget' },
+ 'discriminator' : 'target',
+ 'data' : { 's390x' : 'CpuInfoS390' } }
+
+##
+# @query-cpus-fast:
+#
+# Returns information about all virtual CPUs.
+#
+# Returns: list of @CpuInfoFast
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-cpus-fast" }
+# <- { "return": [
+# {
+# "thread-id": 25627,
+# "props": {
+# "core-id": 0,
+# "thread-id": 0,
+# "socket-id": 0
+# },
+# "qom-path": "/machine/unattached/device[0]",
+# "arch":"x86",
+# "target":"x86_64",
+# "cpu-index": 0
+# },
+# {
+# "thread-id": 25628,
+# "props": {
+# "core-id": 0,
+# "thread-id": 0,
+# "socket-id": 1
+# },
+# "qom-path": "/machine/unattached/device[2]",
+# "arch":"x86",
+# "target":"x86_64",
+# "cpu-index": 1
+# }
+# ]
+# }
+##
+{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] }
+
+##
+# @MachineInfo:
+#
+# Information describing a machine.
+#
+# @name: the name of the machine
+#
+# @alias: an alias for the machine name
+#
+# @is-default: whether the machine is default
+#
+# @cpu-max: maximum number of CPUs supported by the machine type
+# (since 1.5)
+#
+# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7)
+#
+# @numa-mem-supported: true if '-numa node,mem' option is supported by
+# the machine type and false otherwise (since 4.1)
+#
+# @deprecated: if true, the machine type is deprecated and may be removed
+# in future versions of QEMU according to the QEMU deprecation
+# policy (since 4.1)
+#
+# @default-cpu-type: default CPU model typename if none is requested via
+# the -cpu argument. (since 4.2)
+#
+# @default-ram-id: the default ID of initial RAM memory backend (since 5.2)
+#
+# Since: 1.2
+##
+{ 'struct': 'MachineInfo',
+ 'data': { 'name': 'str', '*alias': 'str',
+ '*is-default': 'bool', 'cpu-max': 'int',
+ 'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool',
+ 'deprecated': 'bool', '*default-cpu-type': 'str',
+ '*default-ram-id': 'str' } }
+
+##
+# @query-machines:
+#
+# Return a list of supported machines
+#
+# Returns: a list of MachineInfo
+#
+# Since: 1.2
+##
+{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
+
+##
+# @CurrentMachineParams:
+#
+# Information describing the running machine parameters.
+#
+# @wakeup-suspend-support: true if the machine supports wake up from
+# suspend
+#
+# Since: 4.0
+##
+{ 'struct': 'CurrentMachineParams',
+ 'data': { 'wakeup-suspend-support': 'bool'} }
+
+##
+# @query-current-machine:
+#
+# Return information on the current virtual machine.
+#
+# Returns: CurrentMachineParams
+#
+# Since: 4.0
+##
+{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' }
+
+##
+# @TargetInfo:
+#
+# Information describing the QEMU target.
+#
+# @arch: the target architecture
+#
+# Since: 1.2
+##
+{ 'struct': 'TargetInfo',
+ 'data': { 'arch': 'SysEmuTarget' } }
+
+##
+# @query-target:
+#
+# Return information about the target for this QEMU
+#
+# Returns: TargetInfo
+#
+# Since: 1.2
+##
+{ 'command': 'query-target', 'returns': 'TargetInfo' }
+
+##
+# @UuidInfo:
+#
+# Guest UUID information (Universally Unique Identifier).
+#
+# @UUID: the UUID of the guest
+#
+# Since: 0.14
+#
+# Notes: If no UUID was specified for the guest, a null UUID is returned.
+##
+{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} }
+
+##
+# @query-uuid:
+#
+# Query the guest UUID information.
+#
+# Returns: The @UuidInfo for the guest
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-uuid" }
+# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
+#
+##
+{ 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true }
+
+##
+# @GuidInfo:
+#
+# GUID information.
+#
+# @guid: the globally unique identifier
+#
+# Since: 2.9
+##
+{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} }
+
+##
+# @query-vm-generation-id:
+#
+# Show Virtual Machine Generation ID
+#
+# Since: 2.9
+##
+{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
+
+##
+# @system_reset:
+#
+# Performs a hard reset of a guest.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "system_reset" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_reset' }
+
+##
+# @system_powerdown:
+#
+# Requests that a guest perform a powerdown operation.
+#
+# Since: 0.14
+#
+# Notes: A guest may or may not respond to this command. This command
+# returning does not indicate that a guest has accepted the request or
+# that it has shut down. Many guests will respond to this command by
+# prompting the user in some way.
+# Example:
+#
+# -> { "execute": "system_powerdown" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_powerdown' }
+
+##
+# @system_wakeup:
+#
+# Wake up guest from suspend. If the guest has wake-up from suspend
+# support enabled (wakeup-suspend-support flag from
+# query-current-machine), wake-up guest from suspend if the guest is
+# in SUSPENDED state. Return an error otherwise.
+#
+# Since: 1.1
+#
+# Returns: nothing.
+#
+# Note: prior to 4.0, this command does nothing in case the guest
+# isn't suspended.
+#
+# Example:
+#
+# -> { "execute": "system_wakeup" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_wakeup' }
+
+##
+# @LostTickPolicy:
+#
+# Policy for handling lost ticks in timer devices. Ticks end up getting
+# lost when, for example, the guest is paused.
+#
+# @discard: throw away the missed ticks and continue with future injection
+# normally. The guest OS will see the timer jump ahead by a
+# potentially quite significant amount all at once, as if the
+# intervening chunk of time had simply not existed; needless to
+# say, such a sudden jump can easily confuse a guest OS which is
+# not specifically prepared to deal with it. Assuming the guest
+# OS can deal correctly with the time jump, the time in the guest
+# and in the host should now match.
+#
+# @delay: continue to deliver ticks at the normal rate. The guest OS will
+# not notice anything is amiss, as from its point of view time will
+# have continued to flow normally. The time in the guest should now
+# be behind the time in the host by exactly the amount of time during
+# which ticks have been missed.
+#
+# @slew: deliver ticks at a higher rate to catch up with the missed ticks.
+# The guest OS will not notice anything is amiss, as from its point
+# of view time will have continued to flow normally. Once the timer
+# has managed to catch up with all the missing ticks, the time in
+# the guest and in the host should match.
+#
+# Since: 2.0
+##
+{ 'enum': 'LostTickPolicy',
+ 'data': ['discard', 'delay', 'slew' ] }
+
+##
+# @inject-nmi:
+#
+# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64).
+# The command fails when the guest doesn't support injecting.
+#
+# Returns: If successful, nothing
+#
+# Since: 0.14
+#
+# Note: prior to 2.1, this command was only supported for x86 and s390 VMs
+#
+# Example:
+#
+# -> { "execute": "inject-nmi" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'inject-nmi' }
+
+##
+# @KvmInfo:
+#
+# Information about support for KVM acceleration
+#
+# @enabled: true if KVM acceleration is active
+#
+# @present: true if KVM acceleration is built into this executable
+#
+# Since: 0.14
+##
+{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+
+##
+# @query-kvm:
+#
+# Returns information about KVM acceleration
+#
+# Returns: @KvmInfo
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-kvm" }
+# <- { "return": { "enabled": true, "present": true } }
+#
+##
+{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
+
+##
+# @NumaOptionsType:
+#
+# @node: NUMA nodes configuration
+#
+# @dist: NUMA distance configuration (since 2.10)
+#
+# @cpu: property based CPU(s) to node mapping (Since: 2.10)
+#
+# @hmat-lb: memory latency and bandwidth information (Since: 5.0)
+#
+# @hmat-cache: memory side cache information (Since: 5.0)
+#
+# Since: 2.1
+##
+{ 'enum': 'NumaOptionsType',
+ 'data': [ 'node', 'dist', 'cpu', 'hmat-lb', 'hmat-cache' ] }
+
+##
+# @NumaOptions:
+#
+# A discriminated record of NUMA options. (for OptsVisitor)
+#
+# Since: 2.1
+##
+{ 'union': 'NumaOptions',
+ 'base': { 'type': 'NumaOptionsType' },
+ 'discriminator': 'type',
+ 'data': {
+ 'node': 'NumaNodeOptions',
+ 'dist': 'NumaDistOptions',
+ 'cpu': 'NumaCpuOptions',
+ 'hmat-lb': 'NumaHmatLBOptions',
+ 'hmat-cache': 'NumaHmatCacheOptions' }}
+
+##
+# @NumaNodeOptions:
+#
+# Create a guest NUMA node. (for OptsVisitor)
+#
+# @nodeid: NUMA node ID (increase by 1 from 0 if omitted)
+#
+# @cpus: VCPUs belonging to this node (assign VCPUS round-robin
+# if omitted)
+#
+# @mem: memory size of this node; mutually exclusive with @memdev.
+# Equally divide total memory among nodes if both @mem and @memdev are
+# omitted.
+#
+# @memdev: memory backend object. If specified for one node,
+# it must be specified for all nodes.
+#
+# @initiator: defined in ACPI 6.3 Chapter 5.2.27.3 Table 5-145,
+# points to the nodeid which has the memory controller
+# responsible for this NUMA node. This field provides
+# additional information as to the initiator node that
+# is closest (as in directly attached) to this node, and
+# therefore has the best performance (since 5.0)
+#
+# Since: 2.1
+##
+{ 'struct': 'NumaNodeOptions',
+ 'data': {
+ '*nodeid': 'uint16',
+ '*cpus': ['uint16'],
+ '*mem': 'size',
+ '*memdev': 'str',
+ '*initiator': 'uint16' }}
+
+##
+# @NumaDistOptions:
+#
+# Set the distance between 2 NUMA nodes.
+#
+# @src: source NUMA node.
+#
+# @dst: destination NUMA node.
+#
+# @val: NUMA distance from source node to destination node.
+# When a node is unreachable from another node, set the distance
+# between them to 255.
+#
+# Since: 2.10
+##
+{ 'struct': 'NumaDistOptions',
+ 'data': {
+ 'src': 'uint16',
+ 'dst': 'uint16',
+ 'val': 'uint8' }}
+
+##
+# @X86CPURegister32:
+#
+# A X86 32-bit register
+#
+# Since: 1.5
+##
+{ 'enum': 'X86CPURegister32',
+ 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }
+
+##
+# @X86CPUFeatureWordInfo:
+#
+# Information about a X86 CPU feature word
+#
+# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word
+#
+# @cpuid-input-ecx: Input ECX value for CPUID instruction for that
+# feature word
+#
+# @cpuid-register: Output register containing the feature bits
+#
+# @features: value of output register, containing the feature bits
+#
+# Since: 1.5
+##
+{ 'struct': 'X86CPUFeatureWordInfo',
+ 'data': { 'cpuid-input-eax': 'int',
+ '*cpuid-input-ecx': 'int',
+ 'cpuid-register': 'X86CPURegister32',
+ 'features': 'int' } }
+
+##
+# @DummyForceArrays:
+#
+# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally
+#
+# Since: 2.5
+##
+{ 'struct': 'DummyForceArrays',
+ 'data': { 'unused': ['X86CPUFeatureWordInfo'] } }
+
+##
+# @NumaCpuOptions:
+#
+# Option "-numa cpu" overrides default cpu to node mapping.
+# It accepts the same set of cpu properties as returned by
+# query-hotpluggable-cpus[].props, where node-id could be used to
+# override default node mapping.
+#
+# Since: 2.10
+##
+{ 'struct': 'NumaCpuOptions',
+ 'base': 'CpuInstanceProperties',
+ 'data' : {} }
+
+##
+# @HmatLBMemoryHierarchy:
+#
+# The memory hierarchy in the System Locality Latency and Bandwidth
+# Information Structure of HMAT (Heterogeneous Memory Attribute Table)
+#
+# For more information about @HmatLBMemoryHierarchy, see chapter
+# 5.2.27.4: Table 5-146: Field "Flags" of ACPI 6.3 spec.
+#
+# @memory: the structure represents the memory performance
+#
+# @first-level: first level of memory side cache
+#
+# @second-level: second level of memory side cache
+#
+# @third-level: third level of memory side cache
+#
+# Since: 5.0
+##
+{ 'enum': 'HmatLBMemoryHierarchy',
+ 'data': [ 'memory', 'first-level', 'second-level', 'third-level' ] }
+
+##
+# @HmatLBDataType:
+#
+# Data type in the System Locality Latency and Bandwidth
+# Information Structure of HMAT (Heterogeneous Memory Attribute Table)
+#
+# For more information about @HmatLBDataType, see chapter
+# 5.2.27.4: Table 5-146: Field "Data Type" of ACPI 6.3 spec.
+#
+# @access-latency: access latency (nanoseconds)
+#
+# @read-latency: read latency (nanoseconds)
+#
+# @write-latency: write latency (nanoseconds)
+#
+# @access-bandwidth: access bandwidth (Bytes per second)
+#
+# @read-bandwidth: read bandwidth (Bytes per second)
+#
+# @write-bandwidth: write bandwidth (Bytes per second)
+#
+# Since: 5.0
+##
+{ 'enum': 'HmatLBDataType',
+ 'data': [ 'access-latency', 'read-latency', 'write-latency',
+ 'access-bandwidth', 'read-bandwidth', 'write-bandwidth' ] }
+
+##
+# @NumaHmatLBOptions:
+#
+# Set the system locality latency and bandwidth information
+# between Initiator and Target proximity Domains.
+#
+# For more information about @NumaHmatLBOptions, see chapter
+# 5.2.27.4: Table 5-146 of ACPI 6.3 spec.
+#
+# @initiator: the Initiator Proximity Domain.
+#
+# @target: the Target Proximity Domain.
+#
+# @hierarchy: the Memory Hierarchy. Indicates the performance
+# of memory or side cache.
+#
+# @data-type: presents the type of data, access/read/write
+# latency or hit latency.
+#
+# @latency: the value of latency from @initiator to @target
+# proximity domain, the latency unit is "ns(nanosecond)".
+#
+# @bandwidth: the value of bandwidth between @initiator and @target
+# proximity domain, the bandwidth unit is
+# "Bytes per second".
+#
+# Since: 5.0
+##
+{ 'struct': 'NumaHmatLBOptions',
+ 'data': {
+ 'initiator': 'uint16',
+ 'target': 'uint16',
+ 'hierarchy': 'HmatLBMemoryHierarchy',
+ 'data-type': 'HmatLBDataType',
+ '*latency': 'uint64',
+ '*bandwidth': 'size' }}
+
+##
+# @HmatCacheAssociativity:
+#
+# Cache associativity in the Memory Side Cache Information Structure
+# of HMAT
+#
+# For more information of @HmatCacheAssociativity, see chapter
+# 5.2.27.5: Table 5-147 of ACPI 6.3 spec.
+#
+# @none: None (no memory side cache in this proximity domain,
+# or cache associativity unknown)
+#
+# @direct: Direct Mapped
+#
+# @complex: Complex Cache Indexing (implementation specific)
+#
+# Since: 5.0
+##
+{ 'enum': 'HmatCacheAssociativity',
+ 'data': [ 'none', 'direct', 'complex' ] }
+
+##
+# @HmatCacheWritePolicy:
+#
+# Cache write policy in the Memory Side Cache Information Structure
+# of HMAT
+#
+# For more information of @HmatCacheWritePolicy, see chapter
+# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec.
+#
+# @none: None (no memory side cache in this proximity domain,
+# or cache write policy unknown)
+#
+# @write-back: Write Back (WB)
+#
+# @write-through: Write Through (WT)
+#
+# Since: 5.0
+##
+{ 'enum': 'HmatCacheWritePolicy',
+ 'data': [ 'none', 'write-back', 'write-through' ] }
+
+##
+# @NumaHmatCacheOptions:
+#
+# Set the memory side cache information for a given memory domain.
+#
+# For more information of @NumaHmatCacheOptions, see chapter
+# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec.
+#
+# @node-id: the memory proximity domain to which the memory belongs.
+#
+# @size: the size of memory side cache in bytes.
+#
+# @level: the cache level described in this structure.
+#
+# @associativity: the cache associativity,
+# none/direct-mapped/complex(complex cache indexing).
+#
+# @policy: the write policy, none/write-back/write-through.
+#
+# @line: the cache Line size in bytes.
+#
+# Since: 5.0
+##
+{ 'struct': 'NumaHmatCacheOptions',
+ 'data': {
+ 'node-id': 'uint32',
+ 'size': 'size',
+ 'level': 'uint8',
+ 'associativity': 'HmatCacheAssociativity',
+ 'policy': 'HmatCacheWritePolicy',
+ 'line': 'uint16' }}
+
+##
+# @memsave:
+#
+# Save a portion of guest memory to a file.
+#
+# @val: the virtual address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# @cpu-index: the index of the virtual CPU to use for translating the
+# virtual address (defaults to CPU 0)
+#
+# Returns: Nothing on success
+#
+# Since: 0.14
+#
+# Notes: Errors were not reliably returned until 1.1
+#
+# Example:
+#
+# -> { "execute": "memsave",
+# "arguments": { "val": 10,
+# "size": 100,
+# "filename": "/tmp/virtual-mem-dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'memsave',
+ 'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
+
+##
+# @pmemsave:
+#
+# Save a portion of guest physical memory to a file.
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+#
+# Since: 0.14
+#
+# Notes: Errors were not reliably returned until 1.1
+#
+# Example:
+#
+# -> { "execute": "pmemsave",
+# "arguments": { "val": 10,
+# "size": 100,
+# "filename": "/tmp/physical-mem-dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'pmemsave',
+ 'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @Memdev:
+#
+# Information about memory backend
+#
+# @id: backend's ID if backend has 'id' property (since 2.9)
+#
+# @size: memory backend size
+#
+# @merge: whether memory merge support is enabled
+#
+# @dump: whether memory backend's memory is included in a core dump
+#
+# @prealloc: whether memory was preallocated
+#
+# @share: whether memory is private to QEMU or shared (since 6.1)
+#
+# @reserve: whether swap space (or huge pages) was reserved if applicable.
+# This corresponds to the user configuration and not the actual
+# behavior implemented in the OS to perform the reservation.
+# For example, Linux will never reserve swap space for shared
+# file mappings. (since 6.1)
+#
+# @host-nodes: host nodes for its memory policy
+#
+# @policy: memory policy of memory backend
+#
+# Since: 2.1
+##
+{ 'struct': 'Memdev',
+ 'data': {
+ '*id': 'str',
+ 'size': 'size',
+ 'merge': 'bool',
+ 'dump': 'bool',
+ 'prealloc': 'bool',
+ 'share': 'bool',
+ '*reserve': 'bool',
+ 'host-nodes': ['uint16'],
+ 'policy': 'HostMemPolicy' }}
+
+##
+# @query-memdev:
+#
+# Returns information for all memory backends.
+#
+# Returns: a list of @Memdev.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-memdev" }
+# <- { "return": [
+# {
+# "id": "mem1",
+# "size": 536870912,
+# "merge": false,
+# "dump": true,
+# "prealloc": false,
+# "host-nodes": [0, 1],
+# "policy": "bind"
+# },
+# {
+# "size": 536870912,
+# "merge": false,
+# "dump": true,
+# "prealloc": true,
+# "host-nodes": [2, 3],
+# "policy": "preferred"
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true }
+
+##
+# @CpuInstanceProperties:
+#
+# List of properties to be used for hotplugging a CPU instance,
+# it should be passed by management with device_add command when
+# a CPU is being hotplugged.
+#
+# @node-id: NUMA node ID the CPU belongs to
+# @socket-id: socket number within node/board the CPU belongs to
+# @die-id: die number within node/board the CPU belongs to (Since 4.1)
+# @core-id: core number within die the CPU belongs to
+# @thread-id: thread number within core the CPU belongs to
+#
+# Note: currently there are 5 properties that could be present
+# but management should be prepared to pass through other
+# properties with device_add command to allow for future
+# interface extension. This also requires the filed names to be kept in
+# sync with the properties passed to -device/device_add.
+#
+# Since: 2.7
+##
+{ 'struct': 'CpuInstanceProperties',
+ 'data': { '*node-id': 'int',
+ '*socket-id': 'int',
+ '*die-id': 'int',
+ '*core-id': 'int',
+ '*thread-id': 'int'
+ }
+}
+
+##
+# @HotpluggableCPU:
+#
+# @type: CPU object type for usage with device_add command
+# @props: list of properties to be used for hotplugging CPU
+# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides
+# @qom-path: link to existing CPU object if CPU is present or
+# omitted if CPU is not present.
+#
+# Since: 2.7
+##
+{ 'struct': 'HotpluggableCPU',
+ 'data': { 'type': 'str',
+ 'vcpus-count': 'int',
+ 'props': 'CpuInstanceProperties',
+ '*qom-path': 'str'
+ }
+}
+
+##
+# @query-hotpluggable-cpus:
+#
+# TODO: Better documentation; currently there is none.
+#
+# Returns: a list of HotpluggableCPU objects.
+#
+# Since: 2.7
+#
+# Example:
+#
+# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8:
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+# { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core",
+# "vcpus-count": 1 },
+# { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core",
+# "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"}
+# ]}'
+#
+# For pc machine type started with -smp 1,maxcpus=2:
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+# {
+# "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
+# "props": {"core-id": 0, "socket-id": 1, "thread-id": 0}
+# },
+# {
+# "qom-path": "/machine/unattached/device[0]",
+# "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
+# "props": {"core-id": 0, "socket-id": 0, "thread-id": 0}
+# }
+# ]}
+#
+# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu
+# (Since: 2.11):
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+# {
+# "type": "qemu-s390x-cpu", "vcpus-count": 1,
+# "props": { "core-id": 1 }
+# },
+# {
+# "qom-path": "/machine/unattached/device[0]",
+# "type": "qemu-s390x-cpu", "vcpus-count": 1,
+# "props": { "core-id": 0 }
+# }
+# ]}
+#
+##
+{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'],
+ 'allow-preconfig': true }
+
+##
+# @set-numa-node:
+#
+# Runtime equivalent of '-numa' CLI option, available at
+# preconfigure stage to configure numa mapping before initializing
+# machine.
+#
+# Since 3.0
+##
+{ 'command': 'set-numa-node', 'boxed': true,
+ 'data': 'NumaOptions',
+ 'allow-preconfig': true
+}
+
+##
+# @balloon:
+#
+# Request the balloon driver to change its balloon size.
+#
+# @value: the target logical size of the VM in bytes.
+# We can deduce the size of the balloon using this formula:
+#
+# logical_vm_size = vm_ram_size - balloon_size
+#
+# From it we have: balloon_size = vm_ram_size - @value
+#
+# Returns: - Nothing on success
+# - If the balloon driver is enabled but not functional because the KVM
+# kernel module cannot support it, KvmMissingCap
+# - If no balloon device is present, DeviceNotActive
+#
+# Notes: This command just issues a request to the guest. When it returns,
+# the balloon size may not have changed. A guest can change the balloon
+# size independent of this command.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "balloon", "arguments": { "value": 536870912 } }
+# <- { "return": {} }
+#
+# With a 2.5GiB guest this command inflated the ballon to 3GiB.
+#
+##
+{ 'command': 'balloon', 'data': {'value': 'int'} }
+
+##
+# @BalloonInfo:
+#
+# Information about the guest balloon device.
+#
+# @actual: the logical size of the VM in bytes
+# Formula used: logical_vm_size = vm_ram_size - balloon_size
+#
+# Since: 0.14
+#
+##
+{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } }
+
+##
+# @query-balloon:
+#
+# Return information about the balloon device.
+#
+# Returns: - @BalloonInfo on success
+# - If the balloon driver is enabled but not functional because the KVM
+# kernel module cannot support it, KvmMissingCap
+# - If no balloon device is present, DeviceNotActive
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-balloon" }
+# <- { "return": {
+# "actual": 1073741824,
+# }
+# }
+#
+##
+{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }
+
+##
+# @BALLOON_CHANGE:
+#
+# Emitted when the guest changes the actual BALLOON level. This value is
+# equivalent to the @actual field return by the 'query-balloon' command
+#
+# @actual: the logical size of the VM in bytes
+# Formula used: logical_vm_size = vm_ram_size - balloon_size
+#
+# Note: this event is rate-limited.
+#
+# Since: 1.2
+#
+# Example:
+#
+# <- { "event": "BALLOON_CHANGE",
+# "data": { "actual": 944766976 },
+# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'BALLOON_CHANGE',
+ 'data': { 'actual': 'int' } }
+
+##
+# @MemoryInfo:
+#
+# Actual memory information in bytes.
+#
+# @base-memory: size of "base" memory specified with command line
+# option -m.
+#
+# @plugged-memory: size of memory that can be hot-unplugged. This field
+# is omitted if target doesn't support memory hotplug
+# (i.e. CONFIG_MEM_DEVICE not defined at build time).
+#
+# Since: 2.11
+##
+{ 'struct': 'MemoryInfo',
+ 'data' : { 'base-memory': 'size', '*plugged-memory': 'size' } }
+
+##
+# @query-memory-size-summary:
+#
+# Return the amount of initially allocated and present hotpluggable (if
+# enabled) memory in bytes.
+#
+# Example:
+#
+# -> { "execute": "query-memory-size-summary" }
+# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } }
+#
+# Since: 2.11
+##
+{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' }
+
+##
+# @PCDIMMDeviceInfo:
+#
+# PCDIMMDevice state information
+#
+# @id: device's ID
+#
+# @addr: physical address, where device is mapped
+#
+# @size: size of memory that the device provides
+#
+# @slot: slot number at which device is plugged in
+#
+# @node: NUMA node number where device is plugged in
+#
+# @memdev: memory backend linked with device
+#
+# @hotplugged: true if device was hotplugged
+#
+# @hotpluggable: true if device if could be added/removed while machine is running
+#
+# Since: 2.1
+##
+{ 'struct': 'PCDIMMDeviceInfo',
+ 'data': { '*id': 'str',
+ 'addr': 'int',
+ 'size': 'int',
+ 'slot': 'int',
+ 'node': 'int',
+ 'memdev': 'str',
+ 'hotplugged': 'bool',
+ 'hotpluggable': 'bool'
+ }
+}
+
+##
+# @VirtioPMEMDeviceInfo:
+#
+# VirtioPMEM state information
+#
+# @id: device's ID
+#
+# @memaddr: physical address in memory, where device is mapped
+#
+# @size: size of memory that the device provides
+#
+# @memdev: memory backend linked with device
+#
+# Since: 4.1
+##
+{ 'struct': 'VirtioPMEMDeviceInfo',
+ 'data': { '*id': 'str',
+ 'memaddr': 'size',
+ 'size': 'size',
+ 'memdev': 'str'
+ }
+}
+
+##
+# @VirtioMEMDeviceInfo:
+#
+# VirtioMEMDevice state information
+#
+# @id: device's ID
+#
+# @memaddr: physical address in memory, where device is mapped
+#
+# @requested-size: the user requested size of the device
+#
+# @size: the (current) size of memory that the device provides
+#
+# @max-size: the maximum size of memory that the device can provide
+#
+# @block-size: the block size of memory that the device provides
+#
+# @node: NUMA node number where device is assigned to
+#
+# @memdev: memory backend linked with the region
+#
+# Since: 5.1
+##
+{ 'struct': 'VirtioMEMDeviceInfo',
+ 'data': { '*id': 'str',
+ 'memaddr': 'size',
+ 'requested-size': 'size',
+ 'size': 'size',
+ 'max-size': 'size',
+ 'block-size': 'size',
+ 'node': 'int',
+ 'memdev': 'str'
+ }
+}
+
+##
+# @SgxEPCDeviceInfo:
+#
+# Sgx EPC state information
+#
+# @id: device's ID
+#
+# @memaddr: physical address in memory, where device is mapped
+#
+# @size: size of memory that the device provides
+#
+# @memdev: memory backend linked with device
+#
+# Since: 6.2
+##
+{ 'struct': 'SgxEPCDeviceInfo',
+ 'data': { '*id': 'str',
+ 'memaddr': 'size',
+ 'size': 'size',
+ 'memdev': 'str'
+ }
+}
+
+##
+# @MemoryDeviceInfoKind:
+#
+# Since: 2.1
+##
+{ 'enum': 'MemoryDeviceInfoKind',
+ 'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem', 'sgx-epc' ] }
+
+##
+# @PCDIMMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'PCDIMMDeviceInfoWrapper',
+ 'data': { 'data': 'PCDIMMDeviceInfo' } }
+
+##
+# @VirtioPMEMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'VirtioPMEMDeviceInfoWrapper',
+ 'data': { 'data': 'VirtioPMEMDeviceInfo' } }
+
+##
+# @VirtioMEMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'VirtioMEMDeviceInfoWrapper',
+ 'data': { 'data': 'VirtioMEMDeviceInfo' } }
+
+##
+# @SgxEPCDeviceInfoWrapper:
+#
+# Since: 6.2
+##
+{ 'struct': 'SgxEPCDeviceInfoWrapper',
+ 'data': { 'data': 'SgxEPCDeviceInfo' } }
+
+##
+# @MemoryDeviceInfo:
+#
+# Union containing information about a memory device
+#
+# nvdimm is included since 2.12. virtio-pmem is included since 4.1.
+# virtio-mem is included since 5.1. sgx-epc is included since 6.2.
+#
+# Since: 2.1
+##
+{ 'union': 'MemoryDeviceInfo',
+ 'base': { 'type': 'MemoryDeviceInfoKind' },
+ 'discriminator': 'type',
+ 'data': { 'dimm': 'PCDIMMDeviceInfoWrapper',
+ 'nvdimm': 'PCDIMMDeviceInfoWrapper',
+ 'virtio-pmem': 'VirtioPMEMDeviceInfoWrapper',
+ 'virtio-mem': 'VirtioMEMDeviceInfoWrapper',
+ 'sgx-epc': 'SgxEPCDeviceInfoWrapper'
+ }
+}
+
+##
+# @SgxEPC:
+#
+# Sgx EPC cmdline information
+#
+# @memdev: memory backend linked with device
+#
+# Since: 6.2
+##
+{ 'struct': 'SgxEPC',
+ 'data': { 'memdev': 'str' } }
+
+##
+# @SgxEPCProperties:
+#
+# SGX properties of machine types.
+#
+# @sgx-epc: list of ids of memory-backend-epc objects.
+#
+# Since: 6.2
+##
+{ 'struct': 'SgxEPCProperties',
+ 'data': { 'sgx-epc': ['SgxEPC'] }
+}
+
+##
+# @query-memory-devices:
+#
+# Lists available memory devices and their state
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-memory-devices" }
+# <- { "return": [ { "data":
+# { "addr": 5368709120,
+# "hotpluggable": true,
+# "hotplugged": true,
+# "id": "d1",
+# "memdev": "/objects/memX",
+# "node": 0,
+# "size": 1073741824,
+# "slot": 0},
+# "type": "dimm"
+# } ] }
+#
+##
+{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] }
+
+##
+# @MEMORY_DEVICE_SIZE_CHANGE:
+#
+# Emitted when the size of a memory device changes. Only emitted for memory
+# devices that can actually change the size (e.g., virtio-mem due to guest
+# action).
+#
+# @id: device's ID
+#
+# @size: the new size of memory that the device provides
+#
+# @qom-path: path to the device object in the QOM tree (since 6.2)
+#
+# Note: this event is rate-limited.
+#
+# Since: 5.1
+#
+# Example:
+#
+# <- { "event": "MEMORY_DEVICE_SIZE_CHANGE",
+# "data": { "id": "vm0", "size": 1073741824},
+# "timestamp": { "seconds": 1588168529, "microseconds": 201316 } }
+#
+##
+{ 'event': 'MEMORY_DEVICE_SIZE_CHANGE',
+ 'data': { '*id': 'str', 'size': 'size', 'qom-path' : 'str'} }
+
+
+##
+# @MEM_UNPLUG_ERROR:
+#
+# Emitted when memory hot unplug error occurs.
+#
+# @device: device name
+#
+# @msg: Informative message
+#
+# Features:
+# @deprecated: This event is deprecated. Use @DEVICE_UNPLUG_GUEST_ERROR
+# instead.
+#
+# Since: 2.4
+#
+# Example:
+#
+# <- { "event": "MEM_UNPLUG_ERROR"
+# "data": { "device": "dimm1",
+# "msg": "acpi: device unplug for unsupported device"
+# },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'MEM_UNPLUG_ERROR',
+ 'data': { 'device': 'str', 'msg': 'str' },
+ 'features': ['deprecated'] }
+
+##
+# @SMPConfiguration:
+#
+# Schema for CPU topology configuration. A missing value lets
+# QEMU figure out a suitable value based on the ones that are provided.
+#
+# @cpus: number of virtual CPUs in the virtual machine
+#
+# @sockets: number of sockets in the CPU topology
+#
+# @dies: number of dies per socket in the CPU topology
+#
+# @cores: number of cores per die in the CPU topology
+#
+# @threads: number of threads per core in the CPU topology
+#
+# @maxcpus: maximum number of hotpluggable virtual CPUs in the virtual machine
+#
+# Since: 6.1
+##
+{ 'struct': 'SMPConfiguration', 'data': {
+ '*cpus': 'int',
+ '*sockets': 'int',
+ '*dies': 'int',
+ '*cores': 'int',
+ '*threads': 'int',
+ '*maxcpus': 'int' } }
+
+##
+# @x-query-irq:
+#
+# Query interrupt statistics
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: interrupt statistics
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-irq',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-jit:
+#
+# Query TCG compiler statistics
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: TCG compiler statistics
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-jit',
+ 'returns': 'HumanReadableText',
+ 'if': 'CONFIG_TCG',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-numa:
+#
+# Query NUMA topology information
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: topology information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-numa',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-opcount:
+#
+# Query TCG opcode counters
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: TCG opcode counters
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-opcount',
+ 'returns': 'HumanReadableText',
+ 'if': 'CONFIG_TCG',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-profile:
+#
+# Query TCG profiling information
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: profile information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-profile',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-ramblock:
+#
+# Query system ramblock information
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: system ramblock information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-ramblock',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-rdma:
+#
+# Query RDMA state
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: RDMA state
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-rdma',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-roms:
+#
+# Query information on the registered ROMS
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: registered ROMs
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-roms',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
+
+##
+# @x-query-usb:
+#
+# Query information on the USB devices
+#
+# Features:
+# @unstable: This command is meant for debugging.
+#
+# Returns: USB device information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-usb',
+ 'returns': 'HumanReadableText',
+ 'features': [ 'unstable' ] }
diff --git a/qapi/meson.build b/qapi/meson.build
new file mode 100644
index 000000000..c0c49c15e
--- /dev/null
+++ b/qapi/meson.build
@@ -0,0 +1,150 @@
+util_ss.add(files(
+ 'opts-visitor.c',
+ 'qapi-clone-visitor.c',
+ 'qapi-dealloc-visitor.c',
+ 'qapi-forward-visitor.c',
+ 'qapi-util.c',
+ 'qapi-visit-core.c',
+ 'qobject-input-visitor.c',
+ 'qobject-output-visitor.c',
+ 'string-input-visitor.c',
+ 'string-output-visitor.c',
+))
+if have_system
+ util_ss.add(files('qapi-type-helpers.c'))
+endif
+if have_system or have_tools
+ util_ss.add(files(
+ 'qmp-dispatch.c',
+ 'qmp-event.c',
+ 'qmp-registry.c',
+ ))
+endif
+
+qapi_all_modules = [
+ 'authz',
+ 'block',
+ 'block-core',
+ 'block-export',
+ 'char',
+ 'common',
+ 'compat',
+ 'control',
+ 'crypto',
+ 'dump',
+ 'error',
+ 'introspect',
+ 'job',
+ 'machine',
+ 'machine-target',
+ 'migration',
+ 'misc',
+ 'misc-target',
+ 'net',
+ 'pragma',
+ 'qom',
+ 'replay',
+ 'run-state',
+ 'sockets',
+ 'trace',
+ 'transaction',
+ 'yank',
+]
+if have_system
+ qapi_all_modules += [
+ 'acpi',
+ 'audio',
+ 'qdev',
+ 'pci',
+ 'rdma',
+ 'rocker',
+ 'tpm',
+ ]
+endif
+if have_system or have_tools
+ qapi_all_modules += [
+ 'ui',
+ ]
+endif
+
+qapi_storage_daemon_modules = [
+ 'block-core',
+ 'block-export',
+ 'char',
+ 'common',
+ 'control',
+ 'crypto',
+ 'introspect',
+ 'job',
+ 'qom',
+ 'sockets',
+ 'pragma',
+ 'transaction',
+]
+
+qapi_nonmodule_outputs = [
+ 'qapi-introspect.c', 'qapi-introspect.h',
+ 'qapi-types.c', 'qapi-types.h',
+ 'qapi-visit.h', 'qapi-visit.c',
+ 'qapi-commands.h', 'qapi-commands.c',
+ 'qapi-init-commands.h', 'qapi-init-commands.c',
+ 'qapi-events.h', 'qapi-events.c',
+ 'qapi-emit-events.c', 'qapi-emit-events.h',
+]
+
+# First build all sources
+qapi_util_outputs = [
+ 'qapi-builtin-types.c', 'qapi-builtin-visit.c',
+ 'qapi-builtin-types.h', 'qapi-builtin-visit.h',
+]
+
+qapi_inputs = []
+qapi_specific_outputs = []
+foreach module : qapi_all_modules
+ qapi_inputs += [ files(module + '.json') ]
+ qapi_module_outputs = [
+ 'qapi-types-@0@.c'.format(module),
+ 'qapi-types-@0@.h'.format(module),
+ 'qapi-visit-@0@.c'.format(module),
+ 'qapi-visit-@0@.h'.format(module),
+ ]
+ if have_system or have_tools
+ qapi_module_outputs += [
+ 'qapi-events-@0@.c'.format(module),
+ 'qapi-events-@0@.h'.format(module),
+ 'qapi-commands-@0@.c'.format(module),
+ 'qapi-commands-@0@.h'.format(module),
+ ]
+ endif
+ if module.endswith('-target')
+ qapi_specific_outputs += qapi_module_outputs
+ else
+ qapi_util_outputs += qapi_module_outputs
+ endif
+endforeach
+
+qapi_files = custom_target('shared QAPI source files',
+ output: qapi_util_outputs + qapi_specific_outputs + qapi_nonmodule_outputs,
+ input: [ files('qapi-schema.json') ],
+ command: [ qapi_gen, '-o', 'qapi', '-b', '@INPUT0@' ],
+ depend_files: [ qapi_inputs, qapi_gen_depends ])
+
+# Now go through all the outputs and add them to the right sourceset.
+# These loops must be synchronized with the output of the above custom target.
+
+i = 0
+foreach output : qapi_util_outputs
+ if output.endswith('.h')
+ genh += qapi_files[i]
+ endif
+ util_ss.add(qapi_files[i])
+ i = i + 1
+endforeach
+
+foreach output : qapi_specific_outputs + qapi_nonmodule_outputs
+ if output.endswith('.h')
+ genh += qapi_files[i]
+ endif
+ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: qapi_files[i])
+ i = i + 1
+endforeach
diff --git a/qapi/migration.json b/qapi/migration.json
new file mode 100644
index 000000000..bbfd48cf0
--- /dev/null
+++ b/qapi/migration.json
@@ -0,0 +1,2023 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Migration
+##
+
+{ 'include': 'common.json' }
+{ 'include': 'sockets.json' }
+
+##
+# @MigrationStats:
+#
+# Detailed migration status.
+#
+# @transferred: amount of bytes already transferred to the target VM
+#
+# @remaining: amount of bytes remaining to be transferred to the target VM
+#
+# @total: total amount of bytes involved in the migration process
+#
+# @duplicate: number of duplicate (zero) pages (since 1.2)
+#
+# @skipped: number of skipped zero pages (since 1.5)
+#
+# @normal: number of normal pages (since 1.2)
+#
+# @normal-bytes: number of normal bytes sent (since 1.2)
+#
+# @dirty-pages-rate: number of pages dirtied by second by the
+# guest (since 1.3)
+#
+# @mbps: throughput in megabits/sec. (since 1.6)
+#
+# @dirty-sync-count: number of times that dirty ram was synchronized (since 2.1)
+#
+# @postcopy-requests: The number of page requests received from the destination
+# (since 2.7)
+#
+# @page-size: The number of bytes per page for the various page-based
+# statistics (since 2.10)
+#
+# @multifd-bytes: The number of bytes sent through multifd (since 3.0)
+#
+# @pages-per-second: the number of memory pages transferred per second
+# (Since 4.0)
+#
+# Since: 0.14
+##
+{ 'struct': 'MigrationStats',
+ 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
+ 'duplicate': 'int', 'skipped': 'int', 'normal': 'int',
+ 'normal-bytes': 'int', 'dirty-pages-rate' : 'int',
+ 'mbps' : 'number', 'dirty-sync-count' : 'int',
+ 'postcopy-requests' : 'int', 'page-size' : 'int',
+ 'multifd-bytes' : 'uint64', 'pages-per-second' : 'uint64' } }
+
+##
+# @XBZRLECacheStats:
+#
+# Detailed XBZRLE migration cache statistics
+#
+# @cache-size: XBZRLE cache size
+#
+# @bytes: amount of bytes already transferred to the target VM
+#
+# @pages: amount of pages transferred to the target VM
+#
+# @cache-miss: number of cache miss
+#
+# @cache-miss-rate: rate of cache miss (since 2.1)
+#
+# @encoding-rate: rate of encoded bytes (since 5.1)
+#
+# @overflow: number of overflows
+#
+# Since: 1.2
+##
+{ 'struct': 'XBZRLECacheStats',
+ 'data': {'cache-size': 'size', 'bytes': 'int', 'pages': 'int',
+ 'cache-miss': 'int', 'cache-miss-rate': 'number',
+ 'encoding-rate': 'number', 'overflow': 'int' } }
+
+##
+# @CompressionStats:
+#
+# Detailed migration compression statistics
+#
+# @pages: amount of pages compressed and transferred to the target VM
+#
+# @busy: count of times that no free thread was available to compress data
+#
+# @busy-rate: rate of thread busy
+#
+# @compressed-size: amount of bytes after compression
+#
+# @compression-rate: rate of compressed size
+#
+# Since: 3.1
+##
+{ 'struct': 'CompressionStats',
+ 'data': {'pages': 'int', 'busy': 'int', 'busy-rate': 'number',
+ 'compressed-size': 'int', 'compression-rate': 'number' } }
+
+##
+# @MigrationStatus:
+#
+# An enumeration of migration status.
+#
+# @none: no migration has ever happened.
+#
+# @setup: migration process has been initiated.
+#
+# @cancelling: in the process of cancelling migration.
+#
+# @cancelled: cancelling migration is finished.
+#
+# @active: in the process of doing migration.
+#
+# @postcopy-active: like active, but now in postcopy mode. (since 2.5)
+#
+# @postcopy-paused: during postcopy but paused. (since 3.0)
+#
+# @postcopy-recover: trying to recover from a paused postcopy. (since 3.0)
+#
+# @completed: migration is finished.
+#
+# @failed: some error occurred during migration process.
+#
+# @colo: VM is in the process of fault tolerance, VM can not get into this
+# state unless colo capability is enabled for migration. (since 2.8)
+#
+# @pre-switchover: Paused before device serialisation. (since 2.11)
+#
+# @device: During device serialisation when pause-before-switchover is enabled
+# (since 2.11)
+#
+# @wait-unplug: wait for device unplug request by guest OS to be completed.
+# (since 4.2)
+#
+# Since: 2.3
+#
+##
+{ 'enum': 'MigrationStatus',
+ 'data': [ 'none', 'setup', 'cancelling', 'cancelled',
+ 'active', 'postcopy-active', 'postcopy-paused',
+ 'postcopy-recover', 'completed', 'failed', 'colo',
+ 'pre-switchover', 'device', 'wait-unplug' ] }
+##
+# @VfioStats:
+#
+# Detailed VFIO devices migration statistics
+#
+# @transferred: amount of bytes transferred to the target VM by VFIO devices
+#
+# Since: 5.2
+#
+##
+{ 'struct': 'VfioStats',
+ 'data': {'transferred': 'int' } }
+
+##
+# @MigrationInfo:
+#
+# Information about current migration process.
+#
+# @status: @MigrationStatus describing the current migration status.
+# If this field is not returned, no migration process
+# has been initiated
+#
+# @ram: @MigrationStats containing detailed migration
+# status, only returned if status is 'active' or
+# 'completed'(since 1.2)
+#
+# @disk: @MigrationStats containing detailed disk migration
+# status, only returned if status is 'active' and it is a block
+# migration
+#
+# @xbzrle-cache: @XBZRLECacheStats containing detailed XBZRLE
+# migration statistics, only returned if XBZRLE feature is on and
+# status is 'active' or 'completed' (since 1.2)
+#
+# @total-time: total amount of milliseconds since migration started.
+# If migration has ended, it returns the total migration
+# time. (since 1.2)
+#
+# @downtime: only present when migration finishes correctly
+# total downtime in milliseconds for the guest.
+# (since 1.3)
+#
+# @expected-downtime: only present while migration is active
+# expected downtime in milliseconds for the guest in last walk
+# of the dirty bitmap. (since 1.3)
+#
+# @setup-time: amount of setup time in milliseconds *before* the
+# iterations begin but *after* the QMP command is issued. This is designed
+# to provide an accounting of any activities (such as RDMA pinning) which
+# may be expensive, but do not actually occur during the iterative
+# migration rounds themselves. (since 1.6)
+#
+# @cpu-throttle-percentage: percentage of time guest cpus are being
+# throttled during auto-converge. This is only present when auto-converge
+# has started throttling guest cpus. (Since 2.7)
+#
+# @error-desc: the human readable error description string, when
+# @status is 'failed'. Clients should not attempt to parse the
+# error strings. (Since 2.7)
+#
+# @postcopy-blocktime: total time when all vCPU were blocked during postcopy
+# live migration. This is only present when the postcopy-blocktime
+# migration capability is enabled. (Since 3.0)
+#
+# @postcopy-vcpu-blocktime: list of the postcopy blocktime per vCPU. This is
+# only present when the postcopy-blocktime migration capability
+# is enabled. (Since 3.0)
+#
+# @compression: migration compression statistics, only returned if compression
+# feature is on and status is 'active' or 'completed' (Since 3.1)
+#
+# @socket-address: Only used for tcp, to know what the real port is (Since 4.0)
+#
+# @vfio: @VfioStats containing detailed VFIO devices migration statistics,
+# only returned if VFIO device is present, migration is supported by all
+# VFIO devices and status is 'active' or 'completed' (since 5.2)
+#
+# @blocked-reasons: A list of reasons an outgoing migration is blocked.
+# Present and non-empty when migration is blocked.
+# (since 6.0)
+#
+# Since: 0.14
+##
+{ 'struct': 'MigrationInfo',
+ 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats',
+ '*disk': 'MigrationStats',
+ '*vfio': 'VfioStats',
+ '*xbzrle-cache': 'XBZRLECacheStats',
+ '*total-time': 'int',
+ '*expected-downtime': 'int',
+ '*downtime': 'int',
+ '*setup-time': 'int',
+ '*cpu-throttle-percentage': 'int',
+ '*error-desc': 'str',
+ '*blocked-reasons': ['str'],
+ '*postcopy-blocktime' : 'uint32',
+ '*postcopy-vcpu-blocktime': ['uint32'],
+ '*compression': 'CompressionStats',
+ '*socket-address': ['SocketAddress'] } }
+
+##
+# @query-migrate:
+#
+# Returns information about current migration process. If migration
+# is active there will be another json-object with RAM migration
+# status and if block migration is active another one with block
+# migration status.
+#
+# Returns: @MigrationInfo
+#
+# Since: 0.14
+#
+# Example:
+#
+# 1. Before the first migration
+#
+# -> { "execute": "query-migrate" }
+# <- { "return": {} }
+#
+# 2. Migration is done and has succeeded
+#
+# -> { "execute": "query-migrate" }
+# <- { "return": {
+# "status": "completed",
+# "total-time":12345,
+# "setup-time":12345,
+# "downtime":12345,
+# "ram":{
+# "transferred":123,
+# "remaining":123,
+# "total":246,
+# "duplicate":123,
+# "normal":123,
+# "normal-bytes":123456,
+# "dirty-sync-count":15
+# }
+# }
+# }
+#
+# 3. Migration is done and has failed
+#
+# -> { "execute": "query-migrate" }
+# <- { "return": { "status": "failed" } }
+#
+# 4. Migration is being performed and is not a block migration:
+#
+# -> { "execute": "query-migrate" }
+# <- {
+# "return":{
+# "status":"active",
+# "total-time":12345,
+# "setup-time":12345,
+# "expected-downtime":12345,
+# "ram":{
+# "transferred":123,
+# "remaining":123,
+# "total":246,
+# "duplicate":123,
+# "normal":123,
+# "normal-bytes":123456,
+# "dirty-sync-count":15
+# }
+# }
+# }
+#
+# 5. Migration is being performed and is a block migration:
+#
+# -> { "execute": "query-migrate" }
+# <- {
+# "return":{
+# "status":"active",
+# "total-time":12345,
+# "setup-time":12345,
+# "expected-downtime":12345,
+# "ram":{
+# "total":1057024,
+# "remaining":1053304,
+# "transferred":3720,
+# "duplicate":123,
+# "normal":123,
+# "normal-bytes":123456,
+# "dirty-sync-count":15
+# },
+# "disk":{
+# "total":20971520,
+# "remaining":20880384,
+# "transferred":91136
+# }
+# }
+# }
+#
+# 6. Migration is being performed and XBZRLE is active:
+#
+# -> { "execute": "query-migrate" }
+# <- {
+# "return":{
+# "status":"active",
+# "total-time":12345,
+# "setup-time":12345,
+# "expected-downtime":12345,
+# "ram":{
+# "total":1057024,
+# "remaining":1053304,
+# "transferred":3720,
+# "duplicate":10,
+# "normal":3333,
+# "normal-bytes":3412992,
+# "dirty-sync-count":15
+# },
+# "xbzrle-cache":{
+# "cache-size":67108864,
+# "bytes":20971520,
+# "pages":2444343,
+# "cache-miss":2244,
+# "cache-miss-rate":0.123,
+# "encoding-rate":80.1,
+# "overflow":34434
+# }
+# }
+# }
+#
+##
+{ 'command': 'query-migrate', 'returns': 'MigrationInfo' }
+
+##
+# @MigrationCapability:
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+# This feature allows us to minimize migration traffic for certain work
+# loads, by sending compressed difference of the pages
+#
+# @rdma-pin-all: Controls whether or not the entire VM memory footprint is
+# mlock()'d on demand or all at once. Refer to docs/rdma.txt for usage.
+# Disabled by default. (since 2.0)
+#
+# @zero-blocks: During storage migration encode blocks of zeroes efficiently. This
+# essentially saves 1MB of zeroes per block on the wire. Enabling requires
+# source and target VM to support this feature. To enable it is sufficient
+# to enable the capability on the source VM. The feature is disabled by
+# default. (since 1.6)
+#
+# @compress: Use multiple compression threads to accelerate live migration.
+# This feature can help to reduce the migration traffic, by sending
+# compressed pages. Please note that if compress and xbzrle are both
+# on, compress only takes effect in the ram bulk stage, after that,
+# it will be disabled and only xbzrle takes effect, this can help to
+# minimize migration traffic. The feature is disabled by default.
+# (since 2.4 )
+#
+# @events: generate events for each migration state change
+# (since 2.4 )
+#
+# @auto-converge: If enabled, QEMU will automatically throttle down the guest
+# to speed up convergence of RAM migration. (since 1.6)
+#
+# @postcopy-ram: Start executing on the migration target before all of RAM has
+# been migrated, pulling the remaining pages along as needed. The
+# capacity must have the same setting on both source and target
+# or migration will not even start. NOTE: If the migration fails during
+# postcopy the VM will fail. (since 2.6)
+#
+# @x-colo: If enabled, migration will never end, and the state of the VM on the
+# primary side will be migrated continuously to the VM on secondary
+# side, this process is called COarse-Grain LOck Stepping (COLO) for
+# Non-stop Service. (since 2.8)
+#
+# @release-ram: if enabled, qemu will free the migrated ram pages on the source
+# during postcopy-ram migration. (since 2.9)
+#
+# @block: If enabled, QEMU will also migrate the contents of all block
+# devices. Default is disabled. A possible alternative uses
+# mirror jobs to a builtin NBD server on the destination, which
+# offers more flexibility.
+# (Since 2.10)
+#
+# @return-path: If enabled, migration will use the return path even
+# for precopy. (since 2.10)
+#
+# @pause-before-switchover: Pause outgoing migration before serialising device
+# state and before disabling block IO (since 2.11)
+#
+# @multifd: Use more than one fd for migration (since 4.0)
+#
+# @dirty-bitmaps: If enabled, QEMU will migrate named dirty bitmaps.
+# (since 2.12)
+#
+# @postcopy-blocktime: Calculate downtime for postcopy live migration
+# (since 3.0)
+#
+# @late-block-activate: If enabled, the destination will not activate block
+# devices (and thus take locks) immediately at the end of migration.
+# (since 3.0)
+#
+# @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0)
+#
+# @validate-uuid: Send the UUID of the source to allow the destination
+# to ensure it is the same. (since 4.2)
+#
+# @background-snapshot: If enabled, the migration stream will be a snapshot
+# of the VM exactly at the point when the migration
+# procedure starts. The VM RAM is saved with running VM.
+# (since 6.0)
+#
+# Features:
+# @unstable: Members @x-colo and @x-ignore-shared are experimental.
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+ 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
+ 'compress', 'events', 'postcopy-ram',
+ { 'name': 'x-colo', 'features': [ 'unstable' ] },
+ 'release-ram',
+ 'block', 'return-path', 'pause-before-switchover', 'multifd',
+ 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
+ { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
+ 'validate-uuid', 'background-snapshot'] }
+
+##
+# @MigrationCapabilityStatus:
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'struct': 'MigrationCapabilityStatus',
+ 'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @migrate-set-capabilities:
+#
+# Enable/Disable the following migration capabilities (like xbzrle)
+#
+# @capabilities: json array of capability modifications to make
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "migrate-set-capabilities" , "arguments":
+# { "capabilities": [ { "capability": "xbzrle", "state": true } ] } }
+#
+##
+{ 'command': 'migrate-set-capabilities',
+ 'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
+
+##
+# @query-migrate-capabilities:
+#
+# Returns information about the current migration capabilities status
+#
+# Returns: @MigrationCapabilitiesStatus
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "query-migrate-capabilities" }
+# <- { "return": [
+# {"state": false, "capability": "xbzrle"},
+# {"state": false, "capability": "rdma-pin-all"},
+# {"state": false, "capability": "auto-converge"},
+# {"state": false, "capability": "zero-blocks"},
+# {"state": false, "capability": "compress"},
+# {"state": true, "capability": "events"},
+# {"state": false, "capability": "postcopy-ram"},
+# {"state": false, "capability": "x-colo"}
+# ]}
+#
+##
+{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']}
+
+##
+# @MultiFDCompression:
+#
+# An enumeration of multifd compression methods.
+#
+# @none: no compression.
+# @zlib: use zlib compression method.
+# @zstd: use zstd compression method.
+#
+# Since: 5.0
+#
+##
+{ 'enum': 'MultiFDCompression',
+ 'data': [ 'none', 'zlib',
+ { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
+
+##
+# @BitmapMigrationBitmapAliasTransform:
+#
+# @persistent: If present, the bitmap will be made persistent
+# or transient depending on this parameter.
+#
+# Since: 6.0
+##
+{ 'struct': 'BitmapMigrationBitmapAliasTransform',
+ 'data': {
+ '*persistent': 'bool'
+ } }
+
+##
+# @BitmapMigrationBitmapAlias:
+#
+# @name: The name of the bitmap.
+#
+# @alias: An alias name for migration (for example the bitmap name on
+# the opposite site).
+#
+# @transform: Allows the modification of the migrated bitmap.
+# (since 6.0)
+#
+# Since: 5.2
+##
+{ 'struct': 'BitmapMigrationBitmapAlias',
+ 'data': {
+ 'name': 'str',
+ 'alias': 'str',
+ '*transform': 'BitmapMigrationBitmapAliasTransform'
+ } }
+
+##
+# @BitmapMigrationNodeAlias:
+#
+# Maps a block node name and the bitmaps it has to aliases for dirty
+# bitmap migration.
+#
+# @node-name: A block node name.
+#
+# @alias: An alias block node name for migration (for example the
+# node name on the opposite site).
+#
+# @bitmaps: Mappings for the bitmaps on this node.
+#
+# Since: 5.2
+##
+{ 'struct': 'BitmapMigrationNodeAlias',
+ 'data': {
+ 'node-name': 'str',
+ 'alias': 'str',
+ 'bitmaps': [ 'BitmapMigrationBitmapAlias' ]
+ } }
+
+##
+# @MigrationParameter:
+#
+# Migration parameters enumeration
+#
+# @announce-initial: Initial delay (in milliseconds) before sending the first
+# announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
+# @compress-level: Set the compression level to be used in live migration,
+# the compression level is an integer between 0 and 9, where 0 means
+# no compression, 1 means the best compression speed, and 9 means best
+# compression ratio which will consume more CPU.
+#
+# @compress-threads: Set compression thread count to be used in live migration,
+# the compression thread count is an integer between 1 and 255.
+#
+# @compress-wait-thread: Controls behavior when all compression threads are
+# currently busy. If true (default), wait for a free
+# compression thread to become available; otherwise,
+# send the page uncompressed. (Since 3.1)
+#
+# @decompress-threads: Set decompression thread count to be used in live
+# migration, the decompression thread count is an integer between 1
+# and 255. Usually, decompression is at least 4 times as fast as
+# compression, so set the decompress-threads to the number about 1/4
+# of compress-threads is adequate.
+#
+# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period
+# to trigger throttling. It is expressed as percentage.
+# The default value is 50. (Since 5.0)
+#
+# @cpu-throttle-initial: Initial percentage of time guest cpus are throttled
+# when migration auto-converge is activated. The
+# default value is 20. (Since 2.7)
+#
+# @cpu-throttle-increment: throttle percentage increase each time
+# auto-converge detects that migration is not making
+# progress. The default value is 10. (Since 2.7)
+#
+# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage
+# At the tail stage of throttling, the Guest is very
+# sensitive to CPU percentage while the @cpu-throttle
+# -increment is excessive usually at tail stage.
+# If this parameter is true, we will compute the ideal
+# CPU percentage used by the Guest, which may exactly make
+# the dirty rate match the dirty rate threshold. Then we
+# will choose a smaller throttle increment between the
+# one specified by @cpu-throttle-increment and the one
+# generated by ideal CPU percentage.
+# Therefore, it is compatible to traditional throttling,
+# meanwhile the throttle increment won't be excessive
+# at tail stage.
+# The default value is false. (Since 5.1)
+#
+# @tls-creds: ID of the 'tls-creds' object that provides credentials for
+# establishing a TLS connection over the migration data channel.
+# On the outgoing side of the migration, the credentials must
+# be for a 'client' endpoint, while for the incoming side the
+# credentials must be for a 'server' endpoint. Setting this
+# will enable TLS for all migrations. The default is unset,
+# resulting in unsecured migration at the QEMU level. (Since 2.7)
+#
+# @tls-hostname: hostname of the target host for the migration. This is
+# required when using x509 based TLS credentials and the
+# migration URI does not already include a hostname. For
+# example if using fd: or exec: based migration, the
+# hostname must be provided so that the server's x509
+# certificate identity can be validated. (Since 2.7)
+#
+# @tls-authz: ID of the 'authz' object subclass that provides access control
+# checking of the TLS x509 certificate distinguished name.
+# This object is only resolved at time of use, so can be deleted
+# and recreated on the fly while the migration server is active.
+# If missing, it will default to denying access (Since 4.0)
+#
+# @max-bandwidth: to set maximum speed for migration. maximum speed in
+# bytes per second. (Since 2.8)
+#
+# @downtime-limit: set maximum tolerated downtime for migration. maximum
+# downtime in milliseconds (Since 2.8)
+#
+# @x-checkpoint-delay: The delay time (in ms) between two COLO checkpoints in
+# periodic mode. (Since 2.8)
+#
+# @block-incremental: Affects how much storage is migrated when the
+# block migration capability is enabled. When false, the entire
+# storage backing chain is migrated into a flattened image at
+# the destination; when true, only the active qcow2 layer is
+# migrated and the destination must already have access to the
+# same backing chain as was used on the source. (since 2.10)
+#
+# @multifd-channels: Number of channels used to migrate data in
+# parallel. This is the same number that the
+# number of sockets used for migration. The
+# default value is 2 (since 4.0)
+#
+# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It
+# needs to be a multiple of the target page size
+# and a power of 2
+# (Since 2.11)
+#
+# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy.
+# Defaults to 0 (unlimited). In bytes per second.
+# (Since 3.0)
+#
+# @max-cpu-throttle: maximum cpu throttle percentage.
+# Defaults to 99. (Since 3.1)
+#
+# @multifd-compression: Which compression method to use.
+# Defaults to none. (Since 5.0)
+#
+# @multifd-zlib-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 9, where 0 means no compression, 1 means the best
+# compression speed, and 9 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @multifd-zstd-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 20, where 0 means no compression, 1 means the best
+# compression speed, and 20 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
+# aliases for the purpose of dirty bitmap migration. Such
+# aliases may for example be the corresponding names on the
+# opposite site.
+# The mapping must be one-to-one, but not necessarily
+# complete: On the source, unmapped bitmaps and all bitmaps
+# on unmapped nodes will be ignored. On the destination,
+# encountering an unmapped alias in the incoming migration
+# stream will result in a report, and all further bitmap
+# migration data will then be discarded.
+# Note that the destination does not know about bitmaps it
+# does not receive, so there is no limitation or requirement
+# regarding the number of bitmaps received, or how they are
+# named, or on which nodes they are placed.
+# By default (when this parameter has never been set), bitmap
+# names are mapped to themselves. Nodes are mapped to their
+# block device name if there is one, and to their node name
+# otherwise. (Since 5.2)
+#
+# Features:
+# @unstable: Member @x-checkpoint-delay is experimental.
+#
+# Since: 2.4
+##
+{ 'enum': 'MigrationParameter',
+ 'data': ['announce-initial', 'announce-max',
+ 'announce-rounds', 'announce-step',
+ 'compress-level', 'compress-threads', 'decompress-threads',
+ 'compress-wait-thread', 'throttle-trigger-threshold',
+ 'cpu-throttle-initial', 'cpu-throttle-increment',
+ 'cpu-throttle-tailslow',
+ 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth',
+ 'downtime-limit',
+ { 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] },
+ 'block-incremental',
+ 'multifd-channels',
+ 'xbzrle-cache-size', 'max-postcopy-bandwidth',
+ 'max-cpu-throttle', 'multifd-compression',
+ 'multifd-zlib-level' ,'multifd-zstd-level',
+ 'block-bitmap-mapping' ] }
+
+##
+# @MigrateSetParameters:
+#
+# @announce-initial: Initial delay (in milliseconds) before sending the first
+# announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
+# @compress-level: compression level
+#
+# @compress-threads: compression thread count
+#
+# @compress-wait-thread: Controls behavior when all compression threads are
+# currently busy. If true (default), wait for a free
+# compression thread to become available; otherwise,
+# send the page uncompressed. (Since 3.1)
+#
+# @decompress-threads: decompression thread count
+#
+# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period
+# to trigger throttling. It is expressed as percentage.
+# The default value is 50. (Since 5.0)
+#
+# @cpu-throttle-initial: Initial percentage of time guest cpus are
+# throttled when migration auto-converge is activated.
+# The default value is 20. (Since 2.7)
+#
+# @cpu-throttle-increment: throttle percentage increase each time
+# auto-converge detects that migration is not making
+# progress. The default value is 10. (Since 2.7)
+#
+# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage
+# At the tail stage of throttling, the Guest is very
+# sensitive to CPU percentage while the @cpu-throttle
+# -increment is excessive usually at tail stage.
+# If this parameter is true, we will compute the ideal
+# CPU percentage used by the Guest, which may exactly make
+# the dirty rate match the dirty rate threshold. Then we
+# will choose a smaller throttle increment between the
+# one specified by @cpu-throttle-increment and the one
+# generated by ideal CPU percentage.
+# Therefore, it is compatible to traditional throttling,
+# meanwhile the throttle increment won't be excessive
+# at tail stage.
+# The default value is false. (Since 5.1)
+#
+# @tls-creds: ID of the 'tls-creds' object that provides credentials
+# for establishing a TLS connection over the migration data
+# channel. On the outgoing side of the migration, the credentials
+# must be for a 'client' endpoint, while for the incoming side the
+# credentials must be for a 'server' endpoint. Setting this
+# to a non-empty string enables TLS for all migrations.
+# An empty string means that QEMU will use plain text mode for
+# migration, rather than TLS (Since 2.9)
+# Previously (since 2.7), this was reported by omitting
+# tls-creds instead.
+#
+# @tls-hostname: hostname of the target host for the migration. This
+# is required when using x509 based TLS credentials and the
+# migration URI does not already include a hostname. For
+# example if using fd: or exec: based migration, the
+# hostname must be provided so that the server's x509
+# certificate identity can be validated. (Since 2.7)
+# An empty string means that QEMU will use the hostname
+# associated with the migration URI, if any. (Since 2.9)
+# Previously (since 2.7), this was reported by omitting
+# tls-hostname instead.
+#
+# @max-bandwidth: to set maximum speed for migration. maximum speed in
+# bytes per second. (Since 2.8)
+#
+# @downtime-limit: set maximum tolerated downtime for migration. maximum
+# downtime in milliseconds (Since 2.8)
+#
+# @x-checkpoint-delay: the delay time between two COLO checkpoints. (Since 2.8)
+#
+# @block-incremental: Affects how much storage is migrated when the
+# block migration capability is enabled. When false, the entire
+# storage backing chain is migrated into a flattened image at
+# the destination; when true, only the active qcow2 layer is
+# migrated and the destination must already have access to the
+# same backing chain as was used on the source. (since 2.10)
+#
+# @multifd-channels: Number of channels used to migrate data in
+# parallel. This is the same number that the
+# number of sockets used for migration. The
+# default value is 2 (since 4.0)
+#
+# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It
+# needs to be a multiple of the target page size
+# and a power of 2
+# (Since 2.11)
+#
+# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy.
+# Defaults to 0 (unlimited). In bytes per second.
+# (Since 3.0)
+#
+# @max-cpu-throttle: maximum cpu throttle percentage.
+# The default value is 99. (Since 3.1)
+#
+# @multifd-compression: Which compression method to use.
+# Defaults to none. (Since 5.0)
+#
+# @multifd-zlib-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 9, where 0 means no compression, 1 means the best
+# compression speed, and 9 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @multifd-zstd-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 20, where 0 means no compression, 1 means the best
+# compression speed, and 20 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
+# aliases for the purpose of dirty bitmap migration. Such
+# aliases may for example be the corresponding names on the
+# opposite site.
+# The mapping must be one-to-one, but not necessarily
+# complete: On the source, unmapped bitmaps and all bitmaps
+# on unmapped nodes will be ignored. On the destination,
+# encountering an unmapped alias in the incoming migration
+# stream will result in a report, and all further bitmap
+# migration data will then be discarded.
+# Note that the destination does not know about bitmaps it
+# does not receive, so there is no limitation or requirement
+# regarding the number of bitmaps received, or how they are
+# named, or on which nodes they are placed.
+# By default (when this parameter has never been set), bitmap
+# names are mapped to themselves. Nodes are mapped to their
+# block device name if there is one, and to their node name
+# otherwise. (Since 5.2)
+#
+# Features:
+# @unstable: Member @x-checkpoint-delay is experimental.
+#
+# Since: 2.4
+##
+# TODO either fuse back into MigrationParameters, or make
+# MigrationParameters members mandatory
+{ 'struct': 'MigrateSetParameters',
+ 'data': { '*announce-initial': 'size',
+ '*announce-max': 'size',
+ '*announce-rounds': 'size',
+ '*announce-step': 'size',
+ '*compress-level': 'uint8',
+ '*compress-threads': 'uint8',
+ '*compress-wait-thread': 'bool',
+ '*decompress-threads': 'uint8',
+ '*throttle-trigger-threshold': 'uint8',
+ '*cpu-throttle-initial': 'uint8',
+ '*cpu-throttle-increment': 'uint8',
+ '*cpu-throttle-tailslow': 'bool',
+ '*tls-creds': 'StrOrNull',
+ '*tls-hostname': 'StrOrNull',
+ '*tls-authz': 'StrOrNull',
+ '*max-bandwidth': 'size',
+ '*downtime-limit': 'uint64',
+ '*x-checkpoint-delay': { 'type': 'uint32',
+ 'features': [ 'unstable' ] },
+ '*block-incremental': 'bool',
+ '*multifd-channels': 'uint8',
+ '*xbzrle-cache-size': 'size',
+ '*max-postcopy-bandwidth': 'size',
+ '*max-cpu-throttle': 'uint8',
+ '*multifd-compression': 'MultiFDCompression',
+ '*multifd-zlib-level': 'uint8',
+ '*multifd-zstd-level': 'uint8',
+ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } }
+
+##
+# @migrate-set-parameters:
+#
+# Set various migration parameters.
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "migrate-set-parameters" ,
+# "arguments": { "compress-level": 1 } }
+#
+##
+{ 'command': 'migrate-set-parameters', 'boxed': true,
+ 'data': 'MigrateSetParameters' }
+
+##
+# @MigrationParameters:
+#
+# The optional members aren't actually optional.
+#
+# @announce-initial: Initial delay (in milliseconds) before sending the
+# first announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
+# @compress-level: compression level
+#
+# @compress-threads: compression thread count
+#
+# @compress-wait-thread: Controls behavior when all compression threads are
+# currently busy. If true (default), wait for a free
+# compression thread to become available; otherwise,
+# send the page uncompressed. (Since 3.1)
+#
+# @decompress-threads: decompression thread count
+#
+# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period
+# to trigger throttling. It is expressed as percentage.
+# The default value is 50. (Since 5.0)
+#
+# @cpu-throttle-initial: Initial percentage of time guest cpus are
+# throttled when migration auto-converge is activated.
+# (Since 2.7)
+#
+# @cpu-throttle-increment: throttle percentage increase each time
+# auto-converge detects that migration is not making
+# progress. (Since 2.7)
+#
+# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage
+# At the tail stage of throttling, the Guest is very
+# sensitive to CPU percentage while the @cpu-throttle
+# -increment is excessive usually at tail stage.
+# If this parameter is true, we will compute the ideal
+# CPU percentage used by the Guest, which may exactly make
+# the dirty rate match the dirty rate threshold. Then we
+# will choose a smaller throttle increment between the
+# one specified by @cpu-throttle-increment and the one
+# generated by ideal CPU percentage.
+# Therefore, it is compatible to traditional throttling,
+# meanwhile the throttle increment won't be excessive
+# at tail stage.
+# The default value is false. (Since 5.1)
+#
+# @tls-creds: ID of the 'tls-creds' object that provides credentials
+# for establishing a TLS connection over the migration data
+# channel. On the outgoing side of the migration, the credentials
+# must be for a 'client' endpoint, while for the incoming side the
+# credentials must be for a 'server' endpoint.
+# An empty string means that QEMU will use plain text mode for
+# migration, rather than TLS (Since 2.7)
+# Note: 2.8 reports this by omitting tls-creds instead.
+#
+# @tls-hostname: hostname of the target host for the migration. This
+# is required when using x509 based TLS credentials and the
+# migration URI does not already include a hostname. For
+# example if using fd: or exec: based migration, the
+# hostname must be provided so that the server's x509
+# certificate identity can be validated. (Since 2.7)
+# An empty string means that QEMU will use the hostname
+# associated with the migration URI, if any. (Since 2.9)
+# Note: 2.8 reports this by omitting tls-hostname instead.
+#
+# @tls-authz: ID of the 'authz' object subclass that provides access control
+# checking of the TLS x509 certificate distinguished name. (Since
+# 4.0)
+#
+# @max-bandwidth: to set maximum speed for migration. maximum speed in
+# bytes per second. (Since 2.8)
+#
+# @downtime-limit: set maximum tolerated downtime for migration. maximum
+# downtime in milliseconds (Since 2.8)
+#
+# @x-checkpoint-delay: the delay time between two COLO checkpoints. (Since 2.8)
+#
+# @block-incremental: Affects how much storage is migrated when the
+# block migration capability is enabled. When false, the entire
+# storage backing chain is migrated into a flattened image at
+# the destination; when true, only the active qcow2 layer is
+# migrated and the destination must already have access to the
+# same backing chain as was used on the source. (since 2.10)
+#
+# @multifd-channels: Number of channels used to migrate data in
+# parallel. This is the same number that the
+# number of sockets used for migration.
+# The default value is 2 (since 4.0)
+#
+# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It
+# needs to be a multiple of the target page size
+# and a power of 2
+# (Since 2.11)
+#
+# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy.
+# Defaults to 0 (unlimited). In bytes per second.
+# (Since 3.0)
+#
+# @max-cpu-throttle: maximum cpu throttle percentage.
+# Defaults to 99.
+# (Since 3.1)
+#
+# @multifd-compression: Which compression method to use.
+# Defaults to none. (Since 5.0)
+#
+# @multifd-zlib-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 9, where 0 means no compression, 1 means the best
+# compression speed, and 9 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @multifd-zstd-level: Set the compression level to be used in live
+# migration, the compression level is an integer between 0
+# and 20, where 0 means no compression, 1 means the best
+# compression speed, and 20 means best compression ratio which
+# will consume more CPU.
+# Defaults to 1. (Since 5.0)
+#
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
+# aliases for the purpose of dirty bitmap migration. Such
+# aliases may for example be the corresponding names on the
+# opposite site.
+# The mapping must be one-to-one, but not necessarily
+# complete: On the source, unmapped bitmaps and all bitmaps
+# on unmapped nodes will be ignored. On the destination,
+# encountering an unmapped alias in the incoming migration
+# stream will result in a report, and all further bitmap
+# migration data will then be discarded.
+# Note that the destination does not know about bitmaps it
+# does not receive, so there is no limitation or requirement
+# regarding the number of bitmaps received, or how they are
+# named, or on which nodes they are placed.
+# By default (when this parameter has never been set), bitmap
+# names are mapped to themselves. Nodes are mapped to their
+# block device name if there is one, and to their node name
+# otherwise. (Since 5.2)
+#
+# Features:
+# @unstable: Member @x-checkpoint-delay is experimental.
+#
+# Since: 2.4
+##
+{ 'struct': 'MigrationParameters',
+ 'data': { '*announce-initial': 'size',
+ '*announce-max': 'size',
+ '*announce-rounds': 'size',
+ '*announce-step': 'size',
+ '*compress-level': 'uint8',
+ '*compress-threads': 'uint8',
+ '*compress-wait-thread': 'bool',
+ '*decompress-threads': 'uint8',
+ '*throttle-trigger-threshold': 'uint8',
+ '*cpu-throttle-initial': 'uint8',
+ '*cpu-throttle-increment': 'uint8',
+ '*cpu-throttle-tailslow': 'bool',
+ '*tls-creds': 'str',
+ '*tls-hostname': 'str',
+ '*tls-authz': 'str',
+ '*max-bandwidth': 'size',
+ '*downtime-limit': 'uint64',
+ '*x-checkpoint-delay': { 'type': 'uint32',
+ 'features': [ 'unstable' ] },
+ '*block-incremental': 'bool',
+ '*multifd-channels': 'uint8',
+ '*xbzrle-cache-size': 'size',
+ '*max-postcopy-bandwidth': 'size',
+ '*max-cpu-throttle': 'uint8',
+ '*multifd-compression': 'MultiFDCompression',
+ '*multifd-zlib-level': 'uint8',
+ '*multifd-zstd-level': 'uint8',
+ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } }
+
+##
+# @query-migrate-parameters:
+#
+# Returns information about the current migration parameters
+#
+# Returns: @MigrationParameters
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "query-migrate-parameters" }
+# <- { "return": {
+# "decompress-threads": 2,
+# "cpu-throttle-increment": 10,
+# "compress-threads": 8,
+# "compress-level": 1,
+# "cpu-throttle-initial": 20,
+# "max-bandwidth": 33554432,
+# "downtime-limit": 300
+# }
+# }
+#
+##
+{ 'command': 'query-migrate-parameters',
+ 'returns': 'MigrationParameters' }
+
+##
+# @client_migrate_info:
+#
+# Set migration information for remote display. This makes the server
+# ask the client to automatically reconnect using the new parameters
+# once migration finished successfully. Only implemented for SPICE.
+#
+# @protocol: must be "spice"
+# @hostname: migration target hostname
+# @port: spice tcp port for plaintext channels
+# @tls-port: spice tcp port for tls-secured channels
+# @cert-subject: server certificate subject
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "client_migrate_info",
+# "arguments": { "protocol": "spice",
+# "hostname": "virt42.lab.kraxel.org",
+# "port": 1234 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'client_migrate_info',
+ 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int',
+ '*tls-port': 'int', '*cert-subject': 'str' } }
+
+##
+# @migrate-start-postcopy:
+#
+# Followup to a migration command to switch the migration to postcopy mode.
+# The postcopy-ram capability must be set on both source and destination
+# before the original migration command.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "migrate-start-postcopy" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'migrate-start-postcopy' }
+
+##
+# @MIGRATION:
+#
+# Emitted when a migration event happens
+#
+# @status: @MigrationStatus describing the current migration status.
+#
+# Since: 2.4
+#
+# Example:
+#
+# <- {"timestamp": {"seconds": 1432121972, "microseconds": 744001},
+# "event": "MIGRATION",
+# "data": {"status": "completed"} }
+#
+##
+{ 'event': 'MIGRATION',
+ 'data': {'status': 'MigrationStatus'}}
+
+##
+# @MIGRATION_PASS:
+#
+# Emitted from the source side of a migration at the start of each pass
+# (when it syncs the dirty bitmap)
+#
+# @pass: An incrementing count (starting at 1 on the first pass)
+#
+# Since: 2.6
+#
+# Example:
+#
+# { "timestamp": {"seconds": 1449669631, "microseconds": 239225},
+# "event": "MIGRATION_PASS", "data": {"pass": 2} }
+#
+##
+{ 'event': 'MIGRATION_PASS',
+ 'data': { 'pass': 'int' } }
+
+##
+# @COLOMessage:
+#
+# The message transmission between Primary side and Secondary side.
+#
+# @checkpoint-ready: Secondary VM (SVM) is ready for checkpointing
+#
+# @checkpoint-request: Primary VM (PVM) tells SVM to prepare for checkpointing
+#
+# @checkpoint-reply: SVM gets PVM's checkpoint request
+#
+# @vmstate-send: VM's state will be sent by PVM.
+#
+# @vmstate-size: The total size of VMstate.
+#
+# @vmstate-received: VM's state has been received by SVM.
+#
+# @vmstate-loaded: VM's state has been loaded by SVM.
+#
+# Since: 2.8
+##
+{ 'enum': 'COLOMessage',
+ 'data': [ 'checkpoint-ready', 'checkpoint-request', 'checkpoint-reply',
+ 'vmstate-send', 'vmstate-size', 'vmstate-received',
+ 'vmstate-loaded' ] }
+
+##
+# @COLOMode:
+#
+# The COLO current mode.
+#
+# @none: COLO is disabled.
+#
+# @primary: COLO node in primary side.
+#
+# @secondary: COLO node in slave side.
+#
+# Since: 2.8
+##
+{ 'enum': 'COLOMode',
+ 'data': [ 'none', 'primary', 'secondary'] }
+
+##
+# @FailoverStatus:
+#
+# An enumeration of COLO failover status
+#
+# @none: no failover has ever happened
+#
+# @require: got failover requirement but not handled
+#
+# @active: in the process of doing failover
+#
+# @completed: finish the process of failover
+#
+# @relaunch: restart the failover process, from 'none' -> 'completed' (Since 2.9)
+#
+# Since: 2.8
+##
+{ 'enum': 'FailoverStatus',
+ 'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] }
+
+##
+# @COLO_EXIT:
+#
+# Emitted when VM finishes COLO mode due to some errors happening or
+# at the request of users.
+#
+# @mode: report COLO mode when COLO exited.
+#
+# @reason: describes the reason for the COLO exit.
+#
+# Since: 3.1
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172},
+# "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } }
+#
+##
+{ 'event': 'COLO_EXIT',
+ 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } }
+
+##
+# @COLOExitReason:
+#
+# The reason for a COLO exit.
+#
+# @none: failover has never happened. This state does not occur
+# in the COLO_EXIT event, and is only visible in the result of
+# query-colo-status.
+#
+# @request: COLO exit is due to an external request.
+#
+# @error: COLO exit is due to an internal error.
+#
+# @processing: COLO is currently handling a failover (since 4.0).
+#
+# Since: 3.1
+##
+{ 'enum': 'COLOExitReason',
+ 'data': [ 'none', 'request', 'error' , 'processing' ] }
+
+##
+# @x-colo-lost-heartbeat:
+#
+# Tell qemu that heartbeat is lost, request it to do takeover procedures.
+# If this command is sent to the PVM, the Primary side will exit COLO mode.
+# If sent to the Secondary, the Secondary side will run failover work,
+# then takes over server operation to become the service VM.
+#
+# Features:
+# @unstable: This command is experimental.
+#
+# Since: 2.8
+#
+# Example:
+#
+# -> { "execute": "x-colo-lost-heartbeat" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'x-colo-lost-heartbeat',
+ 'features': [ 'unstable' ] }
+
+##
+# @migrate_cancel:
+#
+# Cancel the current executing migration process.
+#
+# Returns: nothing on success
+#
+# Notes: This command succeeds even if there is no migration process running.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "migrate_cancel" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'migrate_cancel' }
+
+##
+# @migrate-continue:
+#
+# Continue migration when it's in a paused state.
+#
+# @state: The state the migration is currently expected to be in
+#
+# Returns: nothing on success
+# Since: 2.11
+# Example:
+#
+# -> { "execute": "migrate-continue" , "arguments":
+# { "state": "pre-switchover" } }
+# <- { "return": {} }
+##
+{ 'command': 'migrate-continue', 'data': {'state': 'MigrationStatus'} }
+
+##
+# @migrate:
+#
+# Migrates the current running guest to another Virtual Machine.
+#
+# @uri: the Uniform Resource Identifier of the destination VM
+#
+# @blk: do block migration (full disk copy)
+#
+# @inc: incremental disk copy migration
+#
+# @detach: this argument exists only for compatibility reasons and
+# is ignored by QEMU
+#
+# @resume: resume one paused migration, default "off". (since 3.0)
+#
+# Returns: nothing on success
+#
+# Since: 0.14
+#
+# Notes:
+#
+# 1. The 'query-migrate' command should be used to check migration's progress
+# and final result (this information is provided by the 'status' member)
+#
+# 2. All boolean arguments default to false
+#
+# 3. The user Monitor's "detach" argument is invalid in QMP and should not
+# be used
+#
+# Example:
+#
+# -> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'migrate',
+ 'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool',
+ '*detach': 'bool', '*resume': 'bool' } }
+
+##
+# @migrate-incoming:
+#
+# Start an incoming migration, the qemu must have been started
+# with -incoming defer
+#
+# @uri: The Uniform Resource Identifier identifying the source or
+# address to listen on
+#
+# Returns: nothing on success
+#
+# Since: 2.3
+#
+# Notes:
+#
+# 1. It's a bad idea to use a string for the uri, but it needs to stay
+# compatible with -incoming and the format of the uri is already exposed
+# above libvirt.
+#
+# 2. QEMU must be started with -incoming defer to allow migrate-incoming to
+# be used.
+#
+# 3. The uri format is the same as for -incoming
+#
+# Example:
+#
+# -> { "execute": "migrate-incoming",
+# "arguments": { "uri": "tcp::4446" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'migrate-incoming', 'data': {'uri': 'str' } }
+
+##
+# @xen-save-devices-state:
+#
+# Save the state of all devices to file. The RAM and the block devices
+# of the VM are not saved by this command.
+#
+# @filename: the file to save the state of the devices to as binary
+# data. See xen-save-devices-state.txt for a description of the binary
+# format.
+#
+# @live: Optional argument to ask QEMU to treat this command as part of a live
+# migration. Default to true. (since 2.11)
+#
+# Returns: Nothing on success
+#
+# Since: 1.1
+#
+# Example:
+#
+# -> { "execute": "xen-save-devices-state",
+# "arguments": { "filename": "/tmp/save" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'xen-save-devices-state',
+ 'data': {'filename': 'str', '*live':'bool' } }
+
+##
+# @xen-set-global-dirty-log:
+#
+# Enable or disable the global dirty log mode.
+#
+# @enable: true to enable, false to disable.
+#
+# Returns: nothing
+#
+# Since: 1.3
+#
+# Example:
+#
+# -> { "execute": "xen-set-global-dirty-log",
+# "arguments": { "enable": true } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }
+
+##
+# @xen-load-devices-state:
+#
+# Load the state of all devices from file. The RAM and the block devices
+# of the VM are not loaded by this command.
+#
+# @filename: the file to load the state of the devices from as binary
+# data. See xen-save-devices-state.txt for a description of the binary
+# format.
+#
+# Since: 2.7
+#
+# Example:
+#
+# -> { "execute": "xen-load-devices-state",
+# "arguments": { "filename": "/tmp/resume" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} }
+
+##
+# @xen-set-replication:
+#
+# Enable or disable replication.
+#
+# @enable: true to enable, false to disable.
+#
+# @primary: true for primary or false for secondary.
+#
+# @failover: true to do failover, false to stop. but cannot be
+# specified if 'enable' is true. default value is false.
+#
+# Returns: nothing.
+#
+# Example:
+#
+# -> { "execute": "xen-set-replication",
+# "arguments": {"enable": true, "primary": false} }
+# <- { "return": {} }
+#
+# Since: 2.9
+##
+{ 'command': 'xen-set-replication',
+ 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @ReplicationStatus:
+#
+# The result format for 'query-xen-replication-status'.
+#
+# @error: true if an error happened, false if replication is normal.
+#
+# @desc: the human readable error description string, when
+# @error is 'true'.
+#
+# Since: 2.9
+##
+{ 'struct': 'ReplicationStatus',
+ 'data': { 'error': 'bool', '*desc': 'str' },
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @query-xen-replication-status:
+#
+# Query replication status while the vm is running.
+#
+# Returns: A @ReplicationResult object showing the status.
+#
+# Example:
+#
+# -> { "execute": "query-xen-replication-status" }
+# <- { "return": { "error": false } }
+#
+# Since: 2.9
+##
+{ 'command': 'query-xen-replication-status',
+ 'returns': 'ReplicationStatus',
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @xen-colo-do-checkpoint:
+#
+# Xen uses this command to notify replication to trigger a checkpoint.
+#
+# Returns: nothing.
+#
+# Example:
+#
+# -> { "execute": "xen-colo-do-checkpoint" }
+# <- { "return": {} }
+#
+# Since: 2.9
+##
+{ 'command': 'xen-colo-do-checkpoint',
+ 'if': 'CONFIG_REPLICATION' }
+
+##
+# @COLOStatus:
+#
+# The result format for 'query-colo-status'.
+#
+# @mode: COLO running mode. If COLO is running, this field will return
+# 'primary' or 'secondary'.
+#
+# @last-mode: COLO last running mode. If COLO is running, this field
+# will return same like mode field, after failover we can
+# use this field to get last colo mode. (since 4.0)
+#
+# @reason: describes the reason for the COLO exit.
+#
+# Since: 3.1
+##
+{ 'struct': 'COLOStatus',
+ 'data': { 'mode': 'COLOMode', 'last-mode': 'COLOMode',
+ 'reason': 'COLOExitReason' } }
+
+##
+# @query-colo-status:
+#
+# Query COLO status while the vm is running.
+#
+# Returns: A @COLOStatus object showing the status.
+#
+# Example:
+#
+# -> { "execute": "query-colo-status" }
+# <- { "return": { "mode": "primary", "reason": "request" } }
+#
+# Since: 3.1
+##
+{ 'command': 'query-colo-status',
+ 'returns': 'COLOStatus' }
+
+##
+# @migrate-recover:
+#
+# Provide a recovery migration stream URI.
+#
+# @uri: the URI to be used for the recovery of migration stream.
+#
+# Returns: nothing.
+#
+# Example:
+#
+# -> { "execute": "migrate-recover",
+# "arguments": { "uri": "tcp:192.168.1.200:12345" } }
+# <- { "return": {} }
+#
+# Since: 3.0
+##
+{ 'command': 'migrate-recover',
+ 'data': { 'uri': 'str' },
+ 'allow-oob': true }
+
+##
+# @migrate-pause:
+#
+# Pause a migration. Currently it only supports postcopy.
+#
+# Returns: nothing.
+#
+# Example:
+#
+# -> { "execute": "migrate-pause" }
+# <- { "return": {} }
+#
+# Since: 3.0
+##
+{ 'command': 'migrate-pause', 'allow-oob': true }
+
+##
+# @UNPLUG_PRIMARY:
+#
+# Emitted from source side of a migration when migration state is
+# WAIT_UNPLUG. Device was unplugged by guest operating system.
+# Device resources in QEMU are kept on standby to be able to re-plug it in case
+# of migration failure.
+#
+# @device-id: QEMU device id of the unplugged device
+#
+# Since: 4.2
+#
+# Example:
+# {"event": "UNPLUG_PRIMARY", "data": {"device-id": "hostdev0"} }
+#
+##
+{ 'event': 'UNPLUG_PRIMARY',
+ 'data': { 'device-id': 'str' } }
+
+##
+# @DirtyRateVcpu:
+#
+# Dirty rate of vcpu.
+#
+# @id: vcpu index.
+#
+# @dirty-rate: dirty rate.
+#
+# Since: 6.2
+#
+##
+{ 'struct': 'DirtyRateVcpu',
+ 'data': { 'id': 'int', 'dirty-rate': 'int64' } }
+
+##
+# @DirtyRateStatus:
+#
+# An enumeration of dirtyrate status.
+#
+# @unstarted: the dirtyrate thread has not been started.
+#
+# @measuring: the dirtyrate thread is measuring.
+#
+# @measured: the dirtyrate thread has measured and results are available.
+#
+# Since: 5.2
+#
+##
+{ 'enum': 'DirtyRateStatus',
+ 'data': [ 'unstarted', 'measuring', 'measured'] }
+
+##
+# @DirtyRateMeasureMode:
+#
+# An enumeration of mode of measuring dirtyrate.
+#
+# @page-sampling: calculate dirtyrate by sampling pages.
+#
+# @dirty-ring: calculate dirtyrate by dirty ring.
+#
+# @dirty-bitmap: calculate dirtyrate by dirty bitmap.
+#
+# Since: 6.2
+#
+##
+{ 'enum': 'DirtyRateMeasureMode',
+ 'data': ['page-sampling', 'dirty-ring', 'dirty-bitmap'] }
+
+##
+# @DirtyRateInfo:
+#
+# Information about current dirty page rate of vm.
+#
+# @dirty-rate: an estimate of the dirty page rate of the VM in units of
+# MB/s, present only when estimating the rate has completed.
+#
+# @status: status containing dirtyrate query status includes
+# 'unstarted' or 'measuring' or 'measured'
+#
+# @start-time: start time in units of second for calculation
+#
+# @calc-time: time in units of second for sample dirty pages
+#
+# @sample-pages: page count per GB for sample dirty pages
+# the default value is 512 (since 6.1)
+#
+# @mode: mode containing method of calculate dirtyrate includes
+# 'page-sampling' and 'dirty-ring' (Since 6.2)
+#
+# @vcpu-dirty-rate: dirtyrate for each vcpu if dirty-ring
+# mode specified (Since 6.2)
+#
+# Since: 5.2
+#
+##
+{ 'struct': 'DirtyRateInfo',
+ 'data': {'*dirty-rate': 'int64',
+ 'status': 'DirtyRateStatus',
+ 'start-time': 'int64',
+ 'calc-time': 'int64',
+ 'sample-pages': 'uint64',
+ 'mode': 'DirtyRateMeasureMode',
+ '*vcpu-dirty-rate': [ 'DirtyRateVcpu' ] } }
+
+##
+# @calc-dirty-rate:
+#
+# start calculating dirty page rate for vm
+#
+# @calc-time: time in units of second for sample dirty pages
+#
+# @sample-pages: page count per GB for sample dirty pages
+# the default value is 512 (since 6.1)
+#
+# @mode: mechanism of calculating dirtyrate includes
+# 'page-sampling' and 'dirty-ring' (Since 6.1)
+#
+# Since: 5.2
+#
+# Example:
+# {"command": "calc-dirty-rate", "data": {"calc-time": 1,
+# 'sample-pages': 512} }
+#
+##
+{ 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64',
+ '*sample-pages': 'int',
+ '*mode': 'DirtyRateMeasureMode'} }
+
+##
+# @query-dirty-rate:
+#
+# query dirty page rate in units of MB/s for vm
+#
+# Since: 5.2
+##
+{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' }
+
+##
+# @snapshot-save:
+#
+# Save a VM snapshot
+#
+# @job-id: identifier for the newly created job
+# @tag: name of the snapshot to create
+# @vmstate: block device node name to save vmstate to
+# @devices: list of block device node names to save a snapshot to
+#
+# Applications should not assume that the snapshot save is complete
+# when this command returns. The job commands / events must be used
+# to determine completion and to fetch details of any errors that arise.
+#
+# Note that execution of the guest CPUs may be stopped during the
+# time it takes to save the snapshot. A future version of QEMU
+# may ensure CPUs are executing continuously.
+#
+# It is strongly recommended that @devices contain all writable
+# block device nodes if a consistent snapshot is required.
+#
+# If @tag already exists, an error will be reported
+#
+# Returns: nothing
+#
+# Example:
+#
+# -> { "execute": "snapshot-save",
+# "data": {
+# "job-id": "snapsave0",
+# "tag": "my-snap",
+# "vmstate": "disk0",
+# "devices": ["disk0", "disk1"]
+# }
+# }
+# <- { "return": { } }
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "created", "id": "snapsave0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "running", "id": "snapsave0"}}
+# <- {"event": "STOP"}
+# <- {"event": "RESUME"}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "waiting", "id": "snapsave0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "pending", "id": "snapsave0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "concluded", "id": "snapsave0"}}
+# -> {"execute": "query-jobs"}
+# <- {"return": [{"current-progress": 1,
+# "status": "concluded",
+# "total-progress": 1,
+# "type": "snapshot-save",
+# "id": "snapsave0"}]}
+#
+# Since: 6.0
+##
+{ 'command': 'snapshot-save',
+ 'data': { 'job-id': 'str',
+ 'tag': 'str',
+ 'vmstate': 'str',
+ 'devices': ['str'] } }
+
+##
+# @snapshot-load:
+#
+# Load a VM snapshot
+#
+# @job-id: identifier for the newly created job
+# @tag: name of the snapshot to load.
+# @vmstate: block device node name to load vmstate from
+# @devices: list of block device node names to load a snapshot from
+#
+# Applications should not assume that the snapshot load is complete
+# when this command returns. The job commands / events must be used
+# to determine completion and to fetch details of any errors that arise.
+#
+# Note that execution of the guest CPUs will be stopped during the
+# time it takes to load the snapshot.
+#
+# It is strongly recommended that @devices contain all writable
+# block device nodes that can have changed since the original
+# @snapshot-save command execution.
+#
+# Returns: nothing
+#
+# Example:
+#
+# -> { "execute": "snapshot-load",
+# "data": {
+# "job-id": "snapload0",
+# "tag": "my-snap",
+# "vmstate": "disk0",
+# "devices": ["disk0", "disk1"]
+# }
+# }
+# <- { "return": { } }
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "created", "id": "snapload0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "running", "id": "snapload0"}}
+# <- {"event": "STOP"}
+# <- {"event": "RESUME"}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "waiting", "id": "snapload0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "pending", "id": "snapload0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "concluded", "id": "snapload0"}}
+# -> {"execute": "query-jobs"}
+# <- {"return": [{"current-progress": 1,
+# "status": "concluded",
+# "total-progress": 1,
+# "type": "snapshot-load",
+# "id": "snapload0"}]}
+#
+# Since: 6.0
+##
+{ 'command': 'snapshot-load',
+ 'data': { 'job-id': 'str',
+ 'tag': 'str',
+ 'vmstate': 'str',
+ 'devices': ['str'] } }
+
+##
+# @snapshot-delete:
+#
+# Delete a VM snapshot
+#
+# @job-id: identifier for the newly created job
+# @tag: name of the snapshot to delete.
+# @devices: list of block device node names to delete a snapshot from
+#
+# Applications should not assume that the snapshot delete is complete
+# when this command returns. The job commands / events must be used
+# to determine completion and to fetch details of any errors that arise.
+#
+# Returns: nothing
+#
+# Example:
+#
+# -> { "execute": "snapshot-delete",
+# "data": {
+# "job-id": "snapdelete0",
+# "tag": "my-snap",
+# "devices": ["disk0", "disk1"]
+# }
+# }
+# <- { "return": { } }
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "created", "id": "snapdelete0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "running", "id": "snapdelete0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "waiting", "id": "snapdelete0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "pending", "id": "snapdelete0"}}
+# <- {"event": "JOB_STATUS_CHANGE",
+# "data": {"status": "concluded", "id": "snapdelete0"}}
+# -> {"execute": "query-jobs"}
+# <- {"return": [{"current-progress": 1,
+# "status": "concluded",
+# "total-progress": 1,
+# "type": "snapshot-delete",
+# "id": "snapdelete0"}]}
+#
+# Since: 6.0
+##
+{ 'command': 'snapshot-delete',
+ 'data': { 'job-id': 'str',
+ 'tag': 'str',
+ 'devices': ['str'] } }
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
new file mode 100644
index 000000000..5aa2b95b7
--- /dev/null
+++ b/qapi/misc-target.json
@@ -0,0 +1,399 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# @RTC_CHANGE:
+#
+# Emitted when the guest changes the RTC time.
+#
+# @offset: offset between base RTC clock (as specified by -rtc base), and
+# new RTC clock value
+#
+# Note: This event is rate-limited.
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "RTC_CHANGE",
+# "data": { "offset": 78 },
+# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'RTC_CHANGE',
+ 'data': { 'offset': 'int' },
+ 'if': { 'any': [ 'TARGET_ALPHA',
+ 'TARGET_ARM',
+ 'TARGET_HPPA',
+ 'TARGET_I386',
+ 'TARGET_MIPS',
+ 'TARGET_MIPS64',
+ 'TARGET_PPC',
+ 'TARGET_PPC64',
+ 'TARGET_S390X',
+ 'TARGET_SH4',
+ 'TARGET_SPARC' ] } }
+
+##
+# @rtc-reset-reinjection:
+#
+# This command will reset the RTC interrupt reinjection backlog.
+# Can be used if another mechanism to synchronize guest time
+# is in effect, for example QEMU guest agent's guest-set-time
+# command.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "rtc-reset-reinjection" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'rtc-reset-reinjection',
+ 'if': 'TARGET_I386' }
+
+
+##
+# @SevState:
+#
+# An enumeration of SEV state information used during @query-sev.
+#
+# @uninit: The guest is uninitialized.
+#
+# @launch-update: The guest is currently being launched; plaintext data and
+# register state is being imported.
+#
+# @launch-secret: The guest is currently being launched; ciphertext data
+# is being imported.
+#
+# @running: The guest is fully launched or migrated in.
+#
+# @send-update: The guest is currently being migrated out to another machine.
+#
+# @receive-update: The guest is currently being migrated from another machine.
+#
+# Since: 2.12
+##
+{ 'enum': 'SevState',
+ 'data': ['uninit', 'launch-update', 'launch-secret', 'running',
+ 'send-update', 'receive-update' ],
+ 'if': 'TARGET_I386' }
+
+##
+# @SevInfo:
+#
+# Information about Secure Encrypted Virtualization (SEV) support
+#
+# @enabled: true if SEV is active
+#
+# @api-major: SEV API major version
+#
+# @api-minor: SEV API minor version
+#
+# @build-id: SEV FW build id
+#
+# @policy: SEV policy value
+#
+# @state: SEV guest state
+#
+# @handle: SEV firmware handle
+#
+# Since: 2.12
+##
+{ 'struct': 'SevInfo',
+ 'data': { 'enabled': 'bool',
+ 'api-major': 'uint8',
+ 'api-minor' : 'uint8',
+ 'build-id' : 'uint8',
+ 'policy' : 'uint32',
+ 'state' : 'SevState',
+ 'handle' : 'uint32'
+ },
+ 'if': 'TARGET_I386'
+}
+
+##
+# @query-sev:
+#
+# Returns information about SEV
+#
+# Returns: @SevInfo
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev" }
+# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
+# "build-id" : 0, "policy" : 0, "state" : "running",
+# "handle" : 1 } }
+#
+##
+{ 'command': 'query-sev', 'returns': 'SevInfo',
+ 'if': 'TARGET_I386' }
+
+
+##
+# @SevLaunchMeasureInfo:
+#
+# SEV Guest Launch measurement information
+#
+# @data: the measurement value encoded in base64
+#
+# Since: 2.12
+#
+##
+{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'},
+ 'if': 'TARGET_I386' }
+
+##
+# @query-sev-launch-measure:
+#
+# Query the SEV guest launch information.
+#
+# Returns: The @SevLaunchMeasureInfo for the guest
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-launch-measure" }
+# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+#
+##
+{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo',
+ 'if': 'TARGET_I386' }
+
+
+##
+# @SevCapability:
+#
+# The struct describes capability for a Secure Encrypted Virtualization
+# feature.
+#
+# @pdh: Platform Diffie-Hellman key (base64 encoded)
+#
+# @cert-chain: PDH certificate chain (base64 encoded)
+#
+# @cbitpos: C-bit location in page table entry
+#
+# @reduced-phys-bits: Number of physical Address bit reduction when SEV is
+# enabled
+#
+# Since: 2.12
+##
+{ 'struct': 'SevCapability',
+ 'data': { 'pdh': 'str',
+ 'cert-chain': 'str',
+ 'cbitpos': 'int',
+ 'reduced-phys-bits': 'int'},
+ 'if': 'TARGET_I386' }
+
+##
+# @query-sev-capabilities:
+#
+# This command is used to get the SEV capabilities, and is supported on AMD
+# X86 platforms only.
+#
+# Returns: SevCapability objects.
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-capabilities" }
+# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
+# "cbitpos": 47, "reduced-phys-bits": 5}}
+#
+##
+{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
+ 'if': 'TARGET_I386' }
+
+##
+# @sev-inject-launch-secret:
+#
+# This command injects a secret blob into memory of SEV guest.
+#
+# @packet-header: the launch secret packet header encoded in base64
+#
+# @secret: the launch secret data to be injected encoded in base64
+#
+# @gpa: the guest physical address where secret will be injected.
+#
+# Since: 6.0
+#
+##
+{ 'command': 'sev-inject-launch-secret',
+ 'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' },
+ 'if': 'TARGET_I386' }
+
+##
+# @SevAttestationReport:
+#
+# The struct describes attestation report for a Secure Encrypted
+# Virtualization feature.
+#
+# @data: guest attestation report (base64 encoded)
+#
+#
+# Since: 6.1
+##
+{ 'struct': 'SevAttestationReport',
+ 'data': { 'data': 'str'},
+ 'if': 'TARGET_I386' }
+
+##
+# @query-sev-attestation-report:
+#
+# This command is used to get the SEV attestation report, and is
+# supported on AMD X86 platforms only.
+#
+# @mnonce: a random 16 bytes value encoded in base64 (it will be
+# included in report)
+#
+# Returns: SevAttestationReport objects.
+#
+# Since: 6.1
+#
+# Example:
+#
+# -> { "execute" : "query-sev-attestation-report",
+# "arguments": { "mnonce": "aaaaaaa" } }
+# <- { "return" : { "data": "aaaaaaaabbbddddd"} }
+#
+##
+{ 'command': 'query-sev-attestation-report',
+ 'data': { 'mnonce': 'str' },
+ 'returns': 'SevAttestationReport',
+ 'if': 'TARGET_I386' }
+
+##
+# @dump-skeys:
+#
+# Dump guest's storage keys
+#
+# @filename: the path to the file to dump to
+#
+# This command is only supported on s390 architecture.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "dump-skeys",
+# "arguments": { "filename": "/tmp/skeys" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-skeys',
+ 'data': { 'filename': 'str' },
+ 'if': 'TARGET_S390X' }
+
+##
+# @GICCapability:
+#
+# The struct describes capability for a specific GIC (Generic
+# Interrupt Controller) version. These bits are not only decided by
+# QEMU/KVM software version, but also decided by the hardware that
+# the program is running upon.
+#
+# @version: version of GIC to be described. Currently, only 2 and 3
+# are supported.
+#
+# @emulated: whether current QEMU/hardware supports emulated GIC
+# device in user space.
+#
+# @kernel: whether current QEMU/hardware supports hardware
+# accelerated GIC device in kernel.
+#
+# Since: 2.6
+##
+{ 'struct': 'GICCapability',
+ 'data': { 'version': 'int',
+ 'emulated': 'bool',
+ 'kernel': 'bool' },
+ 'if': 'TARGET_ARM' }
+
+##
+# @query-gic-capabilities:
+#
+# This command is ARM-only. It will return a list of GICCapability
+# objects that describe its capability bits.
+#
+# Returns: a list of GICCapability objects.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-gic-capabilities" }
+# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
+# { "version": 3, "emulated": false, "kernel": true } ] }
+#
+##
+{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
+ 'if': 'TARGET_ARM' }
+
+
+##
+# @SGXInfo:
+#
+# Information about intel Safe Guard eXtension (SGX) support
+#
+# @sgx: true if SGX is supported
+#
+# @sgx1: true if SGX1 is supported
+#
+# @sgx2: true if SGX2 is supported
+#
+# @flc: true if FLC is supported
+#
+# @section-size: The EPC section size for guest
+#
+# Since: 6.2
+##
+{ 'struct': 'SGXInfo',
+ 'data': { 'sgx': 'bool',
+ 'sgx1': 'bool',
+ 'sgx2': 'bool',
+ 'flc': 'bool',
+ 'section-size': 'uint64'},
+ 'if': 'TARGET_I386' }
+
+##
+# @query-sgx:
+#
+# Returns information about SGX
+#
+# Returns: @SGXInfo
+#
+# Since: 6.2
+#
+# Example:
+#
+# -> { "execute": "query-sgx" }
+# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
+# "flc": true, "section-size" : 0 } }
+#
+##
+{ 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' }
+
+##
+# @query-sgx-capabilities:
+#
+# Returns information from host SGX capabilities
+#
+# Returns: @SGXInfo
+#
+# Since: 6.2
+#
+# Example:
+#
+# -> { "execute": "query-sgx-capabilities" }
+# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
+# "flc": true, "section-size" : 0 } }
+#
+##
+{ 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' }
diff --git a/qapi/misc.json b/qapi/misc.json
new file mode 100644
index 000000000..358548abe
--- /dev/null
+++ b/qapi/misc.json
@@ -0,0 +1,529 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Miscellanea
+##
+
+{ 'include': 'common.json' }
+
+##
+# @add_client:
+#
+# Allow client connections for VNC, Spice and socket based
+# character devices to be passed in to QEMU via SCM_RIGHTS.
+#
+# @protocol: protocol name. Valid names are "vnc", "spice" or the
+# name of a character device (eg. from -chardev id=XXXX)
+#
+# @fdname: file descriptor name previously passed via 'getfd' command
+#
+# @skipauth: whether to skip authentication. Only applies
+# to "vnc" and "spice" protocols
+#
+# @tls: whether to perform TLS. Only applies to the "spice"
+# protocol
+#
+# Returns: nothing on success.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "add_client", "arguments": { "protocol": "vnc",
+# "fdname": "myclient" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'add_client',
+ 'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',
+ '*tls': 'bool' } }
+
+##
+# @NameInfo:
+#
+# Guest name information.
+#
+# @name: The name of the guest
+#
+# Since: 0.14
+##
+{ 'struct': 'NameInfo', 'data': {'*name': 'str'} }
+
+##
+# @query-name:
+#
+# Return the name information of a guest.
+#
+# Returns: @NameInfo of the guest
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-name" }
+# <- { "return": { "name": "qemu-name" } }
+#
+##
+{ 'command': 'query-name', 'returns': 'NameInfo', 'allow-preconfig': true }
+
+##
+# @IOThreadInfo:
+#
+# Information about an iothread
+#
+# @id: the identifier of the iothread
+#
+# @thread-id: ID of the underlying host thread
+#
+# @poll-max-ns: maximum polling time in ns, 0 means polling is disabled
+# (since 2.9)
+#
+# @poll-grow: how many ns will be added to polling time, 0 means that it's not
+# configured (since 2.9)
+#
+# @poll-shrink: how many ns will be removed from polling time, 0 means that
+# it's not configured (since 2.9)
+#
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
+# 0 means that the engine will use its default (since 6.1)
+#
+# Since: 2.0
+##
+{ 'struct': 'IOThreadInfo',
+ 'data': {'id': 'str',
+ 'thread-id': 'int',
+ 'poll-max-ns': 'int',
+ 'poll-grow': 'int',
+ 'poll-shrink': 'int',
+ 'aio-max-batch': 'int' } }
+
+##
+# @query-iothreads:
+#
+# Returns a list of information about each iothread.
+#
+# Note: this list excludes the QEMU main loop thread, which is not declared
+# using the -object iothread command-line option. It is always the main thread
+# of the process.
+#
+# Returns: a list of @IOThreadInfo for each iothread
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-iothreads" }
+# <- { "return": [
+# {
+# "id":"iothread0",
+# "thread-id":3134
+# },
+# {
+# "id":"iothread1",
+# "thread-id":3135
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'],
+ 'allow-preconfig': true }
+
+##
+# @stop:
+#
+# Stop all guest VCPU execution.
+#
+# Since: 0.14
+#
+# Notes: This function will succeed even if the guest is already in the stopped
+# state. In "inmigrate" state, it will ensure that the guest
+# remains paused once migration finishes, as if the -S option was
+# passed on the command line.
+#
+# Example:
+#
+# -> { "execute": "stop" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'stop' }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since: 0.14
+#
+# Returns: If successful, nothing
+#
+# Notes: This command will succeed if the guest is currently running. It
+# will also succeed if the guest is in the "inmigrate" state; in
+# this case, the effect of the command is to make sure the guest
+# starts once migration finishes, removing the effect of the -S
+# command line option if it was passed.
+#
+# Example:
+#
+# -> { "execute": "cont" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'cont' }
+
+##
+# @x-exit-preconfig:
+#
+# Exit from "preconfig" state
+#
+# This command makes QEMU exit the preconfig state and proceed with
+# VM initialization using configuration data provided on the command line
+# and via the QMP monitor during the preconfig state. The command is only
+# available during the preconfig state (i.e. when the --preconfig command
+# line option was in use).
+#
+# Features:
+# @unstable: This command is experimental.
+#
+# Since 3.0
+#
+# Returns: nothing
+#
+# Example:
+#
+# -> { "execute": "x-exit-preconfig" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'x-exit-preconfig', 'allow-preconfig': true,
+ 'features': [ 'unstable' ] }
+
+##
+# @human-monitor-command:
+#
+# Execute a command on the human monitor and return the output.
+#
+# @command-line: the command to execute in the human monitor
+#
+# @cpu-index: The CPU to use for commands that require an implicit CPU
+#
+# Features:
+# @savevm-monitor-nodes: If present, HMP command savevm only snapshots
+# monitor-owned nodes if they have no parents.
+# This allows the use of 'savevm' with
+# -blockdev. (since 4.2)
+#
+# Returns: the output of the command as a string
+#
+# Since: 0.14
+#
+# Notes: This command only exists as a stop-gap. Its use is highly
+# discouraged. The semantics of this command are not
+# guaranteed: this means that command names, arguments and
+# responses can change or be removed at ANY time. Applications
+# that rely on long term stability guarantees should NOT
+# use this command.
+#
+# Known limitations:
+#
+# * This command is stateless, this means that commands that depend
+# on state information (such as getfd) might not work
+#
+# * Commands that prompt the user for data don't currently work
+#
+# Example:
+#
+# -> { "execute": "human-monitor-command",
+# "arguments": { "command-line": "info kvm" } }
+# <- { "return": "kvm support: enabled\r\n" }
+#
+##
+{ 'command': 'human-monitor-command',
+ 'data': {'command-line': 'str', '*cpu-index': 'int'},
+ 'returns': 'str',
+ 'features': [ 'savevm-monitor-nodes' ] }
+
+##
+# @getfd:
+#
+# Receive a file descriptor via SCM rights and assign it a name
+#
+# @fdname: file descriptor name
+#
+# Returns: Nothing on success
+#
+# Since: 0.14
+#
+# Notes: If @fdname already exists, the file descriptor assigned to
+# it will be closed and replaced by the received file
+# descriptor.
+#
+# The 'closefd' command can be used to explicitly close the
+# file descriptor when it is no longer needed.
+#
+# Example:
+#
+# -> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'getfd', 'data': {'fdname': 'str'} }
+
+##
+# @closefd:
+#
+# Close a file descriptor previously passed via SCM rights
+#
+# @fdname: file descriptor name
+#
+# Returns: Nothing on success
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'closefd', 'data': {'fdname': 'str'} }
+
+##
+# @AddfdInfo:
+#
+# Information about a file descriptor that was added to an fd set.
+#
+# @fdset-id: The ID of the fd set that @fd was added to.
+#
+# @fd: The file descriptor that was received via SCM rights and
+# added to the fd set.
+#
+# Since: 1.2
+##
+{ 'struct': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }
+
+##
+# @add-fd:
+#
+# Add a file descriptor, that was passed via SCM rights, to an fd set.
+#
+# @fdset-id: The ID of the fd set to add the file descriptor to.
+#
+# @opaque: A free-form string that can be used to describe the fd.
+#
+# Returns: - @AddfdInfo on success
+# - If file descriptor was not received, FdNotSupplied
+# - If @fdset-id is a negative value, InvalidParameterValue
+#
+# Notes: The list of fd sets is shared by all monitor connections.
+#
+# If @fdset-id is not specified, a new fd set will be created.
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } }
+# <- { "return": { "fdset-id": 1, "fd": 3 } }
+#
+##
+{ 'command': 'add-fd',
+ 'data': { '*fdset-id': 'int',
+ '*opaque': 'str' },
+ 'returns': 'AddfdInfo' }
+
+##
+# @remove-fd:
+#
+# Remove a file descriptor from an fd set.
+#
+# @fdset-id: The ID of the fd set that the file descriptor belongs to.
+#
+# @fd: The file descriptor that is to be removed.
+#
+# Returns: - Nothing on success
+# - If @fdset-id or @fd is not found, FdNotFound
+#
+# Since: 1.2
+#
+# Notes: The list of fd sets is shared by all monitor connections.
+#
+# If @fd is not specified, all file descriptors in @fdset-id
+# will be removed.
+#
+# Example:
+#
+# -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }
+
+##
+# @FdsetFdInfo:
+#
+# Information about a file descriptor that belongs to an fd set.
+#
+# @fd: The file descriptor value.
+#
+# @opaque: A free-form string that can be used to describe the fd.
+#
+# Since: 1.2
+##
+{ 'struct': 'FdsetFdInfo',
+ 'data': {'fd': 'int', '*opaque': 'str'} }
+
+##
+# @FdsetInfo:
+#
+# Information about an fd set.
+#
+# @fdset-id: The ID of the fd set.
+#
+# @fds: A list of file descriptors that belong to this fd set.
+#
+# Since: 1.2
+##
+{ 'struct': 'FdsetInfo',
+ 'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }
+
+##
+# @query-fdsets:
+#
+# Return information describing all fd sets.
+#
+# Returns: A list of @FdsetInfo
+#
+# Since: 1.2
+#
+# Note: The list of fd sets is shared by all monitor connections.
+#
+# Example:
+#
+# -> { "execute": "query-fdsets" }
+# <- { "return": [
+# {
+# "fds": [
+# {
+# "fd": 30,
+# "opaque": "rdonly:/path/to/file"
+# },
+# {
+# "fd": 24,
+# "opaque": "rdwr:/path/to/file"
+# }
+# ],
+# "fdset-id": 1
+# },
+# {
+# "fds": [
+# {
+# "fd": 28
+# },
+# {
+# "fd": 29
+# }
+# ],
+# "fdset-id": 0
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
+
+##
+# @CommandLineParameterType:
+#
+# Possible types for an option parameter.
+#
+# @string: accepts a character string
+#
+# @boolean: accepts "on" or "off"
+#
+# @number: accepts a number
+#
+# @size: accepts a number followed by an optional suffix (K)ilo,
+# (M)ega, (G)iga, (T)era
+#
+# Since: 1.5
+##
+{ 'enum': 'CommandLineParameterType',
+ 'data': ['string', 'boolean', 'number', 'size'] }
+
+##
+# @CommandLineParameterInfo:
+#
+# Details about a single parameter of a command line option.
+#
+# @name: parameter name
+#
+# @type: parameter @CommandLineParameterType
+#
+# @help: human readable text string, not suitable for parsing.
+#
+# @default: default value string (since 2.1)
+#
+# Since: 1.5
+##
+{ 'struct': 'CommandLineParameterInfo',
+ 'data': { 'name': 'str',
+ 'type': 'CommandLineParameterType',
+ '*help': 'str',
+ '*default': 'str' } }
+
+##
+# @CommandLineOptionInfo:
+#
+# Details about a command line option, including its list of parameter details
+#
+# @option: option name
+#
+# @parameters: an array of @CommandLineParameterInfo
+#
+# Since: 1.5
+##
+{ 'struct': 'CommandLineOptionInfo',
+ 'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }
+
+##
+# @query-command-line-options:
+#
+# Query command line option schema.
+#
+# @option: option name
+#
+# Returns: list of @CommandLineOptionInfo for all options (or for the given
+# @option). Returns an error if the given @option doesn't exist.
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "query-command-line-options",
+# "arguments": { "option": "option-rom" } }
+# <- { "return": [
+# {
+# "parameters": [
+# {
+# "name": "romfile",
+# "type": "string"
+# },
+# {
+# "name": "bootindex",
+# "type": "number"
+# }
+# ],
+# "option": "option-rom"
+# }
+# ]
+# }
+#
+##
+{'command': 'query-command-line-options',
+ 'data': { '*option': 'str' },
+ 'returns': ['CommandLineOptionInfo'],
+ 'allow-preconfig': true }
diff --git a/qapi/net.json b/qapi/net.json
new file mode 100644
index 000000000..7fab2e7cd
--- /dev/null
+++ b/qapi/net.json
@@ -0,0 +1,698 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Net devices
+##
+
+{ 'include': 'common.json' }
+
+##
+# @set_link:
+#
+# Sets the link status of a virtual network adapter.
+#
+# @name: the device name of the virtual network adapter
+#
+# @up: true to set the link status to be up
+#
+# Returns: Nothing on success
+# If @name is not a valid network device, DeviceNotFound
+#
+# Since: 0.14
+#
+# Notes: Not all network adapters support setting link status. This command
+# will succeed even if the network adapter does not support link status
+# notification.
+#
+# Example:
+#
+# -> { "execute": "set_link",
+# "arguments": { "name": "e1000.0", "up": false } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
+
+##
+# @netdev_add:
+#
+# Add a network backend.
+#
+# Additional arguments depend on the type.
+#
+# Since: 0.14
+#
+# Returns: Nothing on success
+# If @type is not a valid network backend, DeviceNotFound
+#
+# Example:
+#
+# -> { "execute": "netdev_add",
+# "arguments": { "type": "user", "id": "netdev1",
+# "dnssearch": "example.org" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'netdev_add', 'data': 'Netdev', 'boxed': true,
+ 'allow-preconfig': true }
+
+##
+# @netdev_del:
+#
+# Remove a network backend.
+#
+# @id: the name of the network backend to remove
+#
+# Returns: Nothing on success
+# If @id is not a valid network backend, DeviceNotFound
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'netdev_del', 'data': {'id': 'str'},
+ 'allow-preconfig': true }
+
+##
+# @NetLegacyNicOptions:
+#
+# Create a new Network Interface Card.
+#
+# @netdev: id of -netdev to connect to
+#
+# @macaddr: MAC address
+#
+# @model: device model (e1000, rtl8139, virtio etc.)
+#
+# @addr: PCI device address
+#
+# @vectors: number of MSI-x vectors, 0 to disable MSI-X
+#
+# Since: 1.2
+##
+{ 'struct': 'NetLegacyNicOptions',
+ 'data': {
+ '*netdev': 'str',
+ '*macaddr': 'str',
+ '*model': 'str',
+ '*addr': 'str',
+ '*vectors': 'uint32' } }
+
+##
+# @NetdevUserOptions:
+#
+# Use the user mode network stack which requires no administrator privilege to
+# run.
+#
+# @hostname: client hostname reported by the builtin DHCP server
+#
+# @restrict: isolate the guest from the host
+#
+# @ipv4: whether to support IPv4, default true for enabled
+# (since 2.6)
+#
+# @ipv6: whether to support IPv6, default true for enabled
+# (since 2.6)
+#
+# @ip: legacy parameter, use net= instead
+#
+# @net: IP network address that the guest will see, in the
+# form addr[/netmask] The netmask is optional, and can be
+# either in the form a.b.c.d or as a number of valid top-most
+# bits. Default is 10.0.2.0/24.
+#
+# @host: guest-visible address of the host
+#
+# @tftp: root directory of the built-in TFTP server
+#
+# @bootfile: BOOTP filename, for use with tftp=
+#
+# @dhcpstart: the first of the 16 IPs the built-in DHCP server can
+# assign
+#
+# @dns: guest-visible address of the virtual nameserver
+#
+# @dnssearch: list of DNS suffixes to search, passed as DHCP option
+# to the guest
+#
+# @domainname: guest-visible domain name of the virtual nameserver
+# (since 3.0)
+#
+# @ipv6-prefix: IPv6 network prefix (default is fec0::) (since
+# 2.6). The network prefix is given in the usual
+# hexadecimal IPv6 address notation.
+#
+# @ipv6-prefixlen: IPv6 network prefix length (default is 64)
+# (since 2.6)
+#
+# @ipv6-host: guest-visible IPv6 address of the host (since 2.6)
+#
+# @ipv6-dns: guest-visible IPv6 address of the virtual
+# nameserver (since 2.6)
+#
+# @smb: root directory of the built-in SMB server
+#
+# @smbserver: IP address of the built-in SMB server
+#
+# @hostfwd: redirect incoming TCP or UDP host connections to guest
+# endpoints
+#
+# @guestfwd: forward guest TCP connections
+#
+# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1)
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevUserOptions',
+ 'data': {
+ '*hostname': 'str',
+ '*restrict': 'bool',
+ '*ipv4': 'bool',
+ '*ipv6': 'bool',
+ '*ip': 'str',
+ '*net': 'str',
+ '*host': 'str',
+ '*tftp': 'str',
+ '*bootfile': 'str',
+ '*dhcpstart': 'str',
+ '*dns': 'str',
+ '*dnssearch': ['String'],
+ '*domainname': 'str',
+ '*ipv6-prefix': 'str',
+ '*ipv6-prefixlen': 'int',
+ '*ipv6-host': 'str',
+ '*ipv6-dns': 'str',
+ '*smb': 'str',
+ '*smbserver': 'str',
+ '*hostfwd': ['String'],
+ '*guestfwd': ['String'],
+ '*tftp-server-name': 'str' } }
+
+##
+# @NetdevTapOptions:
+#
+# Used to configure a host TAP network interface backend.
+#
+# @ifname: interface name
+#
+# @fd: file descriptor of an already opened tap
+#
+# @fds: multiple file descriptors of already opened multiqueue capable
+# tap
+#
+# @script: script to initialize the interface
+#
+# @downscript: script to shut down the interface
+#
+# @br: bridge name (since 2.8)
+#
+# @helper: command to execute to configure bridge
+#
+# @sndbuf: send buffer limit. Understands [TGMKkb] suffixes.
+#
+# @vnet_hdr: enable the IFF_VNET_HDR flag on the tap interface
+#
+# @vhost: enable vhost-net network accelerator
+#
+# @vhostfd: file descriptor of an already opened vhost net device
+#
+# @vhostfds: file descriptors of multiple already opened vhost net
+# devices
+#
+# @vhostforce: vhost on for non-MSIX virtio guests
+#
+# @queues: number of queues to be created for multiqueue capable tap
+#
+# @poll-us: maximum number of microseconds that could
+# be spent on busy polling for tap (since 2.7)
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevTapOptions',
+ 'data': {
+ '*ifname': 'str',
+ '*fd': 'str',
+ '*fds': 'str',
+ '*script': 'str',
+ '*downscript': 'str',
+ '*br': 'str',
+ '*helper': 'str',
+ '*sndbuf': 'size',
+ '*vnet_hdr': 'bool',
+ '*vhost': 'bool',
+ '*vhostfd': 'str',
+ '*vhostfds': 'str',
+ '*vhostforce': 'bool',
+ '*queues': 'uint32',
+ '*poll-us': 'uint32'} }
+
+##
+# @NetdevSocketOptions:
+#
+# Socket netdevs are used to establish a network connection to another
+# QEMU virtual machine via a TCP socket.
+#
+# @fd: file descriptor of an already opened socket
+#
+# @listen: port number, and optional hostname, to listen on
+#
+# @connect: port number, and optional hostname, to connect to
+#
+# @mcast: UDP multicast address and port number
+#
+# @localaddr: source address and port for multicast and udp packets
+#
+# @udp: UDP unicast address and port number
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevSocketOptions',
+ 'data': {
+ '*fd': 'str',
+ '*listen': 'str',
+ '*connect': 'str',
+ '*mcast': 'str',
+ '*localaddr': 'str',
+ '*udp': 'str' } }
+
+##
+# @NetdevL2TPv3Options:
+#
+# Configure an Ethernet over L2TPv3 tunnel.
+#
+# @src: source address
+#
+# @dst: destination address
+#
+# @srcport: source port - mandatory for udp, optional for ip
+#
+# @dstport: destination port - mandatory for udp, optional for ip
+#
+# @ipv6: force the use of ipv6
+#
+# @udp: use the udp version of l2tpv3 encapsulation
+#
+# @cookie64: use 64 bit coookies
+#
+# @counter: have sequence counter
+#
+# @pincounter: pin sequence counter to zero -
+# workaround for buggy implementations or
+# networks with packet reorder
+#
+# @txcookie: 32 or 64 bit transmit cookie
+#
+# @rxcookie: 32 or 64 bit receive cookie
+#
+# @txsession: 32 bit transmit session
+#
+# @rxsession: 32 bit receive session - if not specified
+# set to the same value as transmit
+#
+# @offset: additional offset - allows the insertion of
+# additional application-specific data before the packet payload
+#
+# Since: 2.1
+##
+{ 'struct': 'NetdevL2TPv3Options',
+ 'data': {
+ 'src': 'str',
+ 'dst': 'str',
+ '*srcport': 'str',
+ '*dstport': 'str',
+ '*ipv6': 'bool',
+ '*udp': 'bool',
+ '*cookie64': 'bool',
+ '*counter': 'bool',
+ '*pincounter': 'bool',
+ '*txcookie': 'uint64',
+ '*rxcookie': 'uint64',
+ 'txsession': 'uint32',
+ '*rxsession': 'uint32',
+ '*offset': 'uint32' } }
+
+##
+# @NetdevVdeOptions:
+#
+# Connect to a vde switch running on the host.
+#
+# @sock: socket path
+#
+# @port: port number
+#
+# @group: group owner of socket
+#
+# @mode: permissions for socket
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevVdeOptions',
+ 'data': {
+ '*sock': 'str',
+ '*port': 'uint16',
+ '*group': 'str',
+ '*mode': 'uint16' } }
+
+##
+# @NetdevBridgeOptions:
+#
+# Connect a host TAP network interface to a host bridge device.
+#
+# @br: bridge name
+#
+# @helper: command to execute to configure bridge
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevBridgeOptions',
+ 'data': {
+ '*br': 'str',
+ '*helper': 'str' } }
+
+##
+# @NetdevHubPortOptions:
+#
+# Connect two or more net clients through a software hub.
+#
+# @hubid: hub identifier number
+# @netdev: used to connect hub to a netdev instead of a device (since 2.12)
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevHubPortOptions',
+ 'data': {
+ 'hubid': 'int32',
+ '*netdev': 'str' } }
+
+##
+# @NetdevNetmapOptions:
+#
+# Connect a client to a netmap-enabled NIC or to a VALE switch port
+#
+# @ifname: Either the name of an existing network interface supported by
+# netmap, or the name of a VALE port (created on the fly).
+# A VALE port name is in the form 'valeXXX:YYY', where XXX and
+# YYY are non-negative integers. XXX identifies a switch and
+# YYY identifies a port of the switch. VALE ports having the
+# same XXX are therefore connected to the same switch.
+#
+# @devname: path of the netmap device (default: '/dev/netmap').
+#
+# Since: 2.0
+##
+{ 'struct': 'NetdevNetmapOptions',
+ 'data': {
+ 'ifname': 'str',
+ '*devname': 'str' } }
+
+##
+# @NetdevVhostUserOptions:
+#
+# Vhost-user network backend
+#
+# @chardev: name of a unix socket chardev
+#
+# @vhostforce: vhost on for non-MSIX virtio guests (default: false).
+#
+# @queues: number of queues to be created for multiqueue vhost-user
+# (default: 1) (Since 2.5)
+#
+# Since: 2.1
+##
+{ 'struct': 'NetdevVhostUserOptions',
+ 'data': {
+ 'chardev': 'str',
+ '*vhostforce': 'bool',
+ '*queues': 'int' } }
+
+##
+# @NetdevVhostVDPAOptions:
+#
+# Vhost-vdpa network backend
+#
+# vDPA device is a device that uses a datapath which complies with the virtio
+# specifications with a vendor specific control path.
+#
+# @vhostdev: path of vhost-vdpa device
+# (default:'/dev/vhost-vdpa-0')
+#
+# @queues: number of queues to be created for multiqueue vhost-vdpa
+# (default: 1)
+#
+# Since: 5.1
+##
+{ 'struct': 'NetdevVhostVDPAOptions',
+ 'data': {
+ '*vhostdev': 'str',
+ '*queues': 'int' } }
+
+##
+# @NetClientDriver:
+#
+# Available netdev drivers.
+#
+# Since: 2.7
+#
+# @vhost-vdpa since 5.1
+##
+{ 'enum': 'NetClientDriver',
+ 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
+ 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
+
+##
+# @Netdev:
+#
+# Captures the configuration of a network device.
+#
+# @id: identifier for monitor commands.
+#
+# @type: Specify the driver used for interpreting remaining arguments.
+#
+# Since: 1.2
+#
+# 'l2tpv3' - since 2.1
+##
+{ 'union': 'Netdev',
+ 'base': { 'id': 'str', 'type': 'NetClientDriver' },
+ 'discriminator': 'type',
+ 'data': {
+ 'nic': 'NetLegacyNicOptions',
+ 'user': 'NetdevUserOptions',
+ 'tap': 'NetdevTapOptions',
+ 'l2tpv3': 'NetdevL2TPv3Options',
+ 'socket': 'NetdevSocketOptions',
+ 'vde': 'NetdevVdeOptions',
+ 'bridge': 'NetdevBridgeOptions',
+ 'hubport': 'NetdevHubPortOptions',
+ 'netmap': 'NetdevNetmapOptions',
+ 'vhost-user': 'NetdevVhostUserOptions',
+ 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
+
+##
+# @RxState:
+#
+# Packets receiving state
+#
+# @normal: filter assigned packets according to the mac-table
+#
+# @none: don't receive any assigned packet
+#
+# @all: receive all assigned packets
+#
+# Since: 1.6
+##
+{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] }
+
+##
+# @RxFilterInfo:
+#
+# Rx-filter information for a NIC.
+#
+# @name: net client name
+#
+# @promiscuous: whether promiscuous mode is enabled
+#
+# @multicast: multicast receive state
+#
+# @unicast: unicast receive state
+#
+# @vlan: vlan receive state (Since 2.0)
+#
+# @broadcast-allowed: whether to receive broadcast
+#
+# @multicast-overflow: multicast table is overflowed or not
+#
+# @unicast-overflow: unicast table is overflowed or not
+#
+# @main-mac: the main macaddr string
+#
+# @vlan-table: a list of active vlan id
+#
+# @unicast-table: a list of unicast macaddr string
+#
+# @multicast-table: a list of multicast macaddr string
+#
+# Since: 1.6
+##
+{ 'struct': 'RxFilterInfo',
+ 'data': {
+ 'name': 'str',
+ 'promiscuous': 'bool',
+ 'multicast': 'RxState',
+ 'unicast': 'RxState',
+ 'vlan': 'RxState',
+ 'broadcast-allowed': 'bool',
+ 'multicast-overflow': 'bool',
+ 'unicast-overflow': 'bool',
+ 'main-mac': 'str',
+ 'vlan-table': ['int'],
+ 'unicast-table': ['str'],
+ 'multicast-table': ['str'] }}
+
+##
+# @query-rx-filter:
+#
+# Return rx-filter information for all NICs (or for the given NIC).
+#
+# @name: net client name
+#
+# Returns: list of @RxFilterInfo for all NICs (or for the given NIC).
+# Returns an error if the given @name doesn't exist, or given
+# NIC doesn't support rx-filter querying, or given net client
+# isn't a NIC.
+#
+# Since: 1.6
+#
+# Example:
+#
+# -> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } }
+# <- { "return": [
+# {
+# "promiscuous": true,
+# "name": "vnet0",
+# "main-mac": "52:54:00:12:34:56",
+# "unicast": "normal",
+# "vlan": "normal",
+# "vlan-table": [
+# 4,
+# 0
+# ],
+# "unicast-table": [
+# ],
+# "multicast": "normal",
+# "multicast-overflow": false,
+# "unicast-overflow": false,
+# "multicast-table": [
+# "01:00:5e:00:00:01",
+# "33:33:00:00:00:01",
+# "33:33:ff:12:34:56"
+# ],
+# "broadcast-allowed": false
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-rx-filter',
+ 'data': { '*name': 'str' },
+ 'returns': ['RxFilterInfo'] }
+
+##
+# @NIC_RX_FILTER_CHANGED:
+#
+# Emitted once until the 'query-rx-filter' command is executed, the first event
+# will always be emitted
+#
+# @name: net client name
+#
+# @path: device path
+#
+# Since: 1.6
+#
+# Example:
+#
+# <- { "event": "NIC_RX_FILTER_CHANGED",
+# "data": { "name": "vnet0",
+# "path": "/machine/peripheral/vnet0/virtio-backend" },
+# "timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
+# }
+#
+##
+{ 'event': 'NIC_RX_FILTER_CHANGED',
+ 'data': { '*name': 'str', 'path': 'str' } }
+
+##
+# @AnnounceParameters:
+#
+# Parameters for self-announce timers
+#
+# @initial: Initial delay (in ms) before sending the first GARP/RARP
+# announcement
+#
+# @max: Maximum delay (in ms) between GARP/RARP announcement packets
+#
+# @rounds: Number of self-announcement attempts
+#
+# @step: Delay increase (in ms) after each self-announcement attempt
+#
+# @interfaces: An optional list of interface names, which restricts the
+# announcement to the listed interfaces. (Since 4.1)
+#
+# @id: A name to be used to identify an instance of announce-timers
+# and to allow it to modified later. Not for use as
+# part of the migration parameters. (Since 4.1)
+#
+# Since: 4.0
+##
+
+{ 'struct': 'AnnounceParameters',
+ 'data': { 'initial': 'int',
+ 'max': 'int',
+ 'rounds': 'int',
+ 'step': 'int',
+ '*interfaces': ['str'],
+ '*id' : 'str' } }
+
+##
+# @announce-self:
+#
+# Trigger generation of broadcast RARP frames to update network switches.
+# This can be useful when network bonds fail-over the active slave.
+#
+# Example:
+#
+# -> { "execute": "announce-self",
+# "arguments": {
+# "initial": 50, "max": 550, "rounds": 10, "step": 50,
+# "interfaces": ["vn2", "vn3"], "id": "bob" } }
+# <- { "return": {} }
+#
+# Since: 4.0
+##
+{ 'command': 'announce-self', 'boxed': true,
+ 'data' : 'AnnounceParameters'}
+
+##
+# @FAILOVER_NEGOTIATED:
+#
+# Emitted when VIRTIO_NET_F_STANDBY was enabled during feature negotiation.
+# Failover primary devices which were hidden (not hotplugged when requested)
+# before will now be hotplugged by the virtio-net standby device.
+#
+# device-id: QEMU device id of the unplugged device
+# Since: 4.2
+#
+# Example:
+#
+# <- { "event": "FAILOVER_NEGOTIATED",
+# "data": "net1" }
+#
+##
+{ 'event': 'FAILOVER_NEGOTIATED',
+ 'data': {'device-id': 'str'} }
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
new file mode 100644
index 000000000..587f31baf
--- /dev/null
+++ b/qapi/opts-visitor.c
@@ -0,0 +1,586 @@
+/*
+ * Options Visitor
+ *
+ * Copyright Red Hat, Inc. 2012-2016
+ *
+ * Author: Laszlo Ersek <lersek@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/opts-visitor.h"
+#include "qemu/queue.h"
+#include "qemu/option_int.h"
+#include "qapi/visitor-impl.h"
+
+
+enum ListMode
+{
+ LM_NONE, /* not traversing a list of repeated options */
+
+ LM_IN_PROGRESS, /*
+ * opts_next_list() ready to be called.
+ *
+ * Generating the next list link will consume the most
+ * recently parsed QemuOpt instance of the repeated
+ * option.
+ *
+ * Parsing a value into the list link will examine the
+ * next QemuOpt instance of the repeated option, and
+ * possibly enter LM_SIGNED_INTERVAL or
+ * LM_UNSIGNED_INTERVAL.
+ */
+
+ LM_SIGNED_INTERVAL, /*
+ * opts_next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently stored element from the signed interval,
+ * parsed from the most recent QemuOpt instance of the
+ * repeated option. This may consume QemuOpt itself
+ * and return to LM_IN_PROGRESS.
+ *
+ * Parsing a value into the list link will store the
+ * next element of the signed interval.
+ */
+
+ LM_UNSIGNED_INTERVAL, /* Same as above, only for an unsigned interval. */
+
+ LM_TRAVERSED /*
+ * opts_next_list() has been called.
+ *
+ * No more QemuOpt instance in the list.
+ * The traversal has been completed.
+ */
+};
+
+typedef enum ListMode ListMode;
+
+struct OptsVisitor
+{
+ Visitor visitor;
+
+ /* Ownership remains with opts_visitor_new()'s caller. */
+ const QemuOpts *opts_root;
+
+ unsigned depth;
+
+ /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value
+ * is a non-empty GQueue, enumerating all QemuOpt occurrences with that
+ * name. */
+ GHashTable *unprocessed_opts;
+
+ /* The list currently being traversed with opts_start_list() /
+ * opts_next_list(). The list must have a struct element type in the
+ * schema, with a single mandatory scalar member. */
+ ListMode list_mode;
+ GQueue *repeated_opts;
+
+ /* When parsing a list of repeating options as integers, values of the form
+ * "a-b", representing a closed interval, are allowed. Elements in the
+ * range are generated individually.
+ */
+ union {
+ int64_t s;
+ uint64_t u;
+ } range_next, range_limit;
+
+ /* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for
+ * uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does
+ * not survive or escape the OptsVisitor object.
+ */
+ QemuOpt *fake_id_opt;
+};
+
+
+static OptsVisitor *to_ov(Visitor *v)
+{
+ return container_of(v, OptsVisitor, visitor);
+}
+
+
+static void
+destroy_list(gpointer list)
+{
+ g_queue_free(list);
+}
+
+
+static void
+opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt)
+{
+ GQueue *list;
+
+ list = g_hash_table_lookup(unprocessed_opts, opt->name);
+ if (list == NULL) {
+ list = g_queue_new();
+
+ /* GHashTable will never try to free the keys -- we supply NULL as
+ * "key_destroy_func" in opts_start_struct(). Thus cast away key
+ * const-ness in order to suppress gcc's warning.
+ */
+ g_hash_table_insert(unprocessed_opts, (gpointer)opt->name, list);
+ }
+
+ /* Similarly, destroy_list() doesn't call g_queue_free_full(). */
+ g_queue_push_tail(list, (gpointer)opt);
+}
+
+
+static bool
+opts_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+
+ if (obj) {
+ *obj = g_malloc0(size);
+ }
+ if (ov->depth++ > 0) {
+ return true;
+ }
+
+ ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal,
+ NULL, &destroy_list);
+ QTAILQ_FOREACH(opt, &ov->opts_root->head, next) {
+ /* ensured by qemu-option.c::opts_do_parse() */
+ assert(strcmp(opt->name, "id") != 0);
+
+ opts_visitor_insert(ov->unprocessed_opts, opt);
+ }
+
+ if (ov->opts_root->id != NULL) {
+ ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt);
+
+ ov->fake_id_opt->name = g_strdup("id");
+ ov->fake_id_opt->str = g_strdup(ov->opts_root->id);
+ opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt);
+ }
+ return true;
+}
+
+
+static bool
+opts_check_struct(Visitor *v, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ GHashTableIter iter;
+ GQueue *any;
+
+ if (ov->depth > 1) {
+ return true;
+ }
+
+ /* we should have processed all (distinct) QemuOpt instances */
+ g_hash_table_iter_init(&iter, ov->unprocessed_opts);
+ if (g_hash_table_iter_next(&iter, NULL, (void **)&any)) {
+ const QemuOpt *first;
+
+ first = g_queue_peek_head(any);
+ error_setg(errp, QERR_INVALID_PARAMETER, first->name);
+ return false;
+ }
+ return true;
+}
+
+
+static void
+opts_end_struct(Visitor *v, void **obj)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ if (--ov->depth > 0) {
+ return;
+ }
+
+ g_hash_table_destroy(ov->unprocessed_opts);
+ ov->unprocessed_opts = NULL;
+ if (ov->fake_id_opt) {
+ g_free(ov->fake_id_opt->name);
+ g_free(ov->fake_id_opt->str);
+ g_free(ov->fake_id_opt);
+ }
+ ov->fake_id_opt = NULL;
+}
+
+
+static GQueue *
+lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp)
+{
+ GQueue *list;
+
+ list = g_hash_table_lookup(ov->unprocessed_opts, name);
+ if (!list) {
+ error_setg(errp, QERR_MISSING_PARAMETER, name);
+ }
+ return list;
+}
+
+
+static bool
+opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size,
+ Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ /* we can't traverse a list in a list */
+ assert(ov->list_mode == LM_NONE);
+ /* we don't support visits without a list */
+ assert(list);
+ ov->repeated_opts = lookup_distinct(ov, name, errp);
+ if (!ov->repeated_opts) {
+ *list = NULL;
+ return false;
+ }
+ ov->list_mode = LM_IN_PROGRESS;
+ *list = g_malloc0(size);
+ return true;
+}
+
+
+static GenericList *
+opts_next_list(Visitor *v, GenericList *tail, size_t size)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ switch (ov->list_mode) {
+ case LM_TRAVERSED:
+ return NULL;
+ case LM_SIGNED_INTERVAL:
+ case LM_UNSIGNED_INTERVAL:
+ if (ov->list_mode == LM_SIGNED_INTERVAL) {
+ if (ov->range_next.s < ov->range_limit.s) {
+ ++ov->range_next.s;
+ break;
+ }
+ } else if (ov->range_next.u < ov->range_limit.u) {
+ ++ov->range_next.u;
+ break;
+ }
+ ov->list_mode = LM_IN_PROGRESS;
+ /* range has been completed, fall through in order to pop option */
+
+ case LM_IN_PROGRESS: {
+ const QemuOpt *opt;
+
+ opt = g_queue_pop_head(ov->repeated_opts);
+ if (g_queue_is_empty(ov->repeated_opts)) {
+ g_hash_table_remove(ov->unprocessed_opts, opt->name);
+ ov->repeated_opts = NULL;
+ ov->list_mode = LM_TRAVERSED;
+ return NULL;
+ }
+ break;
+ }
+
+ default:
+ abort();
+ }
+
+ tail->next = g_malloc0(size);
+ return tail->next;
+}
+
+
+static bool
+opts_check_list(Visitor *v, Error **errp)
+{
+ /*
+ * Unvisited list elements will be reported later when checking
+ * whether unvisited struct members remain.
+ */
+ return true;
+}
+
+
+static void
+opts_end_list(Visitor *v, void **obj)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ assert(ov->list_mode == LM_IN_PROGRESS ||
+ ov->list_mode == LM_SIGNED_INTERVAL ||
+ ov->list_mode == LM_UNSIGNED_INTERVAL ||
+ ov->list_mode == LM_TRAVERSED);
+ ov->repeated_opts = NULL;
+ ov->list_mode = LM_NONE;
+}
+
+
+static const QemuOpt *
+lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp)
+{
+ if (ov->list_mode == LM_NONE) {
+ GQueue *list;
+
+ /* the last occurrence of any QemuOpt takes effect when queried by name
+ */
+ list = lookup_distinct(ov, name, errp);
+ return list ? g_queue_peek_tail(list) : NULL;
+ }
+ if (ov->list_mode == LM_TRAVERSED) {
+ error_setg(errp, "Fewer list elements than expected");
+ return NULL;
+ }
+ assert(ov->list_mode == LM_IN_PROGRESS);
+ return g_queue_peek_head(ov->repeated_opts);
+}
+
+
+static void
+processed(OptsVisitor *ov, const char *name)
+{
+ if (ov->list_mode == LM_NONE) {
+ g_hash_table_remove(ov->unprocessed_opts, name);
+ return;
+ }
+ assert(ov->list_mode == LM_IN_PROGRESS);
+ /* do nothing */
+}
+
+
+static bool
+opts_type_str(Visitor *v, const char *name, char **obj, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+
+ opt = lookup_scalar(ov, name, errp);
+ if (!opt) {
+ *obj = NULL;
+ return false;
+ }
+ *obj = g_strdup(opt->str ? opt->str : "");
+ /* Note that we consume a string even if this is called as part of
+ * an enum visit that later fails because the string is not a
+ * valid enum value; this is harmless because tracking what gets
+ * consumed only matters to visit_end_struct() as the final error
+ * check if there were no other failures during the visit. */
+ processed(ov, name);
+ return true;
+}
+
+
+static bool
+opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+
+ opt = lookup_scalar(ov, name, errp);
+ if (!opt) {
+ return false;
+ }
+ if (opt->str) {
+ if (!qapi_bool_parse(opt->name, opt->str, obj, errp)) {
+ return false;
+ }
+ } else {
+ *obj = true;
+ }
+
+ processed(ov, name);
+ return true;
+}
+
+
+static bool
+opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+ const char *str;
+ long long val;
+ char *endptr;
+
+ if (ov->list_mode == LM_SIGNED_INTERVAL) {
+ *obj = ov->range_next.s;
+ return true;
+ }
+
+ opt = lookup_scalar(ov, name, errp);
+ if (!opt) {
+ return false;
+ }
+ str = opt->str ? opt->str : "";
+
+ /* we've gotten past lookup_scalar() */
+ assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS);
+
+ errno = 0;
+ val = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str && INT64_MIN <= val && val <= INT64_MAX) {
+ if (*endptr == '\0') {
+ *obj = val;
+ processed(ov, name);
+ return true;
+ }
+ if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) {
+ long long val2;
+
+ str = endptr + 1;
+ val2 = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str && *endptr == '\0' &&
+ INT64_MIN <= val2 && val2 <= INT64_MAX && val <= val2 &&
+ (val > INT64_MAX - OPTS_VISITOR_RANGE_MAX ||
+ val2 < val + OPTS_VISITOR_RANGE_MAX)) {
+ ov->range_next.s = val;
+ ov->range_limit.s = val2;
+ ov->list_mode = LM_SIGNED_INTERVAL;
+
+ /* as if entering on the top */
+ *obj = ov->range_next.s;
+ return true;
+ }
+ }
+ }
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
+ (ov->list_mode == LM_NONE) ? "an int64 value" :
+ "an int64 value or range");
+ return false;
+}
+
+
+static bool
+opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+ const char *str;
+ unsigned long long val;
+ char *endptr;
+
+ if (ov->list_mode == LM_UNSIGNED_INTERVAL) {
+ *obj = ov->range_next.u;
+ return true;
+ }
+
+ opt = lookup_scalar(ov, name, errp);
+ if (!opt) {
+ return false;
+ }
+ str = opt->str;
+
+ /* we've gotten past lookup_scalar() */
+ assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS);
+
+ if (parse_uint(str, &val, &endptr, 0) == 0 && val <= UINT64_MAX) {
+ if (*endptr == '\0') {
+ *obj = val;
+ processed(ov, name);
+ return true;
+ }
+ if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) {
+ unsigned long long val2;
+
+ str = endptr + 1;
+ if (parse_uint_full(str, &val2, 0) == 0 &&
+ val2 <= UINT64_MAX && val <= val2 &&
+ val2 - val < OPTS_VISITOR_RANGE_MAX) {
+ ov->range_next.u = val;
+ ov->range_limit.u = val2;
+ ov->list_mode = LM_UNSIGNED_INTERVAL;
+
+ /* as if entering on the top */
+ *obj = ov->range_next.u;
+ return true;
+ }
+ }
+ }
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
+ (ov->list_mode == LM_NONE) ? "a uint64 value" :
+ "a uint64 value or range");
+ return false;
+}
+
+
+static bool
+opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
+{
+ OptsVisitor *ov = to_ov(v);
+ const QemuOpt *opt;
+ int err;
+
+ opt = lookup_scalar(ov, name, errp);
+ if (!opt) {
+ return false;
+ }
+
+ err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj);
+ if (err < 0) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
+ "a size value");
+ return false;
+ }
+
+ processed(ov, name);
+ return true;
+}
+
+
+static void
+opts_optional(Visitor *v, const char *name, bool *present)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ /* we only support a single mandatory scalar field in a list node */
+ assert(ov->list_mode == LM_NONE);
+ *present = (lookup_distinct(ov, name, NULL) != NULL);
+}
+
+
+static void
+opts_free(Visitor *v)
+{
+ OptsVisitor *ov = to_ov(v);
+
+ if (ov->unprocessed_opts != NULL) {
+ g_hash_table_destroy(ov->unprocessed_opts);
+ }
+ g_free(ov->fake_id_opt);
+ g_free(ov);
+}
+
+
+Visitor *
+opts_visitor_new(const QemuOpts *opts)
+{
+ OptsVisitor *ov;
+
+ assert(opts);
+ ov = g_malloc0(sizeof *ov);
+
+ ov->visitor.type = VISITOR_INPUT;
+
+ ov->visitor.start_struct = &opts_start_struct;
+ ov->visitor.check_struct = &opts_check_struct;
+ ov->visitor.end_struct = &opts_end_struct;
+
+ ov->visitor.start_list = &opts_start_list;
+ ov->visitor.next_list = &opts_next_list;
+ ov->visitor.check_list = &opts_check_list;
+ ov->visitor.end_list = &opts_end_list;
+
+ ov->visitor.type_int64 = &opts_type_int64;
+ ov->visitor.type_uint64 = &opts_type_uint64;
+ ov->visitor.type_size = &opts_type_size;
+ ov->visitor.type_bool = &opts_type_bool;
+ ov->visitor.type_str = &opts_type_str;
+
+ /* type_number() is not filled in, but this is not the first visitor to
+ * skip some mandatory methods... */
+
+ ov->visitor.optional = &opts_optional;
+ ov->visitor.free = opts_free;
+
+ ov->opts_root = opts;
+
+ return &ov->visitor;
+}
diff --git a/qapi/pci.json b/qapi/pci.json
new file mode 100644
index 000000000..ee7c659fe
--- /dev/null
+++ b/qapi/pci.json
@@ -0,0 +1,316 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+##
+# = PCI
+##
+
+##
+# @PciMemoryRange:
+#
+# A PCI device memory region
+#
+# @base: the starting address (guest physical)
+#
+# @limit: the ending address (guest physical)
+#
+# Since: 0.14
+##
+{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }
+
+##
+# @PciMemoryRegion:
+#
+# Information about a PCI device I/O region.
+#
+# @bar: the index of the Base Address Register for this region
+#
+# @type: - 'io' if the region is a PIO region
+# - 'memory' if the region is a MMIO region
+#
+# @size: memory size
+#
+# @prefetch: if @type is 'memory', true if the memory is prefetchable
+#
+# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit
+#
+# Since: 0.14
+##
+{ 'struct': 'PciMemoryRegion',
+ 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int',
+ '*prefetch': 'bool', '*mem_type_64': 'bool' } }
+
+##
+# @PciBusInfo:
+#
+# Information about a bus of a PCI Bridge device
+#
+# @number: primary bus interface number. This should be the number of the
+# bus the device resides on.
+#
+# @secondary: secondary bus interface number. This is the number of the
+# main bus for the bridge
+#
+# @subordinate: This is the highest number bus that resides below the
+# bridge.
+#
+# @io_range: The PIO range for all devices on this bridge
+#
+# @memory_range: The MMIO range for all devices on this bridge
+#
+# @prefetchable_range: The range of prefetchable MMIO for all devices on
+# this bridge
+#
+# Since: 2.4
+##
+{ 'struct': 'PciBusInfo',
+ 'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int',
+ 'io_range': 'PciMemoryRange',
+ 'memory_range': 'PciMemoryRange',
+ 'prefetchable_range': 'PciMemoryRange' } }
+
+##
+# @PciBridgeInfo:
+#
+# Information about a PCI Bridge device
+#
+# @bus: information about the bus the device resides on
+#
+# @devices: a list of @PciDeviceInfo for each device on this bridge
+#
+# Since: 0.14
+##
+{ 'struct': 'PciBridgeInfo',
+ 'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} }
+
+##
+# @PciDeviceClass:
+#
+# Information about the Class of a PCI device
+#
+# @desc: a string description of the device's class
+#
+# @class: the class code of the device
+#
+# Since: 2.4
+##
+{ 'struct': 'PciDeviceClass',
+ 'data': {'*desc': 'str', 'class': 'int'} }
+
+##
+# @PciDeviceId:
+#
+# Information about the Id of a PCI device
+#
+# @device: the PCI device id
+#
+# @vendor: the PCI vendor id
+#
+# @subsystem: the PCI subsystem id (since 3.1)
+#
+# @subsystem-vendor: the PCI subsystem vendor id (since 3.1)
+#
+# Since: 2.4
+##
+{ 'struct': 'PciDeviceId',
+ 'data': {'device': 'int', 'vendor': 'int', '*subsystem': 'int',
+ '*subsystem-vendor': 'int'} }
+
+##
+# @PciDeviceInfo:
+#
+# Information about a PCI device
+#
+# @bus: the bus number of the device
+#
+# @slot: the slot the device is located in
+#
+# @function: the function of the slot used by the device
+#
+# @class_info: the class of the device
+#
+# @id: the PCI device id
+#
+# @irq: if an IRQ is assigned to the device, the IRQ number
+#
+# @irq_pin: the IRQ pin, zero means no IRQ (since 5.1)
+#
+# @qdev_id: the device name of the PCI device
+#
+# @pci_bridge: if the device is a PCI bridge, the bridge information
+#
+# @regions: a list of the PCI I/O regions associated with the device
+#
+# Notes: the contents of @class_info.desc are not stable and should only be
+# treated as informational.
+#
+# Since: 0.14
+##
+{ 'struct': 'PciDeviceInfo',
+ 'data': {'bus': 'int', 'slot': 'int', 'function': 'int',
+ 'class_info': 'PciDeviceClass', 'id': 'PciDeviceId',
+ '*irq': 'int', 'irq_pin': 'int', 'qdev_id': 'str',
+ '*pci_bridge': 'PciBridgeInfo', 'regions': ['PciMemoryRegion'] }}
+
+##
+# @PciInfo:
+#
+# Information about a PCI bus
+#
+# @bus: the bus index
+#
+# @devices: a list of devices on this bus
+#
+# Since: 0.14
+##
+{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }
+
+##
+# @query-pci:
+#
+# Return information about the PCI bus topology of the guest.
+#
+# Returns: a list of @PciInfo for each PCI bus. Each bus is
+# represented by a json-object, which has a key with a json-array of
+# all PCI devices attached to it. Each device is represented by a
+# json-object.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-pci" }
+# <- { "return": [
+# {
+# "bus": 0,
+# "devices": [
+# {
+# "bus": 0,
+# "qdev_id": "",
+# "slot": 0,
+# "class_info": {
+# "class": 1536,
+# "desc": "Host bridge"
+# },
+# "id": {
+# "device": 32902,
+# "vendor": 4663
+# },
+# "function": 0,
+# "regions": [
+# ]
+# },
+# {
+# "bus": 0,
+# "qdev_id": "",
+# "slot": 1,
+# "class_info": {
+# "class": 1537,
+# "desc": "ISA bridge"
+# },
+# "id": {
+# "device": 32902,
+# "vendor": 28672
+# },
+# "function": 0,
+# "regions": [
+# ]
+# },
+# {
+# "bus": 0,
+# "qdev_id": "",
+# "slot": 1,
+# "class_info": {
+# "class": 257,
+# "desc": "IDE controller"
+# },
+# "id": {
+# "device": 32902,
+# "vendor": 28688
+# },
+# "function": 1,
+# "regions": [
+# {
+# "bar": 4,
+# "size": 16,
+# "address": 49152,
+# "type": "io"
+# }
+# ]
+# },
+# {
+# "bus": 0,
+# "qdev_id": "",
+# "slot": 2,
+# "class_info": {
+# "class": 768,
+# "desc": "VGA controller"
+# },
+# "id": {
+# "device": 4115,
+# "vendor": 184
+# },
+# "function": 0,
+# "regions": [
+# {
+# "prefetch": true,
+# "mem_type_64": false,
+# "bar": 0,
+# "size": 33554432,
+# "address": 4026531840,
+# "type": "memory"
+# },
+# {
+# "prefetch": false,
+# "mem_type_64": false,
+# "bar": 1,
+# "size": 4096,
+# "address": 4060086272,
+# "type": "memory"
+# },
+# {
+# "prefetch": false,
+# "mem_type_64": false,
+# "bar": 6,
+# "size": 65536,
+# "address": -1,
+# "type": "memory"
+# }
+# ]
+# },
+# {
+# "bus": 0,
+# "qdev_id": "",
+# "irq": 11,
+# "slot": 4,
+# "class_info": {
+# "class": 1280,
+# "desc": "RAM controller"
+# },
+# "id": {
+# "device": 6900,
+# "vendor": 4098
+# },
+# "function": 0,
+# "regions": [
+# {
+# "bar": 0,
+# "size": 32,
+# "address": 49280,
+# "type": "io"
+# }
+# ]
+# }
+# ]
+# }
+# ]
+# }
+#
+# Note: This example has been shortened as the real response is too long.
+#
+##
+{ 'command': 'query-pci', 'returns': ['PciInfo'] }
diff --git a/qapi/pragma.json b/qapi/pragma.json
new file mode 100644
index 000000000..3bc0335d1
--- /dev/null
+++ b/qapi/pragma.json
@@ -0,0 +1,64 @@
+{ 'pragma': { 'doc-required': true } }
+
+# Whitelists to permit QAPI rule violations; think twice before you
+# add to them!
+{ 'pragma': {
+ # Commands allowed to return a non-dictionary:
+ 'command-name-exceptions': [
+ 'add_client',
+ 'block_resize',
+ 'block_set_io_throttle',
+ 'client_migrate_info',
+ 'device_add',
+ 'device_del',
+ 'expire_password',
+ 'migrate_cancel',
+ 'netdev_add',
+ 'netdev_del',
+ 'qmp_capabilities',
+ 'set_link',
+ 'set_password',
+ 'system_powerdown',
+ 'system_reset',
+ 'system_wakeup' ],
+ 'command-returns-exceptions': [
+ 'human-monitor-command',
+ 'qom-get',
+ 'query-tpm-models',
+ 'query-tpm-types',
+ 'ringbuf-read' ],
+ # Externally visible types whose member names may use uppercase
+ 'member-name-exceptions': [ # visible in:
+ 'ACPISlotType', # query-acpi-ospm-status
+ 'AcpiTableOptions', # -acpitable
+ 'BlkdebugEvent', # blockdev-add, -blockdev
+ 'BlkdebugSetStateOptions', # blockdev-add, -blockdev
+ 'BlockDeviceInfo', # query-block
+ 'BlockDeviceStats', # query-blockstats
+ 'BlockDeviceTimedStats', # query-blockstats
+ 'BlockIOThrottle', # block_set_io_throttle
+ 'BlockInfo', # query-block
+ 'BlockdevAioOptions', # blockdev-add, -blockdev
+ 'BlockdevDriver', # blockdev-add, query-blockstats, ...
+ 'BlockdevVmdkAdapterType', # blockdev-create (to match VMDK spec)
+ 'BlockdevVmdkSubformat', # blockdev-create (to match VMDK spec)
+ 'ColoCompareProperties', # object_add, -object
+ 'FilterMirrorProperties', # object_add, -object
+ 'FilterRedirectorProperties', # object_add, -object
+ 'FilterRewriterProperties', # object_add, -object
+ 'InputLinuxProperties', # object_add, -object
+ 'NetdevTapOptions', # netdev_add, query-netdev, -netdev
+ 'ObjectType', # object-add, -object
+ 'PCIELinkSpeed', # internal only
+ 'PciBusInfo', # query-pci
+ 'PciDeviceInfo', # query-pci
+ 'PciMemoryRegion', # query-pci
+ 'QKeyCode', # send-key, input-sent-event
+ 'QapiErrorClass', # QMP error replies
+ 'SshHostKeyCheckMode', # blockdev-add, -blockdev
+ 'SysEmuTarget', # query-cpu-fast, query-target
+ 'UuidInfo', # query-uuid
+ 'VncClientInfo', # query-vnc, query-vnc-servers, ...
+ 'X86CPURegister32' # qom-get of x86 CPU properties
+ # feature-words, filtered-features
+ ] } }
diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c
new file mode 100644
index 000000000..c45c5caa3
--- /dev/null
+++ b/qapi/qapi-clone-visitor.c
@@ -0,0 +1,204 @@
+/*
+ * Copy one QAPI object to another
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qnull.h"
+
+struct QapiCloneVisitor {
+ Visitor visitor;
+ size_t depth;
+};
+
+static QapiCloneVisitor *to_qcv(Visitor *v)
+{
+ return container_of(v, QapiCloneVisitor, visitor);
+}
+
+static bool qapi_clone_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ if (!obj) {
+ assert(qcv->depth);
+ /* Only possible when visiting an alternate's object
+ * branch. Nothing further to do here, since the earlier
+ * visit_start_alternate() already copied memory. */
+ return true;
+ }
+
+ *obj = g_memdup(*obj, size);
+ qcv->depth++;
+ return true;
+}
+
+static void qapi_clone_end(Visitor *v, void **obj)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ if (obj) {
+ qcv->depth--;
+ }
+}
+
+static bool qapi_clone_start_list(Visitor *v, const char *name,
+ GenericList **listp, size_t size,
+ Error **errp)
+{
+ return qapi_clone_start_struct(v, name, (void **)listp, size, errp);
+}
+
+static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /* Unshare the tail of the list cloned by g_memdup() */
+ tail->next = g_memdup(tail->next, size);
+ return tail->next;
+}
+
+static bool qapi_clone_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ Error **errp)
+{
+ return qapi_clone_start_struct(v, name, (void **)obj, size, errp);
+}
+
+static bool qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /* Value was already cloned by g_memdup() */
+ return true;
+}
+
+static bool qapi_clone_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /* Value was already cloned by g_memdup() */
+ return true;
+}
+
+static bool qapi_clone_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /* Value was already cloned by g_memdup() */
+ return true;
+}
+
+static bool qapi_clone_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /*
+ * Pointer was already cloned by g_memdup; create fresh copy.
+ * Note that as long as qobject-output-visitor accepts NULL instead of
+ * "", then we must do likewise. However, we want to obey the
+ * input visitor semantics of never producing NULL when the empty
+ * string is intended.
+ */
+ *obj = g_strdup(*obj ?: "");
+ return true;
+}
+
+static bool qapi_clone_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ /* Value was already cloned by g_memdup() */
+ return true;
+}
+
+static bool qapi_clone_type_null(Visitor *v, const char *name, QNull **obj,
+ Error **errp)
+{
+ QapiCloneVisitor *qcv = to_qcv(v);
+
+ assert(qcv->depth);
+ *obj = qnull();
+ return true;
+}
+
+static void qapi_clone_free(Visitor *v)
+{
+ g_free(v);
+}
+
+static Visitor *qapi_clone_visitor_new(void)
+{
+ QapiCloneVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_CLONE;
+ v->visitor.start_struct = qapi_clone_start_struct;
+ v->visitor.end_struct = qapi_clone_end;
+ v->visitor.start_list = qapi_clone_start_list;
+ v->visitor.next_list = qapi_clone_next_list;
+ v->visitor.end_list = qapi_clone_end;
+ v->visitor.start_alternate = qapi_clone_start_alternate;
+ v->visitor.end_alternate = qapi_clone_end;
+ v->visitor.type_int64 = qapi_clone_type_int64;
+ v->visitor.type_uint64 = qapi_clone_type_uint64;
+ v->visitor.type_bool = qapi_clone_type_bool;
+ v->visitor.type_str = qapi_clone_type_str;
+ v->visitor.type_number = qapi_clone_type_number;
+ v->visitor.type_null = qapi_clone_type_null;
+ v->visitor.free = qapi_clone_free;
+
+ return &v->visitor;
+}
+
+void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *,
+ void **, Error **))
+{
+ Visitor *v;
+ void *dst = (void *) src; /* Cast away const */
+
+ if (!src) {
+ return NULL;
+ }
+
+ v = qapi_clone_visitor_new();
+ visit_type(v, NULL, &dst, &error_abort);
+ visit_free(v);
+ return dst;
+}
+
+void qapi_clone_members(void *dst, const void *src, size_t sz,
+ bool (*visit_type_members)(Visitor *, void *,
+ Error **))
+{
+ Visitor *v;
+
+ v = qapi_clone_visitor_new();
+ memcpy(dst, src, sz);
+ to_qcv(v)->depth++;
+ visit_type_members(v, dst, &error_abort);
+ visit_free(v);
+}
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
new file mode 100644
index 000000000..ef283f296
--- /dev/null
+++ b/qapi/qapi-dealloc-visitor.c
@@ -0,0 +1,143 @@
+/*
+ * Dealloc Visitor
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/dealloc-visitor.h"
+#include "qapi/qmp/qnull.h"
+#include "qapi/visitor-impl.h"
+
+struct QapiDeallocVisitor
+{
+ Visitor visitor;
+};
+
+static bool qapi_dealloc_start_struct(Visitor *v, const char *name, void **obj,
+ size_t unused, Error **errp)
+{
+ return true;
+}
+
+static void qapi_dealloc_end_struct(Visitor *v, void **obj)
+{
+ if (obj) {
+ g_free(*obj);
+ }
+}
+
+static void qapi_dealloc_end_alternate(Visitor *v, void **obj)
+{
+ if (obj) {
+ g_free(*obj);
+ }
+}
+
+static bool qapi_dealloc_start_list(Visitor *v, const char *name,
+ GenericList **list, size_t size,
+ Error **errp)
+{
+ return true;
+}
+
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ GenericList *next = tail->next;
+ g_free(tail);
+ return next;
+}
+
+static void qapi_dealloc_end_list(Visitor *v, void **obj)
+{
+}
+
+static bool qapi_dealloc_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ if (obj) {
+ g_free(*obj);
+ }
+ return true;
+}
+
+static bool qapi_dealloc_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ return true;
+}
+
+static bool qapi_dealloc_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ return true;
+}
+
+static bool qapi_dealloc_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ return true;
+}
+
+static bool qapi_dealloc_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ return true;
+}
+
+static bool qapi_dealloc_type_anything(Visitor *v, const char *name,
+ QObject **obj, Error **errp)
+{
+ if (obj) {
+ qobject_unref(*obj);
+ }
+ return true;
+}
+
+static bool qapi_dealloc_type_null(Visitor *v, const char *name,
+ QNull **obj, Error **errp)
+{
+ if (obj) {
+ qobject_unref(*obj);
+ }
+ return true;
+}
+
+static void qapi_dealloc_free(Visitor *v)
+{
+ g_free(container_of(v, QapiDeallocVisitor, visitor));
+}
+
+Visitor *qapi_dealloc_visitor_new(void)
+{
+ QapiDeallocVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_DEALLOC;
+ v->visitor.start_struct = qapi_dealloc_start_struct;
+ v->visitor.end_struct = qapi_dealloc_end_struct;
+ v->visitor.end_alternate = qapi_dealloc_end_alternate;
+ v->visitor.start_list = qapi_dealloc_start_list;
+ v->visitor.next_list = qapi_dealloc_next_list;
+ v->visitor.end_list = qapi_dealloc_end_list;
+ v->visitor.type_int64 = qapi_dealloc_type_int64;
+ v->visitor.type_uint64 = qapi_dealloc_type_uint64;
+ v->visitor.type_bool = qapi_dealloc_type_bool;
+ v->visitor.type_str = qapi_dealloc_type_str;
+ v->visitor.type_number = qapi_dealloc_type_number;
+ v->visitor.type_any = qapi_dealloc_type_anything;
+ v->visitor.type_null = qapi_dealloc_type_null;
+ v->visitor.free = qapi_dealloc_free;
+
+ return &v->visitor;
+}
diff --git a/qapi/qapi-forward-visitor.c b/qapi/qapi-forward-visitor.c
new file mode 100644
index 000000000..4ea7e0bec
--- /dev/null
+++ b/qapi/qapi-forward-visitor.c
@@ -0,0 +1,328 @@
+/*
+ * Forward Visitor
+ *
+ * Copyright (C) 2021 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/compat-policy.h"
+#include "qapi/error.h"
+#include "qapi/forward-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qnull.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/cutils.h"
+#include "qemu/option.h"
+
+struct ForwardFieldVisitor {
+ Visitor visitor;
+
+ Visitor *target;
+ char *from;
+ char *to;
+
+ int depth;
+};
+
+static ForwardFieldVisitor *to_ffv(Visitor *v)
+{
+ return container_of(v, ForwardFieldVisitor, visitor);
+}
+
+static bool forward_field_translate_name(ForwardFieldVisitor *v, const char **name,
+ Error **errp)
+{
+ if (v->depth) {
+ return true;
+ }
+ if (g_str_equal(*name, v->from)) {
+ *name = v->to;
+ return true;
+ }
+ error_setg(errp, QERR_MISSING_PARAMETER, *name);
+ return false;
+}
+
+static bool forward_field_check_struct(Visitor *v, Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ return visit_check_struct(ffv->target, errp);
+}
+
+static bool forward_field_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ if (!visit_start_struct(ffv->target, name, obj, size, errp)) {
+ return false;
+ }
+ ffv->depth++;
+ return true;
+}
+
+static void forward_field_end_struct(Visitor *v, void **obj)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ assert(ffv->depth);
+ ffv->depth--;
+ visit_end_struct(ffv->target, obj);
+}
+
+static bool forward_field_start_list(Visitor *v, const char *name,
+ GenericList **list, size_t size,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ ffv->depth++;
+ return visit_start_list(ffv->target, name, list, size, errp);
+}
+
+static GenericList *forward_field_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ assert(ffv->depth);
+ return visit_next_list(ffv->target, tail, size);
+}
+
+static bool forward_field_check_list(Visitor *v, Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ assert(ffv->depth);
+ return visit_check_list(ffv->target, errp);
+}
+
+static void forward_field_end_list(Visitor *v, void **obj)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ assert(ffv->depth);
+ ffv->depth--;
+ visit_end_list(ffv->target, obj);
+}
+
+static bool forward_field_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ /*
+ * The name passed to start_alternate is used also in the visit_type_* calls
+ * that retrieve the alternate's content; so, do not increase depth here.
+ */
+ return visit_start_alternate(ffv->target, name, obj, size, errp);
+}
+
+static void forward_field_end_alternate(Visitor *v, void **obj)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ visit_end_alternate(ffv->target, obj);
+}
+
+static bool forward_field_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_int64(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_uint64(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_bool(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_str(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_size(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_number(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_any(Visitor *v, const char *name, QObject **obj,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_any(ffv->target, name, obj, errp);
+}
+
+static bool forward_field_type_null(Visitor *v, const char *name,
+ QNull **obj, Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return false;
+ }
+ return visit_type_null(ffv->target, name, obj, errp);
+}
+
+static void forward_field_optional(Visitor *v, const char *name, bool *present)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, NULL)) {
+ *present = false;
+ return;
+ }
+ visit_optional(ffv->target, name, present);
+}
+
+static bool forward_field_policy_reject(Visitor *v, const char *name,
+ unsigned special_features,
+ Error **errp)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, errp)) {
+ return true;
+ }
+ return visit_policy_reject(ffv->target, name, special_features, errp);
+}
+
+static bool forward_field_policy_skip(Visitor *v, const char *name,
+ unsigned special_features)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ if (!forward_field_translate_name(ffv, &name, NULL)) {
+ return true;
+ }
+ return visit_policy_skip(ffv->target, name, special_features);
+}
+
+static void forward_field_complete(Visitor *v, void *opaque)
+{
+ /*
+ * Do nothing, the complete method will be called in due time
+ * on the target visitor.
+ */
+}
+
+static void forward_field_free(Visitor *v)
+{
+ ForwardFieldVisitor *ffv = to_ffv(v);
+
+ g_free(ffv->from);
+ g_free(ffv->to);
+ g_free(ffv);
+}
+
+Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to)
+{
+ ForwardFieldVisitor *v = g_new0(ForwardFieldVisitor, 1);
+
+ /*
+ * Clone and dealloc visitors don't use a name for the toplevel
+ * visit, so they make no sense here.
+ */
+ assert(target->type == VISITOR_OUTPUT || target->type == VISITOR_INPUT);
+
+ v->visitor.type = target->type;
+ v->visitor.start_struct = forward_field_start_struct;
+ v->visitor.check_struct = forward_field_check_struct;
+ v->visitor.end_struct = forward_field_end_struct;
+ v->visitor.start_list = forward_field_start_list;
+ v->visitor.next_list = forward_field_next_list;
+ v->visitor.check_list = forward_field_check_list;
+ v->visitor.end_list = forward_field_end_list;
+ v->visitor.start_alternate = forward_field_start_alternate;
+ v->visitor.end_alternate = forward_field_end_alternate;
+ v->visitor.type_int64 = forward_field_type_int64;
+ v->visitor.type_uint64 = forward_field_type_uint64;
+ v->visitor.type_size = forward_field_type_size;
+ v->visitor.type_bool = forward_field_type_bool;
+ v->visitor.type_str = forward_field_type_str;
+ v->visitor.type_number = forward_field_type_number;
+ v->visitor.type_any = forward_field_type_any;
+ v->visitor.type_null = forward_field_type_null;
+ v->visitor.optional = forward_field_optional;
+ v->visitor.policy_reject = forward_field_policy_reject;
+ v->visitor.policy_skip = forward_field_policy_skip;
+ v->visitor.complete = forward_field_complete;
+ v->visitor.free = forward_field_free;
+
+ v->target = target;
+ v->from = g_strdup(from);
+ v->to = g_strdup(to);
+
+ return &v->visitor;
+}
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
new file mode 100644
index 000000000..4912b9744
--- /dev/null
+++ b/qapi/qapi-schema.json
@@ -0,0 +1,95 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+##
+# = Introduction
+#
+# This document describes all commands currently supported by QMP.
+#
+# Most of the time their usage is exactly the same as in the user Monitor, this
+# means that any other document which also describe commands (the manpage,
+# QEMU's manual, etc) can and should be consulted.
+#
+# QMP has two types of commands: regular and query commands. Regular commands
+# usually change the Virtual Machine's state someway, while query commands just
+# return information. The sections below are divided accordingly.
+#
+# It's important to observe that all communication examples are formatted in
+# a reader-friendly way, so that they're easier to understand. However, in real
+# protocol usage, they're emitted as a single line.
+#
+# Also, the following notation is used to denote data flow:
+#
+# Example:
+#
+# ::
+#
+# -> data issued by the Client
+# <- Server data response
+#
+# Please, refer to the QMP specification (docs/interop/qmp-spec.txt) for
+# detailed information on the Server command and response formats.
+#
+# = Stability Considerations
+#
+# The current QMP command set (described in this file) may be useful for a
+# number of use cases, however it's limited and several commands have bad
+# defined semantics, specially with regard to command completion.
+#
+# These problems are going to be solved incrementally in the next QEMU releases
+# and we're going to establish a deprecation policy for badly defined commands.
+#
+# If you're planning to adopt QMP, please observe the following:
+#
+# 1. The deprecation policy will take effect and be documented soon, please
+# check the documentation of each used command as soon as a new release of
+# QEMU is available
+#
+# 2. DO NOT rely on anything which is not explicit documented
+#
+# 3. Errors, in special, are not documented. Applications should NOT check
+# for specific errors classes or data (it's strongly recommended to only
+# check for the "error" key)
+#
+##
+
+{ 'include': 'pragma.json' }
+
+# Documentation generated with qapi-gen.py is in source order, with
+# included sub-schemas inserted at the first include directive
+# (subsequent include directives have no effect). To get a sane and
+# stable order, it's best to include each sub-schema just once, or
+# include it first right here.
+
+{ 'include': 'error.json' }
+{ 'include': 'common.json' }
+{ 'include': 'sockets.json' }
+{ 'include': 'run-state.json' }
+{ 'include': 'crypto.json' }
+{ 'include': 'block.json' }
+{ 'include': 'block-export.json' }
+{ 'include': 'char.json' }
+{ 'include': 'dump.json' }
+{ 'include': 'job.json' }
+{ 'include': 'net.json' }
+{ 'include': 'rdma.json' }
+{ 'include': 'rocker.json' }
+{ 'include': 'tpm.json' }
+{ 'include': 'ui.json' }
+{ 'include': 'authz.json' }
+{ 'include': 'migration.json' }
+{ 'include': 'transaction.json' }
+{ 'include': 'trace.json' }
+{ 'include': 'compat.json' }
+{ 'include': 'control.json' }
+{ 'include': 'introspect.json' }
+{ 'include': 'qom.json' }
+{ 'include': 'qdev.json' }
+{ 'include': 'machine.json' }
+{ 'include': 'machine-target.json' }
+{ 'include': 'replay.json' }
+{ 'include': 'yank.json' }
+{ 'include': 'misc.json' }
+{ 'include': 'misc-target.json' }
+{ 'include': 'audio.json' }
+{ 'include': 'acpi.json' }
+{ 'include': 'pci.json' }
diff --git a/qapi/qapi-type-helpers.c b/qapi/qapi-type-helpers.c
new file mode 100644
index 000000000..f76b34f64
--- /dev/null
+++ b/qapi/qapi-type-helpers.c
@@ -0,0 +1,23 @@
+/*
+ * QAPI common helper functions
+ *
+ * This file provides helper functions related to types defined
+ * in the QAPI schema.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/type-helpers.h"
+
+HumanReadableText *human_readable_text_from_str(GString *str)
+{
+ HumanReadableText *ret = g_new0(HumanReadableText, 1);
+
+ ret->human_readable_text = g_steal_pointer(&str->str);
+
+ return ret;
+}
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
new file mode 100644
index 000000000..fda704453
--- /dev/null
+++ b/qapi/qapi-util.c
@@ -0,0 +1,154 @@
+/*
+ * QAPI util functions
+ *
+ * Authors:
+ * Hu Tao <hutao@cn.fujitsu.com>
+ * Peter Lieven <pl@kamp.de>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/compat-policy.h"
+#include "qapi/error.h"
+#include "qemu/ctype.h"
+#include "qapi/qmp/qerror.h"
+
+CompatPolicy compat_policy;
+
+static bool compat_policy_input_ok1(const char *adjective,
+ CompatPolicyInput policy,
+ ErrorClass error_class,
+ const char *kind, const char *name,
+ Error **errp)
+{
+ switch (policy) {
+ case COMPAT_POLICY_INPUT_ACCEPT:
+ return true;
+ case COMPAT_POLICY_INPUT_REJECT:
+ error_set(errp, error_class, "%s %s %s disabled by policy",
+ adjective, kind, name);
+ return false;
+ case COMPAT_POLICY_INPUT_CRASH:
+ default:
+ abort();
+ }
+}
+
+bool compat_policy_input_ok(unsigned special_features,
+ const CompatPolicy *policy,
+ ErrorClass error_class,
+ const char *kind, const char *name,
+ Error **errp)
+{
+ if ((special_features & 1u << QAPI_DEPRECATED)
+ && !compat_policy_input_ok1("Deprecated",
+ policy->deprecated_input,
+ error_class, kind, name, errp)) {
+ return false;
+ }
+ if ((special_features & (1u << QAPI_UNSTABLE))
+ && !compat_policy_input_ok1("Unstable",
+ policy->unstable_input,
+ error_class, kind, name, errp)) {
+ return false;
+ }
+ return true;
+}
+
+const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
+{
+ assert(val >= 0 && val < lookup->size);
+
+ return lookup->array[val];
+}
+
+int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
+ int def, Error **errp)
+{
+ int i;
+
+ if (!buf) {
+ return def;
+ }
+
+ for (i = 0; i < lookup->size; i++) {
+ if (!strcmp(buf, lookup->array[i])) {
+ return i;
+ }
+ }
+
+ error_setg(errp, "invalid parameter value: %s", buf);
+ return def;
+}
+
+bool qapi_bool_parse(const char *name, const char *value, bool *obj, Error **errp)
+{
+ if (g_str_equal(value, "on") ||
+ g_str_equal(value, "yes") ||
+ g_str_equal(value, "true") ||
+ g_str_equal(value, "y")) {
+ *obj = true;
+ return true;
+ }
+ if (g_str_equal(value, "off") ||
+ g_str_equal(value, "no") ||
+ g_str_equal(value, "false") ||
+ g_str_equal(value, "n")) {
+ *obj = false;
+ return true;
+ }
+
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
+ "'on' or 'off'");
+ return false;
+}
+
+/*
+ * Parse a valid QAPI name from @str.
+ * A valid name consists of letters, digits, hyphen and underscore.
+ * It may be prefixed by __RFQDN_ (downstream extension), where RFQDN
+ * may contain only letters, digits, hyphen and period.
+ * The special exception for enumeration names is not implemented.
+ * See docs/devel/qapi-code-gen.txt for more on QAPI naming rules.
+ * Keep this consistent with scripts/qapi.py!
+ * If @complete, the parse fails unless it consumes @str completely.
+ * Return its length on success, -1 on failure.
+ */
+int parse_qapi_name(const char *str, bool complete)
+{
+ const char *p = str;
+
+ if (*p == '_') { /* Downstream __RFQDN_ */
+ p++;
+ if (*p != '_') {
+ return -1;
+ }
+ while (*++p) {
+ if (!qemu_isalnum(*p) && *p != '-' && *p != '.') {
+ break;
+ }
+ }
+
+ if (*p != '_') {
+ return -1;
+ }
+ p++;
+ }
+
+ if (!qemu_isalpha(*p)) {
+ return -1;
+ }
+ while (*++p) {
+ if (!qemu_isalnum(*p) && *p != '-' && *p != '_') {
+ break;
+ }
+ }
+
+ if (complete && *p) {
+ return -1;
+ }
+ return p - str;
+}
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
new file mode 100644
index 000000000..6c13510a2
--- /dev/null
+++ b/qapi/qapi-visit-core.c
@@ -0,0 +1,444 @@
+/*
+ * Core Definitions for QAPI Visitor Classes
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/compat-policy.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/visitor.h"
+#include "qapi/visitor-impl.h"
+#include "trace.h"
+
+/* Zero-initialization must result in default policy */
+QEMU_BUILD_BUG_ON(COMPAT_POLICY_INPUT_ACCEPT || COMPAT_POLICY_OUTPUT_ACCEPT);
+
+
+void visit_complete(Visitor *v, void *opaque)
+{
+ assert(v->type != VISITOR_OUTPUT || v->complete);
+ trace_visit_complete(v, opaque);
+ if (v->complete) {
+ v->complete(v, opaque);
+ }
+}
+
+void visit_free(Visitor *v)
+{
+ trace_visit_free(v);
+ if (v) {
+ v->free(v);
+ }
+}
+
+bool visit_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ bool ok;
+
+ trace_visit_start_struct(v, name, obj, size);
+ if (obj) {
+ assert(size);
+ assert(!(v->type & VISITOR_OUTPUT) || *obj);
+ }
+ ok = v->start_struct(v, name, obj, size, errp);
+ if (obj && (v->type & VISITOR_INPUT)) {
+ assert(ok != !*obj);
+ }
+ return ok;
+}
+
+bool visit_check_struct(Visitor *v, Error **errp)
+{
+ trace_visit_check_struct(v);
+ return v->check_struct ? v->check_struct(v, errp) : true;
+}
+
+void visit_end_struct(Visitor *v, void **obj)
+{
+ trace_visit_end_struct(v, obj);
+ v->end_struct(v, obj);
+}
+
+bool visit_start_list(Visitor *v, const char *name, GenericList **list,
+ size_t size, Error **errp)
+{
+ bool ok;
+
+ assert(!list || size >= sizeof(GenericList));
+ trace_visit_start_list(v, name, list, size);
+ ok = v->start_list(v, name, list, size, errp);
+ if (list && (v->type & VISITOR_INPUT)) {
+ assert(ok || !*list);
+ }
+ return ok;
+}
+
+GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
+{
+ assert(tail && size >= sizeof(GenericList));
+ trace_visit_next_list(v, tail, size);
+ return v->next_list(v, tail, size);
+}
+
+bool visit_check_list(Visitor *v, Error **errp)
+{
+ trace_visit_check_list(v);
+ return v->check_list ? v->check_list(v, errp) : true;
+}
+
+void visit_end_list(Visitor *v, void **obj)
+{
+ trace_visit_end_list(v, obj);
+ v->end_list(v, obj);
+}
+
+bool visit_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ Error **errp)
+{
+ bool ok;
+
+ assert(obj && size >= sizeof(GenericAlternate));
+ assert(!(v->type & VISITOR_OUTPUT) || *obj);
+ trace_visit_start_alternate(v, name, obj, size);
+ if (!v->start_alternate) {
+ assert(!(v->type & VISITOR_INPUT));
+ return true;
+ }
+ ok = v->start_alternate(v, name, obj, size, errp);
+ if (v->type & VISITOR_INPUT) {
+ assert(ok != !*obj);
+ }
+ return ok;
+}
+
+void visit_end_alternate(Visitor *v, void **obj)
+{
+ trace_visit_end_alternate(v, obj);
+ if (v->end_alternate) {
+ v->end_alternate(v, obj);
+ }
+}
+
+bool visit_optional(Visitor *v, const char *name, bool *present)
+{
+ trace_visit_optional(v, name, present);
+ if (v->optional) {
+ v->optional(v, name, present);
+ }
+ return *present;
+}
+
+bool visit_policy_reject(Visitor *v, const char *name,
+ unsigned special_features, Error **errp)
+{
+ trace_visit_policy_reject(v, name);
+ if (v->policy_reject) {
+ return v->policy_reject(v, name, special_features, errp);
+ }
+ return false;
+}
+
+bool visit_policy_skip(Visitor *v, const char *name,
+ unsigned special_features)
+{
+ trace_visit_policy_skip(v, name);
+ if (v->policy_skip) {
+ return v->policy_skip(v, name, special_features);
+ }
+ return false;
+}
+
+void visit_set_policy(Visitor *v, CompatPolicy *policy)
+{
+ v->compat_policy = *policy;
+}
+
+bool visit_is_input(Visitor *v)
+{
+ return v->type == VISITOR_INPUT;
+}
+
+bool visit_is_dealloc(Visitor *v)
+{
+ return v->type == VISITOR_DEALLOC;
+}
+
+bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
+{
+ assert(obj);
+ trace_visit_type_int(v, name, obj);
+ return v->type_int64(v, name, obj, errp);
+}
+
+static bool visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
+ uint64_t max, const char *type, Error **errp)
+{
+ uint64_t value = *obj;
+
+ assert(v->type == VISITOR_INPUT || value <= max);
+
+ if (!v->type_uint64(v, name, &value, errp)) {
+ return false;
+ }
+ if (value > max) {
+ assert(v->type == VISITOR_INPUT);
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", type);
+ return false;
+ }
+ *obj = value;
+ return true;
+}
+
+bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
+ Error **errp)
+{
+ uint64_t value;
+ bool ok;
+
+ trace_visit_type_uint8(v, name, obj);
+ value = *obj;
+ ok = visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
+ Error **errp)
+{
+ uint64_t value;
+ bool ok;
+
+ trace_visit_type_uint16(v, name, obj);
+ value = *obj;
+ ok = visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
+ Error **errp)
+{
+ uint64_t value;
+ bool ok;
+
+ trace_visit_type_uint32(v, name, obj);
+ value = *obj;
+ ok = visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ assert(obj);
+ trace_visit_type_uint64(v, name, obj);
+ return v->type_uint64(v, name, obj, errp);
+}
+
+static bool visit_type_intN(Visitor *v, int64_t *obj, const char *name,
+ int64_t min, int64_t max, const char *type,
+ Error **errp)
+{
+ int64_t value = *obj;
+
+ assert(v->type == VISITOR_INPUT || (value >= min && value <= max));
+
+ if (!v->type_int64(v, name, &value, errp)) {
+ return false;
+ }
+ if (value < min || value > max) {
+ assert(v->type == VISITOR_INPUT);
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", type);
+ return false;
+ }
+ *obj = value;
+ return true;
+}
+
+bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
+{
+ int64_t value;
+ bool ok;
+
+ trace_visit_type_int8(v, name, obj);
+ value = *obj;
+ ok = visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_int16(Visitor *v, const char *name, int16_t *obj,
+ Error **errp)
+{
+ int64_t value;
+ bool ok;
+
+ trace_visit_type_int16(v, name, obj);
+ value = *obj;
+ ok = visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t",
+ errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_int32(Visitor *v, const char *name, int32_t *obj,
+ Error **errp)
+{
+ int64_t value;
+ bool ok;
+
+ trace_visit_type_int32(v, name, obj);
+ value = *obj;
+ ok = visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t",
+ errp);
+ *obj = value;
+ return ok;
+}
+
+bool visit_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ assert(obj);
+ trace_visit_type_int64(v, name, obj);
+ return v->type_int64(v, name, obj, errp);
+}
+
+bool visit_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ assert(obj);
+ trace_visit_type_size(v, name, obj);
+ if (v->type_size) {
+ return v->type_size(v, name, obj, errp);
+ }
+ return v->type_uint64(v, name, obj, errp);
+}
+
+bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
+{
+ assert(obj);
+ trace_visit_type_bool(v, name, obj);
+ return v->type_bool(v, name, obj, errp);
+}
+
+bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
+{
+ bool ok;
+
+ assert(obj);
+ /* TODO: Fix callers to not pass NULL when they mean "", so that we
+ * can enable:
+ assert(!(v->type & VISITOR_OUTPUT) || *obj);
+ */
+ trace_visit_type_str(v, name, obj);
+ ok = v->type_str(v, name, obj, errp);
+ if (v->type & VISITOR_INPUT) {
+ assert(ok != !*obj);
+ }
+ return ok;
+}
+
+bool visit_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ assert(obj);
+ trace_visit_type_number(v, name, obj);
+ return v->type_number(v, name, obj, errp);
+}
+
+bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
+{
+ bool ok;
+
+ assert(obj);
+ assert(v->type != VISITOR_OUTPUT || *obj);
+ trace_visit_type_any(v, name, obj);
+ ok = v->type_any(v, name, obj, errp);
+ if (v->type == VISITOR_INPUT) {
+ assert(ok != !*obj);
+ }
+ return ok;
+}
+
+bool visit_type_null(Visitor *v, const char *name, QNull **obj,
+ Error **errp)
+{
+ trace_visit_type_null(v, name, obj);
+ return v->type_null(v, name, obj, errp);
+}
+
+static bool output_type_enum(Visitor *v, const char *name, int *obj,
+ const QEnumLookup *lookup, Error **errp)
+{
+ int value = *obj;
+ char *enum_str;
+
+ enum_str = (char *)qapi_enum_lookup(lookup, value);
+ return visit_type_str(v, name, &enum_str, errp);
+}
+
+static bool input_type_enum(Visitor *v, const char *name, int *obj,
+ const QEnumLookup *lookup, Error **errp)
+{
+ int64_t value;
+ g_autofree char *enum_str = NULL;
+
+ if (!visit_type_str(v, name, &enum_str, errp)) {
+ return false;
+ }
+
+ value = qapi_enum_parse(lookup, enum_str, -1, NULL);
+ if (value < 0) {
+ error_setg(errp, "Parameter '%s' does not accept value '%s'",
+ name ? name : "null", enum_str);
+ return false;
+ }
+
+ if (lookup->special_features
+ && !compat_policy_input_ok(lookup->special_features[value],
+ &v->compat_policy,
+ ERROR_CLASS_GENERIC_ERROR,
+ "value", enum_str, errp)) {
+ return false;
+ }
+
+ *obj = value;
+ return true;
+}
+
+bool visit_type_enum(Visitor *v, const char *name, int *obj,
+ const QEnumLookup *lookup, Error **errp)
+{
+ assert(obj && lookup);
+ trace_visit_type_enum(v, name, obj);
+ switch (v->type) {
+ case VISITOR_INPUT:
+ return input_type_enum(v, name, obj, lookup, errp);
+ case VISITOR_OUTPUT:
+ return output_type_enum(v, name, obj, lookup, errp);
+ case VISITOR_CLONE:
+ /* nothing further to do, scalar value was already copied by
+ * g_memdup() during visit_start_*() */
+ return true;
+ case VISITOR_DEALLOC:
+ /* nothing to deallocate for a scalar */
+ return true;
+ default:
+ abort();
+ }
+}
diff --git a/qapi/qdev.json b/qapi/qdev.json
new file mode 100644
index 000000000..69656b14d
--- /dev/null
+++ b/qapi/qdev.json
@@ -0,0 +1,158 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Device infrastructure (qdev)
+##
+
+{ 'include': 'qom.json' }
+
+##
+# @device-list-properties:
+#
+# List properties associated with a device.
+#
+# @typename: the type name of a device
+#
+# Returns: a list of ObjectPropertyInfo describing a devices properties
+#
+# Note: objects can create properties at runtime, for example to describe
+# links between different devices and/or objects. These properties
+# are not included in the output of this command.
+#
+# Since: 1.2
+##
+{ 'command': 'device-list-properties',
+ 'data': { 'typename': 'str'},
+ 'returns': [ 'ObjectPropertyInfo' ] }
+
+##
+# @device_add:
+#
+# Add a device.
+#
+# @driver: the name of the new device's driver
+#
+# @bus: the device's parent bus (device tree path)
+#
+# @id: the device's ID, must be unique
+#
+# Features:
+# @json-cli: If present, the "-device" command line option supports JSON
+# syntax with a structure identical to the arguments of this
+# command.
+#
+# Notes:
+#
+# Additional arguments depend on the type.
+#
+# 1. For detailed information about this command, please refer to the
+# 'docs/qdev-device-use.txt' file.
+#
+# 2. It's possible to list device properties by running QEMU with the
+# "-device DEVICE,help" command-line argument, where DEVICE is the
+# device's name
+#
+# Example:
+#
+# -> { "execute": "device_add",
+# "arguments": { "driver": "e1000", "id": "net1",
+# "bus": "pci.0",
+# "mac": "52:54:00:12:34:56" } }
+# <- { "return": {} }
+#
+# TODO: This command effectively bypasses QAPI completely due to its
+# "additional arguments" business. It shouldn't have been added to
+# the schema in this form. It should be qapified properly, or
+# replaced by a properly qapified command.
+#
+# Since: 0.13
+##
+{ 'command': 'device_add',
+ 'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
+ 'gen': false, # so we can get the additional arguments
+ 'features': ['json-cli'] }
+
+##
+# @device_del:
+#
+# Remove a device from a guest
+#
+# @id: the device's ID or QOM path
+#
+# Returns: Nothing on success
+# If @id is not a valid device, DeviceNotFound
+#
+# Notes: When this command completes, the device may not be removed from the
+# guest. Hot removal is an operation that requires guest cooperation.
+# This command merely requests that the guest begin the hot removal
+# process. Completion of the device removal process is signaled with a
+# DEVICE_DELETED event. Guest reset will automatically complete removal
+# for all devices. If a guest-side error in the hot removal process is
+# detected, the device will not be removed and a DEVICE_UNPLUG_GUEST_ERROR
+# event is sent. Some errors cannot be detected.
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "device_del",
+# "arguments": { "id": "net1" } }
+# <- { "return": {} }
+#
+# -> { "execute": "device_del",
+# "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'device_del', 'data': {'id': 'str'} }
+
+##
+# @DEVICE_DELETED:
+#
+# Emitted whenever the device removal completion is acknowledged by the guest.
+# At this point, it's safe to reuse the specified device ID. Device removal can
+# be initiated by the guest or by HMP/QMP commands.
+#
+# @device: the device's ID if it has one
+#
+# @path: the device's QOM path
+#
+# Since: 1.5
+#
+# Example:
+#
+# <- { "event": "DEVICE_DELETED",
+# "data": { "device": "virtio-net-pci-0",
+# "path": "/machine/peripheral/virtio-net-pci-0" },
+# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'DEVICE_DELETED',
+ 'data': { '*device': 'str', 'path': 'str' } }
+
+##
+# @DEVICE_UNPLUG_GUEST_ERROR:
+#
+# Emitted when a device hot unplug fails due to a guest reported error.
+#
+# @device: the device's ID if it has one
+#
+# @path: the device's QOM path
+#
+# Since: 6.2
+#
+# Example:
+#
+# <- { "event": "DEVICE_UNPLUG_GUEST_ERROR"
+# "data": { "device": "core1",
+# "path": "/machine/peripheral/core1" },
+# },
+# "timestamp": { "seconds": 1615570772, "microseconds": 202844 } }
+#
+##
+{ 'event': 'DEVICE_UNPLUG_GUEST_ERROR',
+ 'data': { '*device': 'str', 'path': 'str' } }
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
new file mode 100644
index 000000000..d378bccac
--- /dev/null
+++ b/qapi/qmp-dispatch.c
@@ -0,0 +1,275 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "block/aio.h"
+#include "qapi/compat-policy.h"
+#include "qapi/error.h"
+#include "qapi/qmp/dispatch.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
+#include "sysemu/runstate.h"
+#include "qapi/qmp/qbool.h"
+#include "qemu/coroutine.h"
+#include "qemu/main-loop.h"
+
+Visitor *qobject_input_visitor_new_qmp(QObject *obj)
+{
+ Visitor *v = qobject_input_visitor_new(obj);
+
+ visit_set_policy(v, &compat_policy);
+ return v;
+}
+
+Visitor *qobject_output_visitor_new_qmp(QObject **result)
+{
+ Visitor *v = qobject_output_visitor_new(result);
+
+ visit_set_policy(v, &compat_policy);
+ return v;
+}
+
+static QDict *qmp_dispatch_check_obj(QDict *dict, bool allow_oob,
+ Error **errp)
+{
+ const char *exec_key = NULL;
+ const QDictEntry *ent;
+ const char *arg_name;
+ const QObject *arg_obj;
+
+ for (ent = qdict_first(dict); ent;
+ ent = qdict_next(dict, ent)) {
+ arg_name = qdict_entry_key(ent);
+ arg_obj = qdict_entry_value(ent);
+
+ if (!strcmp(arg_name, "execute")
+ || (!strcmp(arg_name, "exec-oob") && allow_oob)) {
+ if (qobject_type(arg_obj) != QTYPE_QSTRING) {
+ error_setg(errp, "QMP input member '%s' must be a string",
+ arg_name);
+ return NULL;
+ }
+ if (exec_key) {
+ error_setg(errp, "QMP input member '%s' clashes with '%s'",
+ arg_name, exec_key);
+ return NULL;
+ }
+ exec_key = arg_name;
+ } else if (!strcmp(arg_name, "arguments")) {
+ if (qobject_type(arg_obj) != QTYPE_QDICT) {
+ error_setg(errp,
+ "QMP input member 'arguments' must be an object");
+ return NULL;
+ }
+ } else if (!strcmp(arg_name, "id")) {
+ continue;
+ } else {
+ error_setg(errp, "QMP input member '%s' is unexpected",
+ arg_name);
+ return NULL;
+ }
+ }
+
+ if (!exec_key) {
+ error_setg(errp, "QMP input lacks member 'execute'");
+ return NULL;
+ }
+
+ return dict;
+}
+
+QDict *qmp_error_response(Error *err)
+{
+ QDict *rsp;
+
+ rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }",
+ QapiErrorClass_str(error_get_class(err)),
+ error_get_pretty(err));
+ error_free(err);
+ return rsp;
+}
+
+/*
+ * Does @qdict look like a command to be run out-of-band?
+ */
+bool qmp_is_oob(const QDict *dict)
+{
+ return qdict_haskey(dict, "exec-oob")
+ && !qdict_haskey(dict, "execute");
+}
+
+typedef struct QmpDispatchBH {
+ const QmpCommand *cmd;
+ Monitor *cur_mon;
+ QDict *args;
+ QObject **ret;
+ Error **errp;
+ Coroutine *co;
+} QmpDispatchBH;
+
+static void do_qmp_dispatch_bh(void *opaque)
+{
+ QmpDispatchBH *data = opaque;
+
+ assert(monitor_cur() == NULL);
+ monitor_set_cur(qemu_coroutine_self(), data->cur_mon);
+ data->cmd->fn(data->args, data->ret, data->errp);
+ monitor_set_cur(qemu_coroutine_self(), NULL);
+ aio_co_wake(data->co);
+}
+
+/*
+ * Runs outside of coroutine context for OOB commands, but in coroutine
+ * context for everything else.
+ */
+QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
+ bool allow_oob, Monitor *cur_mon)
+{
+ Error *err = NULL;
+ bool oob;
+ const char *command;
+ QDict *args;
+ const QmpCommand *cmd;
+ QDict *dict;
+ QObject *id;
+ QObject *ret = NULL;
+ QDict *rsp = NULL;
+
+ dict = qobject_to(QDict, request);
+ if (!dict) {
+ id = NULL;
+ error_setg(&err, "QMP input must be a JSON object");
+ goto out;
+ }
+
+ id = qdict_get(dict, "id");
+
+ if (!qmp_dispatch_check_obj(dict, allow_oob, &err)) {
+ goto out;
+ }
+
+ command = qdict_get_try_str(dict, "execute");
+ oob = false;
+ if (!command) {
+ assert(allow_oob);
+ command = qdict_get_str(dict, "exec-oob");
+ oob = true;
+ }
+ cmd = qmp_find_command(cmds, command);
+ if (cmd == NULL) {
+ error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "The command %s has not been found", command);
+ goto out;
+ }
+ if (!compat_policy_input_ok(cmd->special_features, &compat_policy,
+ ERROR_CLASS_COMMAND_NOT_FOUND,
+ "command", command, &err)) {
+ goto out;
+ }
+ if (!cmd->enabled) {
+ error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "Command %s has been disabled%s%s",
+ command,
+ cmd->disable_reason ? ": " : "",
+ cmd->disable_reason ?: "");
+ goto out;
+ }
+ if (oob && !(cmd->options & QCO_ALLOW_OOB)) {
+ error_setg(&err, "The command %s does not support OOB",
+ command);
+ goto out;
+ }
+
+ if (!qmp_command_available(cmd, &err)) {
+ goto out;
+ }
+
+ if (!qdict_haskey(dict, "arguments")) {
+ args = qdict_new();
+ } else {
+ args = qdict_get_qdict(dict, "arguments");
+ qobject_ref(args);
+ }
+
+ assert(!(oob && qemu_in_coroutine()));
+ assert(monitor_cur() == NULL);
+ if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
+ monitor_set_cur(qemu_coroutine_self(), cur_mon);
+ cmd->fn(args, &ret, &err);
+ monitor_set_cur(qemu_coroutine_self(), NULL);
+ } else {
+ /*
+ * Actual context doesn't match the one the command needs.
+ *
+ * Case 1: we are in coroutine context, but command does not
+ * have QCO_COROUTINE. We need to drop out of coroutine
+ * context for executing it.
+ *
+ * Case 2: we are outside coroutine context, but command has
+ * QCO_COROUTINE. Can't actually happen, because we get here
+ * outside coroutine context only when executing a command
+ * out of band, and OOB commands never have QCO_COROUTINE.
+ */
+ assert(!oob && qemu_in_coroutine() && !(cmd->options & QCO_COROUTINE));
+
+ QmpDispatchBH data = {
+ .cur_mon = cur_mon,
+ .cmd = cmd,
+ .args = args,
+ .ret = &ret,
+ .errp = &err,
+ .co = qemu_coroutine_self(),
+ };
+ aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh,
+ &data);
+ qemu_coroutine_yield();
+ }
+ qobject_unref(args);
+ if (err) {
+ /* or assert(!ret) after reviewing all handlers: */
+ qobject_unref(ret);
+ goto out;
+ }
+
+ if (cmd->options & QCO_NO_SUCCESS_RESP) {
+ g_assert(!ret);
+ return NULL;
+ } else if (!ret) {
+ /*
+ * When the command's schema has no 'returns', cmd->fn()
+ * leaves @ret null. The QMP spec calls for an empty object
+ * then; supply it.
+ */
+ ret = QOBJECT(qdict_new());
+ }
+
+ rsp = qdict_new();
+ qdict_put_obj(rsp, "return", ret);
+
+out:
+ if (err) {
+ assert(!rsp);
+ rsp = qmp_error_response(err);
+ }
+
+ assert(rsp);
+
+ if (id) {
+ qdict_put_obj(rsp, "id", qobject_ref(id));
+ }
+
+ return rsp;
+}
diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
new file mode 100644
index 000000000..19d3cd003
--- /dev/null
+++ b/qapi/qmp-event.c
@@ -0,0 +1,45 @@
+/*
+ * QMP Event related
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ * Wenchao Xia <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/qmp-event.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qjson.h"
+
+static void timestamp_put(QDict *qdict)
+{
+ int err;
+ QDict *ts;
+ qemu_timeval tv;
+
+ err = qemu_gettimeofday(&tv);
+ /* Put -1 to indicate failure of getting host time */
+ ts = qdict_from_jsonf_nofail("{ 'seconds': %lld, 'microseconds': %lld }",
+ err < 0 ? -1LL : (long long)tv.tv_sec,
+ err < 0 ? -1LL : (long long)tv.tv_usec);
+ qdict_put(qdict, "timestamp", ts);
+}
+
+/*
+ * Build a QDict, then fill event name and time stamp, caller should free the
+ * QDict after usage.
+ */
+QDict *qmp_event_build_dict(const char *event_name)
+{
+ QDict *dict = qdict_new();
+ qdict_put_str(dict, "event", event_name);
+ timestamp_put(dict);
+ return dict;
+}
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
new file mode 100644
index 000000000..485bc5e6f
--- /dev/null
+++ b/qapi/qmp-registry.c
@@ -0,0 +1,95 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Michael Roth <mdroth@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/qmp/dispatch.h"
+
+void qmp_register_command(QmpCommandList *cmds, const char *name,
+ QmpCommandFunc *fn, QmpCommandOptions options,
+ unsigned special_features)
+{
+ QmpCommand *cmd = g_malloc0(sizeof(*cmd));
+
+ /* QCO_COROUTINE and QCO_ALLOW_OOB are incompatible for now */
+ assert(!((options & QCO_COROUTINE) && (options & QCO_ALLOW_OOB)));
+
+ cmd->name = name;
+ cmd->fn = fn;
+ cmd->enabled = true;
+ cmd->options = options;
+ cmd->special_features = special_features;
+ QTAILQ_INSERT_TAIL(cmds, cmd, node);
+}
+
+const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name)
+{
+ QmpCommand *cmd;
+
+ QTAILQ_FOREACH(cmd, cmds, node) {
+ if (strcmp(cmd->name, name) == 0) {
+ return cmd;
+ }
+ }
+ return NULL;
+}
+
+static void qmp_toggle_command(QmpCommandList *cmds, const char *name,
+ bool enabled, const char *disable_reason)
+{
+ QmpCommand *cmd;
+
+ QTAILQ_FOREACH(cmd, cmds, node) {
+ if (strcmp(cmd->name, name) == 0) {
+ cmd->enabled = enabled;
+ cmd->disable_reason = disable_reason;
+ return;
+ }
+ }
+}
+
+void qmp_disable_command(QmpCommandList *cmds, const char *name,
+ const char *disable_reason)
+{
+ qmp_toggle_command(cmds, name, false, disable_reason);
+}
+
+void qmp_enable_command(QmpCommandList *cmds, const char *name)
+{
+ qmp_toggle_command(cmds, name, true, NULL);
+}
+
+bool qmp_command_is_enabled(const QmpCommand *cmd)
+{
+ return cmd->enabled;
+}
+
+const char *qmp_command_name(const QmpCommand *cmd)
+{
+ return cmd->name;
+}
+
+bool qmp_has_success_response(const QmpCommand *cmd)
+{
+ return !(cmd->options & QCO_NO_SUCCESS_RESP);
+}
+
+void qmp_for_each_command(const QmpCommandList *cmds, qmp_cmd_callback_fn fn,
+ void *opaque)
+{
+ const QmpCommand *cmd;
+
+ QTAILQ_FOREACH(cmd, cmds, node) {
+ fn(cmd, opaque);
+ }
+}
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
new file mode 100644
index 000000000..f0b4c7ca9
--- /dev/null
+++ b/qapi/qobject-input-visitor.c
@@ -0,0 +1,776 @@
+/*
+ * Input Visitor
+ *
+ * Copyright (C) 2012-2017 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <math.h>
+#include "qapi/compat-policy.h"
+#include "qapi/error.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qnull.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/cutils.h"
+#include "qemu/option.h"
+
+typedef struct StackObject {
+ const char *name; /* Name of @obj in its parent, if any */
+ QObject *obj; /* QDict or QList being visited */
+ void *qapi; /* sanity check that caller uses same pointer */
+
+ GHashTable *h; /* If @obj is QDict: unvisited keys */
+ const QListEntry *entry; /* If @obj is QList: unvisited tail */
+ unsigned index; /* If @obj is QList: list index of @entry */
+
+ QSLIST_ENTRY(StackObject) node; /* parent */
+} StackObject;
+
+struct QObjectInputVisitor {
+ Visitor visitor;
+
+ /* Root of visit at visitor creation. */
+ QObject *root;
+ bool keyval; /* Assume @root made with keyval_parse() */
+
+ /* Stack of objects being visited (all entries will be either
+ * QDict or QList). */
+ QSLIST_HEAD(, StackObject) stack;
+
+ GString *errname; /* Accumulator for full_name() */
+};
+
+static QObjectInputVisitor *to_qiv(Visitor *v)
+{
+ return container_of(v, QObjectInputVisitor, visitor);
+}
+
+/*
+ * Find the full name of something @qiv is currently visiting.
+ * @qiv is visiting something named @name in the stack of containers
+ * @qiv->stack.
+ * If @n is zero, return its full name.
+ * If @n is positive, return the full name of the @n-th container
+ * counting from the top. The stack of containers must have at least
+ * @n elements.
+ * The returned string is valid until the next full_name_nth(@v) or
+ * destruction of @v.
+ */
+static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name,
+ int n)
+{
+ StackObject *so;
+ char buf[32];
+
+ if (qiv->errname) {
+ g_string_truncate(qiv->errname, 0);
+ } else {
+ qiv->errname = g_string_new("");
+ }
+
+ QSLIST_FOREACH(so , &qiv->stack, node) {
+ if (n) {
+ n--;
+ } else if (qobject_type(so->obj) == QTYPE_QDICT) {
+ g_string_prepend(qiv->errname, name ?: "<anonymous>");
+ g_string_prepend_c(qiv->errname, '.');
+ } else {
+ snprintf(buf, sizeof(buf),
+ qiv->keyval ? ".%u" : "[%u]",
+ so->index);
+ g_string_prepend(qiv->errname, buf);
+ }
+ name = so->name;
+ }
+ assert(!n);
+
+ if (name) {
+ g_string_prepend(qiv->errname, name);
+ } else if (qiv->errname->str[0] == '.') {
+ g_string_erase(qiv->errname, 0, 1);
+ } else if (!qiv->errname->str[0]) {
+ return "<anonymous>";
+ }
+
+ return qiv->errname->str;
+}
+
+static const char *full_name(QObjectInputVisitor *qiv, const char *name)
+{
+ return full_name_nth(qiv, name, 0);
+}
+
+static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
+ const char *name,
+ bool consume)
+{
+ StackObject *tos;
+ QObject *qobj;
+ QObject *ret;
+
+ if (QSLIST_EMPTY(&qiv->stack)) {
+ /* Starting at root, name is ignored. */
+ assert(qiv->root);
+ return qiv->root;
+ }
+
+ /* We are in a container; find the next element. */
+ tos = QSLIST_FIRST(&qiv->stack);
+ qobj = tos->obj;
+ assert(qobj);
+
+ if (qobject_type(qobj) == QTYPE_QDICT) {
+ assert(name);
+ ret = qdict_get(qobject_to(QDict, qobj), name);
+ if (tos->h && consume && ret) {
+ bool removed = g_hash_table_remove(tos->h, name);
+ assert(removed);
+ }
+ } else {
+ assert(qobject_type(qobj) == QTYPE_QLIST);
+ assert(!name);
+ if (tos->entry) {
+ ret = qlist_entry_obj(tos->entry);
+ if (consume) {
+ tos->entry = qlist_next(tos->entry);
+ }
+ } else {
+ ret = NULL;
+ }
+ if (consume) {
+ tos->index++;
+ }
+ }
+
+ return ret;
+}
+
+static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
+ const char *name,
+ bool consume, Error **errp)
+{
+ QObject *obj = qobject_input_try_get_object(qiv, name, consume);
+
+ if (!obj) {
+ error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name));
+ }
+ return obj;
+}
+
+static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
+ const char *name,
+ Error **errp)
+{
+ QObject *qobj;
+ QString *qstr;
+
+ qobj = qobject_input_get_object(qiv, name, true, errp);
+ if (!qobj) {
+ return NULL;
+ }
+
+ qstr = qobject_to(QString, qobj);
+ if (!qstr) {
+ switch (qobject_type(qobj)) {
+ case QTYPE_QDICT:
+ case QTYPE_QLIST:
+ error_setg(errp, "Parameters '%s.*' are unexpected",
+ full_name(qiv, name));
+ return NULL;
+ default:
+ /* Non-string scalar (should this be an assertion?) */
+ error_setg(errp, "Internal error: parameter %s invalid",
+ full_name(qiv, name));
+ return NULL;
+ }
+ }
+
+ return qstring_get_str(qstr);
+}
+
+static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
+ const char *name,
+ QObject *obj, void *qapi)
+{
+ GHashTable *h;
+ StackObject *tos = g_new0(StackObject, 1);
+ QDict *qdict = qobject_to(QDict, obj);
+ QList *qlist = qobject_to(QList, obj);
+ const QDictEntry *entry;
+
+ assert(obj);
+ tos->name = name;
+ tos->obj = obj;
+ tos->qapi = qapi;
+
+ if (qdict) {
+ h = g_hash_table_new(g_str_hash, g_str_equal);
+ for (entry = qdict_first(qdict);
+ entry;
+ entry = qdict_next(qdict, entry)) {
+ g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL);
+ }
+ tos->h = h;
+ } else {
+ assert(qlist);
+ tos->entry = qlist_first(qlist);
+ tos->index = -1;
+ }
+
+ QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
+ return tos->entry;
+}
+
+
+static bool qobject_input_check_struct(Visitor *v, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+ GHashTableIter iter;
+ const char *key;
+
+ assert(tos && !tos->entry);
+
+ g_hash_table_iter_init(&iter, tos->h);
+ if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
+ error_setg(errp, "Parameter '%s' is unexpected",
+ full_name(qiv, key));
+ return false;
+ }
+ return true;
+}
+
+static void qobject_input_stack_object_free(StackObject *tos)
+{
+ if (tos->h) {
+ g_hash_table_unref(tos->h);
+ }
+
+ g_free(tos);
+}
+
+static void qobject_input_pop(Visitor *v, void **obj)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(tos && tos->qapi == obj);
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qobject_input_stack_object_free(tos);
+}
+
+static bool qobject_input_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ if (obj) {
+ *obj = NULL;
+ }
+ if (!qobj) {
+ return false;
+ }
+ if (qobject_type(qobj) != QTYPE_QDICT) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "object");
+ return false;
+ }
+
+ qobject_input_push(qiv, name, qobj, obj);
+
+ if (obj) {
+ *obj = g_malloc0(size);
+ }
+ return true;
+}
+
+static void qobject_input_end_struct(Visitor *v, void **obj)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(qobject_type(tos->obj) == QTYPE_QDICT && tos->h);
+ qobject_input_pop(v, obj);
+}
+
+
+static bool qobject_input_start_list(Visitor *v, const char *name,
+ GenericList **list, size_t size,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ const QListEntry *entry;
+
+ if (list) {
+ *list = NULL;
+ }
+ if (!qobj) {
+ return false;
+ }
+ if (qobject_type(qobj) != QTYPE_QLIST) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "array");
+ return false;
+ }
+
+ entry = qobject_input_push(qiv, name, qobj, list);
+ if (entry && list) {
+ *list = g_malloc0(size);
+ }
+ return true;
+}
+
+static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(tos && qobject_to(QList, tos->obj));
+
+ if (!tos->entry) {
+ return NULL;
+ }
+ tail->next = g_malloc0(size);
+ return tail->next;
+}
+
+static bool qobject_input_check_list(Visitor *v, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(tos && qobject_to(QList, tos->obj));
+
+ if (tos->entry) {
+ error_setg(errp, "Only %u list elements expected in %s",
+ tos->index + 1, full_name_nth(qiv, NULL, 1));
+ return false;
+ }
+ return true;
+}
+
+static void qobject_input_end_list(Visitor *v, void **obj)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(qobject_type(tos->obj) == QTYPE_QLIST && !tos->h);
+ qobject_input_pop(v, obj);
+}
+
+static bool qobject_input_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
+
+ if (!qobj) {
+ *obj = NULL;
+ return false;
+ }
+ *obj = g_malloc0(size);
+ (*obj)->type = qobject_type(qobj);
+ return true;
+}
+
+static bool qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QNum *qnum;
+
+ if (!qobj) {
+ return false;
+ }
+ qnum = qobject_to(QNum, qobj);
+ if (!qnum || !qnum_get_try_int(qnum, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "integer");
+ return false;
+ }
+ return true;
+}
+
+static bool qobject_input_type_int64_keyval(Visitor *v, const char *name,
+ int64_t *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+ if (!str) {
+ return false;
+ }
+
+ if (qemu_strtoi64(str, NULL, 0, obj) < 0) {
+ /* TODO report -ERANGE more nicely */
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ full_name(qiv, name), "integer");
+ return false;
+ }
+ return true;
+}
+
+static bool qobject_input_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QNum *qnum;
+ int64_t val;
+
+ if (!qobj) {
+ return false;
+ }
+ qnum = qobject_to(QNum, qobj);
+ if (!qnum) {
+ goto err;
+ }
+
+ if (qnum_get_try_uint(qnum, obj)) {
+ return true;
+ }
+
+ /* Need to accept negative values for backward compatibility */
+ if (qnum_get_try_int(qnum, &val)) {
+ *obj = val;
+ return true;
+ }
+
+err:
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ full_name(qiv, name), "uint64");
+ return false;
+}
+
+static bool qobject_input_type_uint64_keyval(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+ if (!str) {
+ return false;
+ }
+
+ if (qemu_strtou64(str, NULL, 0, obj) < 0) {
+ /* TODO report -ERANGE more nicely */
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ full_name(qiv, name), "integer");
+ return false;
+ }
+ return true;
+}
+
+static bool qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QBool *qbool;
+
+ if (!qobj) {
+ return false;
+ }
+ qbool = qobject_to(QBool, qobj);
+ if (!qbool) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "boolean");
+ return false;
+ }
+
+ *obj = qbool_get_bool(qbool);
+ return true;
+}
+
+static bool qobject_input_type_bool_keyval(Visitor *v, const char *name,
+ bool *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+ if (!str) {
+ return false;
+ }
+
+ if (!qapi_bool_parse(name, str, obj, NULL)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ full_name(qiv, name), "'on' or 'off'");
+ return false;
+ }
+ return true;
+}
+
+static bool qobject_input_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QString *qstr;
+
+ *obj = NULL;
+ if (!qobj) {
+ return false;
+ }
+ qstr = qobject_to(QString, qobj);
+ if (!qstr) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "string");
+ return false;
+ }
+
+ *obj = g_strdup(qstring_get_str(qstr));
+ return true;
+}
+
+static bool qobject_input_type_str_keyval(Visitor *v, const char *name,
+ char **obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+ *obj = g_strdup(str);
+ return !!str;
+}
+
+static bool qobject_input_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QNum *qnum;
+
+ if (!qobj) {
+ return false;
+ }
+ qnum = qobject_to(QNum, qobj);
+ if (!qnum) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "number");
+ return false;
+ }
+
+ *obj = qnum_get_double(qnum);
+ return true;
+}
+
+static bool qobject_input_type_number_keyval(Visitor *v, const char *name,
+ double *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+ double val;
+
+ if (!str) {
+ return false;
+ }
+
+ if (qemu_strtod_finite(str, NULL, &val)) {
+ /* TODO report -ERANGE more nicely */
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "number");
+ return false;
+ }
+
+ *obj = val;
+ return true;
+}
+
+static bool qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ *obj = NULL;
+ if (!qobj) {
+ return false;
+ }
+
+ *obj = qobject_ref(qobj);
+ return true;
+}
+
+static bool qobject_input_type_null(Visitor *v, const char *name,
+ QNull **obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ *obj = NULL;
+ if (!qobj) {
+ return false;
+ }
+
+ if (qobject_type(qobj) != QTYPE_QNULL) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ full_name(qiv, name), "null");
+ return false;
+ }
+ *obj = qnull();
+ return true;
+}
+
+static bool qobject_input_type_size_keyval(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+ if (!str) {
+ return false;
+ }
+
+ if (qemu_strtosz(str, NULL, obj) < 0) {
+ /* TODO report -ERANGE more nicely */
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ full_name(qiv, name), "size");
+ return false;
+ }
+ return true;
+}
+
+static void qobject_input_optional(Visitor *v, const char *name, bool *present)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_try_get_object(qiv, name, false);
+
+ if (!qobj) {
+ *present = false;
+ return;
+ }
+
+ *present = true;
+}
+
+static bool qobject_input_policy_reject(Visitor *v, const char *name,
+ unsigned special_features,
+ Error **errp)
+{
+ return !compat_policy_input_ok(special_features, &v->compat_policy,
+ ERROR_CLASS_GENERIC_ERROR,
+ "parameter", name, errp);
+}
+
+static void qobject_input_free(Visitor *v)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+
+ while (!QSLIST_EMPTY(&qiv->stack)) {
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qobject_input_stack_object_free(tos);
+ }
+
+ qobject_unref(qiv->root);
+ if (qiv->errname) {
+ g_string_free(qiv->errname, TRUE);
+ }
+ g_free(qiv);
+}
+
+static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj)
+{
+ QObjectInputVisitor *v = g_malloc0(sizeof(*v));
+
+ assert(obj);
+
+ v->visitor.type = VISITOR_INPUT;
+ v->visitor.start_struct = qobject_input_start_struct;
+ v->visitor.check_struct = qobject_input_check_struct;
+ v->visitor.end_struct = qobject_input_end_struct;
+ v->visitor.start_list = qobject_input_start_list;
+ v->visitor.next_list = qobject_input_next_list;
+ v->visitor.check_list = qobject_input_check_list;
+ v->visitor.end_list = qobject_input_end_list;
+ v->visitor.start_alternate = qobject_input_start_alternate;
+ v->visitor.optional = qobject_input_optional;
+ v->visitor.policy_reject = qobject_input_policy_reject;
+ v->visitor.free = qobject_input_free;
+
+ v->root = qobject_ref(obj);
+
+ return v;
+}
+
+Visitor *qobject_input_visitor_new(QObject *obj)
+{
+ QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
+
+ v->visitor.type_int64 = qobject_input_type_int64;
+ v->visitor.type_uint64 = qobject_input_type_uint64;
+ v->visitor.type_bool = qobject_input_type_bool;
+ v->visitor.type_str = qobject_input_type_str;
+ v->visitor.type_number = qobject_input_type_number;
+ v->visitor.type_any = qobject_input_type_any;
+ v->visitor.type_null = qobject_input_type_null;
+
+ return &v->visitor;
+}
+
+Visitor *qobject_input_visitor_new_keyval(QObject *obj)
+{
+ QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
+
+ v->visitor.type_int64 = qobject_input_type_int64_keyval;
+ v->visitor.type_uint64 = qobject_input_type_uint64_keyval;
+ v->visitor.type_bool = qobject_input_type_bool_keyval;
+ v->visitor.type_str = qobject_input_type_str_keyval;
+ v->visitor.type_number = qobject_input_type_number_keyval;
+ v->visitor.type_any = qobject_input_type_any;
+ v->visitor.type_null = qobject_input_type_null;
+ v->visitor.type_size = qobject_input_type_size_keyval;
+ v->keyval = true;
+
+ return &v->visitor;
+}
+
+Visitor *qobject_input_visitor_new_str(const char *str,
+ const char *implied_key,
+ Error **errp)
+{
+ bool is_json = str[0] == '{';
+ QObject *obj;
+ QDict *args;
+ Visitor *v;
+
+ if (is_json) {
+ obj = qobject_from_json(str, errp);
+ if (!obj) {
+ return NULL;
+ }
+ args = qobject_to(QDict, obj);
+ assert(args);
+ v = qobject_input_visitor_new(QOBJECT(args));
+ } else {
+ args = keyval_parse(str, implied_key, NULL, errp);
+ if (!args) {
+ return NULL;
+ }
+ v = qobject_input_visitor_new_keyval(QOBJECT(args));
+ }
+ qobject_unref(args);
+
+ return v;
+}
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
new file mode 100644
index 000000000..74770edd7
--- /dev/null
+++ b/qapi/qobject-output-visitor.c
@@ -0,0 +1,280 @@
+/*
+ * Core Definitions for QAPI/QMP Command Registry
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/compat-policy.h"
+#include "qapi/qobject-output-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qnull.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+
+typedef struct QStackEntry {
+ QObject *value;
+ void *qapi; /* sanity check that caller uses same pointer */
+ QSLIST_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+struct QObjectOutputVisitor {
+ Visitor visitor;
+
+ QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
+ QObject *root; /* Root of the output visit */
+ QObject **result; /* User's storage location for result */
+};
+
+#define qobject_output_add(qov, name, value) \
+ qobject_output_add_obj(qov, name, QOBJECT(value))
+#define qobject_output_push(qov, value, qapi) \
+ qobject_output_push_obj(qov, QOBJECT(value), qapi)
+
+static QObjectOutputVisitor *to_qov(Visitor *v)
+{
+ return container_of(v, QObjectOutputVisitor, visitor);
+}
+
+/* Push @value onto the stack of current QObjects being built */
+static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
+ void *qapi)
+{
+ QStackEntry *e = g_malloc0(sizeof(*e));
+
+ assert(qov->root);
+ assert(value);
+ e->value = value;
+ e->qapi = qapi;
+ QSLIST_INSERT_HEAD(&qov->stack, e, node);
+}
+
+/* Pop a value off the stack of QObjects being built, and return it. */
+static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *value;
+
+ assert(e);
+ assert(e->qapi == qapi);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ value = e->value;
+ assert(value);
+ g_free(e);
+ return value;
+}
+
+/* Add @value to the current QObject being built.
+ * If the stack is visiting a dictionary or list, @value is now owned
+ * by that container. Otherwise, @value is now the root. */
+static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
+ QObject *value)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *cur = e ? e->value : NULL;
+
+ if (!cur) {
+ /* Don't allow reuse of visitor on more than one root */
+ assert(!qov->root);
+ qov->root = value;
+ } else {
+ switch (qobject_type(cur)) {
+ case QTYPE_QDICT:
+ assert(name);
+ qdict_put_obj(qobject_to(QDict, cur), name, value);
+ break;
+ case QTYPE_QLIST:
+ assert(!name);
+ qlist_append_obj(qobject_to(QList, cur), value);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
+static bool qobject_output_start_struct(Visitor *v, const char *name,
+ void **obj, size_t unused, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QDict *dict = qdict_new();
+
+ qobject_output_add(qov, name, dict);
+ qobject_output_push(qov, dict, obj);
+ return true;
+}
+
+static void qobject_output_end_struct(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QDICT);
+}
+
+static bool qobject_output_start_list(Visitor *v, const char *name,
+ GenericList **listp, size_t size,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QList *list = qlist_new();
+
+ qobject_output_add(qov, name, list);
+ qobject_output_push(qov, list, listp);
+ return true;
+}
+
+static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ return tail->next;
+}
+
+static void qobject_output_end_list(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QLIST);
+}
+
+static bool qobject_output_type_int64(Visitor *v, const char *name,
+ int64_t *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qnum_from_int(*obj));
+ return true;
+}
+
+static bool qobject_output_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qnum_from_uint(*obj));
+ return true;
+}
+
+static bool qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qbool_from_bool(*obj));
+ return true;
+}
+
+static bool qobject_output_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ if (*obj) {
+ qobject_output_add(qov, name, qstring_from_str(*obj));
+ } else {
+ qobject_output_add(qov, name, qstring_from_str(""));
+ }
+ return true;
+}
+
+static bool qobject_output_type_number(Visitor *v, const char *name,
+ double *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qnum_from_double(*obj));
+ return true;
+}
+
+static bool qobject_output_type_any(Visitor *v, const char *name,
+ QObject **obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+
+ qobject_output_add_obj(qov, name, qobject_ref(*obj));
+ return true;
+}
+
+static bool qobject_output_type_null(Visitor *v, const char *name,
+ QNull **obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qnull());
+ return true;
+}
+
+static bool qobject_output_policy_skip(Visitor *v, const char *name,
+ unsigned special_features)
+{
+ CompatPolicy *pol = &v->compat_policy;
+
+ return ((special_features & 1u << QAPI_DEPRECATED)
+ && pol->deprecated_output == COMPAT_POLICY_OUTPUT_HIDE)
+ || ((special_features & 1u << QAPI_UNSTABLE)
+ && pol->unstable_output == COMPAT_POLICY_OUTPUT_HIDE);
+}
+
+/* Finish building, and return the root object.
+ * The root object is never null. The caller becomes the object's
+ * owner, and should use qobject_unref() when done with it. */
+static void qobject_output_complete(Visitor *v, void *opaque)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+
+ /* A visit must have occurred, with each start paired with end. */
+ assert(qov->root && QSLIST_EMPTY(&qov->stack));
+ assert(opaque == qov->result);
+
+ *qov->result = qobject_ref(qov->root);
+ qov->result = NULL;
+}
+
+static void qobject_output_free(Visitor *v)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QStackEntry *e;
+
+ while (!QSLIST_EMPTY(&qov->stack)) {
+ e = QSLIST_FIRST(&qov->stack);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ g_free(e);
+ }
+
+ qobject_unref(qov->root);
+ g_free(qov);
+}
+
+Visitor *qobject_output_visitor_new(QObject **result)
+{
+ QObjectOutputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_OUTPUT;
+ v->visitor.start_struct = qobject_output_start_struct;
+ v->visitor.end_struct = qobject_output_end_struct;
+ v->visitor.start_list = qobject_output_start_list;
+ v->visitor.next_list = qobject_output_next_list;
+ v->visitor.end_list = qobject_output_end_list;
+ v->visitor.type_int64 = qobject_output_type_int64;
+ v->visitor.type_uint64 = qobject_output_type_uint64;
+ v->visitor.type_bool = qobject_output_type_bool;
+ v->visitor.type_str = qobject_output_type_str;
+ v->visitor.type_number = qobject_output_type_number;
+ v->visitor.type_any = qobject_output_type_any;
+ v->visitor.type_null = qobject_output_type_null;
+ v->visitor.policy_skip = qobject_output_policy_skip;
+ v->visitor.complete = qobject_output_complete;
+ v->visitor.free = qobject_output_free;
+
+ *result = NULL;
+ v->result = result;
+
+ return &v->visitor;
+}
diff --git a/qapi/qom.json b/qapi/qom.json
new file mode 100644
index 000000000..eeb5395ff
--- /dev/null
+++ b/qapi/qom.json
@@ -0,0 +1,951 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+{ 'include': 'authz.json' }
+{ 'include': 'block-core.json' }
+{ 'include': 'common.json' }
+{ 'include': 'crypto.json' }
+
+##
+# = QEMU Object Model (QOM)
+##
+
+##
+# @ObjectPropertyInfo:
+#
+# @name: the name of the property
+#
+# @type: the type of the property. This will typically come in one of four
+# forms:
+#
+# 1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'.
+# These types are mapped to the appropriate JSON type.
+#
+# 2) A child type in the form 'child<subtype>' where subtype is a qdev
+# device type name. Child properties create the composition tree.
+#
+# 3) A link type in the form 'link<subtype>' where subtype is a qdev
+# device type name. Link properties form the device model graph.
+#
+# @description: if specified, the description of the property.
+#
+# @default-value: the default value, if any (since 5.0)
+#
+# Since: 1.2
+##
+{ 'struct': 'ObjectPropertyInfo',
+ 'data': { 'name': 'str',
+ 'type': 'str',
+ '*description': 'str',
+ '*default-value': 'any' } }
+
+##
+# @qom-list:
+#
+# This command will list any properties of a object given a path in the object
+# model.
+#
+# @path: the path within the object model. See @qom-get for a description of
+# this parameter.
+#
+# Returns: a list of @ObjectPropertyInfo that describe the properties of the
+# object.
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "qom-list",
+# "arguments": { "path": "/chardevs" } }
+# <- { "return": [ { "name": "type", "type": "string" },
+# { "name": "parallel0", "type": "child<chardev-vc>" },
+# { "name": "serial0", "type": "child<chardev-vc>" },
+# { "name": "mon0", "type": "child<chardev-stdio>" } ] }
+#
+##
+{ 'command': 'qom-list',
+ 'data': { 'path': 'str' },
+ 'returns': [ 'ObjectPropertyInfo' ],
+ 'allow-preconfig': true }
+
+##
+# @qom-get:
+#
+# This command will get a property from a object model path and return the
+# value.
+#
+# @path: The path within the object model. There are two forms of supported
+# paths--absolute and partial paths.
+#
+# Absolute paths are derived from the root object and can follow child<>
+# or link<> properties. Since they can follow link<> properties, they
+# can be arbitrarily long. Absolute paths look like absolute filenames
+# and are prefixed with a leading slash.
+#
+# Partial paths look like relative filenames. They do not begin
+# with a prefix. The matching rules for partial paths are subtle but
+# designed to make specifying objects easy. At each level of the
+# composition tree, the partial path is matched as an absolute path.
+# The first match is not returned. At least two matches are searched
+# for. A successful result is only returned if only one match is
+# found. If more than one match is found, a flag is return to
+# indicate that the match was ambiguous.
+#
+# @property: The property name to read
+#
+# Returns: The property value. The type depends on the property
+# type. child<> and link<> properties are returned as #str
+# pathnames. All integer property types (u8, u16, etc) are
+# returned as #int.
+#
+# Since: 1.2
+#
+# Example:
+#
+# 1. Use absolute path
+#
+# -> { "execute": "qom-get",
+# "arguments": { "path": "/machine/unattached/device[0]",
+# "property": "hotplugged" } }
+# <- { "return": false }
+#
+# 2. Use partial path
+#
+# -> { "execute": "qom-get",
+# "arguments": { "path": "unattached/sysbus",
+# "property": "type" } }
+# <- { "return": "System" }
+#
+##
+{ 'command': 'qom-get',
+ 'data': { 'path': 'str', 'property': 'str' },
+ 'returns': 'any',
+ 'allow-preconfig': true }
+
+##
+# @qom-set:
+#
+# This command will set a property from a object model path.
+#
+# @path: see @qom-get for a description of this parameter
+#
+# @property: the property name to set
+#
+# @value: a value who's type is appropriate for the property type. See @qom-get
+# for a description of type mapping.
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "qom-set",
+# "arguments": { "path": "/machine",
+# "property": "graphics",
+# "value": false } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'qom-set',
+ 'data': { 'path': 'str', 'property': 'str', 'value': 'any' },
+ 'allow-preconfig': true }
+
+##
+# @ObjectTypeInfo:
+#
+# This structure describes a search result from @qom-list-types
+#
+# @name: the type name found in the search
+#
+# @abstract: the type is abstract and can't be directly instantiated.
+# Omitted if false. (since 2.10)
+#
+# @parent: Name of parent type, if any (since 2.10)
+#
+# Since: 1.1
+##
+{ 'struct': 'ObjectTypeInfo',
+ 'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } }
+
+##
+# @qom-list-types:
+#
+# This command will return a list of types given search parameters
+#
+# @implements: if specified, only return types that implement this type name
+#
+# @abstract: if true, include abstract types in the results
+#
+# Returns: a list of @ObjectTypeInfo or an empty list if no results are found
+#
+# Since: 1.1
+##
+{ 'command': 'qom-list-types',
+ 'data': { '*implements': 'str', '*abstract': 'bool' },
+ 'returns': [ 'ObjectTypeInfo' ],
+ 'allow-preconfig': true }
+
+##
+# @qom-list-properties:
+#
+# List properties associated with a QOM object.
+#
+# @typename: the type name of an object
+#
+# Note: objects can create properties at runtime, for example to describe
+# links between different devices and/or objects. These properties
+# are not included in the output of this command.
+#
+# Returns: a list of ObjectPropertyInfo describing object properties
+#
+# Since: 2.12
+##
+{ 'command': 'qom-list-properties',
+ 'data': { 'typename': 'str'},
+ 'returns': [ 'ObjectPropertyInfo' ],
+ 'allow-preconfig': true }
+
+##
+# @CanHostSocketcanProperties:
+#
+# Properties for can-host-socketcan objects.
+#
+# @if: interface name of the host system CAN bus to connect to
+#
+# @canbus: object ID of the can-bus object to connect to the host interface
+#
+# Since: 2.12
+##
+{ 'struct': 'CanHostSocketcanProperties',
+ 'data': { 'if': 'str',
+ 'canbus': 'str' } }
+
+##
+# @ColoCompareProperties:
+#
+# Properties for colo-compare objects.
+#
+# @primary_in: name of the character device backend to use for the primary
+# input (incoming packets are redirected to @outdev)
+#
+# @secondary_in: name of the character device backend to use for secondary
+# input (incoming packets are only compared to the input on
+# @primary_in and then dropped)
+#
+# @outdev: name of the character device backend to use for output
+#
+# @iothread: name of the iothread to run in
+#
+# @notify_dev: name of the character device backend to be used to communicate
+# with the remote colo-frame (only for Xen COLO)
+#
+# @compare_timeout: the maximum time to hold a packet from @primary_in for
+# comparison with an incoming packet on @secondary_in in
+# milliseconds (default: 3000)
+#
+# @expired_scan_cycle: the interval at which colo-compare checks whether
+# packets from @primary have timed out, in milliseconds
+# (default: 3000)
+#
+# @max_queue_size: the maximum number of packets to keep in the queue for
+# comparing with incoming packets from @secondary_in. If the
+# queue is full and additional packets are received, the
+# additional packets are dropped. (default: 1024)
+#
+# @vnet_hdr_support: if true, vnet header support is enabled (default: false)
+#
+# Since: 2.8
+##
+{ 'struct': 'ColoCompareProperties',
+ 'data': { 'primary_in': 'str',
+ 'secondary_in': 'str',
+ 'outdev': 'str',
+ 'iothread': 'str',
+ '*notify_dev': 'str',
+ '*compare_timeout': 'uint64',
+ '*expired_scan_cycle': 'uint32',
+ '*max_queue_size': 'uint32',
+ '*vnet_hdr_support': 'bool' } }
+
+##
+# @CryptodevBackendProperties:
+#
+# Properties for cryptodev-backend and cryptodev-backend-builtin objects.
+#
+# @queues: the number of queues for the cryptodev backend. Ignored for
+# cryptodev-backend and must be 1 for cryptodev-backend-builtin.
+# (default: 1)
+#
+# Since: 2.8
+##
+{ 'struct': 'CryptodevBackendProperties',
+ 'data': { '*queues': 'uint32' } }
+
+##
+# @CryptodevVhostUserProperties:
+#
+# Properties for cryptodev-vhost-user objects.
+#
+# @chardev: the name of a Unix domain socket character device that connects to
+# the vhost-user server
+#
+# Since: 2.12
+##
+{ 'struct': 'CryptodevVhostUserProperties',
+ 'base': 'CryptodevBackendProperties',
+ 'data': { 'chardev': 'str' } }
+
+##
+# @DBusVMStateProperties:
+#
+# Properties for dbus-vmstate objects.
+#
+# @addr: the name of the DBus bus to connect to
+#
+# @id-list: a comma separated list of DBus IDs of helpers whose data should be
+# included in the VM state on migration
+#
+# Since: 5.0
+##
+{ 'struct': 'DBusVMStateProperties',
+ 'data': { 'addr': 'str' ,
+ '*id-list': 'str' } }
+
+##
+# @NetfilterInsert:
+#
+# Indicates where to insert a netfilter relative to a given other filter.
+#
+# @before: insert before the specified filter
+#
+# @behind: insert behind the specified filter
+#
+# Since: 5.0
+##
+{ 'enum': 'NetfilterInsert',
+ 'data': [ 'before', 'behind' ] }
+
+##
+# @NetfilterProperties:
+#
+# Properties for objects of classes derived from netfilter.
+#
+# @netdev: id of the network device backend to filter
+#
+# @queue: indicates which queue(s) to filter (default: all)
+#
+# @status: indicates whether the filter is enabled ("on") or disabled ("off")
+# (default: "on")
+#
+# @position: specifies where the filter should be inserted in the filter list.
+# "head" means the filter is inserted at the head of the filter list,
+# before any existing filters.
+# "tail" means the filter is inserted at the tail of the filter list,
+# behind any existing filters (default).
+# "id=<id>" means the filter is inserted before or behind the filter
+# specified by <id>, depending on the @insert property.
+# (default: "tail")
+#
+# @insert: where to insert the filter relative to the filter given in @position.
+# Ignored if @position is "head" or "tail". (default: behind)
+#
+# Since: 2.5
+##
+{ 'struct': 'NetfilterProperties',
+ 'data': { 'netdev': 'str',
+ '*queue': 'NetFilterDirection',
+ '*status': 'str',
+ '*position': 'str',
+ '*insert': 'NetfilterInsert' } }
+
+##
+# @FilterBufferProperties:
+#
+# Properties for filter-buffer objects.
+#
+# @interval: a non-zero interval in microseconds. All packets arriving in the
+# given interval are delayed until the end of the interval.
+#
+# Since: 2.5
+##
+{ 'struct': 'FilterBufferProperties',
+ 'base': 'NetfilterProperties',
+ 'data': { 'interval': 'uint32' } }
+
+##
+# @FilterDumpProperties:
+#
+# Properties for filter-dump objects.
+#
+# @file: the filename where the dumped packets should be stored
+#
+# @maxlen: maximum number of bytes in a packet that are stored (default: 65536)
+#
+# Since: 2.5
+##
+{ 'struct': 'FilterDumpProperties',
+ 'base': 'NetfilterProperties',
+ 'data': { 'file': 'str',
+ '*maxlen': 'uint32' } }
+
+##
+# @FilterMirrorProperties:
+#
+# Properties for filter-mirror objects.
+#
+# @outdev: the name of a character device backend to which all incoming packets
+# are mirrored
+#
+# @vnet_hdr_support: if true, vnet header support is enabled (default: false)
+#
+# Since: 2.6
+##
+{ 'struct': 'FilterMirrorProperties',
+ 'base': 'NetfilterProperties',
+ 'data': { 'outdev': 'str',
+ '*vnet_hdr_support': 'bool' } }
+
+##
+# @FilterRedirectorProperties:
+#
+# Properties for filter-redirector objects.
+#
+# At least one of @indev or @outdev must be present. If both are present, they
+# must not refer to the same character device backend.
+#
+# @indev: the name of a character device backend from which packets are
+# received and redirected to the filtered network device
+#
+# @outdev: the name of a character device backend to which all incoming packets
+# are redirected
+#
+# @vnet_hdr_support: if true, vnet header support is enabled (default: false)
+#
+# Since: 2.6
+##
+{ 'struct': 'FilterRedirectorProperties',
+ 'base': 'NetfilterProperties',
+ 'data': { '*indev': 'str',
+ '*outdev': 'str',
+ '*vnet_hdr_support': 'bool' } }
+
+##
+# @FilterRewriterProperties:
+#
+# Properties for filter-rewriter objects.
+#
+# @vnet_hdr_support: if true, vnet header support is enabled (default: false)
+#
+# Since: 2.8
+##
+{ 'struct': 'FilterRewriterProperties',
+ 'base': 'NetfilterProperties',
+ 'data': { '*vnet_hdr_support': 'bool' } }
+
+##
+# @InputBarrierProperties:
+#
+# Properties for input-barrier objects.
+#
+# @name: the screen name as declared in the screens section of barrier.conf
+#
+# @server: hostname of the Barrier server (default: "localhost")
+#
+# @port: TCP port of the Barrier server (default: "24800")
+#
+# @x-origin: x coordinate of the leftmost pixel on the guest screen
+# (default: "0")
+#
+# @y-origin: y coordinate of the topmost pixel on the guest screen
+# (default: "0")
+#
+# @width: the width of secondary screen in pixels (default: "1920")
+#
+# @height: the height of secondary screen in pixels (default: "1080")
+#
+# Since: 4.2
+##
+{ 'struct': 'InputBarrierProperties',
+ 'data': { 'name': 'str',
+ '*server': 'str',
+ '*port': 'str',
+ '*x-origin': 'str',
+ '*y-origin': 'str',
+ '*width': 'str',
+ '*height': 'str' } }
+
+##
+# @InputLinuxProperties:
+#
+# Properties for input-linux objects.
+#
+# @evdev: the path of the host evdev device to use
+#
+# @grab_all: if true, grab is toggled for all devices (e.g. both keyboard and
+# mouse) instead of just one device (default: false)
+#
+# @repeat: enables auto-repeat events (default: false)
+#
+# @grab-toggle: the key or key combination that toggles device grab
+# (default: ctrl-ctrl)
+#
+# Since: 2.6
+##
+{ 'struct': 'InputLinuxProperties',
+ 'data': { 'evdev': 'str',
+ '*grab_all': 'bool',
+ '*repeat': 'bool',
+ '*grab-toggle': 'GrabToggleKeys' } }
+
+##
+# @IothreadProperties:
+#
+# Properties for iothread objects.
+#
+# @poll-max-ns: the maximum number of nanoseconds to busy wait for events.
+# 0 means polling is disabled (default: 32768 on POSIX hosts,
+# 0 otherwise)
+#
+# @poll-grow: the multiplier used to increase the polling time when the
+# algorithm detects it is missing events due to not polling long
+# enough. 0 selects a default behaviour (default: 0)
+#
+# @poll-shrink: the divisor used to decrease the polling time when the
+# algorithm detects it is spending too long polling without
+# encountering events. 0 selects a default behaviour (default: 0)
+#
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
+# 0 means that the engine will use its default
+# (default:0, since 6.1)
+#
+# Since: 2.0
+##
+{ 'struct': 'IothreadProperties',
+ 'data': { '*poll-max-ns': 'int',
+ '*poll-grow': 'int',
+ '*poll-shrink': 'int',
+ '*aio-max-batch': 'int' } }
+
+##
+# @MemoryBackendProperties:
+#
+# Properties for objects of classes derived from memory-backend.
+#
+# @merge: if true, mark the memory as mergeable (default depends on the machine
+# type)
+#
+# @dump: if true, include the memory in core dumps (default depends on the
+# machine type)
+#
+# @host-nodes: the list of NUMA host nodes to bind the memory to
+#
+# @policy: the NUMA policy (default: 'default')
+#
+# @prealloc: if true, preallocate memory (default: false)
+#
+# @prealloc-threads: number of CPU threads to use for prealloc (default: 1)
+#
+# @share: if false, the memory is private to QEMU; if true, it is shared
+# (default: false)
+#
+# @reserve: if true, reserve swap space (or huge pages) if applicable
+# (default: true) (since 6.1)
+#
+# @size: size of the memory region in bytes
+#
+# @x-use-canonical-path-for-ramblock-id: if true, the canoncial path is used
+# for ramblock-id. Disable this for 4.0
+# machine types or older to allow
+# migration with newer QEMU versions.
+# (default: false generally,
+# but true for machine types <= 4.0)
+#
+# Note: prealloc=true and reserve=false cannot be set at the same time. With
+# reserve=true, the behavior depends on the operating system: for example,
+# Linux will not reserve swap space for shared file mappings --
+# "not applicable". In contrast, reserve=false will bail out if it cannot
+# be configured accordingly.
+#
+# Since: 2.1
+##
+{ 'struct': 'MemoryBackendProperties',
+ 'data': { '*dump': 'bool',
+ '*host-nodes': ['uint16'],
+ '*merge': 'bool',
+ '*policy': 'HostMemPolicy',
+ '*prealloc': 'bool',
+ '*prealloc-threads': 'uint32',
+ '*share': 'bool',
+ '*reserve': 'bool',
+ 'size': 'size',
+ '*x-use-canonical-path-for-ramblock-id': 'bool' } }
+
+##
+# @MemoryBackendFileProperties:
+#
+# Properties for memory-backend-file objects.
+#
+# @align: the base address alignment when QEMU mmap(2)s @mem-path. Some
+# backend stores specified by @mem-path require an alignment different
+# than the default one used by QEMU, e.g. the device DAX /dev/dax0.0
+# requires 2M alignment rather than 4K. In such cases, users can
+# specify the required alignment via this option.
+# 0 selects a default alignment (currently the page size). (default: 0)
+#
+# @discard-data: if true, the file contents can be destroyed when QEMU exits,
+# to avoid unnecessarily flushing data to the backing file. Note
+# that ``discard-data`` is only an optimization, and QEMU might
+# not discard file contents if it aborts unexpectedly or is
+# terminated using SIGKILL. (default: false)
+#
+# @mem-path: the path to either a shared memory or huge page filesystem mount
+#
+# @pmem: specifies whether the backing file specified by @mem-path is in
+# host persistent memory that can be accessed using the SNIA NVM
+# programming model (e.g. Intel NVDIMM).
+#
+# @readonly: if true, the backing file is opened read-only; if false, it is
+# opened read-write. (default: false)
+#
+# Since: 2.1
+##
+{ 'struct': 'MemoryBackendFileProperties',
+ 'base': 'MemoryBackendProperties',
+ 'data': { '*align': 'size',
+ '*discard-data': 'bool',
+ 'mem-path': 'str',
+ '*pmem': { 'type': 'bool', 'if': 'CONFIG_LIBPMEM' },
+ '*readonly': 'bool' } }
+
+##
+# @MemoryBackendMemfdProperties:
+#
+# Properties for memory-backend-memfd objects.
+#
+# The @share boolean option is true by default with memfd.
+#
+# @hugetlb: if true, the file to be created resides in the hugetlbfs filesystem
+# (default: false)
+#
+# @hugetlbsize: the hugetlb page size on systems that support multiple hugetlb
+# page sizes (it must be a power of 2 value supported by the
+# system). 0 selects a default page size. This option is ignored
+# if @hugetlb is false. (default: 0)
+#
+# @seal: if true, create a sealed-file, which will block further resizing of
+# the memory (default: true)
+#
+# Since: 2.12
+##
+{ 'struct': 'MemoryBackendMemfdProperties',
+ 'base': 'MemoryBackendProperties',
+ 'data': { '*hugetlb': 'bool',
+ '*hugetlbsize': 'size',
+ '*seal': 'bool' } }
+
+##
+# @MemoryBackendEpcProperties:
+#
+# Properties for memory-backend-epc objects.
+#
+# The @share boolean option is true by default with epc
+#
+# The @merge boolean option is false by default with epc
+#
+# The @dump boolean option is false by default with epc
+#
+# Since: 6.2
+##
+{ 'struct': 'MemoryBackendEpcProperties',
+ 'base': 'MemoryBackendProperties',
+ 'data': {} }
+
+##
+# @PrManagerHelperProperties:
+#
+# Properties for pr-manager-helper objects.
+#
+# @path: the path to a Unix domain socket for connecting to the external helper
+#
+# Since: 2.11
+##
+{ 'struct': 'PrManagerHelperProperties',
+ 'data': { 'path': 'str' } }
+
+##
+# @QtestProperties:
+#
+# Properties for qtest objects.
+#
+# @chardev: the chardev to be used to receive qtest commands on.
+#
+# @log: the path to a log file
+#
+# Since: 6.0
+##
+{ 'struct': 'QtestProperties',
+ 'data': { 'chardev': 'str',
+ '*log': 'str' } }
+
+##
+# @RemoteObjectProperties:
+#
+# Properties for x-remote-object objects.
+#
+# @fd: file descriptor name previously passed via 'getfd' command
+#
+# @devid: the id of the device to be associated with the file descriptor
+#
+# Since: 6.0
+##
+{ 'struct': 'RemoteObjectProperties',
+ 'data': { 'fd': 'str', 'devid': 'str' } }
+
+##
+# @RngProperties:
+#
+# Properties for objects of classes derived from rng.
+#
+# @opened: if true, the device is opened immediately when applying this option
+# and will probably fail when processing the next option. Don't use;
+# only provided for compatibility. (default: false)
+#
+# Features:
+# @deprecated: Member @opened is deprecated. Setting true doesn't make sense,
+# and false is already the default.
+#
+# Since: 1.3
+##
+{ 'struct': 'RngProperties',
+ 'data': { '*opened': { 'type': 'bool', 'features': ['deprecated'] } } }
+
+##
+# @RngEgdProperties:
+#
+# Properties for rng-egd objects.
+#
+# @chardev: the name of a character device backend that provides the connection
+# to the RNG daemon
+#
+# Since: 1.3
+##
+{ 'struct': 'RngEgdProperties',
+ 'base': 'RngProperties',
+ 'data': { 'chardev': 'str' } }
+
+##
+# @RngRandomProperties:
+#
+# Properties for rng-random objects.
+#
+# @filename: the filename of the device on the host to obtain entropy from
+# (default: "/dev/urandom")
+#
+# Since: 1.3
+##
+{ 'struct': 'RngRandomProperties',
+ 'base': 'RngProperties',
+ 'data': { '*filename': 'str' } }
+
+##
+# @SevGuestProperties:
+#
+# Properties for sev-guest objects.
+#
+# @sev-device: SEV device to use (default: "/dev/sev")
+#
+# @dh-cert-file: guest owners DH certificate (encoded with base64)
+#
+# @session-file: guest owners session parameters (encoded with base64)
+#
+# @policy: SEV policy value (default: 0x1)
+#
+# @handle: SEV firmware handle (default: 0)
+#
+# @cbitpos: C-bit location in page table entry (default: 0)
+#
+# @reduced-phys-bits: number of bits in physical addresses that become
+# unavailable when SEV is enabled
+#
+# @kernel-hashes: if true, add hashes of kernel/initrd/cmdline to a
+# designated guest firmware page for measured boot
+# with -kernel (default: false) (since 6.2)
+#
+# Since: 2.12
+##
+{ 'struct': 'SevGuestProperties',
+ 'data': { '*sev-device': 'str',
+ '*dh-cert-file': 'str',
+ '*session-file': 'str',
+ '*policy': 'uint32',
+ '*handle': 'uint32',
+ '*cbitpos': 'uint32',
+ 'reduced-phys-bits': 'uint32',
+ '*kernel-hashes': 'bool' } }
+
+##
+# @ObjectType:
+#
+# Features:
+# @unstable: Member @x-remote-object is experimental.
+#
+# Since: 6.0
+##
+{ 'enum': 'ObjectType',
+ 'data': [
+ 'authz-list',
+ 'authz-listfile',
+ 'authz-pam',
+ 'authz-simple',
+ 'can-bus',
+ { 'name': 'can-host-socketcan',
+ 'if': 'CONFIG_LINUX' },
+ 'colo-compare',
+ 'cryptodev-backend',
+ 'cryptodev-backend-builtin',
+ { 'name': 'cryptodev-vhost-user',
+ 'if': 'CONFIG_VHOST_CRYPTO' },
+ 'dbus-vmstate',
+ 'filter-buffer',
+ 'filter-dump',
+ 'filter-mirror',
+ 'filter-redirector',
+ 'filter-replay',
+ 'filter-rewriter',
+ 'input-barrier',
+ { 'name': 'input-linux',
+ 'if': 'CONFIG_LINUX' },
+ 'iothread',
+ { 'name': 'memory-backend-epc',
+ 'if': 'CONFIG_LINUX' },
+ 'memory-backend-file',
+ { 'name': 'memory-backend-memfd',
+ 'if': 'CONFIG_LINUX' },
+ 'memory-backend-ram',
+ 'pef-guest',
+ { 'name': 'pr-manager-helper',
+ 'if': 'CONFIG_LINUX' },
+ 'qtest',
+ 'rng-builtin',
+ 'rng-egd',
+ { 'name': 'rng-random',
+ 'if': 'CONFIG_POSIX' },
+ 'secret',
+ { 'name': 'secret_keyring',
+ 'if': 'CONFIG_SECRET_KEYRING' },
+ 'sev-guest',
+ 's390-pv-guest',
+ 'throttle-group',
+ 'tls-creds-anon',
+ 'tls-creds-psk',
+ 'tls-creds-x509',
+ 'tls-cipher-suites',
+ { 'name': 'x-remote-object', 'features': [ 'unstable' ] }
+ ] }
+
+##
+# @ObjectOptions:
+#
+# Describes the options of a user creatable QOM object.
+#
+# @qom-type: the class name for the object to be created
+#
+# @id: the name of the new object
+#
+# Since: 6.0
+##
+{ 'union': 'ObjectOptions',
+ 'base': { 'qom-type': 'ObjectType',
+ 'id': 'str' },
+ 'discriminator': 'qom-type',
+ 'data': {
+ 'authz-list': 'AuthZListProperties',
+ 'authz-listfile': 'AuthZListFileProperties',
+ 'authz-pam': 'AuthZPAMProperties',
+ 'authz-simple': 'AuthZSimpleProperties',
+ 'can-host-socketcan': { 'type': 'CanHostSocketcanProperties',
+ 'if': 'CONFIG_LINUX' },
+ 'colo-compare': 'ColoCompareProperties',
+ 'cryptodev-backend': 'CryptodevBackendProperties',
+ 'cryptodev-backend-builtin': 'CryptodevBackendProperties',
+ 'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties',
+ 'if': 'CONFIG_VHOST_CRYPTO' },
+ 'dbus-vmstate': 'DBusVMStateProperties',
+ 'filter-buffer': 'FilterBufferProperties',
+ 'filter-dump': 'FilterDumpProperties',
+ 'filter-mirror': 'FilterMirrorProperties',
+ 'filter-redirector': 'FilterRedirectorProperties',
+ 'filter-replay': 'NetfilterProperties',
+ 'filter-rewriter': 'FilterRewriterProperties',
+ 'input-barrier': 'InputBarrierProperties',
+ 'input-linux': { 'type': 'InputLinuxProperties',
+ 'if': 'CONFIG_LINUX' },
+ 'iothread': 'IothreadProperties',
+ 'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties',
+ 'if': 'CONFIG_LINUX' },
+ 'memory-backend-file': 'MemoryBackendFileProperties',
+ 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties',
+ 'if': 'CONFIG_LINUX' },
+ 'memory-backend-ram': 'MemoryBackendProperties',
+ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties',
+ 'if': 'CONFIG_LINUX' },
+ 'qtest': 'QtestProperties',
+ 'rng-builtin': 'RngProperties',
+ 'rng-egd': 'RngEgdProperties',
+ 'rng-random': { 'type': 'RngRandomProperties',
+ 'if': 'CONFIG_POSIX' },
+ 'secret': 'SecretProperties',
+ 'secret_keyring': { 'type': 'SecretKeyringProperties',
+ 'if': 'CONFIG_SECRET_KEYRING' },
+ 'sev-guest': 'SevGuestProperties',
+ 'throttle-group': 'ThrottleGroupProperties',
+ 'tls-creds-anon': 'TlsCredsAnonProperties',
+ 'tls-creds-psk': 'TlsCredsPskProperties',
+ 'tls-creds-x509': 'TlsCredsX509Properties',
+ 'tls-cipher-suites': 'TlsCredsProperties',
+ 'x-remote-object': 'RemoteObjectProperties'
+ } }
+
+##
+# @object-add:
+#
+# Create a QOM object.
+#
+# Returns: Nothing on success
+# Error if @qom-type is not a valid class name
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "object-add",
+# "arguments": { "qom-type": "rng-random", "id": "rng1",
+# "filename": "/dev/hwrng" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true,
+ 'allow-preconfig': true }
+
+##
+# @object-del:
+#
+# Remove a QOM object.
+#
+# @id: the name of the QOM object to remove
+#
+# Returns: Nothing on success
+# Error if @id is not a valid id for a QOM object
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "object-del", "arguments": { "id": "rng1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'object-del', 'data': {'id': 'str'},
+ 'allow-preconfig': true }
diff --git a/qapi/rdma.json b/qapi/rdma.json
new file mode 100644
index 000000000..a1d2175a8
--- /dev/null
+++ b/qapi/rdma.json
@@ -0,0 +1,39 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = RDMA device
+##
+
+##
+# @RDMA_GID_STATUS_CHANGED:
+#
+# Emitted when guest driver adds/deletes GID to/from device
+#
+# @netdev: RoCE Network Device name
+#
+# @gid-status: Add or delete indication
+#
+# @subnet-prefix: Subnet Prefix
+#
+# @interface-id : Interface ID
+#
+# Since: 4.0
+#
+# Example:
+#
+# <- {"timestamp": {"seconds": 1541579657, "microseconds": 986760},
+# "event": "RDMA_GID_STATUS_CHANGED",
+# "data":
+# {"netdev": "bridge0",
+# "interface-id": 15880512517475447892,
+# "gid-status": true,
+# "subnet-prefix": 33022}}
+#
+##
+{ 'event': 'RDMA_GID_STATUS_CHANGED',
+ 'data': { 'netdev' : 'str',
+ 'gid-status' : 'bool',
+ 'subnet-prefix' : 'uint64',
+ 'interface-id' : 'uint64' } }
diff --git a/qapi/replay.json b/qapi/replay.json
new file mode 100644
index 000000000..bfd83d759
--- /dev/null
+++ b/qapi/replay.json
@@ -0,0 +1,121 @@
+# -*- Mode: Python -*-
+#
+
+##
+# = Record/replay
+##
+
+{ 'include': 'common.json' }
+
+##
+# @ReplayMode:
+#
+# Mode of the replay subsystem.
+#
+# @none: normal execution mode. Replay or record are not enabled.
+#
+# @record: record mode. All non-deterministic data is written into the
+# replay log.
+#
+# @play: replay mode. Non-deterministic data required for system execution
+# is read from the log.
+#
+# Since: 2.5
+##
+{ 'enum': 'ReplayMode',
+ 'data': [ 'none', 'record', 'play' ] }
+
+##
+# @ReplayInfo:
+#
+# Record/replay information.
+#
+# @mode: current mode.
+#
+# @filename: name of the record/replay log file.
+# It is present only in record or replay modes, when the log
+# is recorded or replayed.
+#
+# @icount: current number of executed instructions.
+#
+# Since: 5.2
+#
+##
+{ 'struct': 'ReplayInfo',
+ 'data': { 'mode': 'ReplayMode', '*filename': 'str', 'icount': 'int' } }
+
+##
+# @query-replay:
+#
+# Retrieve the record/replay information.
+# It includes current instruction count which may be used for
+# @replay-break and @replay-seek commands.
+#
+# Returns: record/replay information.
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute": "query-replay" }
+# <- { "return": { "mode": "play", "filename": "log.rr", "icount": 220414 } }
+#
+##
+{ 'command': 'query-replay',
+ 'returns': 'ReplayInfo' }
+
+##
+# @replay-break:
+#
+# Set replay breakpoint at instruction count @icount.
+# Execution stops when the specified instruction is reached.
+# There can be at most one breakpoint. When breakpoint is set, any prior
+# one is removed. The breakpoint may be set only in replay mode and only
+# "in the future", i.e. at instruction counts greater than the current one.
+# The current instruction count can be observed with @query-replay.
+#
+# @icount: instruction count to stop at
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute": "replay-break", "data": { "icount": 220414 } }
+#
+##
+{ 'command': 'replay-break', 'data': { 'icount': 'int' } }
+
+##
+# @replay-delete-break:
+#
+# Remove replay breakpoint which was set with @replay-break.
+# The command is ignored when there are no replay breakpoints.
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute": "replay-delete-break" }
+#
+##
+{ 'command': 'replay-delete-break' }
+
+##
+# @replay-seek:
+#
+# Automatically proceed to the instruction count @icount, when
+# replaying the execution. The command automatically loads nearest
+# snapshot and replays the execution to find the desired instruction.
+# When there is no preceding snapshot or the execution is not replayed,
+# then the command fails.
+# icount for the reference may be obtained with @query-replay command.
+#
+# @icount: target instruction count
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute": "replay-seek", "data": { "icount": 220414 } }
+##
+{ 'command': 'replay-seek', 'data': { 'icount': 'int' } }
diff --git a/qapi/rocker.json b/qapi/rocker.json
new file mode 100644
index 000000000..b48e49a89
--- /dev/null
+++ b/qapi/rocker.json
@@ -0,0 +1,342 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = Rocker switch device
+##
+
+##
+# @RockerSwitch:
+#
+# Rocker switch information.
+#
+# @name: switch name
+#
+# @id: switch ID
+#
+# @ports: number of front-panel ports
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerSwitch',
+ 'data': { 'name': 'str', 'id': 'uint64', 'ports': 'uint32' } }
+
+##
+# @query-rocker:
+#
+# Return rocker switch information.
+#
+# Returns: @Rocker information
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "query-rocker", "arguments": { "name": "sw1" } }
+# <- { "return": {"name": "sw1", "ports": 2, "id": 1327446905938}}
+#
+##
+{ 'command': 'query-rocker',
+ 'data': { 'name': 'str' },
+ 'returns': 'RockerSwitch' }
+
+##
+# @RockerPortDuplex:
+#
+# An eumeration of port duplex states.
+#
+# @half: half duplex
+#
+# @full: full duplex
+#
+# Since: 2.4
+##
+{ 'enum': 'RockerPortDuplex', 'data': [ 'half', 'full' ] }
+
+##
+# @RockerPortAutoneg:
+#
+# An eumeration of port autoneg states.
+#
+# @off: autoneg is off
+#
+# @on: autoneg is on
+#
+# Since: 2.4
+##
+{ 'enum': 'RockerPortAutoneg', 'data': [ 'off', 'on' ] }
+
+##
+# @RockerPort:
+#
+# Rocker switch port information.
+#
+# @name: port name
+#
+# @enabled: port is enabled for I/O
+#
+# @link-up: physical link is UP on port
+#
+# @speed: port link speed in Mbps
+#
+# @duplex: port link duplex
+#
+# @autoneg: port link autoneg
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerPort',
+ 'data': { 'name': 'str', 'enabled': 'bool', 'link-up': 'bool',
+ 'speed': 'uint32', 'duplex': 'RockerPortDuplex',
+ 'autoneg': 'RockerPortAutoneg' } }
+
+##
+# @query-rocker-ports:
+#
+# Return rocker switch port information.
+#
+# Returns: a list of @RockerPort information
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "query-rocker-ports", "arguments": { "name": "sw1" } }
+# <- { "return": [ {"duplex": "full", "enabled": true, "name": "sw1.1",
+# "autoneg": "off", "link-up": true, "speed": 10000},
+# {"duplex": "full", "enabled": true, "name": "sw1.2",
+# "autoneg": "off", "link-up": true, "speed": 10000}
+# ]}
+#
+##
+{ 'command': 'query-rocker-ports',
+ 'data': { 'name': 'str' },
+ 'returns': ['RockerPort'] }
+
+##
+# @RockerOfDpaFlowKey:
+#
+# Rocker switch OF-DPA flow key
+#
+# @priority: key priority, 0 being lowest priority
+#
+# @tbl-id: flow table ID
+#
+# @in-pport: physical input port
+#
+# @tunnel-id: tunnel ID
+#
+# @vlan-id: VLAN ID
+#
+# @eth-type: Ethernet header type
+#
+# @eth-src: Ethernet header source MAC address
+#
+# @eth-dst: Ethernet header destination MAC address
+#
+# @ip-proto: IP Header protocol field
+#
+# @ip-tos: IP header TOS field
+#
+# @ip-dst: IP header destination address
+#
+# Note: optional members may or may not appear in the flow key
+# depending if they're relevant to the flow key.
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerOfDpaFlowKey',
+ 'data' : { 'priority': 'uint32', 'tbl-id': 'uint32', '*in-pport': 'uint32',
+ '*tunnel-id': 'uint32', '*vlan-id': 'uint16',
+ '*eth-type': 'uint16', '*eth-src': 'str', '*eth-dst': 'str',
+ '*ip-proto': 'uint8', '*ip-tos': 'uint8', '*ip-dst': 'str' } }
+
+##
+# @RockerOfDpaFlowMask:
+#
+# Rocker switch OF-DPA flow mask
+#
+# @in-pport: physical input port
+#
+# @tunnel-id: tunnel ID
+#
+# @vlan-id: VLAN ID
+#
+# @eth-src: Ethernet header source MAC address
+#
+# @eth-dst: Ethernet header destination MAC address
+#
+# @ip-proto: IP Header protocol field
+#
+# @ip-tos: IP header TOS field
+#
+# Note: optional members may or may not appear in the flow mask
+# depending if they're relevant to the flow mask.
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerOfDpaFlowMask',
+ 'data' : { '*in-pport': 'uint32', '*tunnel-id': 'uint32',
+ '*vlan-id': 'uint16', '*eth-src': 'str', '*eth-dst': 'str',
+ '*ip-proto': 'uint8', '*ip-tos': 'uint8' } }
+
+##
+# @RockerOfDpaFlowAction:
+#
+# Rocker switch OF-DPA flow action
+#
+# @goto-tbl: next table ID
+#
+# @group-id: group ID
+#
+# @tunnel-lport: tunnel logical port ID
+#
+# @vlan-id: VLAN ID
+#
+# @new-vlan-id: new VLAN ID
+#
+# @out-pport: physical output port
+#
+# Note: optional members may or may not appear in the flow action
+# depending if they're relevant to the flow action.
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerOfDpaFlowAction',
+ 'data' : { '*goto-tbl': 'uint32', '*group-id': 'uint32',
+ '*tunnel-lport': 'uint32', '*vlan-id': 'uint16',
+ '*new-vlan-id': 'uint16', '*out-pport': 'uint32' } }
+
+##
+# @RockerOfDpaFlow:
+#
+# Rocker switch OF-DPA flow
+#
+# @cookie: flow unique cookie ID
+#
+# @hits: count of matches (hits) on flow
+#
+# @key: flow key
+#
+# @mask: flow mask
+#
+# @action: flow action
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerOfDpaFlow',
+ 'data': { 'cookie': 'uint64', 'hits': 'uint64', 'key': 'RockerOfDpaFlowKey',
+ 'mask': 'RockerOfDpaFlowMask', 'action': 'RockerOfDpaFlowAction' } }
+
+##
+# @query-rocker-of-dpa-flows:
+#
+# Return rocker OF-DPA flow information.
+#
+# @name: switch name
+#
+# @tbl-id: flow table ID. If tbl-id is not specified, returns
+# flow information for all tables.
+#
+# Returns: rocker OF-DPA flow information
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "query-rocker-of-dpa-flows",
+# "arguments": { "name": "sw1" } }
+# <- { "return": [ {"key": {"in-pport": 0, "priority": 1, "tbl-id": 0},
+# "hits": 138,
+# "cookie": 0,
+# "action": {"goto-tbl": 10},
+# "mask": {"in-pport": 4294901760}
+# },
+# {...more...},
+# ]}
+#
+##
+{ 'command': 'query-rocker-of-dpa-flows',
+ 'data': { 'name': 'str', '*tbl-id': 'uint32' },
+ 'returns': ['RockerOfDpaFlow'] }
+
+##
+# @RockerOfDpaGroup:
+#
+# Rocker switch OF-DPA group
+#
+# @id: group unique ID
+#
+# @type: group type
+#
+# @vlan-id: VLAN ID
+#
+# @pport: physical port number
+#
+# @index: group index, unique with group type
+#
+# @out-pport: output physical port number
+#
+# @group-id: next group ID
+#
+# @set-vlan-id: VLAN ID to set
+#
+# @pop-vlan: pop VLAN headr from packet
+#
+# @group-ids: list of next group IDs
+#
+# @set-eth-src: set source MAC address in Ethernet header
+#
+# @set-eth-dst: set destination MAC address in Ethernet header
+#
+# @ttl-check: perform TTL check
+#
+# Note: optional members may or may not appear in the group depending
+# if they're relevant to the group type.
+#
+# Since: 2.4
+##
+{ 'struct': 'RockerOfDpaGroup',
+ 'data': { 'id': 'uint32', 'type': 'uint8', '*vlan-id': 'uint16',
+ '*pport': 'uint32', '*index': 'uint32', '*out-pport': 'uint32',
+ '*group-id': 'uint32', '*set-vlan-id': 'uint16',
+ '*pop-vlan': 'uint8', '*group-ids': ['uint32'],
+ '*set-eth-src': 'str', '*set-eth-dst': 'str',
+ '*ttl-check': 'uint8' } }
+
+##
+# @query-rocker-of-dpa-groups:
+#
+# Return rocker OF-DPA group information.
+#
+# @name: switch name
+#
+# @type: group type. If type is not specified, returns
+# group information for all group types.
+#
+# Returns: rocker OF-DPA group information
+#
+# Since: 2.4
+#
+# Example:
+#
+# -> { "execute": "query-rocker-of-dpa-groups",
+# "arguments": { "name": "sw1" } }
+# <- { "return": [ {"type": 0, "out-pport": 2,
+# "pport": 2, "vlan-id": 3841,
+# "pop-vlan": 1, "id": 251723778},
+# {"type": 0, "out-pport": 0,
+# "pport": 0, "vlan-id": 3841,
+# "pop-vlan": 1, "id": 251723776},
+# {"type": 0, "out-pport": 1,
+# "pport": 1, "vlan-id": 3840,
+# "pop-vlan": 1, "id": 251658241},
+# {"type": 0, "out-pport": 0,
+# "pport": 0, "vlan-id": 3840,
+# "pop-vlan": 1, "id": 251658240}
+# ]}
+#
+##
+{ 'command': 'query-rocker-of-dpa-groups',
+ 'data': { 'name': 'str', '*type': 'uint8' },
+ 'returns': ['RockerOfDpaGroup'] }
diff --git a/qapi/run-state.json b/qapi/run-state.json
new file mode 100644
index 000000000..43d66d700
--- /dev/null
+++ b/qapi/run-state.json
@@ -0,0 +1,640 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = VM run state
+##
+
+##
+# @RunState:
+#
+# An enumeration of VM run states.
+#
+# @debug: QEMU is running on a debugger
+#
+# @finish-migrate: guest is paused to finish the migration process
+#
+# @inmigrate: guest is paused waiting for an incoming migration. Note
+# that this state does not tell whether the machine will start at the
+# end of the migration. This depends on the command-line -S option and
+# any invocation of 'stop' or 'cont' that has happened since QEMU was
+# started.
+#
+# @internal-error: An internal error that prevents further guest execution
+# has occurred
+#
+# @io-error: the last IOP has failed and the device is configured to pause
+# on I/O errors
+#
+# @paused: guest has been paused via the 'stop' command
+#
+# @postmigrate: guest is paused following a successful 'migrate'
+#
+# @prelaunch: QEMU was started with -S and guest has not started
+#
+# @restore-vm: guest is paused to restore VM state
+#
+# @running: guest is actively running
+#
+# @save-vm: guest is paused to save the VM state
+#
+# @shutdown: guest is shut down (and -no-shutdown is in use)
+#
+# @suspended: guest is suspended (ACPI S3)
+#
+# @watchdog: the watchdog action is configured to pause and has been triggered
+#
+# @guest-panicked: guest has been panicked as a result of guest OS panic
+#
+# @colo: guest is paused to save/restore VM state under colo checkpoint,
+# VM can not get into this state unless colo capability is enabled
+# for migration. (since 2.8)
+##
+{ 'enum': 'RunState',
+ 'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
+ 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
+ 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
+ 'guest-panicked', 'colo' ] }
+
+##
+# @ShutdownCause:
+#
+# An enumeration of reasons for a Shutdown.
+#
+# @none: No shutdown request pending
+#
+# @host-error: An error prevents further use of guest
+#
+# @host-qmp-quit: Reaction to the QMP command 'quit'
+#
+# @host-qmp-system-reset: Reaction to the QMP command 'system_reset'
+#
+# @host-signal: Reaction to a signal, such as SIGINT
+#
+# @host-ui: Reaction to a UI event, like window close
+#
+# @guest-shutdown: Guest shutdown/suspend request, via ACPI or other
+# hardware-specific means
+#
+# @guest-reset: Guest reset request, and command line turns that into
+# a shutdown
+#
+# @guest-panic: Guest panicked, and command line turns that into a shutdown
+#
+# @subsystem-reset: Partial guest reset that does not trigger QMP events and
+# ignores --no-reboot. This is useful for sanitizing
+# hypercalls on s390 that are used during kexec/kdump/boot
+#
+##
+{ 'enum': 'ShutdownCause',
+ # Beware, shutdown_caused_by_guest() depends on enumeration order
+ 'data': [ 'none', 'host-error', 'host-qmp-quit', 'host-qmp-system-reset',
+ 'host-signal', 'host-ui', 'guest-shutdown', 'guest-reset',
+ 'guest-panic', 'subsystem-reset'] }
+
+##
+# @StatusInfo:
+#
+# Information about VCPU run state
+#
+# @running: true if all VCPUs are runnable, false if not runnable
+#
+# @singlestep: true if VCPUs are in single-step mode
+#
+# @status: the virtual machine @RunState
+#
+# Since: 0.14
+#
+# Notes: @singlestep is enabled through the GDB stub
+##
+{ 'struct': 'StatusInfo',
+ 'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }
+
+##
+# @query-status:
+#
+# Query the run status of all VCPUs
+#
+# Returns: @StatusInfo reflecting all VCPUs
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-status" }
+# <- { "return": { "running": true,
+# "singlestep": false,
+# "status": "running" } }
+#
+##
+{ 'command': 'query-status', 'returns': 'StatusInfo',
+ 'allow-preconfig': true }
+
+##
+# @SHUTDOWN:
+#
+# Emitted when the virtual machine has shut down, indicating that qemu is
+# about to exit.
+#
+# @guest: If true, the shutdown was triggered by a guest request (such as
+# a guest-initiated ACPI shutdown request or other hardware-specific action)
+# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
+#
+# @reason: The @ShutdownCause which resulted in the SHUTDOWN. (since 4.0)
+#
+# Note: If the command-line option "-no-shutdown" has been specified, qemu will
+# not exit, and a STOP event will eventually follow the SHUTDOWN event
+#
+# Since: 0.12
+#
+# Example:
+#
+# <- { "event": "SHUTDOWN", "data": { "guest": true },
+# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
+#
+##
+{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } }
+
+##
+# @POWERDOWN:
+#
+# Emitted when the virtual machine is powered down through the power control
+# system, such as via ACPI.
+#
+# Since: 0.12
+#
+# Example:
+#
+# <- { "event": "POWERDOWN",
+# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
+#
+##
+{ 'event': 'POWERDOWN' }
+
+##
+# @RESET:
+#
+# Emitted when the virtual machine is reset
+#
+# @guest: If true, the reset was triggered by a guest request (such as
+# a guest-initiated ACPI reboot request or other hardware-specific action)
+# rather than a host request (such as the QMP command system_reset).
+# (since 2.10)
+#
+# @reason: The @ShutdownCause of the RESET. (since 4.0)
+#
+# Since: 0.12
+#
+# Example:
+#
+# <- { "event": "RESET", "data": { "guest": false },
+# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
+#
+##
+{ 'event': 'RESET', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } }
+
+##
+# @STOP:
+#
+# Emitted when the virtual machine is stopped
+#
+# Since: 0.12
+#
+# Example:
+#
+# <- { "event": "STOP",
+# "timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
+#
+##
+{ 'event': 'STOP' }
+
+##
+# @RESUME:
+#
+# Emitted when the virtual machine resumes execution
+#
+# Since: 0.12
+#
+# Example:
+#
+# <- { "event": "RESUME",
+# "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
+#
+##
+{ 'event': 'RESUME' }
+
+##
+# @SUSPEND:
+#
+# Emitted when guest enters a hardware suspension state, for example, S3 state,
+# which is sometimes called standby state
+#
+# Since: 1.1
+#
+# Example:
+#
+# <- { "event": "SUSPEND",
+# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
+#
+##
+{ 'event': 'SUSPEND' }
+
+##
+# @SUSPEND_DISK:
+#
+# Emitted when guest enters a hardware suspension state with data saved on
+# disk, for example, S4 state, which is sometimes called hibernate state
+#
+# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering this state
+#
+# Since: 1.2
+#
+# Example:
+#
+# <- { "event": "SUSPEND_DISK",
+# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
+#
+##
+{ 'event': 'SUSPEND_DISK' }
+
+##
+# @WAKEUP:
+#
+# Emitted when the guest has woken up from suspend state and is running
+#
+# Since: 1.1
+#
+# Example:
+#
+# <- { "event": "WAKEUP",
+# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
+#
+##
+{ 'event': 'WAKEUP' }
+
+##
+# @WATCHDOG:
+#
+# Emitted when the watchdog device's timer is expired
+#
+# @action: action that has been taken
+#
+# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
+# followed respectively by the RESET, SHUTDOWN, or STOP events
+#
+# Note: This event is rate-limited.
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "WATCHDOG",
+# "data": { "action": "reset" },
+# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
+#
+##
+{ 'event': 'WATCHDOG',
+ 'data': { 'action': 'WatchdogAction' } }
+
+##
+# @WatchdogAction:
+#
+# An enumeration of the actions taken when the watchdog device's timer is
+# expired
+#
+# @reset: system resets
+#
+# @shutdown: system shutdown, note that it is similar to @powerdown, which
+# tries to set to system status and notify guest
+#
+# @poweroff: system poweroff, the emulator program exits
+#
+# @pause: system pauses, similar to @stop
+#
+# @debug: system enters debug state
+#
+# @none: nothing is done
+#
+# @inject-nmi: a non-maskable interrupt is injected into the first VCPU (all
+# VCPUS on x86) (since 2.4)
+#
+# Since: 2.1
+##
+{ 'enum': 'WatchdogAction',
+ 'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
+ 'inject-nmi' ] }
+
+##
+# @RebootAction:
+#
+# Possible QEMU actions upon guest reboot
+#
+# @reset: Reset the VM
+#
+# @shutdown: Shutdown the VM and exit, according to the shutdown action
+#
+# Since: 6.0
+##
+{ 'enum': 'RebootAction',
+ 'data': [ 'reset', 'shutdown' ] }
+
+##
+# @ShutdownAction:
+#
+# Possible QEMU actions upon guest shutdown
+#
+# @poweroff: Shutdown the VM and exit
+#
+# @pause: pause the VM#
+#
+# Since: 6.0
+##
+{ 'enum': 'ShutdownAction',
+ 'data': [ 'poweroff', 'pause' ] }
+
+##
+# @PanicAction:
+#
+# @none: Continue VM execution
+#
+# @pause: Pause the VM
+#
+# @shutdown: Shutdown the VM and exit, according to the shutdown action
+#
+# Since: 6.0
+##
+{ 'enum': 'PanicAction',
+ 'data': [ 'pause', 'shutdown', 'none' ] }
+
+##
+# @watchdog-set-action:
+#
+# Set watchdog action
+#
+# Since: 2.11
+##
+{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
+##
+# @set-action:
+#
+# Set the actions that will be taken by the emulator in response to guest
+# events.
+#
+# @reboot: @RebootAction action taken on guest reboot.
+#
+# @shutdown: @ShutdownAction action taken on guest shutdown.
+#
+# @panic: @PanicAction action taken on guest panic.
+#
+# @watchdog: @WatchdogAction action taken when watchdog timer expires .
+#
+# Returns: Nothing on success.
+#
+# Since: 6.0
+#
+# Example:
+#
+# -> { "execute": "set-action",
+# "arguments": { "reboot": "shutdown",
+# "shutdown" : "pause",
+# "panic": "pause",
+# "watchdog": "inject-nmi" } }
+# <- { "return": {} }
+##
+{ 'command': 'set-action',
+ 'data': { '*reboot': 'RebootAction',
+ '*shutdown': 'ShutdownAction',
+ '*panic': 'PanicAction',
+ '*watchdog': 'WatchdogAction' },
+ 'allow-preconfig': true }
+
+##
+# @GUEST_PANICKED:
+#
+# Emitted when guest OS panic is detected
+#
+# @action: action that has been taken, currently always "pause"
+#
+# @info: information about a panic (since 2.9)
+#
+# Since: 1.5
+#
+# Example:
+#
+# <- { "event": "GUEST_PANICKED",
+# "data": { "action": "pause" } }
+#
+##
+{ 'event': 'GUEST_PANICKED',
+ 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } }
+
+##
+# @GUEST_CRASHLOADED:
+#
+# Emitted when guest OS crash loaded is detected
+#
+# @action: action that has been taken, currently always "run"
+#
+# @info: information about a panic
+#
+# Since: 5.0
+#
+# Example:
+#
+# <- { "event": "GUEST_CRASHLOADED",
+# "data": { "action": "run" } }
+#
+##
+{ 'event': 'GUEST_CRASHLOADED',
+ 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } }
+
+##
+# @GuestPanicAction:
+#
+# An enumeration of the actions taken when guest OS panic is detected
+#
+# @pause: system pauses
+#
+# Since: 2.1 (poweroff since 2.8, run since 5.0)
+##
+{ 'enum': 'GuestPanicAction',
+ 'data': [ 'pause', 'poweroff', 'run' ] }
+
+##
+# @GuestPanicInformationType:
+#
+# An enumeration of the guest panic information types
+#
+# @hyper-v: hyper-v guest panic information type
+#
+# @s390: s390 guest panic information type (Since: 2.12)
+#
+# Since: 2.9
+##
+{ 'enum': 'GuestPanicInformationType',
+ 'data': [ 'hyper-v', 's390' ] }
+
+##
+# @GuestPanicInformation:
+#
+# Information about a guest panic
+#
+# @type: Crash type that defines the hypervisor specific information
+#
+# Since: 2.9
+##
+{'union': 'GuestPanicInformation',
+ 'base': {'type': 'GuestPanicInformationType'},
+ 'discriminator': 'type',
+ 'data': { 'hyper-v': 'GuestPanicInformationHyperV',
+ 's390': 'GuestPanicInformationS390' } }
+
+##
+# @GuestPanicInformationHyperV:
+#
+# Hyper-V specific guest panic information (HV crash MSRs)
+#
+# Since: 2.9
+##
+{'struct': 'GuestPanicInformationHyperV',
+ 'data': { 'arg1': 'uint64',
+ 'arg2': 'uint64',
+ 'arg3': 'uint64',
+ 'arg4': 'uint64',
+ 'arg5': 'uint64' } }
+
+##
+# @S390CrashReason:
+#
+# Reason why the CPU is in a crashed state.
+#
+# @unknown: no crash reason was set
+#
+# @disabled-wait: the CPU has entered a disabled wait state
+#
+# @extint-loop: clock comparator or cpu timer interrupt with new PSW enabled
+# for external interrupts
+#
+# @pgmint-loop: program interrupt with BAD new PSW
+#
+# @opint-loop: operation exception interrupt with invalid code at the program
+# interrupt new PSW
+#
+# Since: 2.12
+##
+{ 'enum': 'S390CrashReason',
+ 'data': [ 'unknown',
+ 'disabled-wait',
+ 'extint-loop',
+ 'pgmint-loop',
+ 'opint-loop' ] }
+
+##
+# @GuestPanicInformationS390:
+#
+# S390 specific guest panic information (PSW)
+#
+# @core: core id of the CPU that crashed
+# @psw-mask: control fields of guest PSW
+# @psw-addr: guest instruction address
+# @reason: guest crash reason
+#
+# Since: 2.12
+##
+{'struct': 'GuestPanicInformationS390',
+ 'data': { 'core': 'uint32',
+ 'psw-mask': 'uint64',
+ 'psw-addr': 'uint64',
+ 'reason': 'S390CrashReason' } }
+
+##
+# @MEMORY_FAILURE:
+#
+# Emitted when a memory failure occurs on host side.
+#
+# @recipient: recipient is defined as @MemoryFailureRecipient.
+#
+# @action: action that has been taken. action is defined as @MemoryFailureAction.
+#
+# @flags: flags for MemoryFailureAction. action is defined as @MemoryFailureFlags.
+#
+# Since: 5.2
+#
+# Example:
+#
+# <- { "event": "MEMORY_FAILURE",
+# "data": { "recipient": "hypervisor",
+# "action": "fatal",
+# "flags": { 'action-required': false } }
+#
+##
+{ 'event': 'MEMORY_FAILURE',
+ 'data': { 'recipient': 'MemoryFailureRecipient',
+ 'action': 'MemoryFailureAction',
+ 'flags': 'MemoryFailureFlags'} }
+
+##
+# @MemoryFailureRecipient:
+#
+# Hardware memory failure occurs, handled by recipient.
+#
+# @hypervisor: memory failure at QEMU process address space.
+# (none guest memory, but used by QEMU itself).
+#
+# @guest: memory failure at guest memory,
+#
+# Since: 5.2
+#
+##
+{ 'enum': 'MemoryFailureRecipient',
+ 'data': [ 'hypervisor',
+ 'guest' ] }
+
+
+##
+# @MemoryFailureAction:
+#
+# Actions taken by QEMU in response to a hardware memory failure.
+#
+# @ignore: the memory failure could be ignored. This will only be the case
+# for action-optional failures.
+#
+# @inject: memory failure occurred in guest memory, the guest enabled MCE
+# handling mechanism, and QEMU could inject the MCE into the guest
+# successfully.
+#
+# @fatal: the failure is unrecoverable. This occurs for action-required
+# failures if the recipient is the hypervisor; QEMU will exit.
+#
+# @reset: the failure is unrecoverable but confined to the guest. This
+# occurs if the recipient is a guest guest which is not ready
+# to handle memory failures.
+#
+# Since: 5.2
+#
+##
+{ 'enum': 'MemoryFailureAction',
+ 'data': [ 'ignore',
+ 'inject',
+ 'fatal',
+ 'reset' ] }
+
+##
+# @MemoryFailureFlags:
+#
+# Additional information on memory failures.
+#
+# @action-required: whether a memory failure event is action-required
+# or action-optional (e.g. a failure during memory scrub).
+#
+# @recursive: whether the failure occurred while the previous
+# failure was still in progress.
+#
+# Since: 5.2
+#
+##
+{ 'struct': 'MemoryFailureFlags',
+ 'data': { 'action-required': 'bool',
+ 'recursive': 'bool'} }
diff --git a/qapi/sockets.json b/qapi/sockets.json
new file mode 100644
index 000000000..5773d9fcc
--- /dev/null
+++ b/qapi/sockets.json
@@ -0,0 +1,202 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+
+##
+# = Socket data types
+##
+
+{ 'include': 'common.json' }
+
+##
+# @NetworkAddressFamily:
+#
+# The network address family
+#
+# @ipv4: IPV4 family
+#
+# @ipv6: IPV6 family
+#
+# @unix: unix socket
+#
+# @vsock: vsock family (since 2.8)
+#
+# @unknown: otherwise
+#
+# Since: 2.1
+##
+{ 'enum': 'NetworkAddressFamily',
+ 'data': [ 'ipv4', 'ipv6', 'unix', 'vsock', 'unknown' ] }
+
+##
+# @InetSocketAddressBase:
+#
+# @host: host part of the address
+# @port: port part of the address
+##
+{ 'struct': 'InetSocketAddressBase',
+ 'data': {
+ 'host': 'str',
+ 'port': 'str' } }
+
+##
+# @InetSocketAddress:
+#
+# Captures a socket address or address range in the Internet namespace.
+#
+# @numeric: true if the host/port are guaranteed to be numeric,
+# false if name resolution should be attempted. Defaults to false.
+# (Since 2.9)
+#
+# @to: If present, this is range of possible addresses, with port
+# between @port and @to.
+#
+# @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6
+#
+# @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6
+#
+# @keep-alive: enable keep-alive when connecting to this socket. Not supported
+# for passive sockets. (Since 4.2)
+#
+# @mptcp: enable multi-path TCP. (Since 6.1)
+#
+# Since: 1.3
+##
+{ 'struct': 'InetSocketAddress',
+ 'base': 'InetSocketAddressBase',
+ 'data': {
+ '*numeric': 'bool',
+ '*to': 'uint16',
+ '*ipv4': 'bool',
+ '*ipv6': 'bool',
+ '*keep-alive': 'bool',
+ '*mptcp': { 'type': 'bool', 'if': 'HAVE_IPPROTO_MPTCP' } } }
+
+##
+# @UnixSocketAddress:
+#
+# Captures a socket address in the local ("Unix socket") namespace.
+#
+# @path: filesystem path to use
+# @abstract: if true, this is a Linux abstract socket address. @path
+# will be prefixed by a null byte, and optionally padded
+# with null bytes. Defaults to false. (Since 5.1)
+# @tight: if false, pad an abstract socket address with enough null
+# bytes to make it fill struct sockaddr_un member sun_path.
+# Defaults to true. (Since 5.1)
+#
+# Since: 1.3
+##
+{ 'struct': 'UnixSocketAddress',
+ 'data': {
+ 'path': 'str',
+ '*abstract': { 'type': 'bool', 'if': 'CONFIG_LINUX' },
+ '*tight': { 'type': 'bool', 'if': 'CONFIG_LINUX' } } }
+
+##
+# @VsockSocketAddress:
+#
+# Captures a socket address in the vsock namespace.
+#
+# @cid: unique host identifier
+# @port: port
+#
+# Note: string types are used to allow for possible future hostname or
+# service resolution support.
+#
+# Since: 2.8
+##
+{ 'struct': 'VsockSocketAddress',
+ 'data': {
+ 'cid': 'str',
+ 'port': 'str' } }
+
+##
+# @InetSocketAddressWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'InetSocketAddressWrapper',
+ 'data': { 'data': 'InetSocketAddress' } }
+
+##
+# @UnixSocketAddressWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'UnixSocketAddressWrapper',
+ 'data': { 'data': 'UnixSocketAddress' } }
+
+##
+# @VsockSocketAddressWrapper:
+#
+# Since: 2.8
+##
+{ 'struct': 'VsockSocketAddressWrapper',
+ 'data': { 'data': 'VsockSocketAddress' } }
+
+##
+# @StringWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'StringWrapper',
+ 'data': { 'data': 'String' } }
+
+##
+# @SocketAddressLegacy:
+#
+# Captures the address of a socket, which could also be a named file descriptor
+#
+# Note: This type is deprecated in favor of SocketAddress. The
+# difference between SocketAddressLegacy and SocketAddress is that the
+# latter is has fewer {} on the wire.
+#
+# Since: 1.3
+##
+{ 'union': 'SocketAddressLegacy',
+ 'base': { 'type': 'SocketAddressType' },
+ 'discriminator': 'type',
+ 'data': {
+ 'inet': 'InetSocketAddressWrapper',
+ 'unix': 'UnixSocketAddressWrapper',
+ 'vsock': 'VsockSocketAddressWrapper',
+ 'fd': 'StringWrapper' } }
+
+##
+# @SocketAddressType:
+#
+# Available SocketAddress types
+#
+# @inet: Internet address
+#
+# @unix: Unix domain socket
+#
+# @vsock: VMCI address
+#
+# @fd: decimal is for file descriptor number, otherwise a file descriptor name.
+# Named file descriptors are permitted in monitor commands, in combination
+# with the 'getfd' command. Decimal file descriptors are permitted at
+# startup or other contexts where no monitor context is active.
+#
+# Since: 2.9
+##
+{ 'enum': 'SocketAddressType',
+ 'data': [ 'inet', 'unix', 'vsock', 'fd' ] }
+
+##
+# @SocketAddress:
+#
+# Captures the address of a socket, which could also be a named file
+# descriptor
+#
+# @type: Transport type
+#
+# Since: 2.9
+##
+{ 'union': 'SocketAddress',
+ 'base': { 'type': 'SocketAddressType' },
+ 'discriminator': 'type',
+ 'data': { 'inet': 'InetSocketAddress',
+ 'unix': 'UnixSocketAddress',
+ 'vsock': 'VsockSocketAddress',
+ 'fd': 'String' } }
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
new file mode 100644
index 000000000..197139c1c
--- /dev/null
+++ b/qapi/string-input-visitor.c
@@ -0,0 +1,414 @@
+/*
+ * String parsing visitor
+ *
+ * Copyright Red Hat, Inc. 2012-2016
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/string-input-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qnull.h"
+#include "qemu/option.h"
+#include "qemu/cutils.h"
+
+typedef enum ListMode {
+ /* no list parsing active / no list expected */
+ LM_NONE,
+ /* we have an unparsed string remaining */
+ LM_UNPARSED,
+ /* we have an unfinished int64 range */
+ LM_INT64_RANGE,
+ /* we have an unfinished uint64 range */
+ LM_UINT64_RANGE,
+ /* we have parsed the string completely and no range is remaining */
+ LM_END,
+} ListMode;
+
+/* protect against DOS attacks, limit the amount of elements per range */
+#define RANGE_MAX_ELEMENTS 65536
+
+typedef union RangeElement {
+ int64_t i64;
+ uint64_t u64;
+} RangeElement;
+
+struct StringInputVisitor
+{
+ Visitor visitor;
+
+ /* List parsing state */
+ ListMode lm;
+ RangeElement rangeNext;
+ RangeElement rangeEnd;
+ const char *unparsed_string;
+ void *list;
+
+ /* The original string to parse */
+ const char *string;
+};
+
+static StringInputVisitor *to_siv(Visitor *v)
+{
+ return container_of(v, StringInputVisitor, visitor);
+}
+
+static bool start_list(Visitor *v, const char *name, GenericList **list,
+ size_t size, Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ assert(siv->lm == LM_NONE);
+ siv->list = list;
+ siv->unparsed_string = siv->string;
+
+ if (!siv->string[0]) {
+ if (list) {
+ *list = NULL;
+ }
+ siv->lm = LM_END;
+ } else {
+ if (list) {
+ *list = g_malloc0(size);
+ }
+ siv->lm = LM_UNPARSED;
+ }
+ return true;
+}
+
+static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ switch (siv->lm) {
+ case LM_END:
+ return NULL;
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ /* we have an unparsed string or something left in a range */
+ break;
+ default:
+ abort();
+ }
+
+ tail->next = g_malloc0(size);
+ return tail->next;
+}
+
+static bool check_list(Visitor *v, Error **errp)
+{
+ const StringInputVisitor *siv = to_siv(v);
+
+ switch (siv->lm) {
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ error_setg(errp, "Fewer list elements expected");
+ return false;
+ case LM_END:
+ return true;
+ default:
+ abort();
+ }
+}
+
+static void end_list(Visitor *v, void **obj)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ assert(siv->lm != LM_NONE);
+ assert(siv->list == obj);
+ siv->list = NULL;
+ siv->unparsed_string = NULL;
+ siv->lm = LM_NONE;
+}
+
+static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj)
+{
+ const char *endptr;
+ int64_t start, end;
+
+ /* parse a simple int64 or range */
+ if (qemu_strtoi64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtoi64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
+ }
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
+ }
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_INT64_RANGE;
+ siv->rangeNext.i64 = start;
+ siv->rangeEnd.i64 = end;
+ return 0;
+}
+
+static bool parse_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+ int64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple int64, bail out if not completely consumed */
+ if (qemu_strtoi64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int64");
+ return false;
+ }
+ *obj = val;
+ return true;
+ case LM_UNPARSED:
+ if (try_parse_int64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of int64 values or ranges");
+ return false;
+ }
+ assert(siv->lm == LM_INT64_RANGE);
+ /* fall through */
+ case LM_INT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.i64 <= siv->rangeEnd.i64);
+ *obj = siv->rangeNext.i64++;
+
+ if (siv->rangeNext.i64 > siv->rangeEnd.i64 || *obj == INT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return true;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return false;
+ default:
+ abort();
+ }
+}
+
+static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj)
+{
+ const char *endptr;
+ uint64_t start, end;
+
+ /* parse a simple uint64 or range */
+ if (qemu_strtou64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtou64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
+ }
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
+ }
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_UINT64_RANGE;
+ siv->rangeNext.u64 = start;
+ siv->rangeEnd.u64 = end;
+ return 0;
+}
+
+static bool parse_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+ uint64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple uint64, bail out if not completely consumed */
+ if (qemu_strtou64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint64");
+ return false;
+ }
+ *obj = val;
+ return true;
+ case LM_UNPARSED:
+ if (try_parse_uint64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of uint64 values or ranges");
+ return false;
+ }
+ assert(siv->lm == LM_UINT64_RANGE);
+ /* fall through */
+ case LM_UINT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.u64 <= siv->rangeEnd.u64);
+ *obj = siv->rangeNext.u64++;
+
+ if (siv->rangeNext.u64 > siv->rangeEnd.u64 || *obj == UINT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return true;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return false;
+ default:
+ abort();
+ }
+}
+
+static bool parse_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+ uint64_t val;
+
+ assert(siv->lm == LM_NONE);
+ if (!parse_option_size(name, siv->string, &val, errp)) {
+ return false;
+ }
+
+ *obj = val;
+ return true;
+}
+
+static bool parse_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ assert(siv->lm == LM_NONE);
+ return qapi_bool_parse(name ? name : "null", siv->string, obj, errp);
+}
+
+static bool parse_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ assert(siv->lm == LM_NONE);
+ *obj = g_strdup(siv->string);
+ return true;
+}
+
+static bool parse_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+ double val;
+
+ assert(siv->lm == LM_NONE);
+ if (qemu_strtod_finite(siv->string, NULL, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "number");
+ return false;
+ }
+
+ *obj = val;
+ return true;
+}
+
+static bool parse_type_null(Visitor *v, const char *name, QNull **obj,
+ Error **errp)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ assert(siv->lm == LM_NONE);
+ *obj = NULL;
+
+ if (siv->string[0]) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "null");
+ return false;
+ }
+
+ *obj = qnull();
+ return true;
+}
+
+static void string_input_free(Visitor *v)
+{
+ StringInputVisitor *siv = to_siv(v);
+
+ g_free(siv);
+}
+
+Visitor *string_input_visitor_new(const char *str)
+{
+ StringInputVisitor *v;
+
+ assert(str);
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_INPUT;
+ v->visitor.type_int64 = parse_type_int64;
+ v->visitor.type_uint64 = parse_type_uint64;
+ v->visitor.type_size = parse_type_size;
+ v->visitor.type_bool = parse_type_bool;
+ v->visitor.type_str = parse_type_str;
+ v->visitor.type_number = parse_type_number;
+ v->visitor.type_null = parse_type_null;
+ v->visitor.start_list = start_list;
+ v->visitor.next_list = next_list;
+ v->visitor.check_list = check_list;
+ v->visitor.end_list = end_list;
+ v->visitor.free = string_input_free;
+
+ v->string = str;
+ v->lm = LM_NONE;
+ return &v->visitor;
+}
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
new file mode 100644
index 000000000..5506c933d
--- /dev/null
+++ b/qapi/string-output-visitor.c
@@ -0,0 +1,374 @@
+/*
+ * String printing Visitor
+ *
+ * Copyright Red Hat, Inc. 2012-2016
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "qapi/string-output-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/host-utils.h"
+#include <math.h>
+#include "qemu/range.h"
+
+enum ListMode {
+ LM_NONE, /* not traversing a list of repeated options */
+ LM_STARTED, /* next_list() ready to be called */
+
+ LM_IN_PROGRESS, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently parsed QemuOpt instance of the repeated
+ * option.
+ *
+ * Parsing a value into the list link will examine the
+ * next QemuOpt instance of the repeated option, and
+ * possibly enter LM_SIGNED_INTERVAL or
+ * LM_UNSIGNED_INTERVAL.
+ */
+
+ LM_SIGNED_INTERVAL, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently stored element from the signed interval,
+ * parsed from the most recent QemuOpt instance of the
+ * repeated option. This may consume QemuOpt itself
+ * and return to LM_IN_PROGRESS.
+ *
+ * Parsing a value into the list link will store the
+ * next element of the signed interval.
+ */
+
+ LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */
+
+ LM_END, /* next_list() called, about to see last element. */
+};
+
+typedef enum ListMode ListMode;
+
+struct StringOutputVisitor
+{
+ Visitor visitor;
+ bool human;
+ GString *string;
+ char **result;
+ ListMode list_mode;
+ union {
+ int64_t s;
+ uint64_t u;
+ } range_start, range_end;
+ GList *ranges;
+ void *list; /* Only needed for sanity checking the caller */
+};
+
+static StringOutputVisitor *to_sov(Visitor *v)
+{
+ return container_of(v, StringOutputVisitor, visitor);
+}
+
+static void string_output_set(StringOutputVisitor *sov, char *string)
+{
+ if (sov->string) {
+ g_string_free(sov->string, true);
+ }
+ sov->string = g_string_new(string);
+ g_free(string);
+}
+
+static void string_output_append(StringOutputVisitor *sov, int64_t a)
+{
+ Range *r = g_malloc0(sizeof(*r));
+
+ range_set_bounds(r, a, a);
+ sov->ranges = range_list_insert(sov->ranges, r);
+}
+
+static void string_output_append_range(StringOutputVisitor *sov,
+ int64_t s, int64_t e)
+{
+ Range *r = g_malloc0(sizeof(*r));
+
+ range_set_bounds(r, s, e);
+ sov->ranges = range_list_insert(sov->ranges, r);
+}
+
+static void format_string(StringOutputVisitor *sov, Range *r, bool next,
+ bool human)
+{
+ if (range_lob(r) != range_upb(r)) {
+ if (human) {
+ g_string_append_printf(sov->string, "0x%" PRIx64 "-0x%" PRIx64,
+ range_lob(r), range_upb(r));
+
+ } else {
+ g_string_append_printf(sov->string, "%" PRId64 "-%" PRId64,
+ range_lob(r), range_upb(r));
+ }
+ } else {
+ if (human) {
+ g_string_append_printf(sov->string, "0x%" PRIx64, range_lob(r));
+ } else {
+ g_string_append_printf(sov->string, "%" PRId64, range_lob(r));
+ }
+ }
+ if (next) {
+ g_string_append(sov->string, ",");
+ }
+}
+
+static bool print_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ GList *l;
+
+ switch (sov->list_mode) {
+ case LM_NONE:
+ string_output_append(sov, *obj);
+ break;
+
+ case LM_STARTED:
+ sov->range_start.s = *obj;
+ sov->range_end.s = *obj;
+ sov->list_mode = LM_IN_PROGRESS;
+ return true;
+
+ case LM_IN_PROGRESS:
+ if (sov->range_end.s + 1 == *obj) {
+ sov->range_end.s++;
+ } else {
+ if (sov->range_start.s == sov->range_end.s) {
+ string_output_append(sov, sov->range_end.s);
+ } else {
+ assert(sov->range_start.s < sov->range_end.s);
+ string_output_append_range(sov, sov->range_start.s,
+ sov->range_end.s);
+ }
+
+ sov->range_start.s = *obj;
+ sov->range_end.s = *obj;
+ }
+ return true;
+
+ case LM_END:
+ if (sov->range_end.s + 1 == *obj) {
+ sov->range_end.s++;
+ assert(sov->range_start.s < sov->range_end.s);
+ string_output_append_range(sov, sov->range_start.s,
+ sov->range_end.s);
+ } else {
+ if (sov->range_start.s == sov->range_end.s) {
+ string_output_append(sov, sov->range_end.s);
+ } else {
+ assert(sov->range_start.s < sov->range_end.s);
+
+ string_output_append_range(sov, sov->range_start.s,
+ sov->range_end.s);
+ }
+ string_output_append(sov, *obj);
+ }
+ break;
+
+ default:
+ abort();
+ }
+
+ l = sov->ranges;
+ while (l) {
+ Range *r = l->data;
+ format_string(sov, r, l->next != NULL, false);
+ l = l->next;
+ }
+
+ if (sov->human) {
+ l = sov->ranges;
+ g_string_append(sov->string, " (");
+ while (l) {
+ Range *r = l->data;
+ format_string(sov, r, l->next != NULL, true);
+ l = l->next;
+ }
+ g_string_append(sov->string, ")");
+ }
+
+ return true;
+}
+
+static bool print_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ /* FIXME: print_type_int64 mishandles values over INT64_MAX */
+ int64_t i = *obj;
+ return print_type_int64(v, name, &i, errp);
+}
+
+static bool print_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ uint64_t val;
+ char *out, *psize;
+
+ if (!sov->human) {
+ out = g_strdup_printf("%"PRIu64, *obj);
+ string_output_set(sov, out);
+ return true;
+ }
+
+ val = *obj;
+ psize = size_to_str(val);
+ out = g_strdup_printf("%"PRIu64" (%s)", val, psize);
+ string_output_set(sov, out);
+
+ g_free(psize);
+ return true;
+}
+
+static bool print_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ string_output_set(sov, g_strdup(*obj ? "true" : "false"));
+ return true;
+}
+
+static bool print_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ char *out;
+
+ if (sov->human) {
+ out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>");
+ } else {
+ out = g_strdup(*obj ? *obj : "");
+ }
+ string_output_set(sov, out);
+ return true;
+}
+
+static bool print_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ string_output_set(sov, g_strdup_printf("%.17g", *obj));
+ return true;
+}
+
+static bool print_type_null(Visitor *v, const char *name, QNull **obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ char *out;
+
+ if (sov->human) {
+ out = g_strdup("<null>");
+ } else {
+ out = g_strdup("");
+ }
+ string_output_set(sov, out);
+ return true;
+}
+
+static bool
+start_list(Visitor *v, const char *name, GenericList **list, size_t size,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
+
+ /* we can't traverse a list in a list */
+ assert(sov->list_mode == LM_NONE);
+ /* We don't support visits without a list */
+ assert(list);
+ sov->list = list;
+ /* List handling is only needed if there are at least two elements */
+ if (*list && (*list)->next) {
+ sov->list_mode = LM_STARTED;
+ }
+ return true;
+}
+
+static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
+{
+ StringOutputVisitor *sov = to_sov(v);
+ GenericList *ret = tail->next;
+
+ if (ret && !ret->next) {
+ sov->list_mode = LM_END;
+ }
+ return ret;
+}
+
+static void end_list(Visitor *v, void **obj)
+{
+ StringOutputVisitor *sov = to_sov(v);
+
+ assert(sov->list == obj);
+ assert(sov->list_mode == LM_STARTED ||
+ sov->list_mode == LM_END ||
+ sov->list_mode == LM_NONE ||
+ sov->list_mode == LM_IN_PROGRESS);
+ sov->list_mode = LM_NONE;
+}
+
+static void string_output_complete(Visitor *v, void *opaque)
+{
+ StringOutputVisitor *sov = to_sov(v);
+
+ assert(opaque == sov->result);
+ *sov->result = g_string_free(sov->string, false);
+ sov->string = NULL;
+}
+
+static void free_range(void *range, void *dummy)
+{
+ g_free(range);
+}
+
+static void string_output_free(Visitor *v)
+{
+ StringOutputVisitor *sov = to_sov(v);
+
+ if (sov->string) {
+ g_string_free(sov->string, true);
+ }
+
+ g_list_foreach(sov->ranges, free_range, NULL);
+ g_list_free(sov->ranges);
+ g_free(sov);
+}
+
+Visitor *string_output_visitor_new(bool human, char **result)
+{
+ StringOutputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->string = g_string_new(NULL);
+ v->human = human;
+ v->result = result;
+ *result = NULL;
+
+ v->visitor.type = VISITOR_OUTPUT;
+ v->visitor.type_int64 = print_type_int64;
+ v->visitor.type_uint64 = print_type_uint64;
+ v->visitor.type_size = print_type_size;
+ v->visitor.type_bool = print_type_bool;
+ v->visitor.type_str = print_type_str;
+ v->visitor.type_number = print_type_number;
+ v->visitor.type_null = print_type_null;
+ v->visitor.start_list = start_list;
+ v->visitor.next_list = next_list;
+ v->visitor.end_list = end_list;
+ v->visitor.complete = string_output_complete;
+ v->visitor.free = string_output_free;
+
+ return &v->visitor;
+}
diff --git a/qapi/tpm.json b/qapi/tpm.json
new file mode 100644
index 000000000..4e2ea9756
--- /dev/null
+++ b/qapi/tpm.json
@@ -0,0 +1,185 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = TPM (trusted platform module) devices
+##
+
+##
+# @TpmModel:
+#
+# An enumeration of TPM models
+#
+# @tpm-tis: TPM TIS model
+# @tpm-crb: TPM CRB model (since 2.12)
+# @tpm-spapr: TPM SPAPR model (since 5.0)
+#
+# Since: 1.5
+##
+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ],
+ 'if': 'CONFIG_TPM' }
+
+##
+# @query-tpm-models:
+#
+# Return a list of supported TPM models
+#
+# Returns: a list of TpmModel
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "query-tpm-models" }
+# <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] }
+#
+##
+{ 'command': 'query-tpm-models', 'returns': ['TpmModel'],
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TpmType:
+#
+# An enumeration of TPM types
+#
+# @passthrough: TPM passthrough type
+# @emulator: Software Emulator TPM type
+# Since: 2.11
+#
+# Since: 1.5
+##
+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ],
+ 'if': 'CONFIG_TPM' }
+
+##
+# @query-tpm-types:
+#
+# Return a list of supported TPM types
+#
+# Returns: a list of TpmType
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "query-tpm-types" }
+# <- { "return": [ "passthrough", "emulator" ] }
+#
+##
+{ 'command': 'query-tpm-types', 'returns': ['TpmType'],
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TPMPassthroughOptions:
+#
+# Information about the TPM passthrough type
+#
+# @path: string describing the path used for accessing the TPM device
+#
+# @cancel-path: string showing the TPM's sysfs cancel file
+# for cancellation of TPM commands while they are executing
+#
+# Since: 1.5
+##
+{ 'struct': 'TPMPassthroughOptions',
+ 'data': { '*path': 'str',
+ '*cancel-path': 'str' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TPMEmulatorOptions:
+#
+# Information about the TPM emulator type
+#
+# @chardev: Name of a unix socket chardev
+#
+# Since: 2.11
+##
+{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TPMPassthroughOptionsWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'TPMPassthroughOptionsWrapper',
+ 'data': { 'data': 'TPMPassthroughOptions' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TPMEmulatorOptionsWrapper:
+#
+# Since: 2.11
+##
+{ 'struct': 'TPMEmulatorOptionsWrapper',
+ 'data': { 'data': 'TPMEmulatorOptions' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TpmTypeOptions:
+#
+# A union referencing different TPM backend types' configuration options
+#
+# @type: - 'passthrough' The configuration options for the TPM passthrough type
+# - 'emulator' The configuration options for TPM emulator backend type
+#
+# Since: 1.5
+##
+{ 'union': 'TpmTypeOptions',
+ 'base': { 'type': 'TpmType' },
+ 'discriminator': 'type',
+ 'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
+ 'emulator': 'TPMEmulatorOptionsWrapper' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @TPMInfo:
+#
+# Information about the TPM
+#
+# @id: The Id of the TPM
+#
+# @model: The TPM frontend model
+#
+# @options: The TPM (backend) type configuration options
+#
+# Since: 1.5
+##
+{ 'struct': 'TPMInfo',
+ 'data': {'id': 'str',
+ 'model': 'TpmModel',
+ 'options': 'TpmTypeOptions' },
+ 'if': 'CONFIG_TPM' }
+
+##
+# @query-tpm:
+#
+# Return information about the TPM device
+#
+# Returns: @TPMInfo on success
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "query-tpm" }
+# <- { "return":
+# [
+# { "model": "tpm-tis",
+# "options":
+# { "type": "passthrough",
+# "data":
+# { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
+# "path": "/dev/tpm0"
+# }
+# },
+# "id": "tpm0"
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-tpm', 'returns': ['TPMInfo'],
+ 'if': 'CONFIG_TPM' }
diff --git a/qapi/trace-events b/qapi/trace-events
new file mode 100644
index 000000000..ab108c4f0
--- /dev/null
+++ b/qapi/trace-events
@@ -0,0 +1,38 @@
+# See docs/devel/tracing.rst for syntax documentation.
+
+# qapi-visit-core.c
+visit_free(void *v) "v=%p"
+visit_complete(void *v, void *opaque) "v=%p opaque=%p"
+
+visit_start_struct(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_check_struct(void *v) "v=%p"
+visit_end_struct(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_list(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu"
+visit_check_list(void *v) "v=%p"
+visit_end_list(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_alternate(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
+
+visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
+visit_policy_reject(void *v, const char *name) "v=%p name=%s"
+visit_policy_skip(void *v, const char *name) "v=%p name=%s"
+
+visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p"
+visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint8(void *v, const char *name, uint8_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint16(void *v, const char *name, uint16_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint32(void *v, const char *name, uint32_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint64(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_int8(void *v, const char *name, int8_t *obj) "v=%p name=%s obj=%p"
+visit_type_int16(void *v, const char *name, int16_t *obj) "v=%p name=%s obj=%p"
+visit_type_int32(void *v, const char *name, int32_t *obj) "v=%p name=%s obj=%p"
+visit_type_int64(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_size(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_bool(void *v, const char *name, bool *obj) "v=%p name=%s obj=%p"
+visit_type_str(void *v, const char *name, char **obj) "v=%p name=%s obj=%p"
+visit_type_number(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
+visit_type_any(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
+visit_type_null(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
diff --git a/qapi/trace.h b/qapi/trace.h
new file mode 100644
index 000000000..5c3fb674d
--- /dev/null
+++ b/qapi/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-qapi.h"
diff --git a/qapi/trace.json b/qapi/trace.json
new file mode 100644
index 000000000..eedfded51
--- /dev/null
+++ b/qapi/trace.json
@@ -0,0 +1,108 @@
+# -*- mode: python -*-
+#
+# Copyright (C) 2011-2016 Lluís Vilanova <vilanova@ac.upc.edu>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# = Tracing
+##
+
+##
+# @TraceEventState:
+#
+# State of a tracing event.
+#
+# @unavailable: The event is statically disabled.
+#
+# @disabled: The event is dynamically disabled.
+#
+# @enabled: The event is dynamically enabled.
+#
+# Since: 2.2
+##
+{ 'enum': 'TraceEventState',
+ 'data': ['unavailable', 'disabled', 'enabled'] }
+
+##
+# @TraceEventInfo:
+#
+# Information of a tracing event.
+#
+# @name: Event name.
+# @state: Tracing state.
+# @vcpu: Whether this is a per-vCPU event (since 2.7).
+#
+# An event is per-vCPU if it has the "vcpu" property in the "trace-events"
+# files.
+#
+# Since: 2.2
+##
+{ 'struct': 'TraceEventInfo',
+ 'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} }
+
+##
+# @trace-event-get-state:
+#
+# Query the state of events.
+#
+# @name: Event name pattern (case-sensitive glob).
+# @vcpu: The vCPU to query (any by default; since 2.7).
+#
+# Returns: a list of @TraceEventInfo for the matching events
+#
+# An event is returned if:
+#
+# - its name matches the @name pattern, and
+# - if @vcpu is given, the event has the "vcpu" property.
+#
+# Therefore, if @vcpu is given, the operation will only match per-vCPU events,
+# returning their state on the specified vCPU. Special case: if @name is an
+# exact match, @vcpu is given and the event does not have the "vcpu" property,
+# an error is returned.
+#
+# Since: 2.2
+#
+# Example:
+#
+# -> { "execute": "trace-event-get-state",
+# "arguments": { "name": "qemu_memalign" } }
+# <- { "return": [ { "name": "qemu_memalign", "state": "disabled" } ] }
+#
+##
+{ 'command': 'trace-event-get-state',
+ 'data': {'name': 'str', '*vcpu': 'int'},
+ 'returns': ['TraceEventInfo'] }
+
+##
+# @trace-event-set-state:
+#
+# Set the dynamic tracing state of events.
+#
+# @name: Event name pattern (case-sensitive glob).
+# @enable: Whether to enable tracing.
+# @ignore-unavailable: Do not match unavailable events with @name.
+# @vcpu: The vCPU to act upon (all by default; since 2.7).
+#
+# An event's state is modified if:
+# - its name matches the @name pattern, and
+# - if @vcpu is given, the event has the "vcpu" property.
+#
+# Therefore, if @vcpu is given, the operation will only match per-vCPU events,
+# setting their state on the specified vCPU. Special case: if @name is an exact
+# match, @vcpu is given and the event does not have the "vcpu" property, an
+# error is returned.
+#
+# Since: 2.2
+#
+# Example:
+#
+# -> { "execute": "trace-event-set-state",
+# "arguments": { "name": "qemu_memalign", "enable": true } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'trace-event-set-state',
+ 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool',
+ '*vcpu': 'int'} }
diff --git a/qapi/transaction.json b/qapi/transaction.json
new file mode 100644
index 000000000..381a2df78
--- /dev/null
+++ b/qapi/transaction.json
@@ -0,0 +1,258 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Transactions
+##
+
+{ 'include': 'block-core.json' }
+
+##
+# @Abort:
+#
+# This action can be used to test transaction failure.
+#
+# Since: 1.6
+##
+{ 'struct': 'Abort',
+ 'data': { } }
+
+##
+# @ActionCompletionMode:
+#
+# An enumeration of Transactional completion modes.
+#
+# @individual: Do not attempt to cancel any other Actions if any Actions fail
+# after the Transaction request succeeds. All Actions that
+# can complete successfully will do so without waiting on others.
+# This is the default.
+#
+# @grouped: If any Action fails after the Transaction succeeds, cancel all
+# Actions. Actions do not complete until all Actions are ready to
+# complete. May be rejected by Actions that do not support this
+# completion mode.
+#
+# Since: 2.5
+##
+{ 'enum': 'ActionCompletionMode',
+ 'data': [ 'individual', 'grouped' ] }
+
+##
+# @TransactionActionKind:
+#
+# @abort: Since 1.6
+# @block-dirty-bitmap-add: Since 2.5
+# @block-dirty-bitmap-remove: Since 4.2
+# @block-dirty-bitmap-clear: Since 2.5
+# @block-dirty-bitmap-enable: Since 4.0
+# @block-dirty-bitmap-disable: Since 4.0
+# @block-dirty-bitmap-merge: Since 4.0
+# @blockdev-backup: Since 2.3
+# @blockdev-snapshot: Since 2.5
+# @blockdev-snapshot-internal-sync: Since 1.7
+# @blockdev-snapshot-sync: since 1.1
+# @drive-backup: Since 1.6
+#
+# Features:
+# @deprecated: Member @drive-backup is deprecated. Use member
+# @blockdev-backup instead.
+#
+# Since: 1.1
+##
+{ 'enum': 'TransactionActionKind',
+ 'data': [ 'abort', 'block-dirty-bitmap-add', 'block-dirty-bitmap-remove',
+ 'block-dirty-bitmap-clear', 'block-dirty-bitmap-enable',
+ 'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge',
+ 'blockdev-backup', 'blockdev-snapshot',
+ 'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync',
+ { 'name': 'drive-backup', 'features': [ 'deprecated' ] } ] }
+
+##
+# @AbortWrapper:
+#
+# Since: 1.6
+##
+{ 'struct': 'AbortWrapper',
+ 'data': { 'data': 'Abort' } }
+
+##
+# @BlockDirtyBitmapAddWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockDirtyBitmapAddWrapper',
+ 'data': { 'data': 'BlockDirtyBitmapAdd' } }
+
+##
+# @BlockDirtyBitmapWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockDirtyBitmapWrapper',
+ 'data': { 'data': 'BlockDirtyBitmap' } }
+
+##
+# @BlockDirtyBitmapMergeWrapper:
+#
+# Since: 4.0
+##
+{ 'struct': 'BlockDirtyBitmapMergeWrapper',
+ 'data': { 'data': 'BlockDirtyBitmapMerge' } }
+
+##
+# @BlockdevBackupWrapper:
+#
+# Since: 2.3
+##
+{ 'struct': 'BlockdevBackupWrapper',
+ 'data': { 'data': 'BlockdevBackup' } }
+
+##
+# @BlockdevSnapshotWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockdevSnapshotWrapper',
+ 'data': { 'data': 'BlockdevSnapshot' } }
+
+##
+# @BlockdevSnapshotInternalWrapper:
+#
+# Since: 1.7
+##
+{ 'struct': 'BlockdevSnapshotInternalWrapper',
+ 'data': { 'data': 'BlockdevSnapshotInternal' } }
+
+##
+# @BlockdevSnapshotSyncWrapper:
+#
+# Since: 1.1
+##
+{ 'struct': 'BlockdevSnapshotSyncWrapper',
+ 'data': { 'data': 'BlockdevSnapshotSync' } }
+
+##
+# @DriveBackupWrapper:
+#
+# Since: 1.6
+##
+{ 'struct': 'DriveBackupWrapper',
+ 'data': { 'data': 'DriveBackup' } }
+
+##
+# @TransactionAction:
+#
+# A discriminated record of operations that can be performed with
+# @transaction.
+#
+# Since: 1.1
+##
+{ 'union': 'TransactionAction',
+ 'base': { 'type': 'TransactionActionKind' },
+ 'discriminator': 'type',
+ 'data': {
+ 'abort': 'AbortWrapper',
+ 'block-dirty-bitmap-add': 'BlockDirtyBitmapAddWrapper',
+ 'block-dirty-bitmap-remove': 'BlockDirtyBitmapWrapper',
+ 'block-dirty-bitmap-clear': 'BlockDirtyBitmapWrapper',
+ 'block-dirty-bitmap-enable': 'BlockDirtyBitmapWrapper',
+ 'block-dirty-bitmap-disable': 'BlockDirtyBitmapWrapper',
+ 'block-dirty-bitmap-merge': 'BlockDirtyBitmapMergeWrapper',
+ 'blockdev-backup': 'BlockdevBackupWrapper',
+ 'blockdev-snapshot': 'BlockdevSnapshotWrapper',
+ 'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper',
+ 'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper',
+ 'drive-backup': 'DriveBackupWrapper'
+ } }
+
+##
+# @TransactionProperties:
+#
+# Optional arguments to modify the behavior of a Transaction.
+#
+# @completion-mode: Controls how jobs launched asynchronously by
+# Actions will complete or fail as a group.
+# See @ActionCompletionMode for details.
+#
+# Since: 2.5
+##
+{ 'struct': 'TransactionProperties',
+ 'data': {
+ '*completion-mode': 'ActionCompletionMode'
+ }
+}
+
+##
+# @transaction:
+#
+# Executes a number of transactionable QMP commands atomically. If any
+# operation fails, then the entire set of actions will be abandoned and the
+# appropriate error returned.
+#
+# For external snapshots, the dictionary contains the device, the file to use for
+# the new snapshot, and the format. The default format, if not specified, is
+# qcow2.
+#
+# Each new snapshot defaults to being created by QEMU (wiping any
+# contents if the file already exists), but it is also possible to reuse
+# an externally-created file. In the latter case, you should ensure that
+# the new image file has the same contents as the current one; QEMU cannot
+# perform any meaningful check. Typically this is achieved by using the
+# current image file as the backing file for the new image.
+#
+# On failure, the original disks pre-snapshot attempt will be used.
+#
+# For internal snapshots, the dictionary contains the device and the
+# snapshot's name. If an internal snapshot matching name already exists,
+# the request will be rejected. Only some image formats support it, for
+# example, qcow2, and rbd,
+#
+# On failure, qemu will try delete the newly created internal snapshot in the
+# transaction. When an I/O error occurs during deletion, the user needs to fix
+# it later with qemu-img or other command.
+#
+# @actions: List of @TransactionAction;
+# information needed for the respective operations.
+#
+# @properties: structure of additional options to control the
+# execution of the transaction. See @TransactionProperties
+# for additional detail.
+#
+# Returns: nothing on success
+#
+# Errors depend on the operations of the transaction
+#
+# Note: The transaction aborts on the first failure. Therefore, there will be
+# information on only one failed operation returned in an error condition, and
+# subsequent actions will not have been attempted.
+#
+# Since: 1.1
+#
+# Example:
+#
+# -> { "execute": "transaction",
+# "arguments": { "actions": [
+# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd0",
+# "snapshot-file": "/some/place/my-image",
+# "format": "qcow2" } },
+# { "type": "blockdev-snapshot-sync", "data" : { "node-name": "myfile",
+# "snapshot-file": "/some/place/my-image2",
+# "snapshot-node-name": "node3432",
+# "mode": "existing",
+# "format": "qcow2" } },
+# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd1",
+# "snapshot-file": "/some/place/my-image2",
+# "mode": "existing",
+# "format": "qcow2" } },
+# { "type": "blockdev-snapshot-internal-sync", "data" : {
+# "device": "ide-hd2",
+# "name": "snapshot0" } } ] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'transaction',
+ 'data': { 'actions': [ 'TransactionAction' ],
+ '*properties': 'TransactionProperties'
+ }
+}
diff --git a/qapi/ui.json b/qapi/ui.json
new file mode 100644
index 000000000..d7567ac86
--- /dev/null
+++ b/qapi/ui.json
@@ -0,0 +1,1306 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Remote desktop
+##
+
+{ 'include': 'common.json' }
+{ 'include': 'sockets.json' }
+
+##
+# @set_password:
+#
+# Sets the password of a remote display session.
+#
+# @protocol: - 'vnc' to modify the VNC server password
+# - 'spice' to modify the Spice server password
+#
+# @password: the new password
+#
+# @connected: how to handle existing clients when changing the
+# password. If nothing is specified, defaults to 'keep'
+# 'fail' to fail the command if clients are connected
+# 'disconnect' to disconnect existing clients
+# 'keep' to maintain existing clients
+#
+# Returns: - Nothing on success
+# - If Spice is not enabled, DeviceNotFound
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "set_password", "arguments": { "protocol": "vnc",
+# "password": "secret" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'set_password',
+ 'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }
+
+##
+# @expire_password:
+#
+# Expire the password of a remote display server.
+#
+# @protocol: the name of the remote display protocol 'vnc' or 'spice'
+#
+# @time: when to expire the password.
+#
+# - 'now' to expire the password immediately
+# - 'never' to cancel password expiration
+# - '+INT' where INT is the number of seconds from now (integer)
+# - 'INT' where INT is the absolute time in seconds
+#
+# Returns: - Nothing on success
+# - If @protocol is 'spice' and Spice is not active, DeviceNotFound
+#
+# Since: 0.14
+#
+# Notes: Time is relative to the server and currently there is no way to
+# coordinate server time with client time. It is not recommended to
+# use the absolute time version of the @time parameter unless you're
+# sure you are on the same machine as the QEMU instance.
+#
+# Example:
+#
+# -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
+# "time": "+60" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }
+
+##
+# @screendump:
+#
+# Write a PPM of the VGA screen to a file.
+#
+# @filename: the path of a new PPM file to store the image
+#
+# @device: ID of the display device that should be dumped. If this parameter
+# is missing, the primary display will be used. (Since 2.12)
+#
+# @head: head to use in case the device supports multiple heads. If this
+# parameter is missing, head #0 will be used. Also note that the head
+# can only be specified in conjunction with the device ID. (Since 2.12)
+#
+# Returns: Nothing on success
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "screendump",
+# "arguments": { "filename": "/tmp/image" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'screendump',
+ 'data': {'filename': 'str', '*device': 'str', '*head': 'int'},
+ 'coroutine': true }
+
+##
+# == Spice
+##
+
+##
+# @SpiceBasicInfo:
+#
+# The basic information for SPICE network connection
+#
+# @host: IP address
+#
+# @port: port number
+#
+# @family: address family
+#
+# Since: 2.1
+##
+{ 'struct': 'SpiceBasicInfo',
+ 'data': { 'host': 'str',
+ 'port': 'str',
+ 'family': 'NetworkAddressFamily' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SpiceServerInfo:
+#
+# Information about a SPICE server
+#
+# @auth: authentication method
+#
+# Since: 2.1
+##
+{ 'struct': 'SpiceServerInfo',
+ 'base': 'SpiceBasicInfo',
+ 'data': { '*auth': 'str' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SpiceChannel:
+#
+# Information about a SPICE client channel.
+#
+# @connection-id: SPICE connection id number. All channels with the same id
+# belong to the same SPICE session.
+#
+# @channel-type: SPICE channel type number. "1" is the main control
+# channel, filter for this one if you want to track spice
+# sessions only
+#
+# @channel-id: SPICE channel ID number. Usually "0", might be different when
+# multiple channels of the same type exist, such as multiple
+# display channels in a multihead setup
+#
+# @tls: true if the channel is encrypted, false otherwise.
+#
+# Since: 0.14
+##
+{ 'struct': 'SpiceChannel',
+ 'base': 'SpiceBasicInfo',
+ 'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
+ 'tls': 'bool'},
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SpiceQueryMouseMode:
+#
+# An enumeration of Spice mouse states.
+#
+# @client: Mouse cursor position is determined by the client.
+#
+# @server: Mouse cursor position is determined by the server.
+#
+# @unknown: No information is available about mouse mode used by
+# the spice server.
+#
+# Note: spice/enums.h has a SpiceMouseMode already, hence the name.
+#
+# Since: 1.1
+##
+{ 'enum': 'SpiceQueryMouseMode',
+ 'data': [ 'client', 'server', 'unknown' ],
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SpiceInfo:
+#
+# Information about the SPICE session.
+#
+# @enabled: true if the SPICE server is enabled, false otherwise
+#
+# @migrated: true if the last guest migration completed and spice
+# migration had completed as well. false otherwise. (since 1.4)
+#
+# @host: The hostname the SPICE server is bound to. This depends on
+# the name resolution on the host and may be an IP address.
+#
+# @port: The SPICE server's port number.
+#
+# @compiled-version: SPICE server version.
+#
+# @tls-port: The SPICE server's TLS port number.
+#
+# @auth: the current authentication type used by the server
+#
+# - 'none' if no authentication is being used
+# - 'spice' uses SASL or direct TLS authentication, depending on command
+# line options
+#
+# @mouse-mode: The mode in which the mouse cursor is displayed currently. Can
+# be determined by the client or the server, or unknown if spice
+# server doesn't provide this information. (since: 1.1)
+#
+# @channels: a list of @SpiceChannel for each active spice channel
+#
+# Since: 0.14
+##
+{ 'struct': 'SpiceInfo',
+ 'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
+ '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
+ 'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']},
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @query-spice:
+#
+# Returns information about the current SPICE server
+#
+# Returns: @SpiceInfo
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-spice" }
+# <- { "return": {
+# "enabled": true,
+# "auth": "spice",
+# "port": 5920,
+# "tls-port": 5921,
+# "host": "0.0.0.0",
+# "channels": [
+# {
+# "port": "54924",
+# "family": "ipv4",
+# "channel-type": 1,
+# "connection-id": 1804289383,
+# "host": "127.0.0.1",
+# "channel-id": 0,
+# "tls": true
+# },
+# {
+# "port": "36710",
+# "family": "ipv4",
+# "channel-type": 4,
+# "connection-id": 1804289383,
+# "host": "127.0.0.1",
+# "channel-id": 0,
+# "tls": false
+# },
+# [ ... more channels follow ... ]
+# ]
+# }
+# }
+#
+##
+{ 'command': 'query-spice', 'returns': 'SpiceInfo',
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SPICE_CONNECTED:
+#
+# Emitted when a SPICE client establishes a connection
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
+# "event": "SPICE_CONNECTED",
+# "data": {
+# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
+# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
+# }}
+#
+##
+{ 'event': 'SPICE_CONNECTED',
+ 'data': { 'server': 'SpiceBasicInfo',
+ 'client': 'SpiceBasicInfo' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SPICE_INITIALIZED:
+#
+# Emitted after initial handshake and authentication takes place (if any)
+# and the SPICE channel is up and running
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
+# "event": "SPICE_INITIALIZED",
+# "data": {"server": {"auth": "spice", "port": "5921",
+# "family": "ipv4", "host": "127.0.0.1"},
+# "client": {"port": "49004", "family": "ipv4", "channel-type": 3,
+# "connection-id": 1804289383, "host": "127.0.0.1",
+# "channel-id": 0, "tls": true}
+# }}
+#
+##
+{ 'event': 'SPICE_INITIALIZED',
+ 'data': { 'server': 'SpiceServerInfo',
+ 'client': 'SpiceChannel' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SPICE_DISCONNECTED:
+#
+# Emitted when the SPICE connection is closed
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
+# "event": "SPICE_DISCONNECTED",
+# "data": {
+# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
+# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
+# }}
+#
+##
+{ 'event': 'SPICE_DISCONNECTED',
+ 'data': { 'server': 'SpiceBasicInfo',
+ 'client': 'SpiceBasicInfo' },
+ 'if': 'CONFIG_SPICE' }
+
+##
+# @SPICE_MIGRATE_COMPLETED:
+#
+# Emitted when SPICE migration has completed
+#
+# Since: 1.3
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
+# "event": "SPICE_MIGRATE_COMPLETED" }
+#
+##
+{ 'event': 'SPICE_MIGRATE_COMPLETED',
+ 'if': 'CONFIG_SPICE' }
+
+##
+# == VNC
+##
+
+##
+# @VncBasicInfo:
+#
+# The basic information for vnc network connection
+#
+# @host: IP address
+#
+# @service: The service name of the vnc port. This may depend on the host
+# system's service database so symbolic names should not be relied
+# on.
+#
+# @family: address family
+#
+# @websocket: true in case the socket is a websocket (since 2.3).
+#
+# Since: 2.1
+##
+{ 'struct': 'VncBasicInfo',
+ 'data': { 'host': 'str',
+ 'service': 'str',
+ 'family': 'NetworkAddressFamily',
+ 'websocket': 'bool' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncServerInfo:
+#
+# The network connection information for server
+#
+# @auth: authentication method used for
+# the plain (non-websocket) VNC server
+#
+# Since: 2.1
+##
+{ 'struct': 'VncServerInfo',
+ 'base': 'VncBasicInfo',
+ 'data': { '*auth': 'str' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncClientInfo:
+#
+# Information about a connected VNC client.
+#
+# @x509_dname: If x509 authentication is in use, the Distinguished
+# Name of the client.
+#
+# @sasl_username: If SASL authentication is in use, the SASL username
+# used for authentication.
+#
+# Since: 0.14
+##
+{ 'struct': 'VncClientInfo',
+ 'base': 'VncBasicInfo',
+ 'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncInfo:
+#
+# Information about the VNC session.
+#
+# @enabled: true if the VNC server is enabled, false otherwise
+#
+# @host: The hostname the VNC server is bound to. This depends on
+# the name resolution on the host and may be an IP address.
+#
+# @family: - 'ipv6' if the host is listening for IPv6 connections
+# - 'ipv4' if the host is listening for IPv4 connections
+# - 'unix' if the host is listening on a unix domain socket
+# - 'unknown' otherwise
+#
+# @service: The service name of the server's port. This may depends
+# on the host system's service database so symbolic names should not
+# be relied on.
+#
+# @auth: the current authentication type used by the server
+#
+# - 'none' if no authentication is being used
+# - 'vnc' if VNC authentication is being used
+# - 'vencrypt+plain' if VEncrypt is used with plain text authentication
+# - 'vencrypt+tls+none' if VEncrypt is used with TLS and no authentication
+# - 'vencrypt+tls+vnc' if VEncrypt is used with TLS and VNC authentication
+# - 'vencrypt+tls+plain' if VEncrypt is used with TLS and plain text auth
+# - 'vencrypt+x509+none' if VEncrypt is used with x509 and no auth
+# - 'vencrypt+x509+vnc' if VEncrypt is used with x509 and VNC auth
+# - 'vencrypt+x509+plain' if VEncrypt is used with x509 and plain text auth
+# - 'vencrypt+tls+sasl' if VEncrypt is used with TLS and SASL auth
+# - 'vencrypt+x509+sasl' if VEncrypt is used with x509 and SASL auth
+#
+# @clients: a list of @VncClientInfo of all currently connected clients
+#
+# Since: 0.14
+##
+{ 'struct': 'VncInfo',
+ 'data': {'enabled': 'bool', '*host': 'str',
+ '*family': 'NetworkAddressFamily',
+ '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']},
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncPrimaryAuth:
+#
+# vnc primary authentication method.
+#
+# Since: 2.3
+##
+{ 'enum': 'VncPrimaryAuth',
+ 'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
+ 'tls', 'vencrypt', 'sasl' ],
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncVencryptSubAuth:
+#
+# vnc sub authentication method with vencrypt.
+#
+# Since: 2.3
+##
+{ 'enum': 'VncVencryptSubAuth',
+ 'data': [ 'plain',
+ 'tls-none', 'x509-none',
+ 'tls-vnc', 'x509-vnc',
+ 'tls-plain', 'x509-plain',
+ 'tls-sasl', 'x509-sasl' ],
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncServerInfo2:
+#
+# The network connection information for server
+#
+# @auth: The current authentication type used by the servers
+#
+# @vencrypt: The vencrypt sub authentication type used by the
+# servers, only specified in case auth == vencrypt.
+#
+# Since: 2.9
+##
+{ 'struct': 'VncServerInfo2',
+ 'base': 'VncBasicInfo',
+ 'data': { 'auth' : 'VncPrimaryAuth',
+ '*vencrypt' : 'VncVencryptSubAuth' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VncInfo2:
+#
+# Information about a vnc server
+#
+# @id: vnc server name.
+#
+# @server: A list of @VncBasincInfo describing all listening sockets.
+# The list can be empty (in case the vnc server is disabled).
+# It also may have multiple entries: normal + websocket,
+# possibly also ipv4 + ipv6 in the future.
+#
+# @clients: A list of @VncClientInfo of all currently connected clients.
+# The list can be empty, for obvious reasons.
+#
+# @auth: The current authentication type used by the non-websockets servers
+#
+# @vencrypt: The vencrypt authentication type used by the servers,
+# only specified in case auth == vencrypt.
+#
+# @display: The display device the vnc server is linked to.
+#
+# Since: 2.3
+##
+{ 'struct': 'VncInfo2',
+ 'data': { 'id' : 'str',
+ 'server' : ['VncServerInfo2'],
+ 'clients' : ['VncClientInfo'],
+ 'auth' : 'VncPrimaryAuth',
+ '*vencrypt' : 'VncVencryptSubAuth',
+ '*display' : 'str' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @query-vnc:
+#
+# Returns information about the current VNC server
+#
+# Returns: @VncInfo
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-vnc" }
+# <- { "return": {
+# "enabled":true,
+# "host":"0.0.0.0",
+# "service":"50402",
+# "auth":"vnc",
+# "family":"ipv4",
+# "clients":[
+# {
+# "host":"127.0.0.1",
+# "service":"50401",
+# "family":"ipv4"
+# }
+# ]
+# }
+# }
+#
+##
+{ 'command': 'query-vnc', 'returns': 'VncInfo',
+ 'if': 'CONFIG_VNC' }
+##
+# @query-vnc-servers:
+#
+# Returns a list of vnc servers. The list can be empty.
+#
+# Returns: a list of @VncInfo2
+#
+# Since: 2.3
+##
+{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
+ 'if': 'CONFIG_VNC' }
+
+##
+# @change-vnc-password:
+#
+# Change the VNC server password.
+#
+# @password: the new password to use with VNC authentication
+#
+# Since: 1.1
+#
+# Notes: An empty password in this command will set the password to the empty
+# string. Existing clients are unaffected by executing this command.
+##
+{ 'command': 'change-vnc-password',
+ 'data': { 'password': 'str' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VNC_CONNECTED:
+#
+# Emitted when a VNC client establishes a connection
+#
+# @server: server information
+#
+# @client: client information
+#
+# Note: This event is emitted before any authentication takes place, thus
+# the authentication ID is not provided
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "VNC_CONNECTED",
+# "data": {
+# "server": { "auth": "sasl", "family": "ipv4",
+# "service": "5901", "host": "0.0.0.0" },
+# "client": { "family": "ipv4", "service": "58425",
+# "host": "127.0.0.1" } },
+# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
+#
+##
+{ 'event': 'VNC_CONNECTED',
+ 'data': { 'server': 'VncServerInfo',
+ 'client': 'VncBasicInfo' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VNC_INITIALIZED:
+#
+# Emitted after authentication takes place (if any) and the VNC session is
+# made active
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "VNC_INITIALIZED",
+# "data": {
+# "server": { "auth": "sasl", "family": "ipv4",
+# "service": "5901", "host": "0.0.0.0"},
+# "client": { "family": "ipv4", "service": "46089",
+# "host": "127.0.0.1", "sasl_username": "luiz" } },
+# "timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
+#
+##
+{ 'event': 'VNC_INITIALIZED',
+ 'data': { 'server': 'VncServerInfo',
+ 'client': 'VncClientInfo' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# @VNC_DISCONNECTED:
+#
+# Emitted when the connection is closed
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.13
+#
+# Example:
+#
+# <- { "event": "VNC_DISCONNECTED",
+# "data": {
+# "server": { "auth": "sasl", "family": "ipv4",
+# "service": "5901", "host": "0.0.0.0" },
+# "client": { "family": "ipv4", "service": "58425",
+# "host": "127.0.0.1", "sasl_username": "luiz" } },
+# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
+#
+##
+{ 'event': 'VNC_DISCONNECTED',
+ 'data': { 'server': 'VncServerInfo',
+ 'client': 'VncClientInfo' },
+ 'if': 'CONFIG_VNC' }
+
+##
+# = Input
+##
+
+##
+# @MouseInfo:
+#
+# Information about a mouse device.
+#
+# @name: the name of the mouse device
+#
+# @index: the index of the mouse device
+#
+# @current: true if this device is currently receiving mouse events
+#
+# @absolute: true if this device supports absolute coordinates as input
+#
+# Since: 0.14
+##
+{ 'struct': 'MouseInfo',
+ 'data': {'name': 'str', 'index': 'int', 'current': 'bool',
+ 'absolute': 'bool'} }
+
+##
+# @query-mice:
+#
+# Returns information about each active mouse device
+#
+# Returns: a list of @MouseInfo for each device
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "query-mice" }
+# <- { "return": [
+# {
+# "name":"QEMU Microsoft Mouse",
+# "index":0,
+# "current":false,
+# "absolute":false
+# },
+# {
+# "name":"QEMU PS/2 Mouse",
+# "index":1,
+# "current":true,
+# "absolute":true
+# }
+# ]
+# }
+#
+##
+{ 'command': 'query-mice', 'returns': ['MouseInfo'] }
+
+##
+# @QKeyCode:
+#
+# An enumeration of key name.
+#
+# This is used by the @send-key command.
+#
+# @unmapped: since 2.0
+# @pause: since 2.0
+# @ro: since 2.4
+# @kp_comma: since 2.4
+# @kp_equals: since 2.6
+# @power: since 2.6
+# @hiragana: since 2.9
+# @henkan: since 2.9
+# @yen: since 2.9
+#
+# @sleep: since 2.10
+# @wake: since 2.10
+# @audionext: since 2.10
+# @audioprev: since 2.10
+# @audiostop: since 2.10
+# @audioplay: since 2.10
+# @audiomute: since 2.10
+# @volumeup: since 2.10
+# @volumedown: since 2.10
+# @mediaselect: since 2.10
+# @mail: since 2.10
+# @calculator: since 2.10
+# @computer: since 2.10
+# @ac_home: since 2.10
+# @ac_back: since 2.10
+# @ac_forward: since 2.10
+# @ac_refresh: since 2.10
+# @ac_bookmarks: since 2.10
+#
+# @muhenkan: since 2.12
+# @katakanahiragana: since 2.12
+#
+# @lang1: since 6.1
+# @lang2: since 6.1
+#
+# 'sysrq' was mistakenly added to hack around the fact that
+# the ps2 driver was not generating correct scancodes sequences
+# when 'alt+print' was pressed. This flaw is now fixed and the
+# 'sysrq' key serves no further purpose. Any further use of
+# 'sysrq' will be transparently changed to 'print', so they
+# are effectively synonyms.
+#
+# Since: 1.3
+#
+##
+{ 'enum': 'QKeyCode',
+ 'data': [ 'unmapped',
+ 'shift', 'shift_r', 'alt', 'alt_r', 'ctrl',
+ 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e',
+ 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right',
+ 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon',
+ 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b',
+ 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock',
+ 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
+ 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',
+ 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0',
+ 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8',
+ 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',
+ 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
+ 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
+ 'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause',
+ 'ro', 'hiragana', 'henkan', 'yen', 'muhenkan', 'katakanahiragana',
+ 'kp_comma', 'kp_equals', 'power', 'sleep', 'wake',
+ 'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute',
+ 'volumeup', 'volumedown', 'mediaselect',
+ 'mail', 'calculator', 'computer',
+ 'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks',
+ 'lang1', 'lang2' ] }
+
+##
+# @KeyValueKind:
+#
+# Since: 1.3
+##
+{ 'enum': 'KeyValueKind',
+ 'data': [ 'number', 'qcode' ] }
+
+##
+# @IntWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'IntWrapper',
+ 'data': { 'data': 'int' } }
+
+##
+# @QKeyCodeWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'QKeyCodeWrapper',
+ 'data': { 'data': 'QKeyCode' } }
+
+##
+# @KeyValue:
+#
+# Represents a keyboard key.
+#
+# Since: 1.3
+##
+{ 'union': 'KeyValue',
+ 'base': { 'type': 'KeyValueKind' },
+ 'discriminator': 'type',
+ 'data': {
+ 'number': 'IntWrapper',
+ 'qcode': 'QKeyCodeWrapper' } }
+
+##
+# @send-key:
+#
+# Send keys to guest.
+#
+# @keys: An array of @KeyValue elements. All @KeyValues in this array are
+# simultaneously sent to the guest. A @KeyValue.number value is sent
+# directly to the guest, while @KeyValue.qcode must be a valid
+# @QKeyCode value
+#
+# @hold-time: time to delay key up events, milliseconds. Defaults
+# to 100
+#
+# Returns: - Nothing on success
+# - If key is unknown or redundant, InvalidParameter
+#
+# Since: 1.3
+#
+# Example:
+#
+# -> { "execute": "send-key",
+# "arguments": { "keys": [ { "type": "qcode", "data": "ctrl" },
+# { "type": "qcode", "data": "alt" },
+# { "type": "qcode", "data": "delete" } ] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'send-key',
+ 'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }
+
+##
+# @InputButton:
+#
+# Button of a pointer input device (mouse, tablet).
+#
+# @side: front side button of a 5-button mouse (since 2.9)
+#
+# @extra: rear side button of a 5-button mouse (since 2.9)
+#
+# Since: 2.0
+##
+{ 'enum' : 'InputButton',
+ 'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side',
+ 'extra' ] }
+
+##
+# @InputAxis:
+#
+# Position axis of a pointer input device (mouse, tablet).
+#
+# Since: 2.0
+##
+{ 'enum' : 'InputAxis',
+ 'data' : [ 'x', 'y' ] }
+
+##
+# @InputKeyEvent:
+#
+# Keyboard input event.
+#
+# @key: Which key this event is for.
+# @down: True for key-down and false for key-up events.
+#
+# Since: 2.0
+##
+{ 'struct' : 'InputKeyEvent',
+ 'data' : { 'key' : 'KeyValue',
+ 'down' : 'bool' } }
+
+##
+# @InputBtnEvent:
+#
+# Pointer button input event.
+#
+# @button: Which button this event is for.
+# @down: True for key-down and false for key-up events.
+#
+# Since: 2.0
+##
+{ 'struct' : 'InputBtnEvent',
+ 'data' : { 'button' : 'InputButton',
+ 'down' : 'bool' } }
+
+##
+# @InputMoveEvent:
+#
+# Pointer motion input event.
+#
+# @axis: Which axis is referenced by @value.
+# @value: Pointer position. For absolute coordinates the
+# valid range is 0 -> 0x7ffff
+#
+# Since: 2.0
+##
+{ 'struct' : 'InputMoveEvent',
+ 'data' : { 'axis' : 'InputAxis',
+ 'value' : 'int' } }
+
+##
+# @InputEventKind:
+#
+# Since: 2.0
+##
+{ 'enum': 'InputEventKind',
+ 'data': [ 'key', 'btn', 'rel', 'abs' ] }
+
+##
+# @InputKeyEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputKeyEventWrapper',
+ 'data': { 'data': 'InputKeyEvent' } }
+
+##
+# @InputBtnEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputBtnEventWrapper',
+ 'data': { 'data': 'InputBtnEvent' } }
+
+##
+# @InputMoveEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputMoveEventWrapper',
+ 'data': { 'data': 'InputMoveEvent' } }
+
+##
+# @InputEvent:
+#
+# Input event union.
+#
+# @type: the input type, one of:
+#
+# - 'key': Input event of Keyboard
+# - 'btn': Input event of pointer buttons
+# - 'rel': Input event of relative pointer motion
+# - 'abs': Input event of absolute pointer motion
+#
+# Since: 2.0
+##
+{ 'union' : 'InputEvent',
+ 'base': { 'type': 'InputEventKind' },
+ 'discriminator': 'type',
+ 'data' : { 'key' : 'InputKeyEventWrapper',
+ 'btn' : 'InputBtnEventWrapper',
+ 'rel' : 'InputMoveEventWrapper',
+ 'abs' : 'InputMoveEventWrapper' } }
+
+##
+# @input-send-event:
+#
+# Send input event(s) to guest.
+#
+# The @device and @head parameters can be used to send the input event
+# to specific input devices in case (a) multiple input devices of the
+# same kind are added to the virtual machine and (b) you have
+# configured input routing (see docs/multiseat.txt) for those input
+# devices. The parameters work exactly like the device and head
+# properties of input devices. If @device is missing, only devices
+# that have no input routing config are admissible. If @device is
+# specified, both input devices with and without input routing config
+# are admissible, but devices with input routing config take
+# precedence.
+#
+# @device: display device to send event(s) to.
+# @head: head to send event(s) to, in case the
+# display device supports multiple scanouts.
+# @events: List of InputEvent union.
+#
+# Returns: Nothing on success.
+#
+# Since: 2.6
+#
+# Note: The consoles are visible in the qom tree, under
+# /backend/console[$index]. They have a device link and head property,
+# so it is possible to map which console belongs to which device and
+# display.
+#
+# Example:
+#
+# 1. Press left mouse button.
+#
+# -> { "execute": "input-send-event",
+# "arguments": { "device": "video0",
+# "events": [ { "type": "btn",
+# "data" : { "down": true, "button": "left" } } ] } }
+# <- { "return": {} }
+#
+# -> { "execute": "input-send-event",
+# "arguments": { "device": "video0",
+# "events": [ { "type": "btn",
+# "data" : { "down": false, "button": "left" } } ] } }
+# <- { "return": {} }
+#
+# 2. Press ctrl-alt-del.
+#
+# -> { "execute": "input-send-event",
+# "arguments": { "events": [
+# { "type": "key", "data" : { "down": true,
+# "key": {"type": "qcode", "data": "ctrl" } } },
+# { "type": "key", "data" : { "down": true,
+# "key": {"type": "qcode", "data": "alt" } } },
+# { "type": "key", "data" : { "down": true,
+# "key": {"type": "qcode", "data": "delete" } } } ] } }
+# <- { "return": {} }
+#
+# 3. Move mouse pointer to absolute coordinates (20000, 400).
+#
+# -> { "execute": "input-send-event" ,
+# "arguments": { "events": [
+# { "type": "abs", "data" : { "axis": "x", "value" : 20000 } },
+# { "type": "abs", "data" : { "axis": "y", "value" : 400 } } ] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'input-send-event',
+ 'data': { '*device': 'str',
+ '*head' : 'int',
+ 'events' : [ 'InputEvent' ] } }
+
+##
+# @DisplayGTK:
+#
+# GTK display options.
+#
+# @grab-on-hover: Grab keyboard input on mouse hover.
+# @zoom-to-fit: Zoom guest display to fit into the host window. When
+# turned off the host window will be resized instead.
+# In case the display device can notify the guest on
+# window resizes (virtio-gpu) this will default to "on",
+# assuming the guest will resize the display to match
+# the window size then. Otherwise it defaults to "off".
+# Since 3.1
+#
+# Since: 2.12
+#
+##
+{ 'struct' : 'DisplayGTK',
+ 'data' : { '*grab-on-hover' : 'bool',
+ '*zoom-to-fit' : 'bool' } }
+
+##
+# @DisplayEGLHeadless:
+#
+# EGL headless display options.
+#
+# @rendernode: Which DRM render node should be used. Default is the first
+# available node on the host.
+#
+# Since: 3.1
+#
+##
+{ 'struct' : 'DisplayEGLHeadless',
+ 'data' : { '*rendernode' : 'str' } }
+
+ ##
+ # @DisplayGLMode:
+ #
+ # Display OpenGL mode.
+ #
+ # @off: Disable OpenGL (default).
+ # @on: Use OpenGL, pick context type automatically.
+ # Would better be named 'auto' but is called 'on' for backward
+ # compatibility with bool type.
+ # @core: Use OpenGL with Core (desktop) Context.
+ # @es: Use OpenGL with ES (embedded systems) Context.
+ #
+ # Since: 3.0
+ #
+ ##
+{ 'enum' : 'DisplayGLMode',
+ 'data' : [ 'off', 'on', 'core', 'es' ] }
+
+##
+# @DisplayCurses:
+#
+# Curses display options.
+#
+# @charset: Font charset used by guest (default: CP437).
+#
+# Since: 4.0
+#
+##
+{ 'struct' : 'DisplayCurses',
+ 'data' : { '*charset' : 'str' } }
+
+##
+# @DisplayType:
+#
+# Display (user interface) type.
+#
+# @default: The default user interface, selecting from the first available
+# of gtk, sdl, cocoa, and vnc.
+#
+# @none: No user interface or video output display. The guest will
+# still see an emulated graphics card, but its output will not
+# be displayed to the QEMU user.
+#
+# @gtk: The GTK user interface.
+#
+# @sdl: The SDL user interface.
+#
+# @egl-headless: No user interface, offload GL operations to a local
+# DRI device. Graphical display need to be paired with
+# VNC or Spice. (Since 3.1)
+#
+# @curses: Display video output via curses. For graphics device
+# models which support a text mode, QEMU can display this
+# output using a curses/ncurses interface. Nothing is
+# displayed when the graphics device is in graphical mode or
+# if the graphics device does not support a text
+# mode. Generally only the VGA device models support text
+# mode.
+#
+# @cocoa: The Cocoa user interface.
+#
+# @spice-app: Set up a Spice server and run the default associated
+# application to connect to it. The server will redirect
+# the serial console and QEMU monitors. (Since 4.0)
+#
+# Since: 2.12
+#
+##
+{ 'enum' : 'DisplayType',
+ 'data' : [
+ { 'name': 'default' },
+ { 'name': 'none' },
+ { 'name': 'gtk', 'if': 'CONFIG_GTK' },
+ { 'name': 'sdl', 'if': 'CONFIG_SDL' },
+ { 'name': 'egl-headless',
+ 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } },
+ { 'name': 'curses', 'if': 'CONFIG_CURSES' },
+ { 'name': 'cocoa', 'if': 'CONFIG_COCOA' },
+ { 'name': 'spice-app', 'if': 'CONFIG_SPICE'} ] }
+
+##
+# @DisplayOptions:
+#
+# Display (user interface) options.
+#
+# @type: Which DisplayType qemu should use.
+# @full-screen: Start user interface in fullscreen mode (default: off).
+# @window-close: Allow to quit qemu with window close button (default: on).
+# @show-cursor: Force showing the mouse cursor (default: off).
+# (since: 5.0)
+# @gl: Enable OpenGL support (default: off).
+#
+# Since: 2.12
+#
+##
+{ 'union' : 'DisplayOptions',
+ 'base' : { 'type' : 'DisplayType',
+ '*full-screen' : 'bool',
+ '*window-close' : 'bool',
+ '*show-cursor' : 'bool',
+ '*gl' : 'DisplayGLMode' },
+ 'discriminator' : 'type',
+ 'data' : {
+ 'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' },
+ 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' },
+ 'egl-headless': { 'type': 'DisplayEGLHeadless',
+ 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }
+ }
+}
+
+##
+# @query-display-options:
+#
+# Returns information about display configuration
+#
+# Returns: @DisplayOptions
+#
+# Since: 3.1
+#
+##
+{ 'command': 'query-display-options',
+ 'returns': 'DisplayOptions' }
+
+##
+# @DisplayReloadType:
+#
+# Available DisplayReload types.
+#
+# @vnc: VNC display
+#
+# Since: 6.0
+#
+##
+{ 'enum': 'DisplayReloadType',
+ 'data': ['vnc'] }
+
+##
+# @DisplayReloadOptionsVNC:
+#
+# Specify the VNC reload options.
+#
+# @tls-certs: reload tls certs or not.
+#
+# Since: 6.0
+#
+##
+{ 'struct': 'DisplayReloadOptionsVNC',
+ 'data': { '*tls-certs': 'bool' } }
+
+##
+# @DisplayReloadOptions:
+#
+# Options of the display configuration reload.
+#
+# @type: Specify the display type.
+#
+# Since: 6.0
+#
+##
+{ 'union': 'DisplayReloadOptions',
+ 'base': {'type': 'DisplayReloadType'},
+ 'discriminator': 'type',
+ 'data': { 'vnc': 'DisplayReloadOptionsVNC' } }
+
+##
+# @display-reload:
+#
+# Reload display configuration.
+#
+# Returns: Nothing on success.
+#
+# Since: 6.0
+#
+# Example:
+#
+# -> { "execute": "display-reload",
+# "arguments": { "type": "vnc", "tls-certs": true } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'display-reload',
+ 'data': 'DisplayReloadOptions',
+ 'boxed' : true }
diff --git a/qapi/yank.json b/qapi/yank.json
new file mode 100644
index 000000000..167a77559
--- /dev/null
+++ b/qapi/yank.json
@@ -0,0 +1,119 @@
+# -*- Mode: Python -*-
+# vim: filetype=python
+#
+
+##
+# = Yank feature
+##
+
+##
+# @YankInstanceType:
+#
+# An enumeration of yank instance types. See @YankInstance for more
+# information.
+#
+# Since: 6.0
+##
+{ 'enum': 'YankInstanceType',
+ 'data': [ 'block-node', 'chardev', 'migration' ] }
+
+##
+# @YankInstanceBlockNode:
+#
+# Specifies which block graph node to yank. See @YankInstance for more
+# information.
+#
+# @node-name: the name of the block graph node
+#
+# Since: 6.0
+##
+{ 'struct': 'YankInstanceBlockNode',
+ 'data': { 'node-name': 'str' } }
+
+##
+# @YankInstanceChardev:
+#
+# Specifies which character device to yank. See @YankInstance for more
+# information.
+#
+# @id: the chardev's ID
+#
+# Since: 6.0
+##
+{ 'struct': 'YankInstanceChardev',
+ 'data': { 'id': 'str' } }
+
+##
+# @YankInstance:
+#
+# A yank instance can be yanked with the @yank qmp command to recover from a
+# hanging QEMU.
+#
+# Currently implemented yank instances:
+# - nbd block device:
+# Yanking it will shut down the connection to the nbd server without
+# attempting to reconnect.
+# - socket chardev:
+# Yanking it will shut down the connected socket.
+# - migration:
+# Yanking it will shut down all migration connections. Unlike
+# @migrate_cancel, it will not notify the migration process, so migration
+# will go into @failed state, instead of @cancelled state. @yank should be
+# used to recover from hangs.
+#
+# Since: 6.0
+##
+{ 'union': 'YankInstance',
+ 'base': { 'type': 'YankInstanceType' },
+ 'discriminator': 'type',
+ 'data': {
+ 'block-node': 'YankInstanceBlockNode',
+ 'chardev': 'YankInstanceChardev' } }
+
+##
+# @yank:
+#
+# Try to recover from hanging QEMU by yanking the specified instances. See
+# @YankInstance for more information.
+#
+# Takes a list of @YankInstance as argument.
+#
+# Returns: - Nothing on success
+# - @DeviceNotFound error, if any of the YankInstances doesn't exist
+#
+# Example:
+#
+# -> { "execute": "yank",
+# "arguments": {
+# "instances": [
+# { "type": "block-node",
+# "node-name": "nbd0" }
+# ] } }
+# <- { "return": {} }
+#
+# Since: 6.0
+##
+{ 'command': 'yank',
+ 'data': { 'instances': ['YankInstance'] },
+ 'allow-oob': true }
+
+##
+# @query-yank:
+#
+# Query yank instances. See @YankInstance for more information.
+#
+# Returns: list of @YankInstance
+#
+# Example:
+#
+# -> { "execute": "query-yank" }
+# <- { "return": [
+# { "type": "block-node",
+# "node-name": "nbd0" }
+# ] }
+#
+# Since: 6.0
+##
+{ 'command': 'query-yank',
+ 'returns': ['YankInstance'],
+ 'allow-oob': true }