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