xref: /openbmc/qemu/monitor/hmp-cmds.c (revision 93d7620c)
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-misc.h"
26 #include "qapi/qmp/qdict.h"
27 #include "qapi/qmp/qerror.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, QERR_INVALID_PARAMETER, op);
142         hmp_handle_error(mon, err);
143     }
144 }
145 
146 void hmp_exit_preconfig(Monitor *mon, const QDict *qdict)
147 {
148     Error *err = NULL;
149 
150     qmp_x_exit_preconfig(&err);
151     hmp_handle_error(mon, err);
152 }
153 
154 void hmp_cpu(Monitor *mon, const QDict *qdict)
155 {
156     int64_t cpu_index;
157 
158     /* XXX: drop the monitor_set_cpu() usage when all HMP commands that
159             use it are converted to the QAPI */
160     cpu_index = qdict_get_int(qdict, "index");
161     if (monitor_set_cpu(mon, cpu_index) < 0) {
162         monitor_printf(mon, "invalid CPU index\n");
163     }
164 }
165 
166 void hmp_cont(Monitor *mon, const QDict *qdict)
167 {
168     Error *err = NULL;
169 
170     qmp_cont(&err);
171     hmp_handle_error(mon, err);
172 }
173 
174 void hmp_change(Monitor *mon, const QDict *qdict)
175 {
176     const char *device = qdict_get_str(qdict, "device");
177     const char *target = qdict_get_str(qdict, "target");
178     const char *arg = qdict_get_try_str(qdict, "arg");
179     const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
180     bool force = qdict_get_try_bool(qdict, "force", false);
181     Error *err = NULL;
182 
183 #ifdef CONFIG_VNC
184     if (strcmp(device, "vnc") == 0) {
185         hmp_change_vnc(mon, device, target, arg, read_only, force, &err);
186     } else
187 #endif
188     {
189         hmp_change_medium(mon, device, target, arg, read_only, force, &err);
190     }
191 
192     hmp_handle_error(mon, err);
193 }
194 
195 void hmp_getfd(Monitor *mon, const QDict *qdict)
196 {
197     const char *fdname = qdict_get_str(qdict, "fdname");
198     Error *err = NULL;
199 
200     qmp_getfd(fdname, &err);
201     hmp_handle_error(mon, err);
202 }
203 
204 void hmp_closefd(Monitor *mon, const QDict *qdict)
205 {
206     const char *fdname = qdict_get_str(qdict, "fdname");
207     Error *err = NULL;
208 
209     qmp_closefd(fdname, &err);
210     hmp_handle_error(mon, err);
211 }
212 
213 void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
214 {
215     IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
216     IOThreadInfoList *info;
217     IOThreadInfo *value;
218 
219     for (info = info_list; info; info = info->next) {
220         value = info->value;
221         monitor_printf(mon, "%s:\n", value->id);
222         monitor_printf(mon, "  thread_id=%" PRId64 "\n", value->thread_id);
223         monitor_printf(mon, "  poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
224         monitor_printf(mon, "  poll-grow=%" PRId64 "\n", value->poll_grow);
225         monitor_printf(mon, "  poll-shrink=%" PRId64 "\n", value->poll_shrink);
226         monitor_printf(mon, "  aio-max-batch=%" PRId64 "\n",
227                        value->aio_max_batch);
228     }
229 
230     qapi_free_IOThreadInfoList(info_list);
231 }
232 
233 void hmp_help(Monitor *mon, const QDict *qdict)
234 {
235     hmp_help_cmd(mon, qdict_get_try_str(qdict, "name"));
236 }
237 
238 void hmp_info_help(Monitor *mon, const QDict *qdict)
239 {
240     hmp_help_cmd(mon, "info");
241 }
242 
243 void hmp_info_sync_profile(Monitor *mon, const QDict *qdict)
244 {
245     int64_t max = qdict_get_try_int(qdict, "max", 10);
246     bool mean = qdict_get_try_bool(qdict, "mean", false);
247     bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false);
248     enum QSPSortBy sort_by;
249 
250     sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME;
251     qsp_report(max, sort_by, coalesce);
252 }
253 
254 void hmp_info_history(Monitor *mon, const QDict *qdict)
255 {
256     MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
257     int i;
258     const char *str;
259 
260     if (!hmp_mon->rs) {
261         return;
262     }
263     i = 0;
264     for(;;) {
265         str = readline_get_history(hmp_mon->rs, i);
266         if (!str) {
267             break;
268         }
269         monitor_printf(mon, "%d: '%s'\n", i, str);
270         i++;
271     }
272 }
273 
274 void hmp_logfile(Monitor *mon, const QDict *qdict)
275 {
276     Error *err = NULL;
277 
278     if (!qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err)) {
279         error_report_err(err);
280     }
281 }
282 
283 void hmp_log(Monitor *mon, const QDict *qdict)
284 {
285     int mask;
286     const char *items = qdict_get_str(qdict, "items");
287     Error *err = NULL;
288 
289     if (!strcmp(items, "none")) {
290         mask = 0;
291     } else {
292         mask = qemu_str_to_log_mask(items);
293         if (!mask) {
294             hmp_help_cmd(mon, "log");
295             return;
296         }
297     }
298 
299     if (!qemu_set_log(mask, &err)) {
300         error_report_err(err);
301     }
302 }
303 
304 void hmp_gdbserver(Monitor *mon, const QDict *qdict)
305 {
306     const char *device = qdict_get_try_str(qdict, "device");
307     if (!device) {
308         device = "tcp::" DEFAULT_GDBSTUB_PORT;
309     }
310 
311     if (gdbserver_start(device) < 0) {
312         monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
313                        device);
314     } else if (strcmp(device, "none") == 0) {
315         monitor_printf(mon, "Disabled gdbserver\n");
316     } else {
317         monitor_printf(mon, "Waiting for gdb connection on device '%s'\n",
318                        device);
319     }
320 }
321 
322 void hmp_print(Monitor *mon, const QDict *qdict)
323 {
324     int format = qdict_get_int(qdict, "format");
325     hwaddr val = qdict_get_int(qdict, "val");
326 
327     switch(format) {
328     case 'o':
329         monitor_printf(mon, "%#" HWADDR_PRIo, val);
330         break;
331     case 'x':
332         monitor_printf(mon, "%#" HWADDR_PRIx, val);
333         break;
334     case 'u':
335         monitor_printf(mon, "%" HWADDR_PRIu, val);
336         break;
337     default:
338     case 'd':
339         monitor_printf(mon, "%" HWADDR_PRId, val);
340         break;
341     case 'c':
342         monitor_printc(mon, val);
343         break;
344     }
345     monitor_printf(mon, "\n");
346 }
347 
348 void hmp_sum(Monitor *mon, const QDict *qdict)
349 {
350     uint32_t addr;
351     uint16_t sum;
352     uint32_t start = qdict_get_int(qdict, "start");
353     uint32_t size = qdict_get_int(qdict, "size");
354 
355     sum = 0;
356     for(addr = start; addr < (start + size); addr++) {
357         uint8_t val = address_space_ldub(&address_space_memory, addr,
358                                          MEMTXATTRS_UNSPECIFIED, NULL);
359         /* BSD sum algorithm ('sum' Unix command) */
360         sum = (sum >> 1) | (sum << 15);
361         sum += val;
362     }
363     monitor_printf(mon, "%05d\n", sum);
364 }
365 
366 void hmp_ioport_read(Monitor *mon, const QDict *qdict)
367 {
368     int size = qdict_get_int(qdict, "size");
369     int addr = qdict_get_int(qdict, "addr");
370     int has_index = qdict_haskey(qdict, "index");
371     uint32_t val;
372     int suffix;
373 
374     if (has_index) {
375         int index = qdict_get_int(qdict, "index");
376         cpu_outb(addr & IOPORTS_MASK, index & 0xff);
377         addr++;
378     }
379     addr &= 0xffff;
380 
381     switch(size) {
382     default:
383     case 1:
384         val = cpu_inb(addr);
385         suffix = 'b';
386         break;
387     case 2:
388         val = cpu_inw(addr);
389         suffix = 'w';
390         break;
391     case 4:
392         val = cpu_inl(addr);
393         suffix = 'l';
394         break;
395     }
396     monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n",
397                    suffix, addr, size * 2, val);
398 }
399 
400 void hmp_ioport_write(Monitor *mon, const QDict *qdict)
401 {
402     int size = qdict_get_int(qdict, "size");
403     int addr = qdict_get_int(qdict, "addr");
404     int val = qdict_get_int(qdict, "val");
405 
406     addr &= IOPORTS_MASK;
407 
408     switch (size) {
409     default:
410     case 1:
411         cpu_outb(addr, val);
412         break;
413     case 2:
414         cpu_outw(addr, val);
415         break;
416     case 4:
417         cpu_outl(addr, val);
418         break;
419     }
420 }
421 
422 void hmp_boot_set(Monitor *mon, const QDict *qdict)
423 {
424     Error *local_err = NULL;
425     const char *bootdevice = qdict_get_str(qdict, "bootdevice");
426 
427     qemu_boot_set(bootdevice, &local_err);
428     if (local_err) {
429         error_report_err(local_err);
430     } else {
431         monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
432     }
433 }
434 
435 void hmp_info_mtree(Monitor *mon, const QDict *qdict)
436 {
437     bool flatview = qdict_get_try_bool(qdict, "flatview", false);
438     bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
439     bool owner = qdict_get_try_bool(qdict, "owner", false);
440     bool disabled = qdict_get_try_bool(qdict, "disabled", false);
441 
442     mtree_info(flatview, dispatch_tree, owner, disabled);
443 }
444