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