-----Original Message-----
> 1.) When I tested live system with "crash vmlinux /proc/kcore" in kernel v5.7,
>     I met the following crash issue:
>        ........................................
>        crash: seek error: kernel virtual address: ffff75e9fffff000  type: 
> "pud page"
>        ........................................
> 
> 2.) The root cause is the PTOV does not work correctly for some kernel,
>     and then arm64_vtop_4level_4k() does not work correctly too.
> 
>     Why PTOV does not work?
> 
>     The PHYS_OFFSET is just wrapper of memstart_addr.
>      ...............................
>      #define PHYS_OFFSET  ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
>      ...............................
> 
>     Because memstart_addr is changed after physvirt_offset is initialized.
>     so the NUMBER(PHYS_OFFSET) does not return the correct value.

Hmm, it looks like arm64_PTOV() uses the physvirt_offset if available
(5.4 <= kernel < 5.10), I'm still not sure why it does not work correctly.
Would you please explain the issue in more detail?

Thanks,
Kazu

> 
> 3.) How many kernel versions have this bug?
>       1) In kernel v5.4, the patch:
>           "5383cc6efed137 arm64: mm: Introduce vabits_actual"
> 
>           makes the NUMBER(PHYS_OFFSET) do not work correctly.
> 
>       2) In kernel v5.10, the patch:
>           "7bc1a0f9e17658 arm64: mm: use single quantity
>                                  to represent the PA to VA translation"
> 
>           makes the NUMBER(PHYS_OFFSET) work again.
> 
> 4.) What does this patch do?
>     This patch uses the same method as makedumpfile does:
>       Use the PT_LOAD segments to get the phys_offset.
> 
> Signed-off-by: Huang Shijie <[email protected]>
> ---
>  arm64.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/arm64.c b/arm64.c
> index e3fa316..d81c2b9 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -1426,6 +1426,51 @@ arm64_calc_physvirt_offset(void)
> 
>  }
> 
> +/*
> + * Check if an virtual address is a linear address.
> + */
> +#define PAGE_END     (_PAGE_END(ms->VA_BITS_ACTUAL))
> +static int arm64_is_linear_addr(struct machine_specific *ms,
> +                             unsigned long va)
> +{
> +     return (va - PAGE_OFFSET) < (PAGE_END - PAGE_OFFSET);
> +}
> +
> +/*
> + * This function only works for kernel range: [5.4, 5.10).
> + *
> + *      1) In kernel v5.4, the patch:
> + *          "5383cc6efed137 arm64: mm: Introduce vabits_actual"
> + *
> + *          makes the NUMBER(PHYS_OFFSET) do not work correctly.
> + *
> + *      2) In kernel v5.10, the patch:
> + *          "7bc1a0f9e17658 arm64: mm: use single quantity
> + *                                 to represent the PA to VA translation"
> + *
> + *          makes the NUMBER(PHYS_OFFSET) work again.
> + *
> + * This function tries to get the phys_offset from PT_LOAD segments.
> + * This method was originally used by the makedumpfile tool.
> + */
> +static void arm64_get_phys_offset_by_pt_load(struct machine_specific *ms)
> +{
> +     int i;
> +     Elf64_Phdr *h;
> +     struct proc_kcore_data *pkd = arm64_get_pkd();
> +
> +     for (i = 0; i < pkd->segments; i++) {
> +             h = &pkd->load64[i];
> +
> +             if (arm64_is_linear_addr(ms, h->p_vaddr)) {
> +                     ms->phys_offset = h->p_paddr - (h->p_vaddr & 
> ~PAGE_OFFSET);
> +                     return;
> +             }
> +     }
> +
> +     error(FATAL, "We cannot get the correct phys_offset!\n");
> +}
> +
>  static void
>  arm64_calc_phys_offset(void)
>  {
> @@ -1454,6 +1499,14 @@ arm64_calc_phys_offset(void)
>               if ((machdep->flags & NEW_VMEMMAP) &&
>                   ms->kimage_voffset && (sp = 
> kernel_symbol_search("memstart_addr"))) {
>                       if (pc->flags & PROC_KCORE) {
> +                             unsigned long v = arm64_get_kernel_version();
> +
> +                             /* Do special operation for kernel [5.4, 5.10) 
> */
> +                             if (LINUX(5, 4, 0) <= v && v < LINUX(5, 10, 0)) 
> {
> +                                     arm64_get_phys_offset_by_pt_load(ms);
> +                                     return;
> +                             }
> +
>                               if ((string = 
> pc->read_vmcoreinfo("NUMBER(PHYS_OFFSET)"))) {
>                                       ms->phys_offset = htol(string, QUIET, 
> NULL);
>                                       free(string);
> --
> 2.30.2

--
Crash-utility mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to