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