bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 1 | /* |
Markus Armbruster | 864a3fa | 2023-01-24 13:19:46 +0100 | [diff] [blame] | 2 | * QEMU monitor, target-dependent part |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 4 | * Copyright (c) 2003-2004 Fabrice Bellard |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 5 | * |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 6 | * 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 Armbruster | e688df6 | 2018-02-01 12:18:31 +0100 | [diff] [blame] | 24 | |
Peter Maydell | d38ea87 | 2016-01-29 17:50:05 +0000 | [diff] [blame] | 25 | #include "qemu/osdep.h" |
Kevin Wolf | 5bce308 | 2019-06-13 17:33:59 +0200 | [diff] [blame] | 26 | #include "monitor-internal.h" |
Paolo Bonzini | b4a42f8 | 2013-02-04 11:37:52 +0100 | [diff] [blame] | 27 | #include "monitor/qdev.h" |
Mark McLoughlin | 68ac40d | 2009-11-25 18:48:54 +0000 | [diff] [blame] | 28 | #include "net/slirp.h" |
Philippe Mathieu-Daudé | 32cad1f | 2024-12-03 15:20:13 +0100 | [diff] [blame] | 29 | #include "system/device_tree.h" |
Pavel Butsykin | bf95728 | 2015-09-10 18:38:59 +0300 | [diff] [blame] | 30 | #include "monitor/hmp-target.h" |
Markus Armbruster | 275307a | 2019-06-19 22:10:36 +0200 | [diff] [blame] | 31 | #include "monitor/hmp.h" |
Maxim Levitsky | a2dde2f | 2020-03-08 11:24:32 +0200 | [diff] [blame] | 32 | #include "block/block-hmp-cmds.h" |
Kevin Wolf | fa4dcf5 | 2020-01-29 11:22:37 +0100 | [diff] [blame] | 33 | #include "qapi/qapi-commands-control.h" |
Markus Armbruster | 00ca24f | 2019-11-20 19:25:48 +0100 | [diff] [blame] | 34 | #include "qapi/qapi-commands-misc.h" |
Daniel P. Berrangé | dd98234 | 2021-09-08 10:35:43 +0100 | [diff] [blame] | 35 | #include "qapi/qapi-commands-machine.h" |
Markus Armbruster | e688df6 | 2018-02-01 12:18:31 +0100 | [diff] [blame] | 36 | #include "qapi/error.h" |
Veronia Bahaa | f348b6d | 2016-03-20 19:16:19 +0200 | [diff] [blame] | 37 | #include "qemu/cutils.h" |
ths | 6a5bd30 | 2007-12-03 17:05:38 +0000 | [diff] [blame] | 38 | |
Jason J. Herne | a4538a5 | 2015-06-26 14:07:21 -0400 | [diff] [blame] | 39 | #if defined(TARGET_S390X) |
| 40 | #include "hw/s390x/storage-keys.h" |
Claudio Imbrenda | f860d49 | 2016-08-15 18:44:04 +0200 | [diff] [blame] | 41 | #include "hw/s390x/storage-attributes.h" |
Jason J. Herne | a4538a5 | 2015-06-26 14:07:21 -0400 | [diff] [blame] | 42 | #endif |
| 43 | |
Murilo Opsfelder Araujo | c9f8004 | 2022-05-10 20:54:39 -0300 | [diff] [blame] | 44 | /* Make devices configuration available for use in hmp-commands*.hx templates */ |
| 45 | #include CONFIG_DEVICES |
| 46 | |
Kevin Wolf | a0cd5e1 | 2019-06-13 17:33:56 +0200 | [diff] [blame] | 47 | static HMPCommand hmp_info_cmds[]; |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 48 | |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 49 | /** |
| 50 | * Is @name in the '|' separated list of names @list? |
| 51 | */ |
| 52 | int hmp_compare_cmd(const char *name, const char *list) |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 53 | { |
| 54 | const char *p, *pstart; |
| 55 | int len; |
| 56 | len = strlen(name); |
| 57 | p = list; |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 58 | for (;;) { |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 59 | pstart = p; |
Keno Fischer | 5c99fa3 | 2018-06-29 12:32:10 +0200 | [diff] [blame] | 60 | p = qemu_strchrnul(p, '|'); |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 61 | if ((p - pstart) == len && !memcmp(pstart, name, len)) { |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 62 | return 1; |
Wenchao Xia | f5438c0 | 2013-08-27 20:38:21 +0800 | [diff] [blame] | 63 | } |
| 64 | if (*p == '\0') { |
| 65 | break; |
| 66 | } |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 67 | p++; |
Wenchao Xia | f5438c0 | 2013-08-27 20:38:21 +0800 | [diff] [blame] | 68 | } |
Wenchao Xia | dcc70cd | 2013-08-27 20:38:22 +0800 | [diff] [blame] | 69 | return 0; |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Luiz Capitulino | acd0a09 | 2010-09-30 16:00:22 -0300 | [diff] [blame] | 72 | /* Please update hmp-commands.hx when adding or changing commands */ |
Kevin Wolf | a0cd5e1 | 2019-06-13 17:33:56 +0200 | [diff] [blame] | 73 | static HMPCommand hmp_info_cmds[] = { |
Pavel Butsykin | da76ee7 | 2015-09-10 18:38:58 +0300 | [diff] [blame] | 74 | #include "hmp-commands-info.h" |
| 75 | { NULL, NULL, }, |
bellard | 9dc39cb | 2004-03-14 21:38:27 +0000 | [diff] [blame] | 76 | }; |
| 77 | |
Kevin Wolf | a0cd5e1 | 2019-06-13 17:33:56 +0200 | [diff] [blame] | 78 | /* hmp_cmds and hmp_info_cmds would be sorted at runtime */ |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 79 | HMPCommand hmp_cmds[] = { |
Wenchao Xia | a13ced5 | 2013-01-14 14:06:28 +0800 | [diff] [blame] | 80 | #include "hmp-commands.h" |
| 81 | { NULL, NULL, }, |
| 82 | }; |
| 83 | |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 84 | /* |
| 85 | * Set @pval to the value in the register identified by @name. |
| 86 | * return 0 if OK, -1 if not found |
| 87 | */ |
Kevin Wolf | 2fc5d01 | 2020-11-13 12:43:24 +0100 | [diff] [blame] | 88 | int get_monitor_def(Monitor *mon, int64_t *pval, const char *name) |
bellard | 9307c4c | 2004-04-04 12:57:25 +0000 | [diff] [blame] | 89 | { |
Pavel Butsykin | bf95728 | 2015-09-10 18:38:59 +0300 | [diff] [blame] | 90 | const MonitorDef *md = target_monitor_defs(); |
Kevin Wolf | 2fc5d01 | 2020-11-13 12:43:24 +0100 | [diff] [blame] | 91 | CPUState *cs = mon_get_cpu(mon); |
bellard | 92a31b1 | 2005-02-10 22:00:52 +0000 | [diff] [blame] | 92 | void *ptr; |
Alexey Kardashevskiy | 0a9516c | 2015-11-12 14:44:23 +1100 | [diff] [blame] | 93 | uint64_t tmp = 0; |
| 94 | int ret; |
bellard | 92a31b1 | 2005-02-10 22:00:52 +0000 | [diff] [blame] | 95 | |
Thomas Huth | 854e67f | 2017-01-13 13:12:35 +0100 | [diff] [blame] | 96 | if (cs == NULL || md == NULL) { |
Pavel Butsykin | bf95728 | 2015-09-10 18:38:59 +0300 | [diff] [blame] | 97 | return -1; |
| 98 | } |
| 99 | |
| 100 | for(; md->name != NULL; md++) { |
Kevin Wolf | ed7bda5 | 2019-06-13 17:34:01 +0200 | [diff] [blame] | 101 | if (hmp_compare_cmd(name, md->name)) { |
bellard | 9307c4c | 2004-04-04 12:57:25 +0000 | [diff] [blame] | 102 | if (md->get_value) { |
Kevin Wolf | 43cf067 | 2020-11-13 12:43:25 +0100 | [diff] [blame] | 103 | *pval = md->get_value(mon, md, md->offset); |
bellard | 9307c4c | 2004-04-04 12:57:25 +0000 | [diff] [blame] | 104 | } else { |
Kevin Wolf | e7cff9c | 2020-11-13 12:43:26 +0100 | [diff] [blame] | 105 | CPUArchState *env = mon_get_cpu_env(mon); |
bellard | 6a00d60 | 2005-11-21 23:25:50 +0000 | [diff] [blame] | 106 | ptr = (uint8_t *)env + md->offset; |
bellard | 92a31b1 | 2005-02-10 22:00:52 +0000 | [diff] [blame] | 107 | 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 | } |
bellard | 9307c4c | 2004-04-04 12:57:25 +0000 | [diff] [blame] | 118 | } |
| 119 | return 0; |
| 120 | } |
| 121 | } |
Alexey Kardashevskiy | 0a9516c | 2015-11-12 14:44:23 +1100 | [diff] [blame] | 122 | |
Thomas Huth | 854e67f | 2017-01-13 13:12:35 +0100 | [diff] [blame] | 123 | ret = target_get_monitor_def(cs, name, &tmp); |
Alexey Kardashevskiy | 0a9516c | 2015-11-12 14:44:23 +1100 | [diff] [blame] | 124 | if (!ret) { |
| 125 | *pval = (target_long) tmp; |
| 126 | } |
| 127 | |
| 128 | return ret; |
bellard | 9307c4c | 2004-04-04 12:57:25 +0000 | [diff] [blame] | 129 | } |
| 130 | |
Wayne Xia | 816f892 | 2011-10-12 11:32:41 +0800 | [diff] [blame] | 131 | static int |
| 132 | compare_mon_cmd(const void *a, const void *b) |
| 133 | { |
Kevin Wolf | a0cd5e1 | 2019-06-13 17:33:56 +0200 | [diff] [blame] | 134 | return strcmp(((const HMPCommand *)a)->name, |
| 135 | ((const HMPCommand *)b)->name); |
Wayne Xia | 816f892 | 2011-10-12 11:32:41 +0800 | [diff] [blame] | 136 | } |
| 137 | |
Markus Armbruster | 9d2b5f2 | 2023-01-24 13:19:45 +0100 | [diff] [blame] | 138 | static void __attribute__((__constructor__)) sortcmdlist(void) |
Wayne Xia | 816f892 | 2011-10-12 11:32:41 +0800 | [diff] [blame] | 139 | { |
Kevin Wolf | a0cd5e1 | 2019-06-13 17:33:56 +0200 | [diff] [blame] | 140 | 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 Xia | 816f892 | 2011-10-12 11:32:41 +0800 | [diff] [blame] | 146 | } |
| 147 | |
Gerd Hoffmann | f0e48cb | 2021-06-24 12:38:32 +0200 | [diff] [blame] | 148 | void 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é | f9429c6 | 2021-10-08 15:09:00 +0100 | [diff] [blame] | 155 | g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL); |
Gerd Hoffmann | f0e48cb | 2021-06-24 12:38:32 +0200 | [diff] [blame] | 156 | table->cmd = cmd; |
| 157 | return; |
| 158 | } |
| 159 | table++; |
| 160 | } |
| 161 | g_assert_not_reached(); |
| 162 | } |
| 163 | |
Daniel P. Berrangé | f9429c6 | 2021-10-08 15:09:00 +0100 | [diff] [blame] | 164 | void 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 | } |