refactor(mm): make dump more detailed
Make the contents of `mm_dump` more detailed
Change-Id: I29fcb9e478c18d307e2ce1e30960771c38ae0911
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/inc/hf/dlog.h b/inc/hf/dlog.h
index fe02cf5..954f8eb 100644
--- a/inc/hf/dlog.h
+++ b/inc/hf/dlog.h
@@ -104,3 +104,10 @@
dlog("VERBOSE: " __VA_ARGS__); \
} \
} while (0)
+
+/** Print to debug log, with `indent` amount of indentation. */
+#define dlog_indent(indent, ...) \
+ do { \
+ dlog("%*s", (indent) * 2, ""); \
+ dlog(__VA_ARGS__); \
+ } while (0)
diff --git a/src/mm.c b/src/mm.c
index 98774b9..1cfac7b 100644
--- a/src/mm.c
+++ b/src/mm.c
@@ -564,49 +564,95 @@
return true;
}
-/**
- * Writes the given table to the debug log, calling itself recursively to
- * write sub-tables.
- */
-// NOLINTNEXTLINE(misc-no-recursion)
-static void mm_dump_table_recursive(const struct mm_page_table *ptable,
- mm_level_t level, uint8_t depth)
+static void mm_dump_entries(const pte_t *entries, mm_level_t level,
+ uint32_t indent);
+
+static void mm_dump_block_entry(pte_t entry, mm_level_t level, uint32_t indent)
{
+ mm_attr_t attrs = arch_mm_pte_attrs(entry, level);
+ paddr_t addr = arch_mm_block_from_pte(entry, level);
+
+ if (arch_mm_pte_is_valid(entry, level)) {
+ if (level == 0) {
+ dlog("page {\n");
+ } else {
+ dlog("block {\n");
+ }
+ } else {
+ dlog("invalid_block {\n");
+ }
+
+ indent += 1;
+ {
+ dlog_indent(indent, ".addr = %#016lx\n", pa_addr(addr));
+ dlog_indent(indent, ".attrs = %#016lx\n", attrs);
+ }
+ indent -= 1;
+ dlog_indent(indent, "}");
+}
+
+// NOLINTNEXTLINE(misc-no-recursion)
+static void mm_dump_table_entry(pte_t entry, mm_level_t level, uint32_t indent)
+{
+ dlog("table {\n");
+ indent += 1;
+ {
+ mm_attr_t attrs = arch_mm_pte_attrs(entry, level);
+ paddr_t addr = arch_mm_table_from_pte(entry, level);
+ const struct mm_page_table *child_table =
+ mm_page_table_from_pa(addr);
+
+ dlog_indent(indent, ".pte = %#016lx,\n", entry);
+ dlog_indent(indent, ".attrs = %#016lx,\n", attrs);
+ dlog_indent(indent, ".addr = %#016lx,\n", pa_addr(addr));
+ dlog_indent(indent, ".entries = ");
+ mm_dump_entries(child_table->entries, level - 1, indent);
+ dlog(",\n");
+ }
+ indent -= 1;
+ dlog_indent(indent, "}");
+}
+
+// NOLINTNEXTLINE(misc-no-recursion)
+static void mm_dump_entry(pte_t entry, mm_level_t level, uint32_t indent)
+{
+ switch (arch_mm_pte_type(entry, level)) {
+ case PTE_TYPE_ABSENT:
+ dlog("absent {}");
+ break;
+ case PTE_TYPE_INVALID_BLOCK:
+ case PTE_TYPE_VALID_BLOCK: {
+ mm_dump_block_entry(entry, level, indent);
+ break;
+ }
+ case PTE_TYPE_TABLE: {
+ mm_dump_table_entry(entry, level, indent);
+ break;
+ }
+ }
+}
+
+// NOLINTNEXTLINE(misc-no-recursion)
+static void mm_dump_entries(const pte_t *entries, mm_level_t level,
+ uint32_t indent)
+{
+ dlog("{\n");
+ indent += 1;
+
for (size_t i = 0; i < MM_PTE_PER_PAGE; i++) {
- pte_t entry = ptable->entries[i];
+ pte_t entry = entries[i];
if (arch_mm_pte_is_absent(entry, level)) {
continue;
}
- dlog("%*s[level=%u, index=%zu]: ", depth * 2, "", level, i);
-
- switch (arch_mm_pte_type(entry, level)) {
- case PTE_TYPE_ABSENT: {
- /* Do nothing */
- break;
- }
- case PTE_TYPE_INVALID_BLOCK: {
- dlog("INVALID_BLOCK(%#lx)\n", entry);
- break;
- }
- case PTE_TYPE_VALID_BLOCK: {
- dlog("VALID_BLOCK(%#lx)\n", entry);
- break;
- }
- case PTE_TYPE_TABLE: {
- const struct mm_page_table *child_table =
- mm_page_table_from_pa(
- arch_mm_table_from_pte(entry, level));
-
- dlog("TABLE(%#lx)\n", entry);
-
- mm_dump_table_recursive(child_table, level - 1,
- depth + 1);
- break;
- }
- }
+ dlog_indent(indent, "[level = %u, index = %zu] = ", level, i);
+ mm_dump_entry(entry, level, indent);
+ dlog(",\n");
}
+
+ indent -= 1;
+ dlog_indent(indent, "}");
}
/**
@@ -615,13 +661,36 @@
static void mm_ptable_dump(const struct mm_ptable *ptable,
struct mm_flags flags)
{
- struct mm_page_table *tables = mm_page_table_from_pa(ptable->root);
- mm_level_t max_level = mm_max_level(flags);
+ struct mm_page_table *root_tables = mm_page_table_from_pa(ptable->root);
+ mm_level_t root_level = mm_max_level(flags) + 1;
uint8_t root_table_count = mm_root_table_count(flags);
+ uint32_t indent = 0;
- for (size_t i = 0; i < root_table_count; ++i) {
- mm_dump_table_recursive(&tables[i], max_level, max_level);
+ dlog_indent(indent, "mm_ptable {\n");
+ indent += 1;
+ {
+ dlog_indent(indent, ".stage = %s,\n",
+ flags.stage1 ? "stage1" : "stage2");
+ dlog_indent(indent, ".id = %hu,\n", ptable->id);
+ dlog_indent(indent, ".root_tables = {\n");
+
+ indent += 1;
+ {
+ for (size_t i = 0; i < root_table_count; ++i) {
+ dlog_indent(
+ indent,
+ "[level = %u, index = %zu].entries = ",
+ root_level, i);
+ mm_dump_entries(root_tables[i].entries,
+ root_level - 1, indent);
+ dlog(",\n");
+ }
+ }
+ indent -= 1;
+ dlog_indent(indent, "},\n");
}
+ indent -= 1;
+ dlog_indent(indent, "}\n");
}
/**
diff --git a/src/vcpu_test.cc b/src/vcpu_test.cc
index 987bf98..6e740cc 100644
--- a/src/vcpu_test.cc
+++ b/src/vcpu_test.cc
@@ -31,7 +31,6 @@
using struct_vm_locked = struct vm_locked;
constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 64;
-const int TOP_LEVEL = arch_mm_stage2_max_level();
class vcpu : public ::testing::Test
{
protected: