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 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.
we implement the fast page_to_pfn code in arm64_vmemmap_is_page_ptr.
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>
---
v1-->v2:
1.) Copy most of the code from x86_64.
2.) Tested with /proc/kcore.
---
arm64.c | 25 +++++++++++++++++++++++++
defs.h | 1 +
2 files changed, 26 insertions(+)
diff --git a/arm64.c b/arm64.c
index e131102..42746ed 100644
--- a/arm64.c
+++ b/arm64.c
@@ -116,6 +116,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.
@@ -385,6 +407,9 @@ arm64_init(int when)
machdep->stacksize = ARM64_STACK_SIZE;
machdep->flags |= VMEMMAP;
+ /* If vmemmap exists, it means kernel enabled CONFIG_SPARSEMEM_VMEMMAP */
+ if (get_value_vmcoreinfo("vmemmap", &vt->vmemmap, SYMBOL_TYPE))
+ 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 282fcc1..5646fa9 100644
--- a/defs.h
+++ b/defs.h
@@ -2615,6 +2615,7 @@ struct vm_table { /* kernel VM-related data */
ulong vma_cache_fills;
void *mem_sec;
char *mem_section;
+ ulong vmemmap;
int ZONE_HIGHMEM;
ulong *node_online_map;
int node_online_map_len;
--
2.40.1