From 03ce84ec01f99b3d5a86d1fd505f732091879e3e Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Fri, 17 Apr 2020 19:41:27 +0530 Subject: [PATCH 1/4] fix the arm64 vtop and ptov calculations Linux kernel patch "arm64: mm: Introduce vabits_actual" introduced physvirt_offset which is not equal to PHYS_OFFSET - PAGE_OFFSET when kaslr is enabled. physvirt_offset is caculated in arch/arm64/mm/init.c before memstart_addr (PHYS_OFFSET) is randomized. Let vtop and ptov use physvirt_offset instead, whose default value is set to (phys_offset - page_offset) --- arm64.c | 36 +++++++++++++++++++++++++++++++++--- defs.h | 3 ++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/arm64.c b/arm64.c index 09b1b76..7a05f2a 100644 --- a/arm64.c +++ b/arm64.c @@ -31,6 +31,7 @@ static int arm64_search_for_kimage_voffset(ulong); static int verify_kimage_voffset(void); static void arm64_calc_kimage_voffset(void); static void arm64_calc_phys_offset(void); +static void arm64_calc_physvirt_offset(void); static void arm64_calc_virtual_memory_ranges(void); static void arm64_get_section_size_bits(void); static int arm64_kdump_phys_base(ulong *); @@ -362,6 +363,8 @@ arm64_init(int when) /* use machdep parameters */ arm64_calc_phys_offset(); + /* call this after setting phys_offset and page_offset */ + arm64_calc_physvirt_offset(); if (CRASHDEBUG(1)) { if (machdep->flags & NEW_VMEMMAP) @@ -474,6 +477,7 @@ arm64_init(int when) arm64_calc_VA_BITS(); arm64_calc_phys_offset(); machdep->machspec->page_offset = ARM64_PAGE_OFFSET; + arm64_calc_physvirt_offset(); break; } } @@ -967,6 +971,28 @@ arm64_calc_kimage_voffset(void) } static void +arm64_calc_physvirt_offset(void) +{ + struct machine_specific *ms = machdep->machspec; + 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), + sp->value, sp->value - + machdep->machspec->kimage_voffset) > 0) { + ms->physvirt_offset = physvirt_offset; + } + } + + if (CRASHDEBUG(1)) + fprintf(fp, "using %lx as physvirt_offset\n", ms->physvirt_offset); +} + +static void arm64_calc_phys_offset(void) { struct machine_specific *ms = machdep->machspec; @@ -1147,9 +1173,13 @@ arm64_VTOP(ulong addr) return addr - machdep->machspec->kimage_voffset; } - if (addr >= machdep->machspec->page_offset) - return machdep->machspec->phys_offset - + (addr - machdep->machspec->page_offset); + if (addr >= machdep->machspec->page_offset) { + if (machdep->machspec->physvirt_offset) + return addr + machdep->machspec->physvirt_offset; + else + return machdep->machspec->phys_offset + + (addr - machdep->machspec->page_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 923869c..b53562e 100644 --- a/defs.h +++ b/defs.h @@ -3030,7 +3030,7 @@ typedef u64 pte_t; #define MACHINE_TYPE "ARM64" #define PTOV(X) \ - ((unsigned long)(X)-(machdep->machspec->phys_offset)+(machdep->machspec->page_offset)) + ((unsigned long)(X) - (machdep->machspec->physvirt_offset)) #define VTOP(X) arm64_VTOP((ulong)(X)) @@ -3280,6 +3280,7 @@ struct machine_specific { ulong VA_BITS_ACTUAL; ulong CONFIG_ARM64_VA_BITS; ulong VA_START; + ulong physvirt_offset; }; struct arm64_stackframe { --