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. 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 <shijie@xxxxxxxxxxxxxxxxxxxxxx> --- 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 Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki