master
c 818 lines 20.8 KB
Raw
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 "qemu/base-arch-defs.h"
18 #include "system/address-spaces.h"
19 #include "system/ioport.h"
20 #include "exec/gdbstub.h"
21 #include "exec/target_page.h"
22 #include "gdbstub/enums.h"
23 #include "monitor/hmp.h"
24 #include "qemu/help_option.h"
25 #include "monitor/hmp.h"
26 #include "monitor/hmp-completion.h"
27 #include "monitor/monitor-internal.h"
28 #include "monitor/monitor-hmp-internal.h"
29 #include "monitor/qdev.h"
30 #include "qapi/error.h"
31 #include "qapi/qapi-commands-control.h"
32 #include "qapi/qapi-commands-machine.h"
33 #include "qapi/qapi-commands-misc.h"
34 #include "block/block-hmp-cmds.h"
35 #include "qobject/qdict.h"
36 #include "qemu/cutils.h"
37 #include "qemu/log.h"
38 #include "net/slirp.h"
39 #include "system/device_tree.h"
40 #include "system/hw_accel.h"
41 #include "system/memory.h"
42 #include "system/system.h"
43 #include "disas/disas.h"
44
45 /* Please update hmp-commands.hx when adding or changing commands */
46 #ifdef CONFIG_HMP
47 static HMPCommand hmp_info_cmds[] = {
48 #include "hmp-commands-info.h"
49 { NULL, NULL, },
50 };
51
52 /* hmp_cmds and hmp_info_cmds would be sorted at runtime */
53 static HMPCommand hmp_cmds[] = {
54 #include "hmp-commands.h"
55 { NULL, NULL, },
56 };
57 #else
58 static HMPCommand hmp_info_cmds[] = { { NULL, NULL, }, };
59 static HMPCommand hmp_cmds[] = { { NULL, NULL, }, };
60 #endif
61
62 HMPCommand *hmp_cmds_for_target(bool info_command)
63 {
64 return info_command ? hmp_info_cmds : hmp_cmds;
65 }
66
67 static int
68 compare_mon_cmd(const void *a, const void *b)
69 {
70 return strcmp(((const HMPCommand *)a)->name,
71 ((const HMPCommand *)b)->name);
72 }
73
74 static void __attribute__((__constructor__)) sortcmdlist(void)
75 {
76 qsort(hmp_cmds, ARRAY_SIZE(hmp_cmds) - 1,
77 sizeof(*hmp_cmds),
78 compare_mon_cmd);
79 qsort(hmp_info_cmds, ARRAY_SIZE(hmp_info_cmds) - 1,
80 sizeof(*hmp_info_cmds),
81 compare_mon_cmd);
82 }
83
84 bool hmp_handle_error(MonitorHMP *hmp, Error *err)
85 {
86 if (err) {
87 error_reportf_err(err, "Error: ");
88 return true;
89 }
90 return false;
91 }
92
93 /*
94 * Split @str at comma.
95 * A null @str defaults to "".
96 */
97 strList *hmp_split_at_comma(const char *str)
98 {
99 char **split = g_strsplit(str ?: "", ",", -1);
100 strList *res = NULL;
101 strList **tail = &res;
102 int i;
103
104 for (i = 0; split[i]; i++) {
105 QAPI_LIST_APPEND(tail, split[i]);
106 }
107
108 g_free(split);
109 return res;
110 }
111
112 void hmp_info_name(MonitorHMP *hmp, const QDict *qdict)
113 {
114 NameInfo *info;
115
116 info = qmp_query_name(NULL);
117 if (info->name) {
118 monitor_hmp_printf(hmp, "%s\n", info->name);
119 }
120 qapi_free_NameInfo(info);
121 }
122
123 void hmp_info_version(MonitorHMP *hmp, const QDict *qdict)
124 {
125 VersionInfo *info;
126
127 info = qmp_query_version(NULL);
128
129 monitor_hmp_printf(hmp, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
130 info->qemu->major, info->qemu->minor, info->qemu->micro,
131 info->package);
132
133 qapi_free_VersionInfo(info);
134 }
135
136 void hmp_quit(MonitorHMP *hmp, const QDict *qdict)
137 {
138 Monitor *mon = MONITOR(hmp);
139 if (hmp->use_readline) {
140 monitor_suspend(mon);
141 }
142 qmp_quit(NULL);
143 }
144
145 void hmp_stop(MonitorHMP *hmp, const QDict *qdict)
146 {
147 qmp_stop(NULL);
148 }
149
150 void hmp_sync_profile(MonitorHMP *hmp, const QDict *qdict)
151 {
152 const char *op = qdict_get_try_str(qdict, "op");
153
154 if (op == NULL) {
155 bool on = qsp_is_enabled();
156
157 monitor_hmp_printf(hmp, "sync-profile is %s\n", on ? "on" : "off");
158 return;
159 }
160 if (!strcmp(op, "on")) {
161 qsp_enable();
162 } else if (!strcmp(op, "off")) {
163 qsp_disable();
164 } else if (!strcmp(op, "reset")) {
165 qsp_reset();
166 } else {
167 Error *err = NULL;
168
169 error_setg(&err, "invalid parameter '%s',"
170 " expecting 'on', 'off', or 'reset'", op);
171 hmp_handle_error(hmp, err);
172 }
173 }
174
175 void hmp_exit_preconfig(MonitorHMP *hmp, const QDict *qdict)
176 {
177 Error *err = NULL;
178
179 qmp_x_exit_preconfig(&err);
180 hmp_handle_error(hmp, err);
181 }
182
183 void hmp_cpu(MonitorHMP *hmp, const QDict *qdict)
184 {
185 int64_t cpu_index;
186
187 /* XXX: drop the monitor_hmp_set_cpu() usage when all HMP commands that
188 use it are converted to the QAPI */
189 cpu_index = qdict_get_int(qdict, "index");
190 if (monitor_hmp_set_cpu(hmp, cpu_index) < 0) {
191 monitor_hmp_printf(hmp, "invalid CPU index\n");
192 }
193 }
194
195 void hmp_cont(MonitorHMP *hmp, const QDict *qdict)
196 {
197 Error *err = NULL;
198
199 qmp_cont(&err);
200 hmp_handle_error(hmp, err);
201 }
202
203 void hmp_change(MonitorHMP *hmp, const QDict *qdict)
204 {
205 const char *device = qdict_get_str(qdict, "device");
206 const char *target = qdict_get_str(qdict, "target");
207 const char *arg = qdict_get_try_str(qdict, "arg");
208 const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
209 bool force = qdict_get_try_bool(qdict, "force", false);
210 Error *err = NULL;
211
212 #ifdef CONFIG_VNC
213 if (strcmp(device, "vnc") == 0) {
214 hmp_change_vnc(hmp, device, target, arg, read_only, force, &err);
215 } else
216 #endif
217 {
218 hmp_change_medium(hmp, device, target, arg, read_only, force, &err);
219 }
220
221 hmp_handle_error(hmp, err);
222 }
223
224 #ifdef CONFIG_POSIX
225 void hmp_getfd(MonitorHMP *hmp, const QDict *qdict)
226 {
227 const char *fdname = qdict_get_str(qdict, "fdname");
228 Error *err = NULL;
229
230 qmp_getfd(fdname, &err);
231 hmp_handle_error(hmp, err);
232 }
233 #endif
234
235 void hmp_closefd(MonitorHMP *hmp, const QDict *qdict)
236 {
237 const char *fdname = qdict_get_str(qdict, "fdname");
238 Error *err = NULL;
239
240 qmp_closefd(fdname, &err);
241 hmp_handle_error(hmp, err);
242 }
243
244 void hmp_info_iothreads(MonitorHMP *hmp, const QDict *qdict)
245 {
246 IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
247 IOThreadInfoList *info;
248 IOThreadInfo *value;
249
250 for (info = info_list; info; info = info->next) {
251 value = info->value;
252 monitor_hmp_printf(hmp, "%s:\n", value->id);
253 monitor_hmp_printf(hmp, " thread_id=%" PRId64 "\n", value->thread_id);
254 monitor_hmp_printf(hmp, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
255 monitor_hmp_printf(hmp, " poll-grow=%" PRId64 "\n", value->poll_grow);
256 monitor_hmp_printf(hmp, " poll-shrink=%" PRId64 "\n", value->poll_shrink);
257 monitor_hmp_printf(hmp, " poll-weight=%" PRId64 "\n", value->poll_weight);
258 monitor_hmp_printf(hmp, " aio-max-batch=%" PRId64 "\n",
259 value->aio_max_batch);
260 }
261
262 qapi_free_IOThreadInfoList(info_list);
263 }
264
265 void hmp_help(MonitorHMP *hmp, const QDict *qdict)
266 {
267 hmp_help_cmd(hmp, qdict_get_try_str(qdict, "name"));
268 }
269
270 void hmp_clear(MonitorHMP *hmp, const QDict *qdict)
271 {
272 /*
273 * Send an ANSI escape sequence:
274 * "\x1b[H" - move cursor to top-left
275 * "\x1b[2J" - clear visible screen
276 * "\x1b[3J" - clear scrollback
277 */
278 monitor_hmp_printf(hmp, "\x1b[H\x1b[2J\x1b[3J");
279 }
280
281 void hmp_info_help(MonitorHMP *hmp, const QDict *qdict)
282 {
283 hmp_help_cmd(hmp, "info");
284 }
285
286 void hmp_info_sync_profile(MonitorHMP *hmp, const QDict *qdict)
287 {
288 int64_t max = qdict_get_try_int(qdict, "max", 10);
289 bool mean = qdict_get_try_bool(qdict, "mean", false);
290 bool coalesce = !qdict_get_try_bool(qdict, "no_coalesce", false);
291 enum QSPSortBy sort_by;
292
293 sort_by = mean ? QSP_SORT_BY_AVG_WAIT_TIME : QSP_SORT_BY_TOTAL_WAIT_TIME;
294 qsp_report(max, sort_by, coalesce);
295 }
296
297 void hmp_info_history(MonitorHMP *hmp, const QDict *qdict)
298 {
299 int i;
300 const char *str;
301
302 if (!hmp->rs) {
303 return;
304 }
305 i = 0;
306 for(;;) {
307 str = readline_get_history(hmp->rs, i);
308 if (!str) {
309 break;
310 }
311 monitor_hmp_printf(hmp, "%d: '%s'\n", i, str);
312 i++;
313 }
314 }
315
316 void hmp_logfile(MonitorHMP *hmp, const QDict *qdict)
317 {
318 Error *err = NULL;
319
320 if (!qemu_set_log_filename(qdict_get_str(qdict, "filename"), &err)) {
321 error_report_err(err);
322 }
323 }
324
325 void hmp_log(MonitorHMP *hmp, const QDict *qdict)
326 {
327 int mask;
328 const char *items = qdict_get_str(qdict, "items");
329 Error *err = NULL;
330
331 if (!strcmp(items, "none")) {
332 mask = 0;
333 } else {
334 mask = qemu_str_to_log_mask(items);
335 if (!mask) {
336 hmp_help_cmd(hmp, "log");
337 return;
338 }
339 }
340
341 if (!qemu_set_log(mask, &err)) {
342 error_report_err(err);
343 }
344 }
345
346 void hmp_gdbserver(MonitorHMP *hmp, const QDict *qdict)
347 {
348 Error *err = NULL;
349 const char *device = qdict_get_try_str(qdict, "device");
350
351 if (!device) {
352 device = "tcp::" DEFAULT_GDBSTUB_PORT;
353 }
354
355 if (!gdbserver_start(device, &err)) {
356 error_report_err(err);
357 } else if (strcmp(device, "none") == 0) {
358 monitor_hmp_printf(hmp, "Disabled gdbserver\n");
359 } else {
360 monitor_hmp_printf(hmp, "Waiting for gdb connection on device '%s'\n",
361 device);
362 }
363 }
364
365 void hmp_print(MonitorHMP *hmp, const QDict *qdict)
366 {
367 int format = qdict_get_int(qdict, "format");
368 hwaddr val = qdict_get_int(qdict, "val");
369
370 switch(format) {
371 case 'o':
372 monitor_hmp_printf(hmp, "0x%" HWADDR_PRIo, val);
373 break;
374 case 'x':
375 monitor_hmp_printf(hmp, "0x%" HWADDR_PRIx, val);
376 break;
377 case 'u':
378 monitor_hmp_printf(hmp, "%" HWADDR_PRIu, val);
379 break;
380 default:
381 case 'd':
382 monitor_hmp_printf(hmp, "%" HWADDR_PRId, val);
383 break;
384 case 'c':
385 monitor_hmp_printc(hmp, val);
386 break;
387 }
388 monitor_hmp_printf(hmp, "\n");
389 }
390
391 void hmp_sum(MonitorHMP *hmp, const QDict *qdict)
392 {
393 uint32_t addr;
394 uint16_t sum;
395 uint32_t start = qdict_get_int(qdict, "start");
396 uint32_t size = qdict_get_int(qdict, "size");
397
398 sum = 0;
399 for(addr = start; addr < (start + size); addr++) {
400 uint8_t val = address_space_ldub(&address_space_memory, addr,
401 MEMTXATTRS_UNSPECIFIED, NULL);
402 /* BSD sum algorithm ('sum' Unix command) */
403 sum = (sum >> 1) | (sum << 15);
404 sum += val;
405 }
406 monitor_hmp_printf(hmp, "%05d\n", sum);
407 }
408
409 void hmp_ioport_read(MonitorHMP *hmp, const QDict *qdict)
410 {
411 int size = qdict_get_int(qdict, "size");
412 int addr = qdict_get_int(qdict, "addr");
413 int has_index = qdict_haskey(qdict, "index");
414 uint32_t val;
415 int suffix;
416
417 if (has_index) {
418 int index = qdict_get_int(qdict, "index");
419 cpu_outb(addr & IOPORTS_MASK, index & 0xff);
420 addr++;
421 }
422 addr &= 0xffff;
423
424 switch(size) {
425 default:
426 case 1:
427 val = cpu_inb(addr);
428 suffix = 'b';
429 break;
430 case 2:
431 val = cpu_inw(addr);
432 suffix = 'w';
433 break;
434 case 4:
435 val = cpu_inl(addr);
436 suffix = 'l';
437 break;
438 }
439 monitor_hmp_printf(hmp, "port%c[0x%04x] = 0x%0*x\n",
440 suffix, addr, size * 2, val);
441 }
442
443 void hmp_ioport_write(MonitorHMP *hmp, const QDict *qdict)
444 {
445 int size = qdict_get_int(qdict, "size");
446 int addr = qdict_get_int(qdict, "addr");
447 int val = qdict_get_int(qdict, "val");
448
449 addr &= IOPORTS_MASK;
450
451 switch (size) {
452 default:
453 case 1:
454 cpu_outb(addr, val);
455 break;
456 case 2:
457 cpu_outw(addr, val);
458 break;
459 case 4:
460 cpu_outl(addr, val);
461 break;
462 }
463 }
464
465 void hmp_boot_set(MonitorHMP *hmp, const QDict *qdict)
466 {
467 Error *local_err = NULL;
468 const char *bootdevice = qdict_get_str(qdict, "bootdevice");
469
470 qemu_boot_set(bootdevice, &local_err);
471 if (local_err) {
472 error_report_err(local_err);
473 } else {
474 monitor_hmp_printf(hmp, "boot device list now set to %s\n", bootdevice);
475 }
476 }
477
478 void hmp_info_mtree(MonitorHMP *hmp, const QDict *qdict)
479 {
480 bool flatview = qdict_get_try_bool(qdict, "flatview", false);
481 bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
482 bool owner = qdict_get_try_bool(qdict, "owner", false);
483 bool disabled = qdict_get_try_bool(qdict, "disabled", false);
484
485 mtree_info(flatview, dispatch_tree, owner, disabled);
486 }
487
488 #if defined(CONFIG_FDT)
489 void hmp_dumpdtb(MonitorHMP *hmp, const QDict *qdict)
490 {
491 const char *filename = qdict_get_str(qdict, "filename");
492 Error *local_err = NULL;
493
494 qmp_dumpdtb(filename, &local_err);
495
496 if (hmp_handle_error(hmp, local_err)) {
497 return;
498 }
499
500 monitor_hmp_printf(hmp, "DTB dumped to '%s'\n", filename);
501 }
502 #endif
503
504 /* Set the current CPU defined by the user. Callers must hold BQL. */
505 int monitor_hmp_set_cpu(MonitorHMP *hmp, int cpu_index)
506 {
507 CPUState *cpu;
508
509 cpu = qemu_get_cpu(cpu_index);
510 if (cpu == NULL) {
511 return -1;
512 }
513 g_free(hmp->mon_cpu_path);
514 hmp->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
515 return 0;
516 }
517
518 /* Callers must hold BQL. */
519 static CPUState *monitor_hmp_get_cpu_sync(MonitorHMP *hmp, bool synchronize)
520 {
521 CPUState *cpu = NULL;
522
523 if (hmp->mon_cpu_path) {
524 cpu = (CPUState *) object_resolve_path_type(hmp->mon_cpu_path,
525 TYPE_CPU, NULL);
526 if (!cpu) {
527 g_free(hmp->mon_cpu_path);
528 hmp->mon_cpu_path = NULL;
529 }
530 }
531 if (!hmp->mon_cpu_path) {
532 if (!first_cpu) {
533 return NULL;
534 }
535 monitor_hmp_set_cpu(hmp, first_cpu->cpu_index);
536 cpu = first_cpu;
537 }
538 assert(cpu != NULL);
539 if (synchronize) {
540 cpu_synchronize_state(cpu);
541 }
542 return cpu;
543 }
544
545 CPUState *monitor_hmp_get_cpu(MonitorHMP *hmp)
546 {
547 return monitor_hmp_get_cpu_sync(hmp, true);
548 }
549
550 CPUArchState *monitor_hmp_get_cpu_env(MonitorHMP *hmp)
551 {
552 CPUState *cs = monitor_hmp_get_cpu(hmp);
553
554 return cs ? cpu_env(cs) : NULL;
555 }
556
557 int monitor_hmp_get_cpu_index(MonitorHMP *hmp)
558 {
559 CPUState *cs = monitor_hmp_get_cpu_sync(hmp, false);
560
561 return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX;
562 }
563
564 void hmp_info_registers(MonitorHMP *hmp, const QDict *qdict)
565 {
566 bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false);
567 int vcpu = qdict_get_try_int(qdict, "vcpu", -1);
568 CPUState *cs;
569
570 if (all_cpus) {
571 CPU_FOREACH(cs) {
572 monitor_hmp_printf(hmp, "\nCPU#%d\n", cs->cpu_index);
573 cpu_dump_state(cs, NULL, CPU_DUMP_FPU | CPU_DUMP_VPU);
574 }
575 } else {
576 cs = vcpu >= 0 ? qemu_get_cpu(vcpu) : monitor_hmp_get_cpu(hmp);
577
578 if (!cs) {
579 if (vcpu >= 0) {
580 monitor_hmp_printf(hmp, "CPU#%d not available\n", vcpu);
581 } else {
582 monitor_hmp_printf(hmp, "No CPU available\n");
583 }
584 return;
585 }
586
587 monitor_hmp_printf(hmp, "\nCPU#%d\n", cs->cpu_index);
588 cpu_dump_state(cs, NULL, CPU_DUMP_FPU | CPU_DUMP_VPU);
589 }
590 }
591
592 static void memory_dump(MonitorHMP *hmp, int count, int format, int wsize,
593 uint64_t addr, bool is_physical)
594 {
595 int l, line_size, i, max_digits, len;
596 uint8_t buf[16];
597 uint64_t v;
598 CPUState *cs = monitor_hmp_get_cpu(hmp);
599 const unsigned int addr_width = is_physical ? 8 : (target_long_bits() / 4);
600 const bool big_endian = target_big_endian();
601
602 if (!cs && (format == 'i' || !is_physical)) {
603 monitor_hmp_printf(hmp, "Can not dump without CPU\n");
604 return;
605 }
606
607 if (format == 'i') {
608 monitor_disas(hmp, cs, addr, count, is_physical);
609 return;
610 }
611
612 len = wsize * count;
613 if (wsize == 1) {
614 line_size = 8;
615 } else {
616 line_size = 16;
617 }
618 max_digits = 0;
619
620 switch (format) {
621 case 'o':
622 max_digits = DIV_ROUND_UP(wsize * 8, 3);
623 break;
624 default:
625 case 'x':
626 max_digits = (wsize * 8) / 4;
627 break;
628 case 'u':
629 case 'd':
630 max_digits = DIV_ROUND_UP(wsize * 8 * 10, 33);
631 break;
632 case 'c':
633 wsize = 1;
634 break;
635 }
636
637 while (len > 0) {
638 monitor_hmp_printf(hmp, "%0*" PRIx64 ":", addr_width, addr);
639 l = len;
640 if (l > line_size) {
641 l = line_size;
642 }
643 if (is_physical) {
644 AddressSpace *as = cs ? cs->as : &address_space_memory;
645 MemTxResult r = address_space_read(as, addr,
646 MEMTXATTRS_UNSPECIFIED, buf, l);
647 if (r != MEMTX_OK) {
648 monitor_hmp_printf(hmp, " Cannot access memory\n");
649 break;
650 }
651 } else {
652 if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
653 monitor_hmp_printf(hmp, " Cannot access memory\n");
654 break;
655 }
656 }
657 i = 0;
658 while (i < l) {
659 switch (wsize) {
660 default:
661 case 1:
662 v = ldub_p(buf + i);
663 break;
664 case 2:
665 v = (big_endian ? lduw_be_p : lduw_le_p)(buf + i);
666 break;
667 case 4:
668 v = (uint32_t)(big_endian ? ldl_be_p : ldl_le_p)(buf + i);
669 break;
670 case 8:
671 v = (big_endian ? ldq_be_p : ldq_le_p)(buf + i);
672 break;
673 }
674 monitor_hmp_printf(hmp, " ");
675 switch (format) {
676 case 'o':
677 monitor_hmp_printf(hmp, "0%*" PRIo64, max_digits, v);
678 break;
679 case 'x':
680 monitor_hmp_printf(hmp, "0x%0*" PRIx64, max_digits, v);
681 break;
682 case 'u':
683 monitor_hmp_printf(hmp, "%*" PRIu64, max_digits, v);
684 break;
685 case 'd':
686 monitor_hmp_printf(hmp, "%*" PRId64, max_digits, v);
687 break;
688 case 'c':
689 monitor_hmp_printc(hmp, v);
690 break;
691 }
692 i += wsize;
693 }
694 monitor_hmp_printf(hmp, "\n");
695 addr += l;
696 len -= l;
697 }
698 }
699
700 void hmp_memory_dump(MonitorHMP *hmp, const QDict *qdict)
701 {
702 int count = qdict_get_int(qdict, "count");
703 int format = qdict_get_int(qdict, "format");
704 int size = qdict_get_int(qdict, "size");
705 vaddr addr = qdict_get_int(qdict, "addr");
706
707 memory_dump(hmp, count, format, size, addr, false);
708 }
709
710 void hmp_physical_memory_dump(MonitorHMP *hmp, const QDict *qdict)
711 {
712 int count = qdict_get_int(qdict, "count");
713 int format = qdict_get_int(qdict, "format");
714 int size = qdict_get_int(qdict, "size");
715 hwaddr addr = qdict_get_int(qdict, "addr");
716
717 memory_dump(hmp, count, format, size, addr, true);
718 }
719
720 void hmp_gpa2hva(MonitorHMP *hmp, const QDict *qdict)
721 {
722 hwaddr addr = qdict_get_int(qdict, "addr");
723 Error *local_err = NULL;
724 MemoryRegion *mr = NULL;
725 void *ptr;
726
727 ptr = gpa2hva(&mr, addr, 1, &local_err);
728 if (local_err) {
729 error_report_err(local_err);
730 return;
731 }
732
733 monitor_hmp_printf(hmp, "Host virtual address for 0x%" HWADDR_PRIx
734 " (%s) is %p\n",
735 addr, mr->name, ptr);
736
737 memory_region_unref(mr);
738 }
739
740 void hmp_gva2gpa(MonitorHMP *hmp, const QDict *qdict)
741 {
742 vaddr addr = qdict_get_int(qdict, "addr");
743 CPUState *cs = monitor_hmp_get_cpu(hmp);
744 TranslateForDebugResult tres;
745
746 if (!cs) {
747 monitor_hmp_printf(hmp, "No cpu\n");
748 return;
749 }
750
751 if (!cpu_translate_for_debug(cs, addr, &tres)) {
752 monitor_hmp_printf(hmp, "Unmapped\n");
753 } else {
754 monitor_hmp_printf(hmp, "gpa: 0x%" HWADDR_PRIx "\n", tres.physaddr);
755 }
756 }
757
758 #ifdef CONFIG_LINUX
759 static uint64_t vtop(void *ptr, Error **errp)
760 {
761 uint64_t pinfo;
762 uint64_t ret = -1;
763 uintptr_t addr = (uintptr_t) ptr;
764 uintptr_t pagesize = qemu_real_host_page_size();
765 off_t offset = addr / pagesize * sizeof(pinfo);
766 int fd;
767
768 fd = open("/proc/self/pagemap", O_RDONLY);
769 if (fd == -1) {
770 error_setg_file_open(errp, errno, "/proc/self/pagemap");
771 return -1;
772 }
773
774 /* Force copy-on-write if necessary. */
775 qatomic_add((uint8_t *)ptr, 0);
776
777 if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
778 error_setg_errno(errp, errno, "Cannot read pagemap");
779 goto out;
780 }
781 if ((pinfo & (1ull << 63)) == 0) {
782 error_setg(errp, "Page not present");
783 goto out;
784 }
785 ret = (pinfo & 0x007fffffffffffffull) * pagesize;
786 ret |= addr & (pagesize - 1);
787
788 out:
789 close(fd);
790 return ret;
791 }
792
793 void hmp_gpa2hpa(MonitorHMP *hmp, const QDict *qdict)
794 {
795 hwaddr addr = qdict_get_int(qdict, "addr");
796 Error *local_err = NULL;
797 MemoryRegion *mr = NULL;
798 void *ptr;
799 uint64_t physaddr;
800
801 ptr = gpa2hva(&mr, addr, 1, &local_err);
802 if (local_err) {
803 error_report_err(local_err);
804 return;
805 }
806
807 physaddr = vtop(ptr, &local_err);
808 if (local_err) {
809 error_report_err(local_err);
810 } else {
811 monitor_hmp_printf(hmp, "Host physical address for 0x%" HWADDR_PRIx
812 " (%s) is 0x%" PRIx64 "\n",
813 addr, mr->name, (uint64_t) physaddr);
814 }
815
816 memory_region_unref(mr);
817 }
818 #endif