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