1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_ARCHRANDOM_H 3 #define _ASM_ARCHRANDOM_H 4 5 #ifdef CONFIG_ARCH_RANDOM 6 7 #include <linux/bug.h> 8 #include <linux/kernel.h> 9 #include <linux/random.h> 10 #include <asm/cpufeature.h> 11 12 static inline bool __arm64_rndr(unsigned long *v) 13 { 14 bool ok; 15 16 /* 17 * Reads of RNDR set PSTATE.NZCV to 0b0000 on success, 18 * and set PSTATE.NZCV to 0b0100 otherwise. 19 */ 20 asm volatile( 21 __mrs_s("%0", SYS_RNDR_EL0) "\n" 22 " cset %w1, ne\n" 23 : "=r" (*v), "=r" (ok) 24 : 25 : "cc"); 26 27 return ok; 28 } 29 30 static inline bool __must_check arch_get_random_long(unsigned long *v) 31 { 32 return false; 33 } 34 35 static inline bool __must_check arch_get_random_int(unsigned int *v) 36 { 37 return false; 38 } 39 40 static inline bool __must_check arch_get_random_seed_long(unsigned long *v) 41 { 42 /* 43 * Only support the generic interface after we have detected 44 * the system wide capability, avoiding complexity with the 45 * cpufeature code and with potential scheduling between CPUs 46 * with and without the feature. 47 */ 48 if (!cpus_have_const_cap(ARM64_HAS_RNG)) 49 return false; 50 51 return __arm64_rndr(v); 52 } 53 54 55 static inline bool __must_check arch_get_random_seed_int(unsigned int *v) 56 { 57 unsigned long val; 58 bool ok = arch_get_random_seed_long(&val); 59 60 *v = val; 61 return ok; 62 } 63 64 static inline bool __init __early_cpu_has_rndr(void) 65 { 66 /* Open code as we run prior to the first call to cpufeature. */ 67 unsigned long ftr = read_sysreg_s(SYS_ID_AA64ISAR0_EL1); 68 return (ftr >> ID_AA64ISAR0_RNDR_SHIFT) & 0xf; 69 } 70 71 static inline bool __init __must_check 72 arch_get_random_seed_long_early(unsigned long *v) 73 { 74 WARN_ON(system_state != SYSTEM_BOOTING); 75 76 if (!__early_cpu_has_rndr()) 77 return false; 78 79 return __arm64_rndr(v); 80 } 81 #define arch_get_random_seed_long_early arch_get_random_seed_long_early 82 83 #else 84 85 static inline bool __arm64_rndr(unsigned long *v) { return false; } 86 static inline bool __init __early_cpu_has_rndr(void) { return false; } 87 88 #endif /* CONFIG_ARCH_RANDOM */ 89 #endif /* _ASM_ARCHRANDOM_H */ 90