xref: /openbmc/qemu/monitor/hmp-cmds.c (revision b2580720)
1 /*
2  * Human Monitor Interface commands
3  *
4  * Copyright IBM, Corp. 2011
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  * Contributions after 2012-01-13 are licensed under the terms of the
13  * GNU GPL, version 2 or (at your option) any later version.
14  */
15 
16 #include "qemu/osdep.h"
17 #include "exec/address-spaces.h"
18 #include "exec/gdbstub.h"
19 #include "exec/ioport.h"
20 #include "monitor/hmp.h"
21 #include "qemu/help_option.h"
22 #include "monitor/monitor-internal.h"
23 #include "qapi/error.h"
24 #include "qapi/qapi-commands-control.h"
25 #include "qapi/qapi-commands-machine.h"
26 #include "qapi/qapi-commands-misc.h"
27 #include "qapi/qmp/qdict.h"
28 #include "qapi/type-helpers.h"
29 #include "qemu/cutils.h"
30 #include "hw/intc/intc.h"
31 #include "qemu/log.h"
32 #include "sysemu/sysemu.h"
33 
34 bool hmp_handle_error(Monitor *mon, Error *err)
35 {
36     if (err) {
37         error_reportf_err(err, "Error: ");
38         return true;
39     }
40     return false;
41 }
42 
43 /*
44  * Split @str at comma.
45  * A null @str defaults to "".
46  */
47 strList *hmp_split_at_comma(const char *str)
48 {
49     char **split = g_strsplit(str ?: "", ",", -1);
50     strList *res = NULL;
51     strList **tail = &res;
52     int i;
53 
54     for (i = 0; split[i]; i++) {
55         QAPI_LIST_APPEND(tail, split[i]);
56     }
57 
58     g_free(split);
59     return res;
60 }
61 
62 void hmp_info_name(Monitor *mon, const QDict *qdict)
63 {
64     NameInfo *info;
65 
66     info = qmp_query_name(NULL);
67     if (info->name) {
68         monitor_printf(mon, "%s\n", info->name);
69     }
70     qapi_free_NameInfo(info);
71 }
72 
73 void hmp_info_version(Monitor *mon, const QDict *qdict)
74 {
75     VersionInfo *info;
76 
77     info = qmp_query_version(NULL);
78 
79     monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
80                    info->qemu->major, info->qemu->minor, info->qemu->micro,
81                    info->package);
82 
83     qapi_free_VersionInfo(info);
84 }
85 
86 static int hmp_info_pic_foreach(Object *obj, void *opaque)
87 {
88     InterruptStatsProvider *intc;
89     InterruptStatsProviderClass *k;
90     Monitor *mon = opaque;
91 
92     if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
93         intc = INTERRUPT_STATS_PROVIDER(obj);
94         k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
95         if (k->print_info) {
96             g_autoptr(GString) buf = g_string_new("");
97             g_autoptr(HumanReadableText) info = NULL;
98 
99             k->print_info(intc, buf);
100             info = human_readable_text_from_str(buf);
101             monitor_puts(mon, info->human_readable_text);
102         } else {
103             monitor_printf(mon, "Interrupt controller information not available for %s.\n",
104                            object_get_typename(obj));
105         }
106     }
107 
108     return 0;
109 }
110 
111 void hmp_info_pic(Monitor *mon, const QDict *qdict)
112 {
113     object_child_foreach_recursive(object_get_root(),
114                                    hmp_info_pic_foreach, mon);
115 }
116 
117 void hmp_quit(Monitor *mon, const QDict *qdict)
118 {
119     monitor_suspend(mon);
120     qmp_quit(NULL);
121 }
122 
123 void hmp_stop(Monitor *mon, const QDict *qdict)
124 {
125     qmp_stop(NULL);
126 }
127 
128 void hmp_sync_profile(Monitor *mon, const QDict *qdict)
129 {
130     const char *op = qdict_get_try_str(qdict, "op");
131 
132     if (op == NULL) {
133         bool on = qsp_is_enabled();
134 
135         monitor_printf(mon, "sync-profile is %s\n", on ? "on" : "off");
136         return;
137     }
138     if (!strcmp(op, "on")) {
139         qsp_enable();
140     } else if (!strcmp(op, "off")) {
141         qsp_disable();
142     } else if (!strcmp(op, "reset")) {
143         qsp_reset();
144     } else {
145         Error *err = NULL;
146 
147         error_setg(&err, "invalid parameter '%s',"
148                    " expecting 'on', 'off', or 'reset'", op);
149         hmp_handle_error(mon, err);
150     }
151 }
152 
153 void hmp_exit_preconfig(Monitor *mon, const QDict *qdict)
154 {
155     Error *err = NULL;
156 
157     qmp_x_exit_preconfig(&err);
158     hmp_handle_error(mon, err);
159 }
160 
161 void hmp_cpu(Monitor *mon, const QDict *qdict)
162 {
163     int64_t cpu_index;
164 
165     /* XXX: drop the monitor_set_cpu() usage when all HMP commands that
166             use it are converted to the QAPI */
167     cpu_index = qdict_get_int(qdict, "index");
168     if (monitor_set_cpu(mon, cpu_index) < 0) {
169         monitor_printf(mon, "invalid CPU index\n");
170     }
171 }
172 
173 void hmp_cont(Monitor *mon, const QDict *qdict)
174 {
175     Error *err = NULL;
176 
177     qmp_cont(&err);
178     hmp_handle_error(mon, err);
179 }
180 
181 void hmp_change(Monitor *mon, const QDict *qdict)
182 {
183     const char *device = qdict_get_str(qdict, "device");
184     const char *target = qdict_get_str(qdict, "target");
185     const char *arg = qdict_get_try_str(qdict, "arg");
186     const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
187     bool force = qdict_get_try_bool(qdict, "force", false);
188     Error *err = NULL;
189 
190 #ifdef CONFIG_VNC
191     if (strcmp(device, "vnc") == 0) {
192         hmp_change_vnc(mon, device, target, arg, read_only, force, &err);
193     } else
194 #endif
195     {
196         hmp_change_medium(mon, device, target, arg, read_only, force, &err);
197     }
198 
199     hmp_handle_error(mon, err);
200 }
201 
202 #ifdef CONFIG_POSIX
203 void hmp_getfd(Monitor *mon, const QDict *qdict)
204 {
205     const char *fdname = qdict_get_str(qdict, "fdname");
206     Error *err = NULL;
207 
208     qmp_getfd(fdname, &err);
209     hmp_handle_error(mon, err);
210 }
211 #endif
212 
213 void hmp_closefd(Monitor *mon, const QDict *qdict)
214 {
215     const char *fdname = qdict_get_str(qdict, "fdname");
216     Error *err = NULL;
217 
218     qmp_closefd(fdname, &err);
219     hmp_handle_error(mon, err);
220 }
221 
222 void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
223 {
224     IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
225     IOThreadInfoList *info;
226     IOThreadInfo *value;
227 
228     for (info = info_list; info; info = info->next) {
229         value = info->value;
230         monitor_printf(mon, "%s:\n", value->id);
231         monitor_printf(mon, "  thread_id=%" PRId64 "\n", value->thread_id);
232         monitor_printf(mon, "  poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
233         monitor_printf(mon, "  poll-grow=%" PRId64 "\n", value->poll_grow);
234         monitor_printf(mon, "  poll-shrink=%" PRId64 "\n", value->poll_shrink);
235         monitor_printf(mon, "  aio-max-batch=%" PRId64 "\n",
236                        value->aio_max_batch);
237     }
238 
239     qapi_free_IOThreadInfoList(info_list);
240 }
241 
242 void hmp_help(Monitor *mon, const QDict *qdict)
243 {
244     hmp_help_cmd(mon, qdict_get_try_str(qdict, "name"));
245 }
246 
247 void hmp_info_help(Monitor *mon, const QDict *qdict)
248 {
249     hmp_help_cmd(mon, "info");
250 }
251 
252 void hmp_info_sync_profile(Monitor *mon, const QDict *qdict)
253 {
254     int64_t max = qdict_get_try_int(qdict, "max", 10);
255     bool mean = qdict_get_try_bool(qdict, "mean", false);
256     bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false);
257     enum QSPSortBy sort_by;
258 
259     sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME;
260     qsp_report(max, sort_by, coalesce);
261 }
262 
263 void hmp_info_history(Monitor *mon, const QDict *qdict)
264 {
265     MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
266     int i;
267     const char *str;
268 
269     if (!hmp_mon->rs) {
270         return;
271     }
272     i = 0;
273     for(;;) {
274         str = readline_get_history(hmp_mon->rs, i);
275         if (!str) {
276             break;
277         }
278         monitor_printf(mon, "%d: '%s'\n", i, str);
279         i++;
280     }
281 }
282 
283 void hmp_logfile(Monitor *mon, const QDict *qdict)
284 {
285     Error *err = NULL;
286 
287     if (!qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err)) {
288         error_report_err(err);
289     }
290 }
291 
292 void hmp_log(Monitor *mon, const QDict *qdict)
293 {
294     int mask;
295     const char *items = qdict_get_str(qdict, "items");
296     Error *err = NULL;
297 
298     if (!strcmp(items, "none")) {
299         mask = 0;
300     } else {
301         mask = qemu_str_to_log_mask(items);
302         if (!mask) {
303             hmp_help_cmd(mon, "log");
304             return;
305         }
306     }
307 
308     if (!qemu_set_log(mask, &err)) {
309         error_report_err(err);
310     }
311 }
312 
313 void hmp_gdbserver(Monitor *mon, const QDict *qdict)
314 {
315     const char *device = qdict_get_try_str(qdict, "device");
316     if (!device) {
317         device = "tcp::" DEFAULT_GDBSTUB_PORT;
318     }
319 
320     if (gdbserver_start(device) < 0) {
321         monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
322                        device);
323     } else if (strcmp(device, "none") == 0) {
324         monitor_printf(mon, "Disabled gdbserver\n");
325     } else {
326         monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
327                        device);
328     }
329 }
330 
331 void hmp_print(Monitor *mon, const QDict *qdict)
332 {
333     int format = qdict_get_int(qdict, "format");
334     hwaddr val = qdict_get_int(qdict, "val");
335 
336     switch(format) {
337     case 'o':
338         monitor_printf(mon, "%#" HWADDR_PRIo, val);
339         break;
340     case 'x':
341         monitor_printf(mon, "%#" HWADDR_PRIx, val);
342         break;
343     case 'u':
344         monitor_printf(mon, "%" HWADDR_PRIu, val);
345         break;
346     default:
347     case 'd':
348         monitor_printf(mon, "%" HWADDR_PRId, val);
349         break;
350     case 'c':
351         monitor_printc(mon, val);
352         break;
353     }
354     monitor_printf(mon, "\n");
355 }
356 
357 void hmp_sum(Monitor *mon, const QDict *qdict)
358 {
359     uint32_t addr;
360     uint16_t sum;
361     uint32_t start = qdict_get_int(qdict, "start");
362     uint32_t size = qdict_get_int(qdict, "size");
363 
364     sum = 0;
365     for(addr = start; addr < (start + size); addr++) {
366         uint8_t val = address_space_ldub(&address_space_memory, addr,
367                                          MEMTXATTRS_UNSPECIFIED, NULL);
368         /* BSD sum algorithm ('sum' Unix command) */
369         sum = (sum >> 1) | (sum << 15);
370         sum += val;
371     }
372     monitor_printf(mon, "%05d\n", sum);
373 }
374 
375 void hmp_ioport_read(Monitor *mon, const QDict *qdict)
376 {
377     int size = qdict_get_int(qdict, "size");
378     int addr = qdict_get_int(qdict, "addr");
379     int has_index = qdict_haskey(qdict, "index");
380     uint32_t val;
381     int suffix;
382 
383     if (has_index) {
384         int index = qdict_get_int(qdict, "index");
385         cpu_outb(addr & IOPORTS_MASK, index & 0xff);
386         addr++;
387     }
388     addr &= 0xffff;
389 
390     switch(size) {
391     default:
392     case 1:
393         val = cpu_inb(addr);
394         suffix = 'b';
395         break;
396     case 2:
397         val = cpu_inw(addr);
398         suffix = 'w';
399         break;
400     case 4:
401         val = cpu_inl(addr);
402         suffix = 'l';
403         break;
404     }
405     monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n",
406                    suffix, addr, size * 2, val);
407 }
408 
409 void hmp_ioport_write(Monitor *mon, const QDict *qdict)
410 {
411     int size = qdict_get_int(qdict, "size");
412     int addr = qdict_get_int(qdict, "addr");
413     int val = qdict_get_int(qdict, "val");
414 
415     addr &= IOPORTS_MASK;
416 
417     switch (size) {
418     default:
419     case 1:
420         cpu_outb(addr, val);
421         break;
422     case 2:
423         cpu_outw(addr, val);
424         break;
425     case 4:
426         cpu_outl(addr, val);
427         break;
428     }
429 }
430 
431 void hmp_boot_set(Monitor *mon, const QDict *qdict)
432 {
433     Error *local_err = NULL;
434     const char *bootdevice = qdict_get_str(qdict, "bootdevice");
435 
436     qemu_boot_set(bootdevice, &local_err);
437     if (local_err) {
438         error_report_err(local_err);
439     } else {
440         monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
441     }
442 }
443 
444 void hmp_info_mtree(Monitor *mon, const QDict *qdict)
445 {
446     bool flatview = qdict_get_try_bool(qdict, "flatview", false);
447     bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
448     bool owner = qdict_get_try_bool(qdict, "owner", false);
449     bool disabled = qdict_get_try_bool(qdict, "disabled", false);
450 
451     mtree_info(flatview, dispatch_tree, owner, disabled);
452 }
453 
454 #if defined(CONFIG_FDT)
455 void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
456 {
457     const char *filename = qdict_get_str(qdict, "filename");
458     Error *local_err = NULL;
459 
460     qmp_dumpdtb(filename, &local_err);
461 
462     if (hmp_handle_error(mon, local_err)) {
463         return;
464     }
465 
466     monitor_printf(mon, "dtb dumped to %s", filename);
467 }
468 #endif
469