55// Author(s):
66// - Ali Saidi <alisaidi@amazon.com>
77
8+ #[ cfg( target_arch = "aarch64" ) ]
9+ use core:: arch:: asm;
810
911/// Implement an interface for accessing Arm v8.5 RNG instructions.
10- /// An empty struct is used to confirm that the system has the
11- /// instructions available.
12- /// # Example:
12+ ///
13+ /// An empty struct is used to confirm that the system has the instructions available.
14+ ///
15+ /// # Example
16+ ///
1317/// ```no_run
1418/// use cortex_a::asm::random::ArmRng;
1519/// if let Some(rng) = ArmRng::new() {
16- /// let rand_num = rng.rndr();
20+ /// let rand_num = rng.rndr();
1721/// }
1822/// ```
1923#[ derive( Copy , Clone , Debug ) ]
2024pub struct ArmRng ;
2125
22- use crate :: registers:: ID_AA64ISAR0_EL1 ;
23- use core:: arch:: asm;
24- use tock_registers:: interfaces:: Readable ;
25-
2626impl ArmRng {
27- /// Return an empty object that is used to gate calling
28- /// rndr and rndrss on discovery of the feature so each
29- /// call doesn't need to confirm it.
27+ /// Return an empty object that is used to gate calling rndr and rndrss on discovery of the
28+ /// feature so each call doesn't need to confirm it.
29+ # [ cfg ( target_arch = "aarch64" ) ]
3030 #[ inline]
3131 pub fn new ( ) -> Option < Self > {
32- # [ cfg ( not ( target_arch = "aarch64" ) ) ]
33- return None ;
32+ use crate :: registers :: ID_AA64ISAR0_EL1 ;
33+ use tock_registers :: interfaces :: Readable ;
3434
35- #[ cfg( target_arch = "aarch64" ) ]
3635 if ID_AA64ISAR0_EL1 . is_set ( ID_AA64ISAR0_EL1 :: RNDR ) {
3736 Some ( ArmRng )
3837 } else {
3938 None
4039 }
4140 }
4241
42+ #[ cfg( not( target_arch = "aarch64" ) ) ]
43+ pub fn new ( ) -> Option < Self > {
44+ None
45+ }
46+
4347 /// Return an random number from the Arm v8.5 RNG.
44- /// This returns an option because the instruction can fail
45- /// (e.g. the entropy is exhausted or the RNG has failed.)
48+ ///
49+ /// This returns an option because the instruction can fail (e.g. the entropy is exhausted or
50+ /// the RNG has failed.)
51+ #[ cfg( target_arch = "aarch64" ) ]
4652 #[ inline]
4753 pub fn rndr ( & self ) -> Option < u64 > {
4854 let mut flags: u64 ;
4955 let mut data: u64 ;
5056
51- #[ cfg( target_arch = "aarch64" ) ]
5257 unsafe {
5358 asm ! (
5459 "mrs {o}, s3_3_c2_c4_0" ,
@@ -57,22 +62,29 @@ impl ArmRng {
5762 f = out( reg) flags,
5863 options( nomem, nostack) ) ;
5964 }
60- if cfg ! ( not( target_arch = "aarch64" ) ) || flags != 0 {
65+
66+ if flags != 0 {
6167 None
6268 } else {
6369 Some ( data)
6470 }
6571 }
6672
67- /// Return an random number from the Arm v8.5 RNG after reseeding it
68- /// This returns an option because the instruction can fail
69- /// (e.g. the entropy is exhausted or the RNG has failed.)
73+ #[ cfg( not( target_arch = "aarch64" ) ) ]
74+ pub fn rndr ( & self ) -> Option < u64 > {
75+ None
76+ }
77+
78+ /// Return a random number from the Arm v8.5 RNG after reseeding it.
79+ ///
80+ /// This returns an option because the instruction can fail (e.g. the entropy is exhausted or
81+ /// the RNG has failed.)
82+ #[ cfg( target_arch = "aarch64" ) ]
7083 #[ inline]
7184 pub fn rndrss ( & self ) -> Option < u64 > {
7285 let mut flags: u64 ;
7386 let mut data: u64 ;
7487
75- #[ cfg( target_arch = "aarch64" ) ]
7688 unsafe {
7789 asm ! (
7890 "mrs {o}, s3_3_c2_c4_1" ,
@@ -82,30 +94,30 @@ impl ArmRng {
8294 options( nomem, nostack) ) ;
8395 }
8496
85- if cfg ! ( not ( target_arch = "aarch64" ) ) || flags != 0 {
97+ if flags != 0 {
8698 None
8799 } else {
88100 Some ( data)
89101 }
90102 }
91103
92-
104+ #[ cfg( not( target_arch = "aarch64" ) ) ]
105+ pub fn rndrss ( & self ) -> Option < u64 > {
106+ None
107+ }
93108}
94109
95-
96110#[ cfg( all( test, target_os = "linux" ) ) ]
97111mod tests {
98112 use super :: * ;
99113
100114 #[ test]
101115 pub fn test_rndr ( ) {
102- // This works on Linux from userspace since Linux emulatates
103- // the Arm ID registers on the userspace undef.
116+ // This works on Linux from userspace since Linux emulatates the Arm ID registers on the
117+ // userspace undef.
104118 if let Some ( rand) = ArmRng :: new ( ) {
105119 assert ! ( rand. rndr( ) . unwrap( ) != 0 ) ;
106120 assert ! ( rand. rndrss( ) . unwrap( ) != 0 ) ;
107121 }
108122 }
109-
110123}
111-
0 commit comments