1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright 2022 Google LLC 3 // Author: Ard Biesheuvel <ardb@google.com> 4 5 // NOTE: code in this file runs *very* early, and is not permitted to use 6 // global variables or anything that relies on absolute addressing. 7 8 #include <linux/libfdt.h> 9 #include <linux/init.h> 10 #include <linux/linkage.h> 11 #include <linux/types.h> 12 #include <linux/sizes.h> 13 #include <linux/string.h> 14 15 #include <asm/archrandom.h> 16 #include <asm/memory.h> 17 #include <asm/pgtable.h> 18 19 #include "pi.h" 20 21 static u64 __init get_kaslr_seed(void *fdt, int node) 22 { 23 static char const seed_str[] __initconst = "kaslr-seed"; 24 fdt64_t *prop; 25 u64 ret; 26 int len; 27 28 if (node < 0) 29 return 0; 30 31 prop = fdt_getprop_w(fdt, node, seed_str, &len); 32 if (!prop || len != sizeof(u64)) 33 return 0; 34 35 ret = fdt64_to_cpu(*prop); 36 *prop = 0; 37 return ret; 38 } 39 40 u64 __init kaslr_early_init(void *fdt, int chosen) 41 { 42 u64 seed, range; 43 44 if (kaslr_disabled_cmdline()) 45 return 0; 46 47 seed = get_kaslr_seed(fdt, chosen); 48 if (!seed) { 49 if (!__early_cpu_has_rndr() || 50 !__arm64_rndr((unsigned long *)&seed)) 51 return 0; 52 } 53 54 /* 55 * OK, so we are proceeding with KASLR enabled. Calculate a suitable 56 * kernel image offset from the seed. Let's place the kernel in the 57 * 'middle' half of the VMALLOC area, and stay clear of the lower and 58 * upper quarters to avoid colliding with other allocations. 59 */ 60 range = (VMALLOC_END - KIMAGE_VADDR) / 2; 61 return range / 2 + (((__uint128_t)range * seed) >> 64); 62 } 63