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