@@ -42,13 +42,47 @@ static inline bool __arm64_rndr(unsigned long *v)
4242 return ok ;
4343}
4444
45+ static inline bool __arm64_rndrrs (unsigned long * v )
46+ {
47+ bool ok ;
48+
49+ /*
50+ * Reads of RNDRRS set PSTATE.NZCV to 0b0000 on success,
51+ * and set PSTATE.NZCV to 0b0100 otherwise.
52+ */
53+ asm volatile (
54+ __mrs_s ("%0" , SYS_RNDRRS_EL0 ) "\n"
55+ " cset %w1, ne\n"
56+ : "=r" (* v ), "=r" (ok )
57+ :
58+ : "cc" );
59+
60+ return ok ;
61+ }
62+
4563static inline bool __must_check arch_get_random_long (unsigned long * v )
4664{
65+ /*
66+ * Only support the generic interface after we have detected
67+ * the system wide capability, avoiding complexity with the
68+ * cpufeature code and with potential scheduling between CPUs
69+ * with and without the feature.
70+ */
71+ if (cpus_have_const_cap (ARM64_HAS_RNG ) && __arm64_rndr (v ))
72+ return true;
4773 return false;
4874}
4975
5076static inline bool __must_check arch_get_random_int (unsigned int * v )
5177{
78+ if (cpus_have_const_cap (ARM64_HAS_RNG )) {
79+ unsigned long val ;
80+
81+ if (__arm64_rndr (& val )) {
82+ * v = val ;
83+ return true;
84+ }
85+ }
5286 return false;
5387}
5488
@@ -71,12 +105,11 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
71105 }
72106
73107 /*
74- * Only support the generic interface after we have detected
75- * the system wide capability, avoiding complexity with the
76- * cpufeature code and with potential scheduling between CPUs
77- * with and without the feature.
108+ * RNDRRS is not backed by an entropy source but by a DRBG that is
109+ * reseeded after each invocation. This is not a 100% fit but good
110+ * enough to implement this API if no other entropy source exists.
78111 */
79- if (cpus_have_const_cap (ARM64_HAS_RNG ) && __arm64_rndr (v ))
112+ if (cpus_have_const_cap (ARM64_HAS_RNG ) && __arm64_rndrrs (v ))
80113 return true;
81114
82115 return false;
@@ -96,7 +129,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
96129 }
97130
98131 if (cpus_have_const_cap (ARM64_HAS_RNG )) {
99- if (__arm64_rndr (& val )) {
132+ if (__arm64_rndrrs (& val )) {
100133 * v = val ;
101134 return true;
102135 }
0 commit comments