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