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