On 2023/12/19 0:01, Huang Shijie wrote:
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"
Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Applied the 1/2 first,
https://github.com/crash-utility/crash/commit/19d3c56c9fca
and will apply this when a corresponding kernel patch gets applied.
Thanks,
Kazu
> ---
> 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 {