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