[Crash-utility] Fix for the determination of the ARM64 page size

Dave Anderson anderson at redhat.com
Tue Nov 12 15:34:12 UTC 2019


----- Original Message -----
> Hi Dave,
> There is a bug for the determination of the ARM64 page size happen on kernel 3.18 crash kdump.

If it is a kdump, there should be a PAGESIZE vmcoreinfo entry.  
As far as I can tell, the PAGE_SIZE has always been exported
as the second item for all architectures here:

  static int __init crash_save_vmcoreinfo_init(void)
  {
          VMCOREINFO_OSRELEASE(init_uts_ns.name.release);
          VMCOREINFO_PAGESIZE(PAGE_SIZE);
  ...

What does "help -D" show for the vmcoreinfo data on your dumpfile?


> The crash session failed immediately with the error message "crash: cannot determine page size" since the page size cannot be determinted by kernel image header flags field or subtraction of symbol values address.
> ffffffc0024df000 A idmap_pg_dir
> ffffffc0024e2000 A swapper_pg_dir
> ffffffc0024e4000 A tramp_pg_dir
> so value = symbol_value("tramp_pg_dir") - symbol_value("idmap_pg_dir") = 5 * PAGE_SIZE, the vaule result is determined by the order of symbol address:
> [kernel-3.18/arch/arm64/kernel/vmlinux.lds.S]
>         BSS_SECTION(0, 0, 0)
> 
>         . = ALIGN(PAGE_SIZE);
>         idmap_pg_dir = .;
>         . += IDMAP_DIR_SIZE;
>         swapper_pg_dir = .;
>         . += SWAPPER_DIR_SIZE;
> 
> #ifdef CONFIG_ARM64_SW_TTBR0_PAN
>         reserved_ttbr0 = .;
>         . += RESERVED_TTBR0_SIZE;
> #endif
> 
> #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>         tramp_pg_dir = .;
>         . += PAGE_SIZE;
> #endif
> 
> For Linux 4.16 and later kernels have changed the order of symbol definition due to containing the commit 1e1b8c04fa3451e2b7190930adae43c95f0fae31,
> So crash utility upstream commit 764e2d09978bb3f87dfaff4c6a59d4a5cc00f277 to fix it, but it ignore the determination of the ARM64 page size on previous
> Linux 4.16 kernels.
> 
> So I recommend this patch to fix it.

I have several old arm64 dumpfiles, with kernel versions 3.19, 4.2, 4.4, 4.5, 4.7, 
4.9 and 4.14.  However, none of them reach your patch because the code section that
you are patching is only used as a third option after:

  (1) checking the vmcoreinfo data, and 
  (2) checking the kernel image header for the flags field.  

In Linux 4.4, this patch added the page size to the kernel image header:

  commit 9d372c9fab34cd8803141871195141995f85c7f7
  Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
  Date:   Mon Oct 19 14:19:36 2015 +0100

    arm64: Add page size to the kernel image header
    
    This patch adds the page size to the arm64 kernel image header
    so that one can infer the PAGESIZE used by the kernel. This will
    be helpful to diagnose failures to boot the kernel with page size
    not supported by the CPU.

And later on in Linux 4.6, "_kernel_flags_le" was replaced by
"_kernel_flags_le_lo32" and "_kernel_flags_le_hi32":
    
  commit 6ad1fe5d9077a1ab40bf74b61994d2e770b00b14
  Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
  Date:   Sat Dec 26 13:48:02 2015 +0100

    arm64: avoid R_AARCH64_ABS64 relocations for Image header fields
    
    Unfortunately, the current way of using the linker to emit build time
    constants into the Image header will no longer work once we switch to
    the use of PIE executables. The reason is that such constants are emitted
    into the binary using R_AARCH64_ABS64 relocations, which are resolved at
    runtime, not at build time, and the places targeted by those relocations
    will contain zeroes before that.
    
    So refactor the endian swapping linker script constant generation code so
    that it emits the upper and lower 32-bit words separately.

Anyway, given that the page size flags entry was introduced in Linux 4.4, I don't 
believe your patch checking for LINUX(4,16,0) is correct:

+			if (THIS_KERNEL_VERSION < LINUX(4,16,0)) {
+				value = symbol_value("swapper_pg_dir") -
+					symbol_value("idmap_pg_dir");
+			} else {

Do you agree?

Dave




More information about the Crash-utility mailing list