If the kernel exports the vmmemap then we can use that symbol in
crash to optimize access. vmmemap is just an array of page structs
after all.
This patch tries to:
1.) Get the "vmemmap" from the vmcore file.
If we can use the "vmemmap", we implement the arm64_vmemmap_is_page_ptr
and set it to machdep->is_page_ptr.
2.) We implement the fast page_to_pfn code in arm64_vmemmap_is_page_ptr.
3.) Dump "vmemmap" in "help -v".
Test result:
Test the patch: "[PATCH v3] add "files -n" command for an inode"
https://lists.crash-utility.osci.io/archives/list/
devel(a)lists.crash-utility.osci.io/thread/CRLOQP534YKEQPTCXIWVDYK4NA7BOSUK/
Without the this patch:
#files -n xxx (xxx is the inode of vmlinux which is 441M)
This costed about 162 seconds.
With the this patch:
#files -n xxx (xxx is the inode of vmlinux which is 441M)
This costed less then 1 second.
Signed-off-by: Huang Shijie <shijie(a)os.amperecomputing.com>
---
v2 --> v3:
Use arm64_get_vmcoreinfo() to parse the "vmemmap"
Dump it in "help -v"
---
arm64.c | 25 +++++++++++++++++++++++++
defs.h | 1 +
memory.c | 1 +
3 files changed, 27 insertions(+)
diff --git a/arm64.c b/arm64.c
index 57965c6..fd6e9f7 100644
--- a/arm64.c
+++ b/arm64.c
@@ -117,6 +117,28 @@ static void arm64_calc_kernel_start(void)
ms->kimage_end = (sp ? sp->value : 0);
}
+static int
+arm64_vmemmap_is_page_ptr(ulong addr, physaddr_t *phys)
+{
+ ulong size = SIZE(page);
+ ulong pfn, nr;
+
+
+ if (IS_SPARSEMEM() && (machdep->flags & VMEMMAP) &&
+ (addr >= VMEMMAP_VADDR && addr <= VMEMMAP_END) &&
+ !((addr - VMEMMAP_VADDR) % size)) {
+
+ pfn = (addr - vt->vmemmap) / size;
+ nr = pfn_to_section_nr(pfn);
+ if (valid_section_nr(nr)) {
+ if (phys)
+ *phys = PTOB(pfn);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/*
* Do all necessary machine-specific setup here. This is called several times
* during initialization.
@@ -382,6 +404,9 @@ arm64_init(int when)
machdep->stacksize = ARM64_STACK_SIZE;
machdep->flags |= VMEMMAP;
+ /* If vmemmap exists, it means kernel enabled CONFIG_SPARSEMEM_VMEMMAP */
+ if (arm64_get_vmcoreinfo(&vt->vmemmap, "SYMBOL(vmemmap)", NUM_HEX))
+ machdep->is_page_ptr = arm64_vmemmap_is_page_ptr;
machdep->uvtop = arm64_uvtop;
machdep->is_uvaddr = arm64_is_uvaddr;
diff --git a/defs.h b/defs.h
index 0558d13..bb775fd 100644
--- a/defs.h
+++ b/defs.h
@@ -2634,6 +2634,7 @@ struct vm_table { /* kernel VM-related data */
ulong max_mem_section_nr;
ulong zero_paddr;
ulong huge_zero_paddr;
+ ulong vmemmap;
};
#define NODES (0x1)
diff --git a/memory.c b/memory.c
index 3e8da98..c878286 100644
--- a/memory.c
+++ b/memory.c
@@ -14104,6 +14104,7 @@ dump_vm_table(int verbose)
fprintf(fp, " mem_sec: %lx\n", (ulong)vt->mem_sec);
fprintf(fp, " mem_section: %lx\n", (ulong)vt->mem_section);
fprintf(fp, " max_mem_section_nr: %ld\n", (ulong)vt->max_mem_section_nr);
+ fprintf(fp, " vmemmap: %lx\n", (ulong)vt->vmemmap);
fprintf(fp, " ZONE_HIGHMEM: %d\n", vt->ZONE_HIGHMEM);
fprintf(fp, "node_online_map_len: %d\n", vt->node_online_map_len);
if (vt->node_online_map_len) {
--
2.40.1