Make the hierarchical relationship between nodes clearer by adding characters
e.g. qemu-system-riscv64 -M virt -monitor stdio -display none ``` (qemu) info mtree ... memory-region: system │ ├── 0000000000000000-ffffffffffffffff (prio 0, i/o): system │ │ ├── 0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport_window │ │ │ └── 0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport ... │ │ └── 0000000400000000-00000007ffffffff (prio 0, i/o): alias ... ``` Signed-off-by: Chao Liu <lc00...@tecorigin.com> Reviewed-by: Qingze Zhao <zqz00...@tecorigin.com> Reviewed-by: Tingjian Zhang <zhan...@tecorigin.com> --- system/memory.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/system/memory.c b/system/memory.c index 71434e7ad0..3a7faeb533 100644 --- a/system/memory.c +++ b/system/memory.c @@ -3296,6 +3296,27 @@ typedef QTAILQ_HEAD(, MemoryRegionList) MemoryRegionListHead; int128_sub((size), int128_one())) : 0) #define MTREE_INDENT " " +enum mtree_node_type { + MTREE_NODE_T_INNER, + MTREE_NODE_T_TAIL, +}; + +#define PRINT_MTREE_NODE(node_type) do { \ + if (node_type == MTREE_NODE_T_TAIL) { \ + qemu_printf("└── "); \ + } else { \ + qemu_printf("├── "); \ + } \ +} while (0) + +#define PRINT_MTREE_COL(level) do { \ + if (level == 0) { \ + qemu_printf("│ "); \ + } else { \ + qemu_printf("│ "); \ + } \ +} while (0) + static void mtree_expand_owner(const char *label, Object *obj) { DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE); @@ -3335,7 +3356,8 @@ static void mtree_print_mr_owner(const MemoryRegion *mr) static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, hwaddr base, MemoryRegionListHead *alias_print_queue, - bool owner, bool display_disabled) + bool owner, bool display_disabled, + enum mtree_node_type node_type) { MemoryRegionList *new_ml, *ml, *next_ml; MemoryRegionListHead submr_print_queue; @@ -3376,8 +3398,9 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, } if (mr->enabled || display_disabled) { for (i = 0; i < level; i++) { - qemu_printf(MTREE_INDENT); + PRINT_MTREE_COL(i); } + PRINT_MTREE_NODE(node_type); qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx " (prio %d, %s%s): alias %s @%s " HWADDR_FMT_plx "-" HWADDR_FMT_plx "%s", @@ -3398,8 +3421,9 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, } else { if (mr->enabled || display_disabled) { for (i = 0; i < level; i++) { - qemu_printf(MTREE_INDENT); + PRINT_MTREE_COL(i); } + PRINT_MTREE_NODE(node_type); qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx " (prio %d, %s%s): %s%s", cur_start, cur_end, @@ -3435,8 +3459,12 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, } QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) { + if (ml == QTAILQ_LAST(&submr_print_queue)) { + node_type = MTREE_NODE_T_TAIL; + } mtree_print_mr(ml->mr, level + 1, cur_start, - alias_print_queue, owner, display_disabled); + alias_print_queue, owner, + display_disabled, node_type); } QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) { @@ -3614,7 +3642,8 @@ static void mtree_print_as(gpointer key, gpointer value, gpointer user_data) struct AddressSpaceInfo *asi = user_data; g_slist_foreach(as_same_root_mr_list, mtree_print_as_name, NULL); - mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled); + mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled, + MTREE_NODE_T_INNER); qemu_printf("\n"); } @@ -3659,7 +3688,8 @@ static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled) /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, mrqueue) { qemu_printf("memory-region: %s\n", memory_region_name(ml->mr)); - mtree_print_mr(ml->mr, 1, 0, &ml_head, owner, disabled); + mtree_print_mr(ml->mr, 1, 0, &ml_head, owner, disabled, + MTREE_NODE_T_INNER); qemu_printf("\n"); } -- 2.48.1