QAPI patches for 2016-09-19

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJX4BH+AAoJEDhwtADrkYZTXmMP/0RzvxiFXLGcBKyjMPDmPXg4
 mUmje9ZYCRVoR8d8EM4dTnd6WYbUMgXc0oTTrPotwx63s6joRh5o+Mc4angKpAmg
 FbR3mBw44uXUruxmmMNn9WQYw9Z4VkvI5o+6S7AF83RBwyx2S2yJK1FihVZB8/99
 VMUsKnicu1dWlBKlFCJpTFvrv9lo8l5HqFJIzEDMT/HT6uOpiwh6unTmFGIwQ/t2
 QNpd++s5oWpbBrGbSCo2JEwgd83sRZS2NV6lhFdsDTmutbbWwCerLSIJ8YydqjEc
 ELrzwuf6w/G0hzzPvFTaSQX5M191pzXwLtEMZt6X+82OubowASepXvcaftN+w1wt
 qQYaFpqAVjcLZqq4LvJBZ/B8nKxc6858txK9ApMG4XD2qEtLZ5Pr1qv8JSYEjAKW
 id5dSYGVB9M99bPVGaoW/BUe4FzOzG7Cod2Rrf4L8hZ7TZ0EE+occvHdBjtbpTP0
 qV2FKr5N3tivNhLBNOJxnFDaw/E1k0qhDZ97QXxQDjcUu6EDQmtHIvrHc3I/mm97
 bpwSeZLpCTnrg2iIstKrYsPdo0pfpp3YDk7Apm/9tNzDQ05GBBbmkMm1Hz24ZvGD
 kgEkXhlJ6WCKzaZB1gZpoYJJVhT4l//FkONs7maLurGi50n2WxbmDY4wFj/4OZn5
 1pLasJmMGW7J+JHn4+Rm
 =Lojo
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-09-19' into staging

QAPI patches for 2016-09-19

# gpg: Signature made Mon 19 Sep 2016 17:27:42 BST
# gpg:                using RSA key 0x3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2016-09-19:
  Replace qmp-commands.hx by docs/qmp-commands.txt
  qmp-commands.hx: fix some styling
  build-sys: remove qmp-commands-old.h
  monitor: use qmp_dispatch()
  tests: add a test to check invalid args
  qapi: check invalid arguments on no-args commands
  qapi: remove the "middle" mode
  monitor: remove mhandler.cmd_new
  monitor: implement 'qmp_query_commands' without qmp_cmds
  monitor: use qmp_find_command() (using generated qapi code)
  qapi: export the marshallers
  qmp: Hack to keep commands configuration-specific
  qapi: Support unregistering QMP commands
  monitor: register gen:false commands manually
  monitor: simplify invalid_qmp_mode()
  qapi-schema: add 'device_add'
  qapi-schema: use generated marshaller for 'qmp_capabilities'
  build-sys: define QEMU_VERSION_{MAJOR, MINOR, MICRO}

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-09-19 18:06:51 +01:00
commit 33e1666b42
20 changed files with 461 additions and 1872 deletions

1
.gitignore vendored
View File

@ -55,7 +55,6 @@
/qemu-monitor-info.texi
/qemu-version.h
/qemu-version.h.tmp
/qmp-commands.txt
/vscclient
/fsdev/virtfs-proxy-helper
*.[1-9]

View File

@ -1245,7 +1245,6 @@ M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: qmp.c
F: monitor.c
F: qmp-commands.hx
F: docs/*qmp-*
F: scripts/qmp/
T: git git://repo.or.cz/qemu/armbru.git qapi-next

View File

@ -92,7 +92,6 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
DOCS+=qmp-commands.txt
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
@ -312,7 +311,7 @@ $(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." -m $<, \
$(gen-out-type) -o "." $<, \
" GEN $@")
qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
@ -432,7 +431,7 @@ endif
install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) docs/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
@ -555,9 +554,6 @@ qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@," GEN $@")
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")

View File

@ -156,7 +156,7 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/
endif
GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h qmp-commands-old.h
GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h
endif # CONFIG_SOFTMMU
@ -209,13 +209,10 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean: clean-target
rm -f *.a *~ $(PROGS)
rm -f $(shell find . -name '*.[od]')
rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
rm -f hmp-commands.h gdbstub-xml.c
ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp
endif

View File

@ -964,9 +964,9 @@ Example:
Used to generate the marshaling/dispatch functions for the commands
defined in the schema. The generated code implements
qmp_marshal_COMMAND() (mentioned in qmp-commands.hx, and registered
automatically), and declares qmp_COMMAND() that the user must
implement. The following files are generated:
qmp_marshal_COMMAND() (registered automatically), and declares
qmp_COMMAND() that the user must implement. The following files are
generated:
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
QMP command defined in the schema. Functions

File diff suppressed because it is too large Load Diff

View File

@ -119,17 +119,6 @@ There are a few things to be noticed:
5. Printing to the terminal is discouraged for QMP commands, we do it here
because it's the easiest way to demonstrate a QMP command
Now a little hack is needed. As we're still using the old QMP server we need
to add the new command to its internal dispatch table. This step won't be
required in the near future. Open the qmp-commands.hx file and add the
following at the bottom:
{
.name = "hello-world",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_hello_world,
},
You're done. Now build qemu, run it as suggested in the "Testing" section,
and then type the following QMP command:
@ -174,21 +163,6 @@ There are two important details to be noticed:
2. The C implementation signature must follow the schema's argument ordering,
which is defined by the "data" member
The last step is to update the qmp-commands.hx file:
{
.name = "hello-world",
.args_type = "message:s?",
.mhandler.cmd_new = qmp_marshal_hello_world,
},
Notice that the "args_type" member got our "message" argument. The character
"s" stands for "string" and "?" means it's optional. This too must be ordered
according to the C implementation and schema file. You can look for more
examples in the qmp-commands.hx file if you need to define more arguments.
Again, this step won't be required in the future.
Time to test our new version of the "hello-world" command. Build qemu, run it as
described in the "Testing" section and then send two commands:
@ -337,7 +311,7 @@ we should add it to the hmp-commands.hx file:
.args_type = "message:s?",
.params = "hello-world [message]",
.help = "Print message to the standard output",
.mhandler.cmd = hmp_hello_world,
.cmd = hmp_hello_world,
},
STEXI
@ -454,14 +428,6 @@ There are a number of things to be noticed:
6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
otherwise qemu won't build
The last step is to add the correspoding entry in the qmp-commands.hx file:
{
.name = "query-alarm-clock",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_query_alarm_clock,
},
Time to test the new command. Build qemu, run it as described in the "Testing"
section and try this:
@ -518,7 +484,7 @@ in the monitor.c file. The entry for the "info alarmclock" follows:
.args_type = "",
.params = "",
.help = "show information about the alarm clock",
.mhandler.info = hmp_info_alarm_clock,
.cmd = hmp_info_alarm_clock,
},
To test this, run qemu and type "info alarmclock" in the user monitor.
@ -600,14 +566,6 @@ iteration of the loop. That's because the alarm timer method in use is the
first element of the alarm_timers array. Also notice that QAPI lists are handled
by hand and we return the head of the list.
To test this you have to add the corresponding qmp-commands.hx entry:
{
.name = "query-alarm-methods",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_query_alarm_methods,
},
Now Build qemu, run it as explained in the "Testing" section and try our new
command:

View File

@ -18,7 +18,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the version of QEMU",
.mhandler.cmd = hmp_info_version,
.cmd = hmp_info_version,
},
STEXI
@ -32,7 +32,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the network state",
.mhandler.cmd = hmp_info_network,
.cmd = hmp_info_network,
},
STEXI
@ -46,7 +46,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the character devices",
.mhandler.cmd = hmp_info_chardev,
.cmd = hmp_info_chardev,
},
STEXI
@ -61,7 +61,7 @@ ETEXI
.params = "[-n] [-v] [device]",
.help = "show info of one block device or all block devices "
"(-n: show named nodes; -v: show details)",
.mhandler.cmd = hmp_info_block,
.cmd = hmp_info_block,
},
STEXI
@ -75,7 +75,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show block device statistics",
.mhandler.cmd = hmp_info_blockstats,
.cmd = hmp_info_blockstats,
},
STEXI
@ -89,7 +89,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show progress of ongoing block device operations",
.mhandler.cmd = hmp_info_block_jobs,
.cmd = hmp_info_block_jobs,
},
STEXI
@ -103,7 +103,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the cpu registers",
.mhandler.cmd = hmp_info_registers,
.cmd = hmp_info_registers,
},
STEXI
@ -118,7 +118,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show local apic state",
.mhandler.cmd = hmp_info_local_apic,
.cmd = hmp_info_local_apic,
},
#endif
@ -134,7 +134,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show io apic state",
.mhandler.cmd = hmp_info_io_apic,
.cmd = hmp_info_io_apic,
},
#endif
@ -149,7 +149,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show infos for each CPU",
.mhandler.cmd = hmp_info_cpus,
.cmd = hmp_info_cpus,
},
STEXI
@ -163,7 +163,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the command line history",
.mhandler.cmd = hmp_info_history,
.cmd = hmp_info_history,
},
STEXI
@ -180,11 +180,11 @@ ETEXI
.params = "",
.help = "show the interrupts statistics (if available)",
#ifdef TARGET_SPARC
.mhandler.cmd = sun4m_hmp_info_irq,
.cmd = sun4m_hmp_info_irq,
#elif defined(TARGET_LM32)
.mhandler.cmd = lm32_hmp_info_irq,
.cmd = lm32_hmp_info_irq,
#else
.mhandler.cmd = hmp_info_irq,
.cmd = hmp_info_irq,
#endif
},
@ -200,11 +200,11 @@ ETEXI
.params = "",
.help = "show i8259 (PIC) state",
#ifdef TARGET_SPARC
.mhandler.cmd = sun4m_hmp_info_pic,
.cmd = sun4m_hmp_info_pic,
#elif defined(TARGET_LM32)
.mhandler.cmd = lm32_hmp_info_pic,
.cmd = lm32_hmp_info_pic,
#else
.mhandler.cmd = hmp_info_pic,
.cmd = hmp_info_pic,
#endif
},
#endif
@ -220,7 +220,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show PCI info",
.mhandler.cmd = hmp_info_pci,
.cmd = hmp_info_pci,
},
STEXI
@ -236,7 +236,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show virtual to physical memory mappings",
.mhandler.cmd = hmp_info_tlb,
.cmd = hmp_info_tlb,
},
#endif
@ -252,7 +252,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the active virtual memory mappings",
.mhandler.cmd = hmp_info_mem,
.cmd = hmp_info_mem,
},
#endif
@ -267,7 +267,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory tree",
.mhandler.cmd = hmp_info_mtree,
.cmd = hmp_info_mtree,
},
STEXI
@ -281,7 +281,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show dynamic compiler info",
.mhandler.cmd = hmp_info_jit,
.cmd = hmp_info_jit,
},
STEXI
@ -295,7 +295,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show dynamic compiler opcode counters",
.mhandler.cmd = hmp_info_opcount,
.cmd = hmp_info_opcount,
},
STEXI
@ -309,7 +309,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show KVM information",
.mhandler.cmd = hmp_info_kvm,
.cmd = hmp_info_kvm,
},
STEXI
@ -323,7 +323,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show NUMA information",
.mhandler.cmd = hmp_info_numa,
.cmd = hmp_info_numa,
},
STEXI
@ -337,7 +337,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show guest USB devices",
.mhandler.cmd = hmp_info_usb,
.cmd = hmp_info_usb,
},
STEXI
@ -351,7 +351,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show host USB devices",
.mhandler.cmd = hmp_info_usbhost,
.cmd = hmp_info_usbhost,
},
STEXI
@ -365,7 +365,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show profiling information",
.mhandler.cmd = hmp_info_profile,
.cmd = hmp_info_profile,
},
STEXI
@ -379,7 +379,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show capture information",
.mhandler.cmd = hmp_info_capture,
.cmd = hmp_info_capture,
},
STEXI
@ -393,7 +393,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the currently saved VM snapshots",
.mhandler.cmd = hmp_info_snapshots,
.cmd = hmp_info_snapshots,
},
STEXI
@ -407,7 +407,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
.mhandler.cmd = hmp_info_status,
.cmd = hmp_info_status,
},
STEXI
@ -421,7 +421,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show which guest mouse is receiving events",
.mhandler.cmd = hmp_info_mice,
.cmd = hmp_info_mice,
},
STEXI
@ -435,7 +435,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the vnc server status",
.mhandler.cmd = hmp_info_vnc,
.cmd = hmp_info_vnc,
},
STEXI
@ -450,7 +450,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the spice server status",
.mhandler.cmd = hmp_info_spice,
.cmd = hmp_info_spice,
},
#endif
@ -465,7 +465,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM name",
.mhandler.cmd = hmp_info_name,
.cmd = hmp_info_name,
},
STEXI
@ -479,7 +479,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM UUID",
.mhandler.cmd = hmp_info_uuid,
.cmd = hmp_info_uuid,
},
STEXI
@ -493,7 +493,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show CPU statistics",
.mhandler.cmd = hmp_info_cpustats,
.cmd = hmp_info_cpustats,
},
STEXI
@ -508,7 +508,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show user network stack connection states",
.mhandler.cmd = hmp_info_usernet,
.cmd = hmp_info_usernet,
},
#endif
@ -523,7 +523,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show migration status",
.mhandler.cmd = hmp_info_migrate,
.cmd = hmp_info_migrate,
},
STEXI
@ -537,7 +537,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration capabilities",
.mhandler.cmd = hmp_info_migrate_capabilities,
.cmd = hmp_info_migrate_capabilities,
},
STEXI
@ -551,7 +551,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration parameters",
.mhandler.cmd = hmp_info_migrate_parameters,
.cmd = hmp_info_migrate_parameters,
},
STEXI
@ -565,7 +565,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration xbzrle cache size",
.mhandler.cmd = hmp_info_migrate_cache_size,
.cmd = hmp_info_migrate_cache_size,
},
STEXI
@ -579,7 +579,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show balloon information",
.mhandler.cmd = hmp_info_balloon,
.cmd = hmp_info_balloon,
},
STEXI
@ -593,7 +593,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show device tree",
.mhandler.cmd = hmp_info_qtree,
.cmd = hmp_info_qtree,
},
STEXI
@ -607,7 +607,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show qdev device model list",
.mhandler.cmd = hmp_info_qdm,
.cmd = hmp_info_qdm,
},
STEXI
@ -621,7 +621,7 @@ ETEXI
.args_type = "path:s?",
.params = "[path]",
.help = "show QOM composition tree",
.mhandler.cmd = hmp_info_qom_tree,
.cmd = hmp_info_qom_tree,
},
STEXI
@ -635,7 +635,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show roms",
.mhandler.cmd = hmp_info_roms,
.cmd = hmp_info_roms,
},
STEXI
@ -650,7 +650,7 @@ ETEXI
.params = "[name] [vcpu]",
.help = "show available trace-events & their state "
"(name: event name pattern; vcpu: vCPU to query, default is any)",
.mhandler.cmd = hmp_info_trace_events,
.cmd = hmp_info_trace_events,
.command_completion = info_trace_events_completion,
},
@ -665,7 +665,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the TPM device",
.mhandler.cmd = hmp_info_tpm,
.cmd = hmp_info_tpm,
},
STEXI
@ -679,7 +679,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory backends",
.mhandler.cmd = hmp_info_memdev,
.cmd = hmp_info_memdev,
},
STEXI
@ -693,7 +693,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory devices",
.mhandler.cmd = hmp_info_memory_devices,
.cmd = hmp_info_memory_devices,
},
STEXI
@ -707,7 +707,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show iothreads",
.mhandler.cmd = hmp_info_iothreads,
.cmd = hmp_info_iothreads,
},
STEXI
@ -721,7 +721,7 @@ ETEXI
.args_type = "name:s",
.params = "name",
.help = "Show rocker switch",
.mhandler.cmd = hmp_rocker,
.cmd = hmp_rocker,
},
STEXI
@ -735,7 +735,7 @@ ETEXI
.args_type = "name:s",
.params = "name",
.help = "Show rocker ports",
.mhandler.cmd = hmp_rocker_ports,
.cmd = hmp_rocker_ports,
},
STEXI
@ -749,7 +749,7 @@ ETEXI
.args_type = "name:s,tbl_id:i?",
.params = "name [tbl_id]",
.help = "Show rocker OF-DPA flow tables",
.mhandler.cmd = hmp_rocker_of_dpa_flows,
.cmd = hmp_rocker_of_dpa_flows,
},
STEXI
@ -763,7 +763,7 @@ ETEXI
.args_type = "name:s,type:i?",
.params = "name [type]",
.help = "Show rocker OF-DPA groups",
.mhandler.cmd = hmp_rocker_of_dpa_groups,
.cmd = hmp_rocker_of_dpa_groups,
},
STEXI
@ -778,7 +778,7 @@ ETEXI
.args_type = "addr:l",
.params = "address",
.help = "Display the value of a storage key",
.mhandler.cmd = hmp_info_skeys,
.cmd = hmp_info_skeys,
},
#endif
@ -793,7 +793,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "Display the latest dump status",
.mhandler.cmd = hmp_info_dump,
.cmd = hmp_info_dump,
},
STEXI
@ -807,7 +807,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "Show information about hotpluggable CPUs",
.mhandler.cmd = hmp_hotpluggable_cpus,
.cmd = hmp_hotpluggable_cpus,
},
STEXI

View File

@ -14,7 +14,7 @@ ETEXI
.args_type = "name:S?",
.params = "[cmd]",
.help = "show the help",
.mhandler.cmd = do_help_cmd,
.cmd = do_help_cmd,
},
STEXI
@ -28,7 +28,7 @@ ETEXI
.args_type = "device:B",
.params = "device|all",
.help = "commit changes to the disk images (if -snapshot is used) or backing files",
.mhandler.cmd = hmp_commit,
.cmd = hmp_commit,
},
STEXI
@ -47,7 +47,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "quit the emulator",
.mhandler.cmd = hmp_quit,
.cmd = hmp_quit,
},
STEXI
@ -61,7 +61,7 @@ ETEXI
.args_type = "device:B,size:o",
.params = "device size",
.help = "resize a block image",
.mhandler.cmd = hmp_block_resize,
.cmd = hmp_block_resize,
},
STEXI
@ -78,7 +78,7 @@ ETEXI
.args_type = "device:B,speed:o?,base:s?",
.params = "device [speed [base]]",
.help = "copy data from a backing file into a block device",
.mhandler.cmd = hmp_block_stream,
.cmd = hmp_block_stream,
},
STEXI
@ -92,7 +92,7 @@ ETEXI
.args_type = "device:B,speed:o",
.params = "device speed",
.help = "set maximum speed for a background block operation",
.mhandler.cmd = hmp_block_job_set_speed,
.cmd = hmp_block_job_set_speed,
},
STEXI
@ -107,7 +107,7 @@ ETEXI
.params = "[-f] device",
.help = "stop an active background block operation (use -f"
"\n\t\t\t if the operation is currently paused)",
.mhandler.cmd = hmp_block_job_cancel,
.cmd = hmp_block_job_cancel,
},
STEXI
@ -121,7 +121,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "stop an active background block operation",
.mhandler.cmd = hmp_block_job_complete,
.cmd = hmp_block_job_complete,
},
STEXI
@ -136,7 +136,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "pause an active background block operation",
.mhandler.cmd = hmp_block_job_pause,
.cmd = hmp_block_job_pause,
},
STEXI
@ -150,7 +150,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "resume a paused background block operation",
.mhandler.cmd = hmp_block_job_resume,
.cmd = hmp_block_job_resume,
},
STEXI
@ -164,7 +164,7 @@ ETEXI
.args_type = "force:-f,device:B",
.params = "[-f] device",
.help = "eject a removable medium (use -f to force it)",
.mhandler.cmd = hmp_eject,
.cmd = hmp_eject,
},
STEXI
@ -178,7 +178,7 @@ ETEXI
.args_type = "id:B",
.params = "device",
.help = "remove host block device",
.mhandler.cmd = hmp_drive_del,
.cmd = hmp_drive_del,
},
STEXI
@ -197,7 +197,7 @@ ETEXI
.args_type = "device:B,target:F,arg:s?,read-only-mode:s?",
.params = "device filename [format [read-only-mode]]",
.help = "change a removable medium, optional format",
.mhandler.cmd = hmp_change,
.cmd = hmp_change,
},
STEXI
@ -256,7 +256,7 @@ ETEXI
.args_type = "filename:F",
.params = "filename",
.help = "save screen into PPM image 'filename'",
.mhandler.cmd = hmp_screendump,
.cmd = hmp_screendump,
},
STEXI
@ -270,7 +270,7 @@ ETEXI
.args_type = "filename:F",
.params = "filename",
.help = "output logs to 'filename'",
.mhandler.cmd = hmp_logfile,
.cmd = hmp_logfile,
},
STEXI
@ -285,7 +285,7 @@ ETEXI
.params = "name on|off [vcpu]",
.help = "changes status of a specific trace event "
"(vcpu: vCPU to set, default is all)",
.mhandler.cmd = hmp_trace_event,
.cmd = hmp_trace_event,
.command_completion = trace_event_completion,
},
@ -301,7 +301,7 @@ ETEXI
.args_type = "op:s?,arg:F?",
.params = "on|off|flush|set [arg]",
.help = "open, close, or flush trace file, or set a new file name",
.mhandler.cmd = hmp_trace_file,
.cmd = hmp_trace_file,
},
STEXI
@ -316,7 +316,7 @@ ETEXI
.args_type = "items:s",
.params = "item1[,...]",
.help = "activate logging of the specified items",
.mhandler.cmd = hmp_log,
.cmd = hmp_log,
},
STEXI
@ -330,7 +330,7 @@ ETEXI
.args_type = "name:s?",
.params = "[tag|id]",
.help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
.mhandler.cmd = hmp_savevm,
.cmd = hmp_savevm,
},
STEXI
@ -347,7 +347,7 @@ ETEXI
.args_type = "name:s",
.params = "tag|id",
.help = "restore a VM snapshot from its tag or id",
.mhandler.cmd = hmp_loadvm,
.cmd = hmp_loadvm,
.command_completion = loadvm_completion,
},
@ -363,7 +363,7 @@ ETEXI
.args_type = "name:s",
.params = "tag|id",
.help = "delete a VM snapshot from its tag or id",
.mhandler.cmd = hmp_delvm,
.cmd = hmp_delvm,
.command_completion = delvm_completion,
},
@ -378,7 +378,7 @@ ETEXI
.args_type = "option:s?",
.params = "[on|off]",
.help = "run emulation in singlestep mode or switch to normal mode",
.mhandler.cmd = hmp_singlestep,
.cmd = hmp_singlestep,
},
STEXI
@ -393,7 +393,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "stop emulation",
.mhandler.cmd = hmp_stop,
.cmd = hmp_stop,
},
STEXI
@ -407,7 +407,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "resume emulation",
.mhandler.cmd = hmp_cont,
.cmd = hmp_cont,
},
STEXI
@ -421,7 +421,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "wakeup guest from suspend",
.mhandler.cmd = hmp_system_wakeup,
.cmd = hmp_system_wakeup,
},
STEXI
@ -435,7 +435,7 @@ ETEXI
.args_type = "device:s?",
.params = "[device]",
.help = "start gdbserver on given device (default 'tcp::1234'), stop with 'none'",
.mhandler.cmd = hmp_gdbserver,
.cmd = hmp_gdbserver,
},
STEXI
@ -449,7 +449,7 @@ ETEXI
.args_type = "fmt:/,addr:l",
.params = "/fmt addr",
.help = "virtual memory dump starting at 'addr'",
.mhandler.cmd = hmp_memory_dump,
.cmd = hmp_memory_dump,
},
STEXI
@ -463,7 +463,7 @@ ETEXI
.args_type = "fmt:/,addr:l",
.params = "/fmt addr",
.help = "physical memory dump starting at 'addr'",
.mhandler.cmd = hmp_physical_memory_dump,
.cmd = hmp_physical_memory_dump,
},
STEXI
@ -530,7 +530,7 @@ ETEXI
.args_type = "fmt:/,val:l",
.params = "/fmt expr",
.help = "print expression value (use $reg for CPU register access)",
.mhandler.cmd = do_print,
.cmd = do_print,
},
STEXI
@ -545,7 +545,7 @@ ETEXI
.args_type = "fmt:/,addr:i,index:i.",
.params = "/fmt addr",
.help = "I/O port read",
.mhandler.cmd = hmp_ioport_read,
.cmd = hmp_ioport_read,
},
STEXI
@ -559,7 +559,7 @@ ETEXI
.args_type = "fmt:/,addr:i,val:i",
.params = "/fmt addr value",
.help = "I/O port write",
.mhandler.cmd = hmp_ioport_write,
.cmd = hmp_ioport_write,
},
STEXI
@ -573,7 +573,7 @@ ETEXI
.args_type = "keys:s,hold-time:i?",
.params = "keys [hold_ms]",
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
.mhandler.cmd = hmp_sendkey,
.cmd = hmp_sendkey,
.command_completion = sendkey_completion,
},
@ -596,7 +596,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "reset the system",
.mhandler.cmd = hmp_system_reset,
.cmd = hmp_system_reset,
},
STEXI
@ -610,7 +610,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "send system power down event",
.mhandler.cmd = hmp_system_powerdown,
.cmd = hmp_system_powerdown,
},
STEXI
@ -624,7 +624,7 @@ ETEXI
.args_type = "start:i,size:i",
.params = "addr size",
.help = "compute the checksum of a memory region",
.mhandler.cmd = hmp_sum,
.cmd = hmp_sum,
},
STEXI
@ -638,7 +638,7 @@ ETEXI
.args_type = "devname:s",
.params = "device",
.help = "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')",
.mhandler.cmd = hmp_usb_add,
.cmd = hmp_usb_add,
},
STEXI
@ -653,7 +653,7 @@ ETEXI
.args_type = "devname:s",
.params = "device",
.help = "remove USB device 'bus.addr'",
.mhandler.cmd = hmp_usb_del,
.cmd = hmp_usb_del,
},
STEXI
@ -669,7 +669,7 @@ ETEXI
.args_type = "device:O",
.params = "driver[,prop=value][,...]",
.help = "add device, like -device on the command line",
.mhandler.cmd = hmp_device_add,
.cmd = hmp_device_add,
.command_completion = device_add_completion,
},
@ -684,7 +684,7 @@ ETEXI
.args_type = "id:s",
.params = "device",
.help = "remove device",
.mhandler.cmd = hmp_device_del,
.cmd = hmp_device_del,
.command_completion = device_del_completion,
},
@ -700,7 +700,7 @@ ETEXI
.args_type = "index:i",
.params = "index",
.help = "set the default CPU",
.mhandler.cmd = hmp_cpu,
.cmd = hmp_cpu,
},
STEXI
@ -714,7 +714,7 @@ ETEXI
.args_type = "dx_str:s,dy_str:s,dz_str:s?",
.params = "dx dy [dz]",
.help = "send mouse move events",
.mhandler.cmd = hmp_mouse_move,
.cmd = hmp_mouse_move,
},
STEXI
@ -729,7 +729,7 @@ ETEXI
.args_type = "button_state:i",
.params = "state",
.help = "change mouse button state (1=L, 2=M, 4=R)",
.mhandler.cmd = hmp_mouse_button,
.cmd = hmp_mouse_button,
},
STEXI
@ -743,7 +743,7 @@ ETEXI
.args_type = "index:i",
.params = "index",
.help = "set which mouse device receives events",
.mhandler.cmd = hmp_mouse_set,
.cmd = hmp_mouse_set,
},
STEXI
@ -761,7 +761,7 @@ ETEXI
.args_type = "path:F,freq:i?,bits:i?,nchannels:i?",
.params = "path [frequency [bits [channels]]]",
.help = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)",
.mhandler.cmd = hmp_wavcapture,
.cmd = hmp_wavcapture,
},
STEXI
@item wavcapture @var{filename} [@var{frequency} [@var{bits} [@var{channels}]]]
@ -782,7 +782,7 @@ ETEXI
.args_type = "n:i",
.params = "capture index",
.help = "stop capture",
.mhandler.cmd = hmp_stopcapture,
.cmd = hmp_stopcapture,
},
STEXI
@item stopcapture @var{index}
@ -798,7 +798,7 @@ ETEXI
.args_type = "val:l,size:i,filename:s",
.params = "addr size file",
.help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
.mhandler.cmd = hmp_memsave,
.cmd = hmp_memsave,
},
STEXI
@ -812,7 +812,7 @@ ETEXI
.args_type = "val:l,size:i,filename:s",
.params = "addr size file",
.help = "save to disk physical memory dump starting at 'addr' of size 'size'",
.mhandler.cmd = hmp_pmemsave,
.cmd = hmp_pmemsave,
},
STEXI
@ -826,7 +826,7 @@ ETEXI
.args_type = "bootdevice:s",
.params = "bootdevice",
.help = "define new values for the boot device list",
.mhandler.cmd = hmp_boot_set,
.cmd = hmp_boot_set,
},
STEXI
@ -844,7 +844,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "inject an NMI",
.mhandler.cmd = hmp_nmi,
.cmd = hmp_nmi,
},
STEXI
@item nmi @var{cpu}
@ -858,7 +858,7 @@ ETEXI
.args_type = "device:s,data:s",
.params = "device data",
.help = "Write to a ring buffer character device",
.mhandler.cmd = hmp_ringbuf_write,
.cmd = hmp_ringbuf_write,
.command_completion = ringbuf_write_completion,
},
@ -875,7 +875,7 @@ ETEXI
.args_type = "device:s,size:i",
.params = "device size",
.help = "Read from a ring buffer character device",
.mhandler.cmd = hmp_ringbuf_read,
.cmd = hmp_ringbuf_read,
.command_completion = ringbuf_write_completion,
},
@ -901,7 +901,7 @@ ETEXI
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)",
.mhandler.cmd = hmp_migrate,
.cmd = hmp_migrate,
},
@ -918,7 +918,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "cancel the current VM migration",
.mhandler.cmd = hmp_migrate_cancel,
.cmd = hmp_migrate_cancel,
},
STEXI
@ -933,7 +933,7 @@ ETEXI
.args_type = "uri:s",
.params = "uri",
.help = "Continue an incoming migration from an -incoming defer",
.mhandler.cmd = hmp_migrate_incoming,
.cmd = hmp_migrate_incoming,
},
STEXI
@ -954,7 +954,7 @@ ETEXI
"The cache size affects the number of cache misses."
"In case of a high cache miss ratio you need to increase"
" the cache size",
.mhandler.cmd = hmp_migrate_set_cache_size,
.cmd = hmp_migrate_set_cache_size,
},
STEXI
@ -969,7 +969,7 @@ ETEXI
.params = "value",
.help = "set maximum speed (in bytes) for migrations. "
"Defaults to MB if no size suffix is specified, ie. B/K/M/G/T",
.mhandler.cmd = hmp_migrate_set_speed,
.cmd = hmp_migrate_set_speed,
},
STEXI
@ -983,7 +983,7 @@ ETEXI
.args_type = "value:T",
.params = "value",
.help = "set maximum tolerated downtime (in seconds) for migrations",
.mhandler.cmd = hmp_migrate_set_downtime,
.cmd = hmp_migrate_set_downtime,
},
STEXI
@ -997,7 +997,7 @@ ETEXI
.args_type = "capability:s,state:b",
.params = "capability state",
.help = "Enable/Disable the usage of a capability for migration",
.mhandler.cmd = hmp_migrate_set_capability,
.cmd = hmp_migrate_set_capability,
.command_completion = migrate_set_capability_completion,
},
@ -1012,7 +1012,7 @@ ETEXI
.args_type = "parameter:s,value:s",
.params = "parameter value",
.help = "Set the parameter for migration",
.mhandler.cmd = hmp_migrate_set_parameter,
.cmd = hmp_migrate_set_parameter,
.command_completion = migrate_set_parameter_completion,
},
@ -1029,7 +1029,7 @@ ETEXI
.help = "Followup to a migration command to switch the migration"
" to postcopy mode. The postcopy-ram capability must "
"be set before the original migration command.",
.mhandler.cmd = hmp_migrate_start_postcopy,
.cmd = hmp_migrate_start_postcopy,
},
STEXI
@ -1044,7 +1044,7 @@ ETEXI
.args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
.params = "protocol hostname port tls-port cert-subject",
.help = "set migration information for remote display",
.mhandler.cmd = hmp_client_migrate_info,
.cmd = hmp_client_migrate_info,
},
STEXI
@ -1067,7 +1067,7 @@ ETEXI
"-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
"begin: the starting physical address.\n\t\t\t"
"length: the memory size, in bytes.",
.mhandler.cmd = hmp_dump_guest_memory,
.cmd = hmp_dump_guest_memory,
},
@ -1094,7 +1094,7 @@ ETEXI
.args_type = "filename:F",
.params = "",
.help = "Save guest storage keys into file 'filename'.\n",
.mhandler.cmd = hmp_dump_skeys,
.cmd = hmp_dump_skeys,
},
#endif
@ -1116,7 +1116,7 @@ ETEXI
"The default format is qcow2. The -n flag requests QEMU\n\t\t\t"
"to reuse the image found in new-image-file, instead of\n\t\t\t"
"recreating it from scratch.",
.mhandler.cmd = hmp_snapshot_blkdev,
.cmd = hmp_snapshot_blkdev,
},
STEXI
@ -1132,7 +1132,7 @@ ETEXI
.help = "take an internal snapshot of device.\n\t\t\t"
"The format of the image used by device must\n\t\t\t"
"support it, such as qcow2.\n\t\t\t",
.mhandler.cmd = hmp_snapshot_blkdev_internal,
.cmd = hmp_snapshot_blkdev_internal,
},
STEXI
@ -1150,7 +1150,7 @@ ETEXI
"the snapshot matching both id and name.\n\t\t\t"
"The format of the image used by device must\n\t\t\t"
"support it, such as qcow2.\n\t\t\t",
.mhandler.cmd = hmp_snapshot_delete_blkdev_internal,
.cmd = hmp_snapshot_delete_blkdev_internal,
},
STEXI
@ -1171,7 +1171,7 @@ ETEXI
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
"so that the result does not need a backing file.\n\t\t\t",
.mhandler.cmd = hmp_drive_mirror,
.cmd = hmp_drive_mirror,
},
STEXI
@item drive_mirror
@ -1194,7 +1194,7 @@ ETEXI
"so that the result does not need a backing file.\n\t\t\t"
"The -c flag requests QEMU to compress backup data\n\t\t\t"
"(if the target format supports it).\n\t\t\t",
.mhandler.cmd = hmp_drive_backup,
.cmd = hmp_drive_backup,
},
STEXI
@item drive_backup
@ -1212,7 +1212,7 @@ ETEXI
"[,snapshot=on|off][,cache=on|off]\n"
"[,readonly=on|off][,copy-on-read=on|off]",
.help = "add drive to PCI storage controller",
.mhandler.cmd = hmp_drive_add,
.cmd = hmp_drive_add,
},
STEXI
@ -1236,7 +1236,7 @@ ETEXI
"<error_status> = error string or 32bit\n\t\t\t"
"<tlb header> = 32bit x 4\n\t\t\t"
"<tlb header prefix> = 32bit x 4",
.mhandler.cmd = hmp_pcie_aer_inject_error,
.cmd = hmp_pcie_aer_inject_error,
},
STEXI
@ -1250,7 +1250,7 @@ ETEXI
.args_type = "device:s,opts:s?",
.params = "tap|user|socket|vde|netmap|bridge|vhost-user|dump [options]",
.help = "add host VLAN client",
.mhandler.cmd = hmp_host_net_add,
.cmd = hmp_host_net_add,
.command_completion = host_net_add_completion,
},
@ -1265,7 +1265,7 @@ ETEXI
.args_type = "vlan_id:i,device:s",
.params = "vlan_id name",
.help = "remove host VLAN client",
.mhandler.cmd = hmp_host_net_remove,
.cmd = hmp_host_net_remove,
.command_completion = host_net_remove_completion,
},
@ -1280,7 +1280,7 @@ ETEXI
.args_type = "netdev:O",
.params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user],id=str[,prop=value][,...]",
.help = "add host network device",
.mhandler.cmd = hmp_netdev_add,
.cmd = hmp_netdev_add,
.command_completion = netdev_add_completion,
},
@ -1295,7 +1295,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "remove host network device",
.mhandler.cmd = hmp_netdev_del,
.cmd = hmp_netdev_del,
.command_completion = netdev_del_completion,
},
@ -1310,7 +1310,7 @@ ETEXI
.args_type = "object:O",
.params = "[qom-type=]type,id=str[,prop=value][,...]",
.help = "create QOM object",
.mhandler.cmd = hmp_object_add,
.cmd = hmp_object_add,
.command_completion = object_add_completion,
},
@ -1325,7 +1325,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "destroy QOM object",
.mhandler.cmd = hmp_object_del,
.cmd = hmp_object_del,
.command_completion = object_del_completion,
},
@ -1341,7 +1341,7 @@ ETEXI
.args_type = "arg1:s,arg2:s?,arg3:s?",
.params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
.mhandler.cmd = hmp_hostfwd_add,
.cmd = hmp_hostfwd_add,
},
#endif
STEXI
@ -1356,7 +1356,7 @@ ETEXI
.args_type = "arg1:s,arg2:s?,arg3:s?",
.params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
.help = "remove host-to-guest TCP or UDP redirection",
.mhandler.cmd = hmp_hostfwd_remove,
.cmd = hmp_hostfwd_remove,
},
#endif
@ -1371,7 +1371,7 @@ ETEXI
.args_type = "value:M",
.params = "target",
.help = "request VM to change its memory allocation (in MB)",
.mhandler.cmd = hmp_balloon,
.cmd = hmp_balloon,
},
STEXI
@ -1385,7 +1385,7 @@ ETEXI
.args_type = "name:s,up:b",
.params = "name on|off",
.help = "change the link status of a network adapter",
.mhandler.cmd = hmp_set_link,
.cmd = hmp_set_link,
.command_completion = set_link_completion,
},
@ -1400,7 +1400,7 @@ ETEXI
.args_type = "action:s",
.params = "[reset|shutdown|poweroff|pause|debug|none]",
.help = "change watchdog action",
.mhandler.cmd = hmp_watchdog_action,
.cmd = hmp_watchdog_action,
.command_completion = watchdog_action_completion,
},
@ -1415,7 +1415,7 @@ ETEXI
.args_type = "aclname:s",
.params = "aclname",
.help = "list rules in the access control list",
.mhandler.cmd = hmp_acl_show,
.cmd = hmp_acl_show,
},
STEXI
@ -1432,7 +1432,7 @@ ETEXI
.args_type = "aclname:s,policy:s",
.params = "aclname allow|deny",
.help = "set default access control list policy",
.mhandler.cmd = hmp_acl_policy,
.cmd = hmp_acl_policy,
},
STEXI
@ -1448,7 +1448,7 @@ ETEXI
.args_type = "aclname:s,match:s,policy:s,index:i?",
.params = "aclname match allow|deny [index]",
.help = "add a match rule to the access control list",
.mhandler.cmd = hmp_acl_add,
.cmd = hmp_acl_add,
},
STEXI
@ -1467,7 +1467,7 @@ ETEXI
.args_type = "aclname:s,match:s",
.params = "aclname match",
.help = "remove a match rule from the access control list",
.mhandler.cmd = hmp_acl_remove,
.cmd = hmp_acl_remove,
},
STEXI
@ -1481,7 +1481,7 @@ ETEXI
.args_type = "aclname:s",
.params = "aclname",
.help = "reset the access control list",
.mhandler.cmd = hmp_acl_reset,
.cmd = hmp_acl_reset,
},
STEXI
@ -1496,7 +1496,7 @@ ETEXI
.args_type = "all:-a,writable:-w,uri:s",
.params = "nbd_server_start [-a] [-w] host:port",
.help = "serve block devices on the given host and port",
.mhandler.cmd = hmp_nbd_server_start,
.cmd = hmp_nbd_server_start,
},
STEXI
@item nbd_server_start @var{host}:@var{port}
@ -1512,7 +1512,7 @@ ETEXI
.args_type = "writable:-w,device:B",
.params = "nbd_server_add [-w] device",
.help = "export a block device via NBD",
.mhandler.cmd = hmp_nbd_server_add,
.cmd = hmp_nbd_server_add,
},
STEXI
@item nbd_server_add @var{device}
@ -1527,7 +1527,7 @@ ETEXI
.args_type = "",
.params = "nbd_server_stop",
.help = "stop serving block devices using the NBD protocol",
.mhandler.cmd = hmp_nbd_server_stop,
.cmd = hmp_nbd_server_stop,
},
STEXI
@item nbd_server_stop
@ -1543,7 +1543,7 @@ ETEXI
.args_type = "broadcast:-b,cpu_index:i,bank:i,status:l,mcg_status:l,addr:l,misc:l",
.params = "[-b] cpu bank status mcgstatus addr misc",
.help = "inject a MCE on the given CPU [and broadcast to other CPUs with -b option]",
.mhandler.cmd = hmp_mce,
.cmd = hmp_mce,
},
#endif
@ -1558,7 +1558,7 @@ ETEXI
.args_type = "fdname:s",
.params = "getfd name",
.help = "receive a file descriptor via SCM rights and assign it a name",
.mhandler.cmd = hmp_getfd,
.cmd = hmp_getfd,
},
STEXI
@ -1574,7 +1574,7 @@ ETEXI
.args_type = "fdname:s",
.params = "closefd name",
.help = "close a file descriptor previously passed via SCM rights",
.mhandler.cmd = hmp_closefd,
.cmd = hmp_closefd,
},
STEXI
@ -1590,7 +1590,7 @@ ETEXI
.args_type = "device:B,password:s",
.params = "block_passwd device password",
.help = "set the password of encrypted block devices",
.mhandler.cmd = hmp_block_passwd,
.cmd = hmp_block_passwd,
},
STEXI
@ -1604,7 +1604,7 @@ ETEXI
.args_type = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
.params = "device bps bps_rd bps_wr iops iops_rd iops_wr",
.help = "change I/O throttle limits for a block drive",
.mhandler.cmd = hmp_block_set_io_throttle,
.cmd = hmp_block_set_io_throttle,
},
STEXI
@ -1618,7 +1618,7 @@ ETEXI
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.mhandler.cmd = hmp_set_password,
.cmd = hmp_set_password,
},
STEXI
@ -1637,7 +1637,7 @@ ETEXI
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.mhandler.cmd = hmp_expire_password,
.cmd = hmp_expire_password,
},
STEXI
@ -1668,7 +1668,7 @@ ETEXI
.args_type = "args:s",
.params = "args",
.help = "add chardev",
.mhandler.cmd = hmp_chardev_add,
.cmd = hmp_chardev_add,
.command_completion = chardev_add_completion,
},
@ -1684,7 +1684,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "remove chardev",
.mhandler.cmd = hmp_chardev_remove,
.cmd = hmp_chardev_remove,
.command_completion = chardev_remove_completion,
},
@ -1700,7 +1700,7 @@ ETEXI
.args_type = "device:B,command:s",
.params = "[device] \"[command]\"",
.help = "run a qemu-io command on a block device",
.mhandler.cmd = hmp_qemu_io,
.cmd = hmp_qemu_io,
},
STEXI
@ -1715,7 +1715,7 @@ ETEXI
.args_type = "id:i",
.params = "id",
.help = "add cpu",
.mhandler.cmd = hmp_cpu_add,
.cmd = hmp_cpu_add,
},
STEXI
@ -1729,7 +1729,7 @@ ETEXI
.args_type = "path:s?",
.params = "path",
.help = "list QOM properties",
.mhandler.cmd = hmp_qom_list,
.cmd = hmp_qom_list,
},
STEXI
@ -1742,7 +1742,7 @@ ETEXI
.args_type = "path:s,property:s,value:s",
.params = "path property value",
.help = "set QOM property",
.mhandler.cmd = hmp_qom_set,
.cmd = hmp_qom_set,
},
STEXI
@ -1755,8 +1755,8 @@ ETEXI
.args_type = "item:s?",
.params = "[subcommand]",
.help = "show various information about the system state",
.mhandler.cmd = hmp_info_help,
.sub_table = info_cmds,
.cmd = hmp_info_help,
.sub_table = info_cmds,
},
STEXI

View File

@ -36,6 +36,7 @@ typedef struct QmpCommand
void qmp_register_command(const char *name, QmpCommandFunc *fn,
QmpCommandOptions options);
void qmp_unregister_command(const char *name);
QmpCommand *qmp_find_command(const char *name);
QObject *qmp_dispatch(QObject *request);
void qmp_disable_command(const char *name);

428
monitor.c
View File

@ -79,6 +79,7 @@
#include "sysemu/block-backend.h"
#include "sysemu/qtest.h"
#include "qemu/cutils.h"
#include "qapi/qmp/dispatch.h"
/* for hmp_info_irq/pic */
#if defined(TARGET_SPARC)
@ -129,13 +130,10 @@ typedef struct mon_cmd_t {
const char *args_type;
const char *params;
const char *help;
union {
void (*cmd)(Monitor *mon, const QDict *qdict);
void (*cmd_new)(QDict *params, QObject **ret_data, Error **errp);
} mhandler;
/* @sub_table is a list of 2nd level of commands. If it do not exist,
* mhandler should be used. If it exist, sub_table[?].mhandler should be
* used, and mhandler of 1st level plays the role of help function.
void (*cmd)(Monitor *mon, const QDict *qdict);
/* @sub_table is a list of 2nd level of commands. If it does not exist,
* cmd should be used. If it exists, sub_table[?].cmd should be
* used, and cmd of 1st level plays the role of help function.
*/
struct mon_cmd_t *sub_table;
void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
@ -168,7 +166,6 @@ struct MonFdset {
};
typedef struct {
QObject *id;
JSONMessageParser parser;
/*
* When a client connects, we're in capabilities negotiation mode.
@ -231,8 +228,6 @@ static int mon_refcount;
static mon_cmd_t mon_cmds[];
static mon_cmd_t info_cmds[];
static const mon_cmd_t qmp_cmds[];
Monitor *cur_mon;
static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
@ -403,49 +398,6 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
QDECREF(json);
}
static QDict *build_qmp_error_dict(Error *err)
{
QObject *obj;
obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %s } }",
QapiErrorClass_lookup[error_get_class(err)],
error_get_pretty(err));
return qobject_to_qdict(obj);
}
static void monitor_protocol_emitter(Monitor *mon, QObject *data,
Error *err)
{
QDict *qmp;
trace_monitor_protocol_emitter(mon);
if (!err) {
/* success response */
qmp = qdict_new();
if (data) {
qobject_incref(data);
qdict_put_obj(qmp, "return", data);
} else {
/* return an empty QDict by default */
qdict_put(qmp, "return", qdict_new());
}
} else {
/* error response */
qmp = build_qmp_error_dict(err);
}
if (mon->qmp.id) {
qdict_put_obj(qmp, "id", mon->qmp.id);
mon->qmp.id = NULL;
}
monitor_json_emitter(mon, QOBJECT(qmp));
QDECREF(qmp);
}
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
/* Limit guest-triggerable events to 1 per second */
[QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS },
@ -617,7 +569,7 @@ static void monitor_qapi_event_init(void)
qmp_event_set_func_emit(monitor_qapi_event_queue);
}
static void qmp_capabilities(QDict *params, QObject **ret_data, Error **errp)
void qmp_qmp_capabilities(Error **errp)
{
cur_mon->qmp.in_command_mode = true;
}
@ -956,21 +908,28 @@ static void hmp_info_help(Monitor *mon, const QDict *qdict)
help_cmd(mon, "info");
}
CommandInfoList *qmp_query_commands(Error **errp)
static void query_commands_cb(QmpCommand *cmd, void *opaque)
{
CommandInfoList *info, *cmd_list = NULL;
const mon_cmd_t *cmd;
CommandInfoList *info, **list = opaque;
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value));
info->value->name = g_strdup(cmd->name);
info->next = cmd_list;
cmd_list = info;
if (!cmd->enabled) {
return;
}
return cmd_list;
info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value));
info->value->name = g_strdup(cmd->name);
info->next = *list;
*list = info;
}
CommandInfoList *qmp_query_commands(Error **errp)
{
CommandInfoList *list = NULL;
qmp_for_each_command(query_commands_cb, &list);
return list;
}
EventInfoList *qmp_query_events(Error **errp)
@ -1007,6 +966,49 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
*ret_data = qobject_from_json(qmp_schema_json);
}
/*
* We used to define commands in qmp-commands.hx in addition to the
* QAPI schema. This permitted defining some of them only in certain
* configurations. query-commands has always reflected that (good,
* because it lets QMP clients figure out what's actually available),
* while query-qmp-schema never did (not so good). This function is a
* hack to keep the configuration-specific commands defined exactly as
* before, even though qmp-commands.hx is gone.
*
* FIXME Educate the QAPI schema on configuration-specific commands,
* and drop this hack.
*/
static void qmp_unregister_commands_hack(void)
{
#ifndef CONFIG_SPICE
qmp_unregister_command("query-spice");
#endif
#ifndef TARGET_I386
qmp_unregister_command("rtc-reset-reinjection");
#endif
#ifndef TARGET_S390X
qmp_unregister_command("dump-skeys");
#endif
#ifndef TARGET_ARM
qmp_unregister_command("query-gic-capabilities");
#endif
}
static void qmp_init_marshal(void)
{
qmp_register_command("query-qmp-schema", qmp_query_qmp_schema,
QCO_NO_OPTIONS);
qmp_register_command("device_add", qmp_device_add,
QCO_NO_OPTIONS);
qmp_register_command("netdev_add", qmp_netdev_add,
QCO_NO_OPTIONS);
/* call it after the rest of qapi_init() */
register_module_init(qmp_unregister_commands_hack, MODULE_INIT_QAPI);
}
qapi_init(qmp_init_marshal);
/* set the current CPU defined by the user */
int monitor_set_cpu(int cpu_index)
{
@ -2163,11 +2165,6 @@ static mon_cmd_t mon_cmds[] = {
{ NULL, NULL, },
};
static const mon_cmd_t qmp_cmds[] = {
#include "qmp-commands-old.h"
{ /* NULL */ },
};
/*******************************************************************/
static const char *pch;
@ -2518,11 +2515,6 @@ static const mon_cmd_t *search_dispatch_table(const mon_cmd_t *disp_table,
return NULL;
}
static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
{
return search_dispatch_table(qmp_cmds, cmdname);
}
/*
* Parse command name from @cmdp according to command table @table.
* If blank, return NULL.
@ -2954,7 +2946,7 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline)
return;
}
cmd->mhandler.cmd(mon, qdict);
cmd->cmd(mon, qdict);
QDECREF(qdict);
}
@ -3653,219 +3645,26 @@ static int monitor_can_read(void *opaque)
return (mon->suspend_cnt == 0) ? 1 : 0;
}
static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd,
static bool invalid_qmp_mode(const Monitor *mon, const char *cmd,
Error **errp)
{
bool is_cap = cmd->mhandler.cmd_new == qmp_capabilities;
bool is_cap = g_str_equal(cmd, "qmp_capabilities");
if (is_cap && mon->qmp.in_command_mode) {
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
"Capabilities negotiation is already complete, command "
"'%s' ignored", cmd->name);
"'%s' ignored", cmd);
return true;
}
if (!is_cap && !mon->qmp.in_command_mode) {
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
"Expecting capabilities negotiation with "
"'qmp_capabilities' before command '%s'", cmd->name);
"'qmp_capabilities' before command '%s'", cmd);
return true;
}
return false;
}
/*
* Argument validation rules:
*
* 1. The argument must exist in cmd_args qdict
* 2. The argument type must be the expected one
*
* Special case: If the argument doesn't exist in cmd_args and
* the QMP_ACCEPT_UNKNOWNS flag is set, then the
* checking is skipped for it.
*/
static void check_client_args_type(const QDict *client_args,
const QDict *cmd_args, int flags,
Error **errp)
{
const QDictEntry *ent;
for (ent = qdict_first(client_args); ent;ent = qdict_next(client_args,ent)){
QObject *obj;
QString *arg_type;
const QObject *client_arg = qdict_entry_value(ent);
const char *client_arg_name = qdict_entry_key(ent);
obj = qdict_get(cmd_args, client_arg_name);
if (!obj) {
if (flags & QMP_ACCEPT_UNKNOWNS) {
/* handler accepts unknowns */
continue;
}
/* client arg doesn't exist */
error_setg(errp, QERR_INVALID_PARAMETER, client_arg_name);
return;
}
arg_type = qobject_to_qstring(obj);
assert(arg_type != NULL);
/* check if argument's type is correct */
switch (qstring_get_str(arg_type)[0]) {
case 'F':
case 'B':
case 's':
if (qobject_type(client_arg) != QTYPE_QSTRING) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
client_arg_name, "string");
return;
}
break;
case 'i':
case 'l':
case 'M':
case 'o':
if (qobject_type(client_arg) != QTYPE_QINT) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
client_arg_name, "int");
return;
}
break;
case 'T':
if (qobject_type(client_arg) != QTYPE_QINT &&
qobject_type(client_arg) != QTYPE_QFLOAT) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
client_arg_name, "number");
return;
}
break;
case 'b':
case '-':
if (qobject_type(client_arg) != QTYPE_QBOOL) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
client_arg_name, "bool");
return;
}
break;
case 'O':
assert(flags & QMP_ACCEPT_UNKNOWNS);
break;
case 'q':
/* Any QObject can be passed. */
break;
case '/':
case '.':
/*
* These types are not supported by QMP and thus are not
* handled here. Fall through.
*/
default:
abort();
}
}
}
/*
* - Check if the client has passed all mandatory args
* - Set special flags for argument validation
*/
static void check_mandatory_args(const QDict *cmd_args,
const QDict *client_args, int *flags,
Error **errp)
{
const QDictEntry *ent;
for (ent = qdict_first(cmd_args); ent; ent = qdict_next(cmd_args, ent)) {
const char *cmd_arg_name = qdict_entry_key(ent);
QString *type = qobject_to_qstring(qdict_entry_value(ent));
assert(type != NULL);
if (qstring_get_str(type)[0] == 'O') {
assert((*flags & QMP_ACCEPT_UNKNOWNS) == 0);
*flags |= QMP_ACCEPT_UNKNOWNS;
} else if (qstring_get_str(type)[0] != '-' &&
qstring_get_str(type)[1] != '?' &&
!qdict_haskey(client_args, cmd_arg_name)) {
error_setg(errp, QERR_MISSING_PARAMETER, cmd_arg_name);
return;
}
}
}
static QDict *qdict_from_args_type(const char *args_type)
{
int i;
QDict *qdict;
QString *key, *type, *cur_qs;
assert(args_type != NULL);
qdict = qdict_new();
if (args_type == NULL || args_type[0] == '\0') {
/* no args, empty qdict */
goto out;
}
key = qstring_new();
type = qstring_new();
cur_qs = key;
for (i = 0;; i++) {
switch (args_type[i]) {
case ',':
case '\0':
qdict_put(qdict, qstring_get_str(key), type);
QDECREF(key);
if (args_type[i] == '\0') {
goto out;
}
type = qstring_new(); /* qdict has ref */
cur_qs = key = qstring_new();
break;
case ':':
cur_qs = type;
break;
default:
qstring_append_chr(cur_qs, args_type[i]);
break;
}
}
out:
return qdict;
}
/*
* Client argument checking rules:
*
* 1. Client must provide all mandatory arguments
* 2. Each argument provided by the client must be expected
* 3. Each argument provided by the client must have the type expected
* by the command
*/
static void qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args,
Error **errp)
{
Error *err = NULL;
int flags;
QDict *cmd_args;
cmd_args = qdict_from_args_type(cmd->args_type);
flags = 0;
check_mandatory_args(cmd_args, client_args, &flags, &err);
if (err) {
goto out;
}
check_client_args_type(client_args, cmd_args, flags, &err);
out:
error_propagate(errp, err);
QDECREF(cmd_args);
}
/*
* Input object checking rules
*
@ -3924,65 +3723,58 @@ static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
{
Error *local_err = NULL;
QObject *obj, *data;
QDict *input, *args;
const mon_cmd_t *cmd;
QObject *req, *rsp = NULL, *id = NULL;
QDict *qdict = NULL;
const char *cmd_name;
Monitor *mon = cur_mon;
Error *err = NULL;
args = input = NULL;
data = NULL;
obj = json_parser_parse(tokens, NULL);
if (!obj) {
// FIXME: should be triggered in json_parser_parse()
error_setg(&local_err, QERR_JSON_PARSING);
req = json_parser_parse_err(tokens, NULL, &err);
if (err || !req || qobject_type(req) != QTYPE_QDICT) {
if (!err) {
error_setg(&err, QERR_JSON_PARSING);
}
goto err_out;
}
input = qmp_check_input_obj(obj, &local_err);
if (!input) {
qobject_decref(obj);
qdict = qmp_check_input_obj(req, &err);
if (!qdict) {
goto err_out;
}
mon->qmp.id = qdict_get(input, "id");
qobject_incref(mon->qmp.id);
id = qdict_get(qdict, "id");
qobject_incref(id);
qdict_del(qdict, "id");
cmd_name = qdict_get_str(input, "execute");
cmd_name = qdict_get_str(qdict, "execute");
trace_handle_qmp_command(mon, cmd_name);
cmd = qmp_find_cmd(cmd_name);
if (!cmd) {
error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND,
"The command %s has not been found", cmd_name);
goto err_out;
}
if (invalid_qmp_mode(mon, cmd, &local_err)) {
if (invalid_qmp_mode(mon, cmd_name, &err)) {
goto err_out;
}
obj = qdict_get(input, "arguments");
if (!obj) {
args = qdict_new();
} else {
args = qobject_to_qdict(obj);
QINCREF(args);
}
qmp_check_client_args(cmd, args, &local_err);
if (local_err) {
goto err_out;
}
cmd->mhandler.cmd_new(args, &data, &local_err);
rsp = qmp_dispatch(req);
err_out:
monitor_protocol_emitter(mon, data, local_err);
qobject_decref(data);
error_free(local_err);
QDECREF(input);
QDECREF(args);
if (err) {
qdict = qdict_new();
qdict_put_obj(qdict, "error", qmp_build_error_object(err));
error_free(err);
rsp = QOBJECT(qdict);
}
if (rsp) {
if (id) {
qdict_put_obj(qobject_to_qdict(rsp), "id", id);
id = NULL;
}
monitor_json_emitter(mon, rsp);
}
qobject_decref(id);
qobject_decref(rsp);
qobject_decref(req);
}
static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
@ -4047,7 +3839,9 @@ static QObject *get_qmp_greeting(void)
QObject *ver = NULL;
qmp_marshal_query_version(NULL, &ver, NULL);
return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': []}}",
ver);
}
static void monitor_qmp_event(void *opaque, int event)

View File

@ -20,6 +20,27 @@
# QAPI introspection
{ 'include': 'qapi/introspect.json' }
##
# @qmp_capabilities:
#
# Enable QMP capabilities.
#
# Arguments: None.
#
# Example:
#
# -> { "execute": "qmp_capabilities" }
# <- { "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/qmp-spec.txt)
#
# Since: 0.13
#
##
{ 'command': 'qmp_capabilities' }
##
# @LostTickPolicy:
#
@ -2179,6 +2200,46 @@
##
{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }
##
# @device_add:
#
# @driver: the name of the new device's driver
#
# @bus: #optional the device's parent bus (device tree path)
#
# @id: the device's ID, must be unique
#
# Additional arguments depend on the type.
#
# Add a device.
#
# Notes:
# 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', 'id': 'str'},
'gen': false } # so we can get the additional arguments
##
# @device_del:
#

View File

@ -30,6 +30,14 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn,
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
}
void qmp_unregister_command(const char *name)
{
QmpCommand *cmd = qmp_find_command(name);
QTAILQ_REMOVE(&qmp_commands, cmd, node);
g_free(cmd);
}
QmpCommand *qmp_find_command(const char *name)
{
QmpCommand *cmd;

16
qmp.c
View File

@ -51,21 +51,11 @@ NameInfo *qmp_query_name(Error **errp)
VersionInfo *qmp_query_version(Error **errp)
{
VersionInfo *info = g_new0(VersionInfo, 1);
const char *version = QEMU_VERSION;
const char *tmp;
int err;
info->qemu = g_new0(VersionTriple, 1);
err = qemu_strtoll(version, &tmp, 10, &info->qemu->major);
assert(err == 0);
tmp++;
err = qemu_strtoll(tmp, &tmp, 10, &info->qemu->minor);
assert(err == 0);
tmp++;
err = qemu_strtoll(tmp, &tmp, 10, &info->qemu->micro);
assert(err == 0);
info->qemu->major = QEMU_VERSION_MAJOR;
info->qemu->minor = QEMU_VERSION_MINOR;
info->qemu->micro = QEMU_VERSION_MICRO;
info->package = g_strdup(QEMU_PKGVERSION);
return info;

View File

@ -7,7 +7,13 @@ while read line; do
case $line in
VERSION=*) # configuration
version=${line#*=}
major=$(echo "$version" | cut -d. -f1)
minor=$(echo "$version" | cut -d. -f2)
micro=$(echo "$version" | cut -d. -f3)
echo "#define QEMU_VERSION \"$version\""
echo "#define QEMU_VERSION_MAJOR $major"
echo "#define QEMU_VERSION_MINOR $minor"
echo "#define QEMU_VERSION_MICRO $micro"
;;
qemu_*dir=*) # qemu-specific directory configuration
name=${line%=*}

View File

@ -84,10 +84,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out,
def gen_marshal_proto(name):
ret = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
if not middle_mode:
ret = 'static ' + ret
return ret
return 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
def gen_marshal_decl(name):
@ -98,6 +95,8 @@ def gen_marshal_decl(name):
def gen_marshal(name, arg_type, boxed, ret_type):
have_args = arg_type and not arg_type.is_empty()
ret = mcgen('''
%(proto)s
@ -112,17 +111,31 @@ def gen_marshal(name, arg_type, boxed, ret_type):
''',
c_type=ret_type.c_type())
if arg_type and not arg_type.is_empty():
if have_args:
visit_members = ('visit_type_%s_members(v, &arg, &err);'
% arg_type.c_name())
ret += mcgen('''
Visitor *v;
%(c_name)s arg = {0};
''',
c_name=arg_type.c_name())
else:
visit_members = ''
ret += mcgen('''
Visitor *v = NULL;
if (args) {
''')
push_indent()
ret += mcgen('''
v = qmp_input_visitor_new(QOBJECT(args), true);
visit_start_struct(v, NULL, NULL, 0, &err);
if (err) {
goto out;
}
visit_type_%(c_name)s_members(v, &arg, &err);
%(visit_members)s
if (!err) {
visit_check_struct(v, &err);
}
@ -131,35 +144,47 @@ def gen_marshal(name, arg_type, boxed, ret_type):
goto out;
}
''',
c_name=arg_type.c_name())
visit_members=visit_members)
else:
if not have_args:
pop_indent()
ret += mcgen('''
(void)args;
}
''')
ret += gen_call(name, arg_type, boxed, ret_type)
# 'goto out' produced above for arg_type, and by gen_call() for ret_type
if (arg_type and not arg_type.is_empty()) or ret_type:
ret += mcgen('''
ret += mcgen('''
out:
''')
ret += mcgen('''
error_propagate(errp, err);
''')
if arg_type and not arg_type.is_empty():
ret += mcgen('''
visit_free(v);
''')
if have_args:
visit_members = ('visit_type_%s_members(v, &arg, NULL);'
% arg_type.c_name())
else:
visit_members = ''
ret += mcgen('''
if (args) {
''')
push_indent()
ret += mcgen('''
v = qapi_dealloc_visitor_new();
visit_start_struct(v, NULL, NULL, 0, NULL);
visit_type_%(c_name)s_members(v, &arg, NULL);
%(visit_members)s
visit_end_struct(v, NULL);
visit_free(v);
''',
c_name=arg_type.c_name())
visit_members=visit_members)
if not have_args:
pop_indent()
ret += mcgen('''
}
''')
ret += mcgen('''
}
@ -209,8 +234,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
self._visited_ret_types = set()
def visit_end(self):
if not middle_mode:
self.defn += gen_registry(self._regy)
self.defn += gen_registry(self._regy)
self._regy = None
self._visited_ret_types = None
@ -222,21 +246,12 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
if ret_type and ret_type not in self._visited_ret_types:
self._visited_ret_types.add(ret_type)
self.defn += gen_marshal_output(ret_type)
if middle_mode:
self.decl += gen_marshal_decl(name)
self.decl += gen_marshal_decl(name)
self.defn += gen_marshal(name, arg_type, boxed, ret_type)
if not middle_mode:
self._regy += gen_register_command(name, success_response)
self._regy += gen_register_command(name, success_response)
middle_mode = False
(input_file, output_dir, do_c, do_h, prefix, opts) = \
parse_command_line("m", ["middle"])
for o, a in opts:
if o in ("-m", "--middle"):
middle_mode = True
(input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
c_comment = '''
/*

View File

@ -198,6 +198,26 @@ static void test_qga_ping(gconstpointer fix)
QDECREF(ret);
}
static void test_qga_invalid_args(gconstpointer fix)
{
const TestFixture *fixture = fix;
QDict *ret, *error;
const gchar *class, *desc;
ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', "
"'arguments': {'foo': 42 }}");
g_assert_nonnull(ret);
error = qdict_get_qdict(ret, "error");
class = qdict_get_try_str(error, "class");
desc = qdict_get_try_str(error, "desc");
g_assert_cmpstr(class, ==, "GenericError");
g_assert_cmpstr(desc, ==, "QMP input object member 'foo' is unexpected");
QDECREF(ret);
}
static void test_qga_invalid_cmd(gconstpointer fix)
{
const TestFixture *fixture = fix;
@ -911,6 +931,7 @@ int main(int argc, char **argv)
g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
g_test_add_data_func("/qga/invalid-args", &fix, test_qga_invalid_args);
g_test_add_data_func("/qga/fsfreeze-status", &fix,
test_qga_fsfreeze_status);

View File

@ -106,6 +106,7 @@ static void test_dispatch_cmd(void)
static void test_dispatch_cmd_failure(void)
{
QDict *req = qdict_new();
QDict *args = qdict_new();
QObject *resp;
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
@ -116,6 +117,20 @@ static void test_dispatch_cmd_failure(void)
qobject_decref(resp);
QDECREF(req);
/* check that with extra arguments it throws an error */
req = qdict_new();
qdict_put(args, "a", qint_from_int(66));
qdict_put(req, "arguments", args);
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
resp = qmp_dispatch(QOBJECT(req));
assert(resp != NULL);
assert(qdict_haskey(qobject_to_qdict(resp), "error"));
qobject_decref(resp);
QDECREF(req);
}
static QObject *test_qmp_dispatch(QDict *req)

View File

@ -98,7 +98,6 @@ qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p"
# monitor.c
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
monitor_protocol_emitter(void *mon) "mon %p"
monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p"
monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p"
monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event=%d data=%p rate=%" PRId64

1
vl.c
View File

@ -2987,6 +2987,7 @@ int main(int argc, char **argv, char **envp)
qemu_init_exec_dir(argv[0]);
module_call_init(MODULE_INIT_QOM);
module_call_init(MODULE_INIT_QAPI);
qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts);