[PATCH] arm64: mm: Pass physical address explicitly in map_range

Pingfan Liu piliu at redhat.com
Thu Mar 14 05:53:29 PDT 2024


This patch is not a fix, just a improvement in code reading.

At the present, the deduction of a symbol's physical address hides in
the compiler's trick. Introduce a function paddr(), which make the
process explicitly at the sacrifice of one sub and one add instruction.

Signed-off-by: Pingfan Liu <piliu at redhat.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: Kees Cook <keescook at chromium.org>
To: linux-arm-kernel at lists.infradead.org
---
 arch/arm64/kernel/pi/map_kernel.c | 30 +++++++++++++++---------------
 arch/arm64/kernel/pi/map_range.c  | 21 +++++++++++++++++++--
 arch/arm64/kernel/pi/pi.h         |  1 +
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index cac1e1f63c44..f0bad9ff3cce 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -78,16 +78,16 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
 	twopass |= enable_scs;
 	prot = twopass ? data_prot : text_prot;
 
-	map_segment(init_pg_dir, &pgdp, va_offset, _stext, _etext, prot,
+	map_segment(init_pg_dir, &pgdp, va_offset, paddr(_stext), paddr(_etext), prot,
 		    !twopass, root_level);
-	map_segment(init_pg_dir, &pgdp, va_offset, __start_rodata,
-		    __inittext_begin, data_prot, false, root_level);
-	map_segment(init_pg_dir, &pgdp, va_offset, __inittext_begin,
-		    __inittext_end, prot, false, root_level);
-	map_segment(init_pg_dir, &pgdp, va_offset, __initdata_begin,
-		    __initdata_end, data_prot, false, root_level);
-	map_segment(init_pg_dir, &pgdp, va_offset, _data, _end, data_prot,
-		    true, root_level);
+	map_segment(init_pg_dir, &pgdp, va_offset, paddr(__start_rodata),
+		    paddr(__inittext_begin), data_prot, false, root_level);
+	map_segment(init_pg_dir, &pgdp, va_offset, paddr(__inittext_begin),
+		    paddr(__inittext_end), prot, false, root_level);
+	map_segment(init_pg_dir, &pgdp, va_offset, paddr(__initdata_begin),
+		    paddr(__initdata_end), data_prot, false, root_level);
+	map_segment(init_pg_dir, &pgdp, va_offset, paddr(_data), paddr(_end),
+		    data_prot, true, root_level);
 	dsb(ishst);
 
 	idmap_cpu_replace_ttbr1(init_pg_dir);
@@ -109,7 +109,7 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
 		 * potential TLB conflicts when creating the contiguous
 		 * descriptors.
 		 */
-		unmap_segment(init_pg_dir, va_offset, _stext, _etext,
+		unmap_segment(init_pg_dir, va_offset, paddr(_stext), paddr(_etext),
 			      root_level);
 		dsb(ishst);
 		isb();
@@ -120,10 +120,10 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
 		 * Remap these segments with different permissions
 		 * No new page table allocations should be needed
 		 */
-		map_segment(init_pg_dir, NULL, va_offset, _stext, _etext,
-			    text_prot, true, root_level);
-		map_segment(init_pg_dir, NULL, va_offset, __inittext_begin,
-			    __inittext_end, text_prot, false, root_level);
+		map_segment(init_pg_dir, NULL, va_offset, paddr(_stext),
+			    paddr(_etext), text_prot, true, root_level);
+		map_segment(init_pg_dir, NULL, va_offset, paddr(__inittext_begin),
+			    paddr(__inittext_end), text_prot, false, root_level);
 	}
 
 	/* Copy the root page table to its final location */
@@ -223,7 +223,7 @@ static void __init map_fdt(u64 fdt)
 asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
 {
 	static char const chosen_str[] __initconst = "/chosen";
-	u64 va_base, pa_base = (u64)&_text;
+	u64 va_base, pa_base = paddr(_text);
 	u64 kaslr_offset = pa_base % MIN_KIMG_ALIGN;
 	int root_level = 4 - CONFIG_PGTABLE_LEVELS;
 	int va_bits = VA_BITS;
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 5410b2cac590..b5a68dcf3cf5 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -87,6 +87,23 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	}
 }
 
+u64 __init paddr(char *symbol)
+{
+	u64 _text_paddr;
+	u64 delta;
+
+	asm volatile(
+		"adrp %0, _text;"
+		"add %0, %0, #:lo12:_text;"
+		: "=r" (_text_paddr)
+		:
+		:
+	);
+
+	delta = symbol - _text;
+	return _text_paddr + delta;
+}
+
 asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, pteval_t clrmask)
 {
 	u64 ptep = (u64)pg_dir + PAGE_SIZE;
@@ -96,9 +113,9 @@ asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, pteval_t clrmask)
 	pgprot_val(text_prot) &= ~clrmask;
 	pgprot_val(data_prot) &= ~clrmask;
 
-	map_range(&ptep, (u64)_stext, (u64)__initdata_begin, (u64)_stext,
+	map_range(&ptep, paddr(_stext), paddr(__initdata_begin), paddr(_stext),
 		  text_prot, IDMAP_ROOT_LEVEL, (pte_t *)pg_dir, false, 0);
-	map_range(&ptep, (u64)__initdata_begin, (u64)_end, (u64)__initdata_begin,
+	map_range(&ptep, paddr(__initdata_begin), paddr(_end), paddr(__initdata_begin),
 		  data_prot, IDMAP_ROOT_LEVEL, (pte_t *)pg_dir, false, 0);
 
 	return ptep;
diff --git a/arch/arm64/kernel/pi/pi.h b/arch/arm64/kernel/pi/pi.h
index c91e5e965cd3..7ffba712da06 100644
--- a/arch/arm64/kernel/pi/pi.h
+++ b/arch/arm64/kernel/pi/pi.h
@@ -28,6 +28,7 @@ u64 kaslr_early_init(void *fdt, int chosen);
 void relocate_kernel(u64 offset);
 int scs_patch(const u8 eh_frame[], int size);
 
+u64 paddr(char *symbol);
 void map_range(u64 *pgd, u64 start, u64 end, u64 pa, pgprot_t prot,
 	       int level, pte_t *tbl, bool may_use_cont, u64 va_offset);
 
-- 
2.41.0




More information about the linux-arm-kernel mailing list