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