1
1
//! Physical memory protection configuration
2
2
3
+ use crate :: result:: { Error , Result } ;
4
+
3
5
/// Permission enum contains all possible permission modes for pmp registers
4
6
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
5
7
pub enum Permission {
@@ -13,6 +15,28 @@ pub enum Permission {
13
15
RWX = 0b111 ,
14
16
}
15
17
18
+ impl TryFrom < u8 > for Permission {
19
+ type Error = Error ;
20
+
21
+ fn try_from ( val : u8 ) -> Result < Self > {
22
+ match val {
23
+ 0b000 => Ok ( Self :: NONE ) ,
24
+ 0b001 => Ok ( Self :: R ) ,
25
+ 0b010 => Ok ( Self :: W ) ,
26
+ 0b011 => Ok ( Self :: RW ) ,
27
+ 0b100 => Ok ( Self :: X ) ,
28
+ 0b101 => Ok ( Self :: RX ) ,
29
+ 0b110 => Ok ( Self :: WX ) ,
30
+ 0b111 => Ok ( Self :: RWX ) ,
31
+ _ => Err ( Error :: InvalidValue {
32
+ field : "permission" ,
33
+ value : val as usize ,
34
+ bitmask : 0b111 ,
35
+ } ) ,
36
+ }
37
+ }
38
+ }
39
+
16
40
/// Range enum contains all possible addressing modes for pmp registers
17
41
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
18
42
pub enum Range {
@@ -22,6 +46,24 @@ pub enum Range {
22
46
NAPOT = 0b11 ,
23
47
}
24
48
49
+ impl TryFrom < u8 > for Range {
50
+ type Error = Error ;
51
+
52
+ fn try_from ( val : u8 ) -> Result < Self > {
53
+ match val {
54
+ 0b00 => Ok ( Self :: OFF ) ,
55
+ 0b01 => Ok ( Self :: TOR ) ,
56
+ 0b10 => Ok ( Self :: NA4 ) ,
57
+ 0b11 => Ok ( Self :: NAPOT ) ,
58
+ _ => Err ( Error :: InvalidValue {
59
+ field : "range" ,
60
+ value : val as usize ,
61
+ bitmask : 0b11 ,
62
+ } ) ,
63
+ }
64
+ }
65
+ }
66
+
25
67
/// Pmp struct holds a high-level representation of a single pmp configuration
26
68
#[ derive( Clone , Copy , Debug ) ]
27
69
pub struct Pmp {
@@ -42,38 +84,46 @@ pub struct Pmpcsr {
42
84
43
85
impl Pmpcsr {
44
86
/// Take the register contents and translate into a Pmp configuration struct
87
+ ///
88
+ /// **WARNING**: panics on:
89
+ ///
90
+ /// - non-`riscv` targets
91
+ /// - `index` is out of bounds
92
+ /// - register fields contain invalid values
45
93
#[ inline]
46
94
pub fn into_config ( & self , index : usize ) -> Pmp {
47
- #[ cfg( riscv32) ]
48
- assert ! ( index < 4 ) ;
49
-
50
- #[ cfg( riscv64) ]
51
- assert ! ( index < 8 ) ;
52
-
53
- let byte = ( self . bits >> ( 8 * index) ) as u8 ; // move config to LSB and drop the rest
54
- let permission = byte & 0x7 ; // bits 0-2
55
- let range = ( byte >> 3 ) & 0x3 ; // bits 3-4
56
- Pmp {
57
- byte,
58
- permission : match permission {
59
- 0 => Permission :: NONE ,
60
- 1 => Permission :: R ,
61
- 2 => Permission :: W ,
62
- 3 => Permission :: RW ,
63
- 4 => Permission :: X ,
64
- 5 => Permission :: RX ,
65
- 6 => Permission :: WX ,
66
- 7 => Permission :: RWX ,
67
- _ => unreachable ! ( ) ,
68
- } ,
69
- range : match range {
70
- 0 => Range :: OFF ,
71
- 1 => Range :: TOR ,
72
- 2 => Range :: NA4 ,
73
- 3 => Range :: NAPOT ,
74
- _ => unreachable ! ( ) ,
75
- } ,
76
- locked : ( byte & ( 1 << 7 ) ) != 0 ,
95
+ self . try_into_config ( index) . unwrap ( )
96
+ }
97
+
98
+ /// Attempts to take the register contents, and translate into a Pmp configuration struct.
99
+ #[ inline]
100
+ pub fn try_into_config ( & self , index : usize ) -> Result < Pmp > {
101
+ let max = match ( ) {
102
+ #[ cfg( riscv32) ]
103
+ ( ) => Ok ( 4usize ) ,
104
+ #[ cfg( riscv64) ]
105
+ ( ) => Ok ( 8usize ) ,
106
+ #[ cfg( not( any( riscv32, riscv64) ) ) ]
107
+ ( ) => Err ( Error :: Unimplemented ) ,
108
+ } ?;
109
+
110
+ if index < max {
111
+ let byte = ( self . bits >> ( 8 * index) ) as u8 ; // move config to LSB and drop the rest
112
+ let permission = byte & 0x7 ; // bits 0-2
113
+ let range = ( byte >> 3 ) & 0x3 ; // bits 3-4
114
+
115
+ Ok ( Pmp {
116
+ byte,
117
+ permission : permission. try_into ( ) ?,
118
+ range : range. try_into ( ) ?,
119
+ locked : ( byte & ( 1 << 7 ) ) != 0 ,
120
+ } )
121
+ } else {
122
+ Err ( Error :: IndexOutOfBounds {
123
+ index,
124
+ min : 0 ,
125
+ max : max - 1 ,
126
+ } )
77
127
}
78
128
}
79
129
}
0 commit comments