diff --git a/0001-arm64-rename-ARM64_PAGE_OFFSET_ACTUAL-to-ARM64_FLIP_.patch b/0001-arm64-rename-ARM64_PAGE_OFFSET_ACTUAL-to-ARM64_FLIP_.patch new file mode 100644 index 0000000..6d91794 --- /dev/null +++ b/0001-arm64-rename-ARM64_PAGE_OFFSET_ACTUAL-to-ARM64_FLIP_.patch @@ -0,0 +1,61 @@ +From 5719afc7a40868418405a87a2711088556e68a3b Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Fri, 2 Jul 2021 10:14:21 +0800 +Subject: [PATCH 1/4] arm64: rename ARM64_PAGE_OFFSET_ACTUAL to + ARM64_FLIP_PAGE_OFFSET_ACTUAL + +Reflect the flipped layout of kernel VA, which is introduced by +kernel commit 14c127c957c1 ("arm64: mm: Flip kernel VA space"). + +Signed-off-by: Pingfan Liu +--- + arm64.c | 10 ++++++---- + defs.h | 3 ++- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/arm64.c b/arm64.c +index 8934961..9fe1a4a 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -217,10 +217,12 @@ arm64_init(int when) + arm64_calc_VA_BITS(); + arm64_calc_KERNELPACMASK(); + ms = machdep->machspec; ++ ++ /* vabits_actual introduced after mm flip, so it should be flipped layout */ + if (ms->VA_BITS_ACTUAL) { +- ms->page_offset = ARM64_PAGE_OFFSET_ACTUAL; +- machdep->identity_map_base = ARM64_PAGE_OFFSET_ACTUAL; +- machdep->kvbase = ARM64_PAGE_OFFSET_ACTUAL; ++ ms->page_offset = ARM64_FLIP_PAGE_OFFSET_ACTUAL; ++ machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET_ACTUAL; ++ machdep->kvbase = ARM64_FLIP_PAGE_OFFSET_ACTUAL; + ms->userspace_top = ARM64_USERSPACE_TOP_ACTUAL; + } else { + ms->page_offset = ARM64_PAGE_OFFSET; +@@ -401,7 +403,7 @@ arm64_init(int when) + fprintf(fp, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS); + fprintf(fp, " VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL); + fprintf(fp, "(calculated) VA_BITS: %ld\n", ms->VA_BITS); +- fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_PAGE_OFFSET_ACTUAL); ++ fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET_ACTUAL); + fprintf(fp, " VA_START: %lx\n", ms->VA_START); + fprintf(fp, " modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end); + fprintf(fp, " vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end); +diff --git a/defs.h b/defs.h +index 5d32954..eb7ce6a 100644 +--- a/defs.h ++++ b/defs.h +@@ -3233,7 +3233,8 @@ typedef signed int s32; + + #define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \ + << (machdep->machspec->VA_BITS - 1)) +-#define ARM64_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \ ++/* kernels >= v5.4 the kernel VA space is flipped */ ++#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \ + - ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1) + + #define ARM64_USERSPACE_TOP ((1UL) << machdep->machspec->VA_BITS) +-- +2.29.2 + diff --git a/0002-arm64-assign-page_offset-with-VA_BITS-kernel-configu.patch b/0002-arm64-assign-page_offset-with-VA_BITS-kernel-configu.patch new file mode 100644 index 0000000..70af173 --- /dev/null +++ b/0002-arm64-assign-page_offset-with-VA_BITS-kernel-configu.patch @@ -0,0 +1,56 @@ +From 167d37e347fe35c6f7db826e8539e192c4375564 Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Fri, 2 Jul 2021 10:14:22 +0800 +Subject: [PATCH 2/4] arm64: assign page_offset with VA_BITS kernel + configuration value + +On RHEL9, crash hits a bug when executing "crash /proc/kcore": +seek error: kernel virtual address: ffff6a0f3fff0000 type: "pmd page" + +The kernel virtual address does not vary with vabits_actual, instead, +is determined by configuration value. But crash does not observe this +fact. + +Since vabits_actual related kernel commit is introduced after arm64 +mm layout flip commit, so changes are safe under the condition if +(ms->VA_BITS_ACTUAL), and keep the else branch untouched. + +Signed-off-by: Pingfan Liu +--- + arm64.c | 7 ++++--- + defs.h | 1 + + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/arm64.c b/arm64.c +index 9fe1a4a..149db36 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -220,9 +220,10 @@ arm64_init(int when) + + /* vabits_actual introduced after mm flip, so it should be flipped layout */ + if (ms->VA_BITS_ACTUAL) { +- ms->page_offset = ARM64_FLIP_PAGE_OFFSET_ACTUAL; +- machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET_ACTUAL; +- machdep->kvbase = ARM64_FLIP_PAGE_OFFSET_ACTUAL; ++ ms->page_offset = ARM64_FLIP_PAGE_OFFSET; ++ /* useless on arm64 */ ++ machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET; ++ machdep->kvbase = ARM64_FLIP_PAGE_OFFSET; + ms->userspace_top = ARM64_USERSPACE_TOP_ACTUAL; + } else { + ms->page_offset = ARM64_PAGE_OFFSET; +diff --git a/defs.h b/defs.h +index eb7ce6a..b7b20af 100644 +--- a/defs.h ++++ b/defs.h +@@ -3234,6 +3234,7 @@ typedef signed int s32; + #define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \ + << (machdep->machspec->VA_BITS - 1)) + /* kernels >= v5.4 the kernel VA space is flipped */ ++#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->CONFIG_ARM64_VA_BITS) + #define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \ + - ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1) + +-- +2.29.2 + diff --git a/0003-arm64-use-dedicated-bits-to-record-the-VA-space-layo.patch b/0003-arm64-use-dedicated-bits-to-record-the-VA-space-layo.patch new file mode 100644 index 0000000..dfb3067 --- /dev/null +++ b/0003-arm64-use-dedicated-bits-to-record-the-VA-space-layo.patch @@ -0,0 +1,83 @@ +From bf1379a8b6ff8d6a8fa12978f7194f15f85c4380 Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Fri, 2 Jul 2021 10:14:23 +0800 +Subject: [PATCH 3/4] arm64: use dedicated bits to record the VA space layout + changes + +arm64 memory layout experiences big changes due to the following kernel +commits in date descending order: + 5. 7bc1a0f9e176 arm64: mm: use single quantity to represent the PA to VA translation + 4. b6d00d47e81a arm64: mm: Introduce 52-bit Kernel VAs + 3. 5383cc6efed1 arm64: mm: Introduce vabits_actual + 2. 14c127c957c1 arm64: mm: Flip kernel VA space + 1. f80fb3a3d508 arm64: add support for kernel ASLR + +For 1, crash has already used NEW_VMEMMAP to trace it. +For 2, crash lacks a flag to tag it and handle it differently. +For 3, two important kernel variables vabits_actual and physvirt_offset +are introduced. +For 4, since it comes immediately after 3, crash-utility does not need +to distinguish it. +For 5, kernel variable phyvirt_offset is removed + +These changes have effects on PTOV()/VTOP() formula. So introducing +two bits HAS_PHYSVIRT_OFFSET and FLIPPED_VM as hint to apply different +formula. + +Signed-off-by: Pingfan Liu +--- + arm64.c | 10 ++++++++++ + defs.h | 2 ++ + 2 files changed, 12 insertions(+) + +diff --git a/arm64.c b/arm64.c +index 149db36..b04369f 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -563,6 +563,10 @@ arm64_dump_machdep_table(ulong arg) + fprintf(fp, "%sMACHDEP_BT_TEXT", others++ ? "|" : ""); + if (machdep->flags & NEW_VMEMMAP) + fprintf(fp, "%sNEW_VMEMMAP", others++ ? "|" : ""); ++ if (machdep->flags & FLIPPED_VM) ++ fprintf(fp, "%sFLIPPED_VM", others++ ? "|" : ""); ++ if (machdep->flags & HAS_PHYSVIRT_OFFSET) ++ fprintf(fp, "%sHAS_PHYSVIRT_OFFSET", others++ ? "|" : ""); + fprintf(fp, ")\n"); + + fprintf(fp, " kvbase: %lx\n", machdep->kvbase); +@@ -997,6 +1001,7 @@ arm64_calc_physvirt_offset(void) + if (READMEM(pc->mfd, &physvirt_offset, sizeof(physvirt_offset), + sp->value, sp->value - + machdep->machspec->kimage_voffset) > 0) { ++ machdep->flags |= HAS_PHYSVIRT_OFFSET; + ms->physvirt_offset = physvirt_offset; + } + } +@@ -3963,6 +3968,11 @@ arm64_calc_VA_BITS(void) + error(FATAL, "cannot determine VA_BITS_ACTUAL\n"); + } + ++ /* ++ * The mm flip commit is introduced before 52-bits VA, which is before the ++ * commit to export NUMBER(TCR_EL1_T1SZ) ++ */ ++ machdep->flags |= FLIPPED_VM; + return; + } + +diff --git a/defs.h b/defs.h +index b7b20af..eca145c 100644 +--- a/defs.h ++++ b/defs.h +@@ -3214,6 +3214,8 @@ typedef signed int s32; + #define NEW_VMEMMAP (0x80) + #define VM_L4_4K (0x100) + #define UNW_4_14 (0x200) ++#define FLIPPED_VM (0x400) ++#define HAS_PHYSVIRT_OFFSET (0x800) + + /* + * Get kimage_voffset from /dev/crash +-- +2.29.2 + diff --git a/0004-arm64-implement-switchable-PTOV-VTOP-for-kernels-5.1.patch b/0004-arm64-implement-switchable-PTOV-VTOP-for-kernels-5.1.patch new file mode 100644 index 0000000..8370c09 --- /dev/null +++ b/0004-arm64-implement-switchable-PTOV-VTOP-for-kernels-5.1.patch @@ -0,0 +1,165 @@ +From f53b73e8380bca054cebd2b61ff118c46609429b Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Fri, 2 Jul 2021 10:14:24 +0800 +Subject: [PATCH 4/4] arm64: implement switchable PTOV()/VTOP() for kernels >= + 5.10 + +Crash encounters a bug like the following: + ... + SECTION_SIZE_BITS: 30 + CONFIG_ARM64_VA_BITS: 52 + VA_BITS_ACTUAL: 48 + (calculated) VA_BITS: 48 + PAGE_OFFSET: ffff000000000000 + VA_START: ffff800000000000 + modules: ffff800008000000 - ffff80000fffffff + vmalloc: ffff800010000000 - ffffffdfdffeffff + kernel image: ffff800010000000 - ffff800012750000 + vmemmap: ffffffdfffe00000 - ffffffffffffffff + + + + read_netdump: addr: ffff800011c53bc8 paddr: eb453bc8 cnt: 4 offset: 1c73bc8 + irq_stack_ptr: + type: 1, TYPE_CODE_PTR + target_typecode: 8, TYPE_CODE_INT + target_length: 8 + length: 8 + GNU_GET_DATATYPE[thread_union]: returned via gdb_error_hook + + + read_netdump: READ_ERROR: offset not found for paddr: fff1000bf79c0050 + crash: read error: kernel virtual address: ffff000b779c0050 type: "IRQ stack pointer" + ... + +Apparently, for a normal system, the 'paddr: fff1000bf79c0050' is +unreasonable. + +This bug connects with kernel commit 7bc1a0f9e176 ("arm64: mm: use +single quantity to represent the PA to VA translation"), which removed +physvirt_offset kernel variable and changed the PTOV()/VTOP() formulas. + +Implement switchable PTOV()/VTOP() to cope with different kernel +version. + +Signed-off-by: Pingfan Liu +--- + arm64.c | 37 +++++++++++++++++++++++++++++++++---- + defs.h | 9 ++++----- + 2 files changed, 37 insertions(+), 9 deletions(-) + +diff --git a/arm64.c b/arm64.c +index b04369f..d73d5c5 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -994,8 +994,6 @@ arm64_calc_physvirt_offset(void) + ulong physvirt_offset; + struct syment *sp; + +- ms->physvirt_offset = ms->phys_offset - ms->page_offset; +- + if ((sp = kernel_symbol_search("physvirt_offset")) && + machdep->machspec->kimage_voffset) { + if (READMEM(pc->mfd, &physvirt_offset, sizeof(physvirt_offset), +@@ -1003,8 +1001,13 @@ arm64_calc_physvirt_offset(void) + machdep->machspec->kimage_voffset) > 0) { + machdep->flags |= HAS_PHYSVIRT_OFFSET; + ms->physvirt_offset = physvirt_offset; ++ return; + } + } ++ ++ /* Useless if no symbol 'physvirt_offset', just keep semantics */ ++ ms->physvirt_offset = ms->phys_offset - ms->page_offset; ++ + } + + static void +@@ -1051,6 +1054,7 @@ arm64_calc_phys_offset(void) + if (READMEM(pc->mfd, &phys_offset, sizeof(phys_offset), + vaddr, paddr) > 0) { + ms->phys_offset = phys_offset; ++ + return; + } + } +@@ -1178,6 +1182,21 @@ arm64_init_kernel_pgd(void) + vt->kernel_pgd[i] = value; + } + ++ulong arm64_PTOV(ulong paddr) ++{ ++ struct machine_specific *ms = machdep->machspec; ++ ++ /* ++ * Either older kernel before kernel has 'physvirt_offset' or newer ++ * kernel which removes 'physvirt_offset' has the same formula: ++ * #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) ++ */ ++ if (!(machdep->flags & HAS_PHYSVIRT_OFFSET)) ++ return (paddr - ms->phys_offset) | PAGE_OFFSET; ++ else ++ return paddr - ms->physvirt_offset; ++} ++ + ulong + arm64_VTOP(ulong addr) + { +@@ -1188,8 +1207,18 @@ arm64_VTOP(ulong addr) + return addr - machdep->machspec->kimage_voffset; + } + +- if (addr >= machdep->machspec->page_offset) +- return addr + machdep->machspec->physvirt_offset; ++ if (addr >= machdep->machspec->page_offset) { ++ if (machdep->flags & HAS_PHYSVIRT_OFFSET) { ++ return addr + machdep->machspec->physvirt_offset; ++ } else { ++ /* ++ * Either older kernel before kernel has 'physvirt_offset' or newer ++ * kernel which removes 'physvirt_offset' has the same formula: ++ * #define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) ++ */ ++ return (addr & ~PAGE_OFFSET) + machdep->machspec->phys_offset; ++ } ++ } + else if (machdep->machspec->kimage_voffset) + return addr - machdep->machspec->kimage_voffset; + else /* no randomness */ +diff --git a/defs.h b/defs.h +index eca145c..c91177a 100644 +--- a/defs.h ++++ b/defs.h +@@ -3092,11 +3092,6 @@ typedef u64 pte_t; + #define _64BIT_ + #define MACHINE_TYPE "ARM64" + +-#define PTOV(X) \ +- ((unsigned long)(X) - (machdep->machspec->physvirt_offset)) +- +-#define VTOP(X) arm64_VTOP((ulong)(X)) +- + #define USERSPACE_TOP (machdep->machspec->userspace_top) + #define PAGE_OFFSET (machdep->machspec->page_offset) + #define VMALLOC_START (machdep->machspec->vmalloc_start_addr) +@@ -3106,6 +3101,9 @@ typedef u64 pte_t; + #define MODULES_VADDR (machdep->machspec->modules_vaddr) + #define MODULES_END (machdep->machspec->modules_end) + ++#define PTOV(X) arm64_PTOV((ulong)(X)) ++#define VTOP(X) arm64_VTOP((ulong)(X)) ++ + #define IS_VMALLOC_ADDR(X) arm64_IS_VMALLOC_ADDR((ulong)(X)) + + #define PAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask) +@@ -5910,6 +5908,7 @@ void unwind_backtrace(struct bt_info *); + void arm64_init(int); + void arm64_dump_machdep_table(ulong); + ulong arm64_VTOP(ulong); ++ulong arm64_PTOV(ulong); + int arm64_IS_VMALLOC_ADDR(ulong); + ulong arm64_swp_type(ulong); + ulong arm64_swp_offset(ulong); +-- +2.29.2 + diff --git a/crash.spec b/crash.spec index e5c8589..4cf874e 100644 --- a/crash.spec +++ b/crash.spec @@ -21,6 +21,10 @@ Patch0: lzo_snappy.patch Patch1: 0001-Fix-for-kmem-s-S-option-on-Linux-5.7-and-later-kerne.patch Patch2: 0001-memory-Add-support-for-SECTION_TAINT_ZONE_DEVICE-fla.patch Patch3: 0002-memory-Fix-for-kmem-n-option-to-display-NID-correctl.patch +Patch4: 0001-arm64-rename-ARM64_PAGE_OFFSET_ACTUAL-to-ARM64_FLIP_.patch +Patch5: 0002-arm64-assign-page_offset-with-VA_BITS-kernel-configu.patch +Patch6: 0003-arm64-use-dedicated-bits-to-record-the-VA-space-layo.patch +Patch7: 0004-arm64-implement-switchable-PTOV-VTOP-for-kernels-5.1.patch %description The core analysis suite is a self-contained tool that can be used to @@ -44,6 +48,10 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 %build # This package has an internal copy of GDB which has broken configure code for