| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2019-06-13 17:33:58 +02:00
										 |  |  |  * Human Monitor Interface commands | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright IBM, Corp. 2011 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Authors: | 
					
						
							|  |  |  |  *  Anthony Liguori   <aliguori@us.ibm.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This work is licensed under the terms of the GNU GPL, version 2.  See | 
					
						
							|  |  |  |  * the COPYING file in the top-level directory. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-01-13 17:44:23 +01:00
										 |  |  |  * Contributions after 2012-01-13 are licensed under the terms of the | 
					
						
							|  |  |  |  * GNU GPL, version 2 or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-29 17:50:05 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:43 +01:00
										 |  |  | #include "exec/address-spaces.h"
 | 
					
						
							|  |  |  | #include "exec/gdbstub.h"
 | 
					
						
							|  |  |  | #include "exec/ioport.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 22:10:36 +02:00
										 |  |  | #include "monitor/hmp.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-11 05:52:22 -05:00
										 |  |  | #include "qemu/help_option.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:43 +01:00
										 |  |  | #include "monitor/monitor-internal.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-01 12:18:31 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-29 11:22:37 +01:00
										 |  |  | #include "qapi/qapi-commands-control.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-26 17:13:27 -06:00
										 |  |  | #include "qapi/qapi-commands-misc.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-01 12:18:39 +01:00
										 |  |  | #include "qapi/qmp/qdict.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-20 19:16:19 +02:00
										 |  |  | #include "qemu/cutils.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-26 22:23:27 +02:00
										 |  |  | #include "hw/intc/intc.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:43 +01:00
										 |  |  | #include "qemu/log.h"
 | 
					
						
							|  |  |  | #include "sysemu/sysemu.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 16:18:25 +01:00
										 |  |  | bool hmp_handle_error(Monitor *mon, Error *err) | 
					
						
							| 
									
										
										
										
											2011-11-22 16:32:37 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     if (err) { | 
					
						
							|  |  |  |         error_reportf_err(err, "Error: "); | 
					
						
							| 
									
										
										
										
											2021-10-28 16:18:25 +01:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2011-11-22 16:32:37 -02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-28 16:18:25 +01:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2011-11-22 16:32:37 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  |  * Split @str at comma. | 
					
						
							|  |  |  |  * A null @str defaults to "". | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  | strList *hmp_split_at_comma(const char *str) | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  |     char **split = g_strsplit(str ?: "", ",", -1); | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  |     strList *res = NULL; | 
					
						
							| 
									
										
										
										
											2021-01-13 16:10:12 -06:00
										 |  |  |     strList **tail = &res; | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  |     for (i = 0; split[i]; i++) { | 
					
						
							|  |  |  |         QAPI_LIST_APPEND(tail, split[i]); | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:28 +01:00
										 |  |  |     g_free(split); | 
					
						
							| 
									
										
										
										
											2019-06-20 19:47:03 +01:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-14 14:06:25 +08:00
										 |  |  | void hmp_info_name(Monitor *mon, const QDict *qdict) | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     NameInfo *info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     info = qmp_query_name(NULL); | 
					
						
							| 
									
										
										
										
											2022-11-04 17:06:59 +01:00
										 |  |  |     if (info->name) { | 
					
						
							| 
									
										
										
										
											2011-09-02 12:34:48 -05:00
										 |  |  |         monitor_printf(mon, "%s\n", info->name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     qapi_free_NameInfo(info); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-08-26 17:38:13 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-14 14:06:25 +08:00
										 |  |  | void hmp_info_version(Monitor *mon, const QDict *qdict) | 
					
						
							| 
									
										
										
										
											2011-08-26 17:38:13 -03:00
										 |  |  | { | 
					
						
							|  |  |  |     VersionInfo *info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     info = qmp_query_version(NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n", | 
					
						
							| 
									
										
										
										
											2015-05-04 09:05:31 -06:00
										 |  |  |                    info->qemu->major, info->qemu->minor, info->qemu->micro, | 
					
						
							| 
									
										
										
										
											2011-08-26 17:38:13 -03:00
										 |  |  |                    info->package); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qapi_free_VersionInfo(info); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-12 15:10:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 22:23:27 +02:00
										 |  |  | static int hmp_info_pic_foreach(Object *obj, void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     InterruptStatsProvider *intc; | 
					
						
							|  |  |  |     InterruptStatsProviderClass *k; | 
					
						
							|  |  |  |     Monitor *mon = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { | 
					
						
							|  |  |  |         intc = INTERRUPT_STATS_PROVIDER(obj); | 
					
						
							|  |  |  |         k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); | 
					
						
							|  |  |  |         if (k->print_info) { | 
					
						
							|  |  |  |             k->print_info(intc, mon); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             monitor_printf(mon, "Interrupt controller information not available for %s.\n", | 
					
						
							|  |  |  |                            object_get_typename(obj)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_pic(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     object_child_foreach_recursive(object_get_root(), | 
					
						
							|  |  |  |                                    hmp_info_pic_foreach, mon); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 14:20:28 -03:00
										 |  |  | void hmp_quit(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     monitor_suspend(mon); | 
					
						
							|  |  |  |     qmp_quit(NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-15 14:34:39 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | void hmp_stop(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qmp_stop(NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-15 14:41:46 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 16:00:03 -04:00
										 |  |  | void hmp_sync_profile(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *op = qdict_get_try_str(qdict, "op"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (op == NULL) { | 
					
						
							|  |  |  |         bool on = qsp_is_enabled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         monitor_printf(mon, "sync-profile is %s\n", on ? "on" : "off"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!strcmp(op, "on")) { | 
					
						
							|  |  |  |         qsp_enable(); | 
					
						
							|  |  |  |     } else if (!strcmp(op, "off")) { | 
					
						
							|  |  |  |         qsp_disable(); | 
					
						
							|  |  |  |     } else if (!strcmp(op, "reset")) { | 
					
						
							|  |  |  |         qsp_reset(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         Error *err = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-31 12:10:54 +01:00
										 |  |  |         error_setg(&err, "invalid parameter '%s'," | 
					
						
							|  |  |  |                    " expecting 'on', 'off', or 'reset'", op); | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |         hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2018-08-15 16:00:03 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 16:39:46 +01:00
										 |  |  | void hmp_exit_preconfig(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Error *err = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-05 11:14:02 +02:00
										 |  |  |     qmp_x_exit_preconfig(&err); | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2018-06-20 16:39:46 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 14:31:39 -03:00
										 |  |  | void hmp_cpu(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int64_t cpu_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* XXX: drop the monitor_set_cpu() usage when all HMP commands that
 | 
					
						
							|  |  |  |             use it are converted to the QAPI */ | 
					
						
							|  |  |  |     cpu_index = qdict_get_int(qdict, "index"); | 
					
						
							| 
									
										
										
										
											2020-10-05 17:58:42 +02:00
										 |  |  |     if (monitor_set_cpu(mon, cpu_index) < 0) { | 
					
						
							| 
									
										
										
										
											2011-10-06 14:31:39 -03:00
										 |  |  |         monitor_printf(mon, "invalid CPU index\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-22 16:32:37 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | void hmp_cont(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     Error *err = NULL; | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     qmp_cont(&err); | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2011-11-22 17:58:31 -02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-23 12:55:53 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-08 11:13:50 -02:00
										 |  |  | void hmp_change(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *device = qdict_get_str(qdict, "device"); | 
					
						
							|  |  |  |     const char *target = qdict_get_str(qdict, "target"); | 
					
						
							|  |  |  |     const char *arg = qdict_get_try_str(qdict, "arg"); | 
					
						
							| 
									
										
										
										
											2015-10-26 21:39:18 +01:00
										 |  |  |     const char *read_only = qdict_get_try_str(qdict, "read-only-mode"); | 
					
						
							| 
									
										
										
										
											2022-04-13 01:18:46 +03:00
										 |  |  |     bool force = qdict_get_try_bool(qdict, "force", false); | 
					
						
							| 
									
										
										
										
											2011-12-08 11:13:50 -02:00
										 |  |  |     Error *err = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												qapi: add conditions to VNC type/commands/events on the schema
Add #if defined(CONFIG_VNC) in generated code, and adjust the
qmp/hmp code accordingly.
query-qmp-schema no longer reports the command/events etc as
available when disabled at compile.
Commands made conditional:
* query-vnc, query-vnc-servers, change-vnc-password
  Before the patch, the commands for !CONFIG_VNC are stubs that fail
  like this:
    {"error": {"class": "GenericError",
               "desc": "The feature 'vnc' is not enabled"}}
  Afterwards, they fail like this:
    {"error": {"class": "CommandNotFound",
               "desc": "The command FOO has not been found"}}
  I call that an improvement, because it lets clients distinguish
  between command unavailable (class CommandNotFound) and command failed
  (class GenericError).
Events made conditional:
* VNC_CONNECTED, VNC_INITIALIZED, VNC_DISCONNECTED
HMP change:
* info vnc
  Will return "unknown command: 'info vnc'" when VNC is compiled
  out (same as error for spice when --disable-spice)
Occurrences of VNC (case insensitive) in the schema that aren't
covered by this change:
* add_client
  Command has other uses, including "socket bases character devices".
  These are unconditional as far as I can tell.
* set_password, expire_password
  In theory, these commands could be used for managing any service's
  password.  In practice, they're used for VNC and SPICE services.
  They're documented for "remote display session" / "remote display
  server".
  The service is selected by argument @protocol.  The code special-cases
  protocol-specific argument checking, then calls a protocol-specific
  function to do the work.  If it fails, the command fails with "Could
  not set password".  It does when the service isn't compiled in (it's a
  stub then).
  We could make these commands conditional on the conjunction of all
  services [currently: defined(CONFIG_VNC) || defined(CONFIG_SPICE)],
  but I doubt it's worthwhile.
* change
  Command has other uses, namely changing media.
  This patch inlines a stub; no functional change.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-14-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
											
										 
											2018-07-03 17:56:47 +02:00
										 |  |  | #ifdef CONFIG_VNC
 | 
					
						
							| 
									
										
										
										
											2015-10-26 21:39:16 +01:00
										 |  |  |     if (strcmp(device, "vnc") == 0) { | 
					
						
							| 
									
										
										
										
											2023-01-09 20:03:17 +01:00
										 |  |  |         hmp_change_vnc(mon, device, target, arg, read_only, force, &err); | 
					
						
							| 
									
										
											  
											
												qapi: add conditions to VNC type/commands/events on the schema
Add #if defined(CONFIG_VNC) in generated code, and adjust the
qmp/hmp code accordingly.
query-qmp-schema no longer reports the command/events etc as
available when disabled at compile.
Commands made conditional:
* query-vnc, query-vnc-servers, change-vnc-password
  Before the patch, the commands for !CONFIG_VNC are stubs that fail
  like this:
    {"error": {"class": "GenericError",
               "desc": "The feature 'vnc' is not enabled"}}
  Afterwards, they fail like this:
    {"error": {"class": "CommandNotFound",
               "desc": "The command FOO has not been found"}}
  I call that an improvement, because it lets clients distinguish
  between command unavailable (class CommandNotFound) and command failed
  (class GenericError).
Events made conditional:
* VNC_CONNECTED, VNC_INITIALIZED, VNC_DISCONNECTED
HMP change:
* info vnc
  Will return "unknown command: 'info vnc'" when VNC is compiled
  out (same as error for spice when --disable-spice)
Occurrences of VNC (case insensitive) in the schema that aren't
covered by this change:
* add_client
  Command has other uses, including "socket bases character devices".
  These are unconditional as far as I can tell.
* set_password, expire_password
  In theory, these commands could be used for managing any service's
  password.  In practice, they're used for VNC and SPICE services.
  They're documented for "remote display session" / "remote display
  server".
  The service is selected by argument @protocol.  The code special-cases
  protocol-specific argument checking, then calls a protocol-specific
  function to do the work.  If it fails, the command fails with "Could
  not set password".  It does when the service isn't compiled in (it's a
  stub then).
  We could make these commands conditional on the conjunction of all
  services [currently: defined(CONFIG_VNC) || defined(CONFIG_SPICE)],
  but I doubt it's worthwhile.
* change
  Command has other uses, namely changing media.
  This patch inlines a stub; no functional change.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-14-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
											
										 
											2018-07-03 17:56:47 +02:00
										 |  |  |     } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:26 +01:00
										 |  |  |         hmp_change_medium(mon, device, target, arg, read_only, force, &err); | 
					
						
							| 
									
										
										
										
											2011-12-08 11:13:50 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2011-12-08 11:13:50 -02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-12-14 16:49:14 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 19:05:41 +04:00
										 |  |  | #ifdef CONFIG_POSIX
 | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | void hmp_getfd(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *fdname = qdict_get_str(qdict, "fdname"); | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     Error *err = NULL; | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     qmp_getfd(fdname, &err); | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-03-02 19:05:41 +04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | void hmp_closefd(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *fdname = qdict_get_str(qdict, "fdname"); | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     Error *err = NULL; | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 13:26:29 +02:00
										 |  |  |     qmp_closefd(fdname, &err); | 
					
						
							| 
									
										
										
										
											2019-12-05 20:46:18 +03:00
										 |  |  |     hmp_handle_error(mon, err); | 
					
						
							| 
									
										
										
										
											2012-06-22 14:36:09 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-08-31 10:56:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-26 16:07:13 +08:00
										 |  |  | void hmp_info_iothreads(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IOThreadInfoList *info_list = qmp_query_iothreads(NULL); | 
					
						
							|  |  |  |     IOThreadInfoList *info; | 
					
						
							| 
									
										
										
										
											2017-02-10 10:41:17 +01:00
										 |  |  |     IOThreadInfo *value; | 
					
						
							| 
									
										
										
										
											2015-06-26 16:07:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (info = info_list; info; info = info->next) { | 
					
						
							| 
									
										
										
										
											2017-02-10 10:41:17 +01:00
										 |  |  |         value = info->value; | 
					
						
							|  |  |  |         monitor_printf(mon, "%s:\n", value->id); | 
					
						
							|  |  |  |         monitor_printf(mon, "  thread_id=%" PRId64 "\n", value->thread_id); | 
					
						
							|  |  |  |         monitor_printf(mon, "  poll-max-ns=%" PRId64 "\n", value->poll_max_ns); | 
					
						
							|  |  |  |         monitor_printf(mon, "  poll-grow=%" PRId64 "\n", value->poll_grow); | 
					
						
							|  |  |  |         monitor_printf(mon, "  poll-shrink=%" PRId64 "\n", value->poll_shrink); | 
					
						
							| 
									
										
										
										
											2021-07-21 11:42:10 +02:00
										 |  |  |         monitor_printf(mon, "  aio-max-batch=%" PRId64 "\n", | 
					
						
							|  |  |  |                        value->aio_max_batch); | 
					
						
							| 
									
										
										
										
											2015-06-26 16:07:13 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qapi_free_IOThreadInfoList(info_list); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-24 13:19:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void hmp_help(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     hmp_help_cmd(mon, qdict_get_try_str(qdict, "name")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_help(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     hmp_help_cmd(mon, "info"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_sync_profile(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int64_t max = qdict_get_try_int(qdict, "max", 10); | 
					
						
							|  |  |  |     bool mean = qdict_get_try_bool(qdict, "mean", false); | 
					
						
							|  |  |  |     bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false); | 
					
						
							|  |  |  |     enum QSPSortBy sort_by; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME; | 
					
						
							|  |  |  |     qsp_report(max, sort_by, coalesce); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_history(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common); | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     const char *str; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!hmp_mon->rs) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     i = 0; | 
					
						
							|  |  |  |     for(;;) { | 
					
						
							|  |  |  |         str = readline_get_history(hmp_mon->rs, i); | 
					
						
							|  |  |  |         if (!str) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         monitor_printf(mon, "%d: '%s'\n", i, str); | 
					
						
							|  |  |  |         i++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_logfile(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Error *err = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err)) { | 
					
						
							|  |  |  |         error_report_err(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_log(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int mask; | 
					
						
							|  |  |  |     const char *items = qdict_get_str(qdict, "items"); | 
					
						
							|  |  |  |     Error *err = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!strcmp(items, "none")) { | 
					
						
							|  |  |  |         mask = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         mask = qemu_str_to_log_mask(items); | 
					
						
							|  |  |  |         if (!mask) { | 
					
						
							|  |  |  |             hmp_help_cmd(mon, "log"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!qemu_set_log(mask, &err)) { | 
					
						
							|  |  |  |         error_report_err(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_gdbserver(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *device = qdict_get_try_str(qdict, "device"); | 
					
						
							|  |  |  |     if (!device) { | 
					
						
							|  |  |  |         device = "tcp::" DEFAULT_GDBSTUB_PORT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (gdbserver_start(device) < 0) { | 
					
						
							|  |  |  |         monitor_printf(mon, "Could not open gdbserver on device '%s'\n", | 
					
						
							|  |  |  |                        device); | 
					
						
							|  |  |  |     } else if (strcmp(device, "none") == 0) { | 
					
						
							|  |  |  |         monitor_printf(mon, "Disabled gdbserver\n"); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         monitor_printf(mon, "Waiting for gdb connection on device '%s'\n", | 
					
						
							|  |  |  |                        device); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_print(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int format = qdict_get_int(qdict, "format"); | 
					
						
							|  |  |  |     hwaddr val = qdict_get_int(qdict, "val"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch(format) { | 
					
						
							|  |  |  |     case 'o': | 
					
						
							|  |  |  |         monitor_printf(mon, "%#" HWADDR_PRIo, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 'x': | 
					
						
							|  |  |  |         monitor_printf(mon, "%#" HWADDR_PRIx, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 'u': | 
					
						
							|  |  |  |         monitor_printf(mon, "%" HWADDR_PRIu, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case 'd': | 
					
						
							|  |  |  |         monitor_printf(mon, "%" HWADDR_PRId, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 'c': | 
					
						
							|  |  |  |         monitor_printc(mon, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     monitor_printf(mon, "\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_sum(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t addr; | 
					
						
							|  |  |  |     uint16_t sum; | 
					
						
							|  |  |  |     uint32_t start = qdict_get_int(qdict, "start"); | 
					
						
							|  |  |  |     uint32_t size = qdict_get_int(qdict, "size"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sum = 0; | 
					
						
							|  |  |  |     for(addr = start; addr < (start + size); addr++) { | 
					
						
							|  |  |  |         uint8_t val = address_space_ldub(&address_space_memory, addr, | 
					
						
							|  |  |  |                                          MEMTXATTRS_UNSPECIFIED, NULL); | 
					
						
							|  |  |  |         /* BSD sum algorithm ('sum' Unix command) */ | 
					
						
							|  |  |  |         sum = (sum >> 1) | (sum << 15); | 
					
						
							|  |  |  |         sum += val; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     monitor_printf(mon, "%05d\n", sum); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_ioport_read(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int size = qdict_get_int(qdict, "size"); | 
					
						
							|  |  |  |     int addr = qdict_get_int(qdict, "addr"); | 
					
						
							|  |  |  |     int has_index = qdict_haskey(qdict, "index"); | 
					
						
							|  |  |  |     uint32_t val; | 
					
						
							|  |  |  |     int suffix; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (has_index) { | 
					
						
							|  |  |  |         int index = qdict_get_int(qdict, "index"); | 
					
						
							|  |  |  |         cpu_outb(addr & IOPORTS_MASK, index & 0xff); | 
					
						
							|  |  |  |         addr++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     addr &= 0xffff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch(size) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |         val = cpu_inb(addr); | 
					
						
							|  |  |  |         suffix = 'b'; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |         val = cpu_inw(addr); | 
					
						
							|  |  |  |         suffix = 'w'; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |         val = cpu_inl(addr); | 
					
						
							|  |  |  |         suffix = 'l'; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n", | 
					
						
							|  |  |  |                    suffix, addr, size * 2, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_ioport_write(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int size = qdict_get_int(qdict, "size"); | 
					
						
							|  |  |  |     int addr = qdict_get_int(qdict, "addr"); | 
					
						
							|  |  |  |     int val = qdict_get_int(qdict, "val"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addr &= IOPORTS_MASK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (size) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |         cpu_outb(addr, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |         cpu_outw(addr, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |         cpu_outl(addr, val); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_boot_set(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Error *local_err = NULL; | 
					
						
							|  |  |  |     const char *bootdevice = qdict_get_str(qdict, "bootdevice"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qemu_boot_set(bootdevice, &local_err); | 
					
						
							|  |  |  |     if (local_err) { | 
					
						
							|  |  |  |         error_report_err(local_err); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         monitor_printf(mon, "boot device list now set to %s\n", bootdevice); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_mtree(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool flatview = qdict_get_try_bool(qdict, "flatview", false); | 
					
						
							|  |  |  |     bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false); | 
					
						
							|  |  |  |     bool owner = qdict_get_try_bool(qdict, "owner", false); | 
					
						
							|  |  |  |     bool disabled = qdict_get_try_bool(qdict, "disabled", false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mtree_info(flatview, dispatch_tree, owner, disabled); | 
					
						
							|  |  |  | } |