blob: 37dfd7fd4c60cde9c22bc1032e90597ce8bce2f4 [file] [log] [blame]
bellard9dc39cb2004-03-14 21:38:27 +00001/*
Markus Armbruster864a3fa2023-01-24 13:19:46 +01002 * QEMU monitor, target-dependent part
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard9dc39cb2004-03-14 21:38:27 +00004 * Copyright (c) 2003-2004 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellard9dc39cb2004-03-14 21:38:27 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
Markus Armbrustere688df62018-02-01 12:18:31 +010024
Peter Maydelld38ea872016-01-29 17:50:05 +000025#include "qemu/osdep.h"
Kevin Wolf5bce3082019-06-13 17:33:59 +020026#include "monitor-internal.h"
Paolo Bonzinib4a42f82013-02-04 11:37:52 +010027#include "monitor/qdev.h"
Mark McLoughlin68ac40d2009-11-25 18:48:54 +000028#include "net/slirp.h"
Philippe Mathieu-Daudé32cad1f2024-12-03 15:20:13 +010029#include "system/device_tree.h"
Pavel Butsykinbf957282015-09-10 18:38:59 +030030#include "monitor/hmp-target.h"
Markus Armbruster275307a2019-06-19 22:10:36 +020031#include "monitor/hmp.h"
Maxim Levitskya2dde2f2020-03-08 11:24:32 +020032#include "block/block-hmp-cmds.h"
Kevin Wolffa4dcf52020-01-29 11:22:37 +010033#include "qapi/qapi-commands-control.h"
Markus Armbruster00ca24f2019-11-20 19:25:48 +010034#include "qapi/qapi-commands-misc.h"
Daniel P. Berrangédd982342021-09-08 10:35:43 +010035#include "qapi/qapi-commands-machine.h"
Markus Armbrustere688df62018-02-01 12:18:31 +010036#include "qapi/error.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020037#include "qemu/cutils.h"
ths6a5bd302007-12-03 17:05:38 +000038
Jason J. Hernea4538a52015-06-26 14:07:21 -040039#if defined(TARGET_S390X)
40#include "hw/s390x/storage-keys.h"
Claudio Imbrendaf860d492016-08-15 18:44:04 +020041#include "hw/s390x/storage-attributes.h"
Jason J. Hernea4538a52015-06-26 14:07:21 -040042#endif
43
Murilo Opsfelder Araujoc9f80042022-05-10 20:54:39 -030044/* Make devices configuration available for use in hmp-commands*.hx templates */
45#include CONFIG_DEVICES
46
Kevin Wolfa0cd5e12019-06-13 17:33:56 +020047static HMPCommand hmp_info_cmds[];
bellard9dc39cb2004-03-14 21:38:27 +000048
Kevin Wolfed7bda52019-06-13 17:34:01 +020049/**
50 * Is @name in the '|' separated list of names @list?
51 */
52int hmp_compare_cmd(const char *name, const char *list)
bellard9dc39cb2004-03-14 21:38:27 +000053{
54 const char *p, *pstart;
55 int len;
56 len = strlen(name);
57 p = list;
Kevin Wolfed7bda52019-06-13 17:34:01 +020058 for (;;) {
bellard9dc39cb2004-03-14 21:38:27 +000059 pstart = p;
Keno Fischer5c99fa32018-06-29 12:32:10 +020060 p = qemu_strchrnul(p, '|');
Kevin Wolfed7bda52019-06-13 17:34:01 +020061 if ((p - pstart) == len && !memcmp(pstart, name, len)) {
bellard9dc39cb2004-03-14 21:38:27 +000062 return 1;
Wenchao Xiaf5438c02013-08-27 20:38:21 +080063 }
64 if (*p == '\0') {
65 break;
66 }
Kevin Wolfed7bda52019-06-13 17:34:01 +020067 p++;
Wenchao Xiaf5438c02013-08-27 20:38:21 +080068 }
Wenchao Xiadcc70cd2013-08-27 20:38:22 +080069 return 0;
bellard9dc39cb2004-03-14 21:38:27 +000070}
71
Luiz Capitulinoacd0a092010-09-30 16:00:22 -030072/* Please update hmp-commands.hx when adding or changing commands */
Kevin Wolfa0cd5e12019-06-13 17:33:56 +020073static HMPCommand hmp_info_cmds[] = {
Pavel Butsykinda76ee72015-09-10 18:38:58 +030074#include "hmp-commands-info.h"
75 { NULL, NULL, },
bellard9dc39cb2004-03-14 21:38:27 +000076};
77
Kevin Wolfa0cd5e12019-06-13 17:33:56 +020078/* hmp_cmds and hmp_info_cmds would be sorted at runtime */
Kevin Wolfed7bda52019-06-13 17:34:01 +020079HMPCommand hmp_cmds[] = {
Wenchao Xiaa13ced52013-01-14 14:06:28 +080080#include "hmp-commands.h"
81 { NULL, NULL, },
82};
83
Kevin Wolfed7bda52019-06-13 17:34:01 +020084/*
85 * Set @pval to the value in the register identified by @name.
86 * return 0 if OK, -1 if not found
87 */
Kevin Wolf2fc5d012020-11-13 12:43:24 +010088int get_monitor_def(Monitor *mon, int64_t *pval, const char *name)
bellard9307c4c2004-04-04 12:57:25 +000089{
Pavel Butsykinbf957282015-09-10 18:38:59 +030090 const MonitorDef *md = target_monitor_defs();
Kevin Wolf2fc5d012020-11-13 12:43:24 +010091 CPUState *cs = mon_get_cpu(mon);
bellard92a31b12005-02-10 22:00:52 +000092 void *ptr;
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +110093 uint64_t tmp = 0;
94 int ret;
bellard92a31b12005-02-10 22:00:52 +000095
Thomas Huth854e67f2017-01-13 13:12:35 +010096 if (cs == NULL || md == NULL) {
Pavel Butsykinbf957282015-09-10 18:38:59 +030097 return -1;
98 }
99
100 for(; md->name != NULL; md++) {
Kevin Wolfed7bda52019-06-13 17:34:01 +0200101 if (hmp_compare_cmd(name, md->name)) {
bellard9307c4c2004-04-04 12:57:25 +0000102 if (md->get_value) {
Kevin Wolf43cf0672020-11-13 12:43:25 +0100103 *pval = md->get_value(mon, md, md->offset);
bellard9307c4c2004-04-04 12:57:25 +0000104 } else {
Kevin Wolfe7cff9c2020-11-13 12:43:26 +0100105 CPUArchState *env = mon_get_cpu_env(mon);
bellard6a00d602005-11-21 23:25:50 +0000106 ptr = (uint8_t *)env + md->offset;
bellard92a31b12005-02-10 22:00:52 +0000107 switch(md->type) {
108 case MD_I32:
109 *pval = *(int32_t *)ptr;
110 break;
111 case MD_TLONG:
112 *pval = *(target_long *)ptr;
113 break;
114 default:
115 *pval = 0;
116 break;
117 }
bellard9307c4c2004-04-04 12:57:25 +0000118 }
119 return 0;
120 }
121 }
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +1100122
Thomas Huth854e67f2017-01-13 13:12:35 +0100123 ret = target_get_monitor_def(cs, name, &tmp);
Alexey Kardashevskiy0a9516c2015-11-12 14:44:23 +1100124 if (!ret) {
125 *pval = (target_long) tmp;
126 }
127
128 return ret;
bellard9307c4c2004-04-04 12:57:25 +0000129}
130
Wayne Xia816f8922011-10-12 11:32:41 +0800131static int
132compare_mon_cmd(const void *a, const void *b)
133{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +0200134 return strcmp(((const HMPCommand *)a)->name,
135 ((const HMPCommand *)b)->name);
Wayne Xia816f8922011-10-12 11:32:41 +0800136}
137
Markus Armbruster9d2b5f22023-01-24 13:19:45 +0100138static void __attribute__((__constructor__)) sortcmdlist(void)
Wayne Xia816f8922011-10-12 11:32:41 +0800139{
Kevin Wolfa0cd5e12019-06-13 17:33:56 +0200140 qsort(hmp_cmds, ARRAY_SIZE(hmp_cmds) - 1,
141 sizeof(*hmp_cmds),
142 compare_mon_cmd);
143 qsort(hmp_info_cmds, ARRAY_SIZE(hmp_info_cmds) - 1,
144 sizeof(*hmp_info_cmds),
145 compare_mon_cmd);
Wayne Xia816f8922011-10-12 11:32:41 +0800146}
147
Gerd Hoffmannf0e48cb2021-06-24 12:38:32 +0200148void monitor_register_hmp(const char *name, bool info,
149 void (*cmd)(Monitor *mon, const QDict *qdict))
150{
151 HMPCommand *table = info ? hmp_info_cmds : hmp_cmds;
152
153 while (table->name != NULL) {
154 if (strcmp(table->name, name) == 0) {
Daniel P. Berrangéf9429c62021-10-08 15:09:00 +0100155 g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
Gerd Hoffmannf0e48cb2021-06-24 12:38:32 +0200156 table->cmd = cmd;
157 return;
158 }
159 table++;
160 }
161 g_assert_not_reached();
162}
163
Daniel P. Berrangéf9429c62021-10-08 15:09:00 +0100164void monitor_register_hmp_info_hrt(const char *name,
165 HumanReadableText *(*handler)(Error **errp))
166{
167 HMPCommand *table = hmp_info_cmds;
168
169 while (table->name != NULL) {
170 if (strcmp(table->name, name) == 0) {
171 g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
172 table->cmd_info_hrt = handler;
173 return;
174 }
175 table++;
176 }
177 g_assert_not_reached();
178}