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-monitor-info.texi
/qemu-version.h /qemu-version.h
/qemu-version.h.tmp /qemu-version.h.tmp
/qmp-commands.txt
/vscclient /vscclient
/fsdev/virtfs-proxy-helper /fsdev/virtfs-proxy-helper
*.[1-9] *.[1-9]

View File

@ -1245,7 +1245,6 @@ M: Markus Armbruster <armbru@redhat.com>
S: Supported S: Supported
F: qmp.c F: qmp.c
F: monitor.c F: monitor.c
F: qmp-commands.hx
F: docs/*qmp-* F: docs/*qmp-*
F: scripts/qmp/ F: scripts/qmp/
T: git git://repo.or.cz/qemu/armbru.git qapi-next 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 ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8 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 ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1 DOCS+=fsdev/virtfs-proxy-helper.1
endif endif
@ -312,7 +311,7 @@ $(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
qmp-commands.h qmp-marshal.c :\ qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." -m $<, \ $(gen-out-type) -o "." $<, \
" GEN $@") " GEN $@")
qmp-introspect.h qmp-introspect.c :\ qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
@ -432,7 +431,7 @@ endif
install-doc: $(DOCS) install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)" $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(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 ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 "$(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 qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@") $(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 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@") $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")

View File

@ -156,7 +156,7 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/ obj-y += hw/$(TARGET_BASE_ARCH)/
endif 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 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 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)$@") $(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 clean: clean-target
rm -f *.a *~ $(PROGS) rm -f *.a *~ $(PROGS)
rm -f $(shell find . -name '*.[od]') 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 ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp rm -f *.stp
endif endif

View File

@ -964,9 +964,9 @@ Example:
Used to generate the marshaling/dispatch functions for the commands Used to generate the marshaling/dispatch functions for the commands
defined in the schema. The generated code implements defined in the schema. The generated code implements
qmp_marshal_COMMAND() (mentioned in qmp-commands.hx, and registered qmp_marshal_COMMAND() (registered automatically), and declares
automatically), and declares qmp_COMMAND() that the user must qmp_COMMAND() that the user must implement. The following files are
implement. The following files are generated: generated:
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each $(prefix)qmp-marshal.c: command marshal/dispatch functions for each
QMP command defined in the schema. Functions 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 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 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, You're done. Now build qemu, run it as suggested in the "Testing" section,
and then type the following QMP command: 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, 2. The C implementation signature must follow the schema's argument ordering,
which is defined by the "data" member 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 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: 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?", .args_type = "message:s?",
.params = "hello-world [message]", .params = "hello-world [message]",
.help = "Print message to the standard output", .help = "Print message to the standard output",
.mhandler.cmd = hmp_hello_world, .cmd = hmp_hello_world,
}, },
STEXI 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, 6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
otherwise qemu won't build 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" Time to test the new command. Build qemu, run it as described in the "Testing"
section and try this: section and try this:
@ -518,7 +484,7 @@ in the monitor.c file. The entry for the "info alarmclock" follows:
.args_type = "", .args_type = "",
.params = "", .params = "",
.help = "show information about the alarm clock", .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. 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 first element of the alarm_timers array. Also notice that QAPI lists are handled
by hand and we return the head of the list. 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 Now Build qemu, run it as explained in the "Testing" section and try our new
command: command:

View File

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

View File

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

View File

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

428
monitor.c
View File

@ -79,6 +79,7 @@
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "sysemu/qtest.h" #include "sysemu/qtest.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qapi/qmp/dispatch.h"
/* for hmp_info_irq/pic */ /* for hmp_info_irq/pic */
#if defined(TARGET_SPARC) #if defined(TARGET_SPARC)
@ -129,13 +130,10 @@ typedef struct mon_cmd_t {
const char *args_type; const char *args_type;
const char *params; const char *params;
const char *help; const char *help;
union { void (*cmd)(Monitor *mon, const QDict *qdict);
void (*cmd)(Monitor *mon, const QDict *qdict); /* @sub_table is a list of 2nd level of commands. If it does not exist,
void (*cmd_new)(QDict *params, QObject **ret_data, Error **errp); * cmd should be used. If it exists, sub_table[?].cmd should be
} mhandler; * used, and cmd of 1st level plays the role of help function.
/* @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.
*/ */
struct mon_cmd_t *sub_table; struct mon_cmd_t *sub_table;
void (*command_completion)(ReadLineState *rs, int nb_args, const char *str); void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
@ -168,7 +166,6 @@ struct MonFdset {
}; };
typedef struct { typedef struct {
QObject *id;
JSONMessageParser parser; JSONMessageParser parser;
/* /*
* When a client connects, we're in capabilities negotiation mode. * 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 mon_cmds[];
static mon_cmd_t info_cmds[]; static mon_cmd_t info_cmds[];
static const mon_cmd_t qmp_cmds[];
Monitor *cur_mon; Monitor *cur_mon;
static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME; static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
@ -403,49 +398,6 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
QDECREF(json); 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] = { static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
/* Limit guest-triggerable events to 1 per second */ /* Limit guest-triggerable events to 1 per second */
[QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS }, [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); 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; 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"); help_cmd(mon, "info");
} }
CommandInfoList *qmp_query_commands(Error **errp) static void query_commands_cb(QmpCommand *cmd, void *opaque)
{ {
CommandInfoList *info, *cmd_list = NULL; CommandInfoList *info, **list = opaque;
const mon_cmd_t *cmd;
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) { if (!cmd->enabled) {
info = g_malloc0(sizeof(*info)); return;
info->value = g_malloc0(sizeof(*info->value));
info->value->name = g_strdup(cmd->name);
info->next = cmd_list;
cmd_list = info;
} }
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) 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); *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 */ /* set the current CPU defined by the user */
int monitor_set_cpu(int cpu_index) int monitor_set_cpu(int cpu_index)
{ {
@ -2163,11 +2165,6 @@ static mon_cmd_t mon_cmds[] = {
{ NULL, NULL, }, { NULL, NULL, },
}; };
static const mon_cmd_t qmp_cmds[] = {
#include "qmp-commands-old.h"
{ /* NULL */ },
};
/*******************************************************************/ /*******************************************************************/
static const char *pch; static const char *pch;
@ -2518,11 +2515,6 @@ static const mon_cmd_t *search_dispatch_table(const mon_cmd_t *disp_table,
return NULL; 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. * Parse command name from @cmdp according to command table @table.
* If blank, return NULL. * If blank, return NULL.
@ -2954,7 +2946,7 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline)
return; return;
} }
cmd->mhandler.cmd(mon, qdict); cmd->cmd(mon, qdict);
QDECREF(qdict); QDECREF(qdict);
} }
@ -3653,219 +3645,26 @@ static int monitor_can_read(void *opaque)
return (mon->suspend_cnt == 0) ? 1 : 0; 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) 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) { if (is_cap && mon->qmp.in_command_mode) {
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
"Capabilities negotiation is already complete, command " "Capabilities negotiation is already complete, command "
"'%s' ignored", cmd->name); "'%s' ignored", cmd);
return true; return true;
} }
if (!is_cap && !mon->qmp.in_command_mode) { if (!is_cap && !mon->qmp.in_command_mode) {
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
"Expecting capabilities negotiation with " "Expecting capabilities negotiation with "
"'qmp_capabilities' before command '%s'", cmd->name); "'qmp_capabilities' before command '%s'", cmd);
return true; return true;
} }
return false; 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 * 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) static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
{ {
Error *local_err = NULL; QObject *req, *rsp = NULL, *id = NULL;
QObject *obj, *data; QDict *qdict = NULL;
QDict *input, *args;
const mon_cmd_t *cmd;
const char *cmd_name; const char *cmd_name;
Monitor *mon = cur_mon; Monitor *mon = cur_mon;
Error *err = NULL;
args = input = NULL; req = json_parser_parse_err(tokens, NULL, &err);
data = NULL; if (err || !req || qobject_type(req) != QTYPE_QDICT) {
if (!err) {
obj = json_parser_parse(tokens, NULL); error_setg(&err, QERR_JSON_PARSING);
if (!obj) { }
// FIXME: should be triggered in json_parser_parse()
error_setg(&local_err, QERR_JSON_PARSING);
goto err_out; goto err_out;
} }
input = qmp_check_input_obj(obj, &local_err); qdict = qmp_check_input_obj(req, &err);
if (!input) { if (!qdict) {
qobject_decref(obj);
goto err_out; goto err_out;
} }
mon->qmp.id = qdict_get(input, "id"); id = qdict_get(qdict, "id");
qobject_incref(mon->qmp.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); trace_handle_qmp_command(mon, cmd_name);
cmd = qmp_find_cmd(cmd_name);
if (!cmd) { if (invalid_qmp_mode(mon, cmd_name, &err)) {
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)) {
goto err_out; goto err_out;
} }
obj = qdict_get(input, "arguments"); rsp = qmp_dispatch(req);
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);
err_out: err_out:
monitor_protocol_emitter(mon, data, local_err); if (err) {
qobject_decref(data); qdict = qdict_new();
error_free(local_err); qdict_put_obj(qdict, "error", qmp_build_error_object(err));
QDECREF(input); error_free(err);
QDECREF(args); 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) 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; QObject *ver = NULL;
qmp_marshal_query_version(NULL, &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) static void monitor_qmp_event(void *opaque, int event)

View File

@ -20,6 +20,27 @@
# QAPI introspection # QAPI introspection
{ 'include': 'qapi/introspect.json' } { '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: # @LostTickPolicy:
# #
@ -2179,6 +2200,46 @@
## ##
{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } { '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: # @device_del:
# #

View File

@ -30,6 +30,14 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn,
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node); 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 *qmp_find_command(const char *name)
{ {
QmpCommand *cmd; QmpCommand *cmd;

16
qmp.c
View File

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

View File

@ -7,7 +7,13 @@ while read line; do
case $line in case $line in
VERSION=*) # configuration VERSION=*) # configuration
version=${line#*=} 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 \"$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 qemu_*dir=*) # qemu-specific directory configuration
name=${line%=*} 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): def gen_marshal_proto(name):
ret = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name) return 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
if not middle_mode:
ret = 'static ' + ret
return ret
def gen_marshal_decl(name): def gen_marshal_decl(name):
@ -98,6 +95,8 @@ def gen_marshal_decl(name):
def gen_marshal(name, arg_type, boxed, ret_type): def gen_marshal(name, arg_type, boxed, ret_type):
have_args = arg_type and not arg_type.is_empty()
ret = mcgen(''' ret = mcgen('''
%(proto)s %(proto)s
@ -112,17 +111,31 @@ def gen_marshal(name, arg_type, boxed, ret_type):
''', ''',
c_type=ret_type.c_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(''' ret += mcgen('''
Visitor *v; Visitor *v;
%(c_name)s arg = {0}; %(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); v = qmp_input_visitor_new(QOBJECT(args), true);
visit_start_struct(v, NULL, NULL, 0, &err); visit_start_struct(v, NULL, NULL, 0, &err);
if (err) { if (err) {
goto out; goto out;
} }
visit_type_%(c_name)s_members(v, &arg, &err); %(visit_members)s
if (!err) { if (!err) {
visit_check_struct(v, &err); visit_check_struct(v, &err);
} }
@ -131,35 +144,47 @@ def gen_marshal(name, arg_type, boxed, ret_type):
goto out; goto out;
} }
''', ''',
c_name=arg_type.c_name()) visit_members=visit_members)
else: if not have_args:
pop_indent()
ret += mcgen(''' ret += mcgen('''
}
(void)args;
''') ''')
ret += gen_call(name, arg_type, boxed, ret_type) ret += gen_call(name, arg_type, boxed, ret_type)
# 'goto out' produced above for arg_type, and by gen_call() for ret_type ret += mcgen('''
if (arg_type and not arg_type.is_empty()) or ret_type:
ret += mcgen('''
out: out:
''')
ret += mcgen('''
error_propagate(errp, err); error_propagate(errp, err);
''')
if arg_type and not arg_type.is_empty():
ret += mcgen('''
visit_free(v); 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(); v = qapi_dealloc_visitor_new();
visit_start_struct(v, NULL, NULL, 0, NULL); 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_end_struct(v, NULL);
visit_free(v); visit_free(v);
''', ''',
c_name=arg_type.c_name()) visit_members=visit_members)
if not have_args:
pop_indent()
ret += mcgen('''
}
''')
ret += mcgen(''' ret += mcgen('''
} }
@ -209,8 +234,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
self._visited_ret_types = set() self._visited_ret_types = set()
def visit_end(self): def visit_end(self):
if not middle_mode: self.defn += gen_registry(self._regy)
self.defn += gen_registry(self._regy)
self._regy = None self._regy = None
self._visited_ret_types = 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: if ret_type and ret_type not in self._visited_ret_types:
self._visited_ret_types.add(ret_type) self._visited_ret_types.add(ret_type)
self.defn += gen_marshal_output(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) 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()
(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
c_comment = ''' c_comment = '''
/* /*

View File

@ -198,6 +198,26 @@ static void test_qga_ping(gconstpointer fix)
QDECREF(ret); 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) static void test_qga_invalid_cmd(gconstpointer fix)
{ {
const TestFixture *fixture = 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/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/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-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, g_test_add_data_func("/qga/fsfreeze-status", &fix,
test_qga_fsfreeze_status); test_qga_fsfreeze_status);

View File

@ -106,6 +106,7 @@ static void test_dispatch_cmd(void)
static void test_dispatch_cmd_failure(void) static void test_dispatch_cmd_failure(void)
{ {
QDict *req = qdict_new(); QDict *req = qdict_new();
QDict *args = qdict_new();
QObject *resp; QObject *resp;
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2"))); 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); qobject_decref(resp);
QDECREF(req); 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) 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 # monitor.c
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\"" 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_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_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 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]); qemu_init_exec_dir(argv[0]);
module_call_init(MODULE_INIT_QOM); module_call_init(MODULE_INIT_QOM);
module_call_init(MODULE_INIT_QAPI);
qemu_add_opts(&qemu_drive_opts); qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts);