diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2011-09-11 20:22:05 +0000 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-10-02 16:27:13 +0200 |
commit | 314e298735903035ba2b7b0f3cf39981f4171546 (patch) | |
tree | 51a57705a5d1eaab97529863de5f5d40b9483294 | |
parent | 3917149d96cfa5f619de770af6059f37b6e1df77 (diff) | |
download | qemu-314e298735903035ba2b7b0f3cf39981f4171546.tar.gz qemu-314e298735903035ba2b7b0f3cf39981f4171546.tar.bz2 qemu-314e298735903035ba2b7b0f3cf39981f4171546.zip |
memory: simple memory tree printer
Add a monitor command 'info mtree' to show the memory hierarchy
much like /proc/iomem in Linux.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | memory.c | 91 | ||||
-rw-r--r-- | memory.h | 2 | ||||
-rw-r--r-- | monitor.c | 13 |
3 files changed, 106 insertions, 0 deletions
@@ -1271,3 +1271,94 @@ void set_system_io_map(MemoryRegion *mr) address_space_io.root = mr; memory_region_update_topology(); } + +typedef struct MemoryRegionList MemoryRegionList; + +struct MemoryRegionList { + const MemoryRegion *mr; + bool printed; + QTAILQ_ENTRY(MemoryRegionList) queue; +}; + +typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead; + +static void mtree_print_mr(fprintf_function mon_printf, void *f, + const MemoryRegion *mr, unsigned int level, + target_phys_addr_t base, + MemoryRegionListHead *print_queue) +{ + const MemoryRegion *submr; + unsigned int i; + + + if (!mr) { + return; + } + + for (i = 0; i < level; i++) { + mon_printf(f, " "); + } + + if (mr->alias) { + MemoryRegionList *ml; + bool found = false; + + /* check if the alias is already in the queue */ + QTAILQ_FOREACH(ml, print_queue, queue) { + if (ml->mr == mr->alias && !ml->printed) { + found = true; + } + } + + if (!found) { + ml = g_new(MemoryRegionList, 1); + ml->mr = mr->alias; + ml->printed = false; + QTAILQ_INSERT_TAIL(print_queue, ml, queue); + } + mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " : alias %s @%s " + TARGET_FMT_plx "-" TARGET_FMT_plx "\n", + base + mr->addr, + base + mr->addr + (target_phys_addr_t)mr->size - 1, + mr->name, + mr->alias->name, + mr->alias_offset, + mr->alias_offset + (target_phys_addr_t)mr->size - 1); + } else { + mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " : %s\n", + base + mr->addr, + base + mr->addr + (target_phys_addr_t)mr->size - 1, + mr->name); + } + QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) { + mtree_print_mr(mon_printf, f, submr, level + 1, base + mr->addr, + print_queue); + } +} + +void mtree_info(fprintf_function mon_printf, void *f) +{ + MemoryRegionListHead ml_head; + MemoryRegionList *ml, *ml2; + + QTAILQ_INIT(&ml_head); + + mon_printf(f, "memory\n"); + mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head); + + /* print aliased regions */ + QTAILQ_FOREACH(ml, &ml_head, queue) { + if (!ml->printed) { + mon_printf(f, "%s\n", ml->mr->name); + mtree_print_mr(mon_printf, f, ml->mr, 0, 0, &ml_head); + } + } + + QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) { + g_free(ml2); + } + + QTAILQ_INIT(&ml_head); + mon_printf(f, "I/O\n"); + mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head); +} @@ -501,6 +501,8 @@ void memory_region_transaction_begin(void); */ void memory_region_transaction_commit(void); +void mtree_info(fprintf_function mon_printf, void *f); + #endif #endif @@ -63,6 +63,7 @@ #endif #include "trace/control.h" #include "ui/qemu-spice.h" +#include "memory.h" //#define DEBUG //#define DEBUG_COMPLETION @@ -2470,6 +2471,11 @@ static void tlb_info(Monitor *mon) } #endif +static void do_info_mtree(Monitor *mon) +{ + mtree_info((fprintf_function)monitor_printf, mon); +} + static void do_info_kvm_print(Monitor *mon, const QObject *data) { QDict *qdict; @@ -2978,6 +2984,13 @@ static const mon_cmd_t info_cmds[] = { }, #endif { + .name = "mtree", + .args_type = "", + .params = "", + .help = "show memory tree", + .mhandler.info = do_info_mtree, + }, + { .name = "jit", .args_type = "", .params = "", |