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 "qemu/log.h" 30 #include "sysemu/sysemu.h" 31 32 bool hmp_handle_error(Monitor *mon, Error *err) 33 { 34 if (err) { 35 error_reportf_err(err, "Error: "); 36 return true; 37 } 38 return false; 39 } 40 41 /* 42 * Split @str at comma. 43 * A null @str defaults to "". 44 */ 45 strList *hmp_split_at_comma(const char *str) 46 { 47 char **split = g_strsplit(str ?: "", ",", -1); 48 strList *res = NULL; 49 strList **tail = &res; 50 int i; 51 52 for (i = 0; split[i]; i++) { 53 QAPI_LIST_APPEND(tail, split[i]); 54 } 55 56 g_free(split); 57 return res; 58 } 59 60 void hmp_info_name(Monitor *mon, const QDict *qdict) 61 { 62 NameInfo *info; 63 64 info = qmp_query_name(NULL); 65 if (info->name) { 66 monitor_printf(mon, "%s\n", info->name); 67 } 68 qapi_free_NameInfo(info); 69 } 70 71 void hmp_info_version(Monitor *mon, const QDict *qdict) 72 { 73 VersionInfo *info; 74 75 info = qmp_query_version(NULL); 76 77 monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n", 78 info->qemu->major, info->qemu->minor, info->qemu->micro, 79 info->package); 80 81 qapi_free_VersionInfo(info); 82 } 83 84 void hmp_quit(Monitor *mon, const QDict *qdict) 85 { 86 monitor_suspend(mon); 87 qmp_quit(NULL); 88 } 89 90 void hmp_stop(Monitor *mon, const QDict *qdict) 91 { 92 qmp_stop(NULL); 93 } 94 95 void hmp_sync_profile(Monitor *mon, const QDict *qdict) 96 { 97 const char *op = qdict_get_try_str(qdict, "op"); 98 99 if (op == NULL) { 100 bool on = qsp_is_enabled(); 101 102 monitor_printf(mon, "sync-profile is %s\n", on ? "on" : "off"); 103 return; 104 } 105 if (!strcmp(op, "on")) { 106 qsp_enable(); 107 } else if (!strcmp(op, "off")) { 108 qsp_disable(); 109 } else if (!strcmp(op, "reset")) { 110 qsp_reset(); 111 } else { 112 Error *err = NULL; 113 114 error_setg(&err, "invalid parameter '%s'," 115 " expecting 'on', 'off', or 'reset'", op); 116 hmp_handle_error(mon, err); 117 } 118 } 119 120 void hmp_exit_preconfig(Monitor *mon, const QDict *qdict) 121 { 122 Error *err = NULL; 123 124 qmp_x_exit_preconfig(&err); 125 hmp_handle_error(mon, err); 126 } 127 128 void hmp_cpu(Monitor *mon, const QDict *qdict) 129 { 130 int64_t cpu_index; 131 132 /* XXX: drop the monitor_set_cpu() usage when all HMP commands that 133 use it are converted to the QAPI */ 134 cpu_index = qdict_get_int(qdict, "index"); 135 if (monitor_set_cpu(mon, cpu_index) < 0) { 136 monitor_printf(mon, "invalid CPU index\n"); 137 } 138 } 139 140 void hmp_cont(Monitor *mon, const QDict *qdict) 141 { 142 Error *err = NULL; 143 144 qmp_cont(&err); 145 hmp_handle_error(mon, err); 146 } 147 148 void hmp_change(Monitor *mon, const QDict *qdict) 149 { 150 const char *device = qdict_get_str(qdict, "device"); 151 const char *target = qdict_get_str(qdict, "target"); 152 const char *arg = qdict_get_try_str(qdict, "arg"); 153 const char *read_only = qdict_get_try_str(qdict, "read-only-mode"); 154 bool force = qdict_get_try_bool(qdict, "force", false); 155 Error *err = NULL; 156 157 #ifdef CONFIG_VNC 158 if (strcmp(device, "vnc") == 0) { 159 hmp_change_vnc(mon, device, target, arg, read_only, force, &err); 160 } else 161 #endif 162 { 163 hmp_change_medium(mon, device, target, arg, read_only, force, &err); 164 } 165 166 hmp_handle_error(mon, err); 167 } 168 169 #ifdef CONFIG_POSIX 170 void hmp_getfd(Monitor *mon, const QDict *qdict) 171 { 172 const char *fdname = qdict_get_str(qdict, "fdname"); 173 Error *err = NULL; 174 175 qmp_getfd(fdname, &err); 176 hmp_handle_error(mon, err); 177 } 178 #endif 179 180 void hmp_closefd(Monitor *mon, const QDict *qdict) 181 { 182 const char *fdname = qdict_get_str(qdict, "fdname"); 183 Error *err = NULL; 184 185 qmp_closefd(fdname, &err); 186 hmp_handle_error(mon, err); 187 } 188 189 void hmp_info_iothreads(Monitor *mon, const QDict *qdict) 190 { 191 IOThreadInfoList *info_list = qmp_query_iothreads(NULL); 192 IOThreadInfoList *info; 193 IOThreadInfo *value; 194 195 for (info = info_list; info; info = info->next) { 196 value = info->value; 197 monitor_printf(mon, "%s:\n", value->id); 198 monitor_printf(mon, " thread_id=%" PRId64 "\n", value->thread_id); 199 monitor_printf(mon, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns); 200 monitor_printf(mon, " poll-grow=%" PRId64 "\n", value->poll_grow); 201 monitor_printf(mon, " poll-shrink=%" PRId64 "\n", value->poll_shrink); 202 monitor_printf(mon, " aio-max-batch=%" PRId64 "\n", 203 value->aio_max_batch); 204 } 205 206 qapi_free_IOThreadInfoList(info_list); 207 } 208 209 void hmp_help(Monitor *mon, const QDict *qdict) 210 { 211 hmp_help_cmd(mon, qdict_get_try_str(qdict, "name")); 212 } 213 214 void hmp_info_help(Monitor *mon, const QDict *qdict) 215 { 216 hmp_help_cmd(mon, "info"); 217 } 218 219 void hmp_info_sync_profile(Monitor *mon, const QDict *qdict) 220 { 221 int64_t max = qdict_get_try_int(qdict, "max", 10); 222 bool mean = qdict_get_try_bool(qdict, "mean", false); 223 bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false); 224 enum QSPSortBy sort_by; 225 226 sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME; 227 qsp_report(max, sort_by, coalesce); 228 } 229 230 void hmp_info_history(Monitor *mon, const QDict *qdict) 231 { 232 MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common); 233 int i; 234 const char *str; 235 236 if (!hmp_mon->rs) { 237 return; 238 } 239 i = 0; 240 for(;;) { 241 str = readline_get_history(hmp_mon->rs, i); 242 if (!str) { 243 break; 244 } 245 monitor_printf(mon, "%d: '%s'\n", i, str); 246 i++; 247 } 248 } 249 250 void hmp_logfile(Monitor *mon, const QDict *qdict) 251 { 252 Error *err = NULL; 253 254 if (!qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err)) { 255 error_report_err(err); 256 } 257 } 258 259 void hmp_log(Monitor *mon, const QDict *qdict) 260 { 261 int mask; 262 const char *items = qdict_get_str(qdict, "items"); 263 Error *err = NULL; 264 265 if (!strcmp(items, "none")) { 266 mask = 0; 267 } else { 268 mask = qemu_str_to_log_mask(items); 269 if (!mask) { 270 hmp_help_cmd(mon, "log"); 271 return; 272 } 273 } 274 275 if (!qemu_set_log(mask, &err)) { 276 error_report_err(err); 277 } 278 } 279 280 void hmp_gdbserver(Monitor *mon, const QDict *qdict) 281 { 282 const char *device = qdict_get_try_str(qdict, "device"); 283 if (!device) { 284 device = "tcp::" DEFAULT_GDBSTUB_PORT; 285 } 286 287 if (gdbserver_start(device) < 0) { 288 monitor_printf(mon, "Could not open gdbserver on device '%s'\n", 289 device); 290 } else if (strcmp(device, "none") == 0) { 291 monitor_printf(mon, "Disabled gdbserver\n"); 292 } else { 293 monitor_printf(mon, "Waiting for gdb connection on device '%s'\n", 294 device); 295 } 296 } 297 298 void hmp_print(Monitor *mon, const QDict *qdict) 299 { 300 int format = qdict_get_int(qdict, "format"); 301 hwaddr val = qdict_get_int(qdict, "val"); 302 303 switch(format) { 304 case 'o': 305 monitor_printf(mon, "%#" HWADDR_PRIo, val); 306 break; 307 case 'x': 308 monitor_printf(mon, "%#" HWADDR_PRIx, val); 309 break; 310 case 'u': 311 monitor_printf(mon, "%" HWADDR_PRIu, val); 312 break; 313 default: 314 case 'd': 315 monitor_printf(mon, "%" HWADDR_PRId, val); 316 break; 317 case 'c': 318 monitor_printc(mon, val); 319 break; 320 } 321 monitor_printf(mon, "\n"); 322 } 323 324 void hmp_sum(Monitor *mon, const QDict *qdict) 325 { 326 uint32_t addr; 327 uint16_t sum; 328 uint32_t start = qdict_get_int(qdict, "start"); 329 uint32_t size = qdict_get_int(qdict, "size"); 330 331 sum = 0; 332 for(addr = start; addr < (start + size); addr++) { 333 uint8_t val = address_space_ldub(&address_space_memory, addr, 334 MEMTXATTRS_UNSPECIFIED, NULL); 335 /* BSD sum algorithm ('sum' Unix command) */ 336 sum = (sum >> 1) | (sum << 15); 337 sum += val; 338 } 339 monitor_printf(mon, "%05d\n", sum); 340 } 341 342 void hmp_ioport_read(Monitor *mon, const QDict *qdict) 343 { 344 int size = qdict_get_int(qdict, "size"); 345 int addr = qdict_get_int(qdict, "addr"); 346 int has_index = qdict_haskey(qdict, "index"); 347 uint32_t val; 348 int suffix; 349 350 if (has_index) { 351 int index = qdict_get_int(qdict, "index"); 352 cpu_outb(addr & IOPORTS_MASK, index & 0xff); 353 addr++; 354 } 355 addr &= 0xffff; 356 357 switch(size) { 358 default: 359 case 1: 360 val = cpu_inb(addr); 361 suffix = 'b'; 362 break; 363 case 2: 364 val = cpu_inw(addr); 365 suffix = 'w'; 366 break; 367 case 4: 368 val = cpu_inl(addr); 369 suffix = 'l'; 370 break; 371 } 372 monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n", 373 suffix, addr, size * 2, val); 374 } 375 376 void hmp_ioport_write(Monitor *mon, const QDict *qdict) 377 { 378 int size = qdict_get_int(qdict, "size"); 379 int addr = qdict_get_int(qdict, "addr"); 380 int val = qdict_get_int(qdict, "val"); 381 382 addr &= IOPORTS_MASK; 383 384 switch (size) { 385 default: 386 case 1: 387 cpu_outb(addr, val); 388 break; 389 case 2: 390 cpu_outw(addr, val); 391 break; 392 case 4: 393 cpu_outl(addr, val); 394 break; 395 } 396 } 397 398 void hmp_boot_set(Monitor *mon, const QDict *qdict) 399 { 400 Error *local_err = NULL; 401 const char *bootdevice = qdict_get_str(qdict, "bootdevice"); 402 403 qemu_boot_set(bootdevice, &local_err); 404 if (local_err) { 405 error_report_err(local_err); 406 } else { 407 monitor_printf(mon, "boot device list now set to %s\n", bootdevice); 408 } 409 } 410 411 void hmp_info_mtree(Monitor *mon, const QDict *qdict) 412 { 413 bool flatview = qdict_get_try_bool(qdict, "flatview", false); 414 bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false); 415 bool owner = qdict_get_try_bool(qdict, "owner", false); 416 bool disabled = qdict_get_try_bool(qdict, "disabled", false); 417 418 mtree_info(flatview, dispatch_tree, owner, disabled); 419 } 420 421 #if defined(CONFIG_FDT) 422 void hmp_dumpdtb(Monitor *mon, const QDict *qdict) 423 { 424 const char *filename = qdict_get_str(qdict, "filename"); 425 Error *local_err = NULL; 426 427 qmp_dumpdtb(filename, &local_err); 428 429 if (hmp_handle_error(mon, local_err)) { 430 return; 431 } 432 433 monitor_printf(mon, "dtb dumped to %s", filename); 434 } 435 #endif 436