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 it in "help -m"
Test result:
Without the this patch:
#files -p xxx > /dev/null (xxx is the inode of vmlinux which is 441M)
This costed about 185 seconds.
With the this patch:
#files -p xxx > /dev/null (xxx is the inode of vmlinux which is 441M)
This costed 3 seconds.
Signed-off-by: Huang Shijie <shijie(a)os.amperecomputing.com>
---
v3 --> v4:
Use "files -p" to measure the time.
Dump it in "help -m"
---
arm64.c | 26 ++++++++++++++++++++++++++
defs.h | 1 +
2 files changed, 27 insertions(+)
diff --git a/arm64.c b/arm64.c
index 57965c6..fc4ba64 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 - machdep->machspec->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(&ms->vmemmap, "SYMBOL(vmemmap)", NUM_HEX))
+ machdep->is_page_ptr = arm64_vmemmap_is_page_ptr;
machdep->uvtop = arm64_uvtop;
machdep->is_uvaddr = arm64_is_uvaddr;
@@ -1096,6 +1121,7 @@ arm64_dump_machdep_table(ulong arg)
fprintf(fp, " vmemmap_vaddr: %016lx\n", ms->vmemmap_vaddr);
fprintf(fp, " vmemmap_end: %016lx\n", ms->vmemmap_end);
if (machdep->flags & NEW_VMEMMAP) {
+ fprintf(fp, " vmemmap: %016lx\n", ms->vmemmap);
fprintf(fp, " kimage_text: %016lx\n", ms->kimage_text);
fprintf(fp, " kimage_end: %016lx\n", ms->kimage_end);
fprintf(fp, " kimage_voffset: %016lx\n", ms->kimage_voffset);
diff --git a/defs.h b/defs.h
index 0558d13..3431a32 100644
--- a/defs.h
+++ b/defs.h
@@ -3486,6 +3486,7 @@ struct machine_specific {
ulong CONFIG_ARM64_KERNELPACMASK;
ulong physvirt_offset;
ulong struct_page_size;
+ ulong vmemmap;
};
struct arm64_stackframe {
--
2.40.1