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