5
5
// Author(s):
6
6
// - Ali Saidi <[email protected] >
7
7
8
+ #[ cfg( target_arch = "aarch64" ) ]
9
+ use core:: arch:: asm;
8
10
9
11
/// 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
+ ///
13
17
/// ```no_run
14
18
/// use cortex_a::asm::random::ArmRng;
15
19
/// if let Some(rng) = ArmRng::new() {
16
- /// let rand_num = rng.rndr();
20
+ /// let rand_num = rng.rndr();
17
21
/// }
18
22
/// ```
19
23
#[ derive( Copy , Clone , Debug ) ]
20
24
pub struct ArmRng ;
21
25
22
- use crate :: registers:: ID_AA64ISAR0_EL1 ;
23
- use core:: arch:: asm;
24
- use tock_registers:: interfaces:: Readable ;
25
-
26
26
impl 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" ) ]
30
30
#[ inline]
31
31
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 ;
34
34
35
- #[ cfg( target_arch = "aarch64" ) ]
36
35
if ID_AA64ISAR0_EL1 . is_set ( ID_AA64ISAR0_EL1 :: RNDR ) {
37
36
Some ( ArmRng )
38
37
} else {
39
38
None
40
39
}
41
40
}
42
41
42
+ #[ cfg( not( target_arch = "aarch64" ) ) ]
43
+ pub fn new ( ) -> Option < Self > {
44
+ None
45
+ }
46
+
43
47
/// 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" ) ]
46
52
#[ inline]
47
53
pub fn rndr ( & self ) -> Option < u64 > {
48
54
let mut flags: u64 ;
49
55
let mut data: u64 ;
50
56
51
- #[ cfg( target_arch = "aarch64" ) ]
52
57
unsafe {
53
58
asm ! (
54
59
"mrs {o}, s3_3_c2_c4_0" ,
@@ -57,22 +62,29 @@ impl ArmRng {
57
62
f = out( reg) flags,
58
63
options( nomem, nostack) ) ;
59
64
}
60
- if cfg ! ( not( target_arch = "aarch64" ) ) || flags != 0 {
65
+
66
+ if flags != 0 {
61
67
None
62
68
} else {
63
69
Some ( data)
64
70
}
65
71
}
66
72
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" ) ]
70
83
#[ inline]
71
84
pub fn rndrss ( & self ) -> Option < u64 > {
72
85
let mut flags: u64 ;
73
86
let mut data: u64 ;
74
87
75
- #[ cfg( target_arch = "aarch64" ) ]
76
88
unsafe {
77
89
asm ! (
78
90
"mrs {o}, s3_3_c2_c4_1" ,
@@ -82,30 +94,30 @@ impl ArmRng {
82
94
options( nomem, nostack) ) ;
83
95
}
84
96
85
- if cfg ! ( not ( target_arch = "aarch64" ) ) || flags != 0 {
97
+ if flags != 0 {
86
98
None
87
99
} else {
88
100
Some ( data)
89
101
}
90
102
}
91
103
92
-
104
+ #[ cfg( not( target_arch = "aarch64" ) ) ]
105
+ pub fn rndrss ( & self ) -> Option < u64 > {
106
+ None
107
+ }
93
108
}
94
109
95
-
96
110
#[ cfg( all( test, target_os = "linux" ) ) ]
97
111
mod tests {
98
112
use super :: * ;
99
113
100
114
#[ test]
101
115
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.
104
118
if let Some ( rand) = ArmRng :: new ( ) {
105
119
assert ! ( rand. rndr( ) . unwrap( ) != 0 ) ;
106
120
assert ! ( rand. rndrss( ) . unwrap( ) != 0 ) ;
107
121
}
108
122
}
109
-
110
123
}
111
-
0 commit comments