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 {
@@ -76,6 +118,37 @@ impl Pmpcsr {
76
118
locked : ( byte & ( 1 << 7 ) ) != 0 ,
77
119
}
78
120
}
121
+
122
+ /// Attempts to take the register contents, and translate into a Pmp configuration struct.
123
+ #[ inline]
124
+ pub fn try_into_config ( & self , index : usize ) -> Result < Pmp > {
125
+ let max = if cfg ! ( riscv32) {
126
+ Ok ( 4usize )
127
+ } else if cfg ! ( riscv64) {
128
+ Ok ( 8usize )
129
+ } else {
130
+ Err ( Error :: Unimplemented )
131
+ } ?;
132
+
133
+ if index < max {
134
+ let byte = ( self . bits >> ( 8 * index) ) as u8 ; // move config to LSB and drop the rest
135
+ let permission = byte & 0x7 ; // bits 0-2
136
+ let range = ( byte >> 3 ) & 0x3 ; // bits 3-4
137
+
138
+ Ok ( Pmp {
139
+ byte,
140
+ permission : permission. try_into ( ) ?,
141
+ range : range. try_into ( ) ?,
142
+ locked : ( byte & ( 1 << 7 ) ) != 0 ,
143
+ } )
144
+ } else {
145
+ Err ( Error :: OutOfBounds {
146
+ index,
147
+ min : 0 ,
148
+ max : max - 1 ,
149
+ } )
150
+ }
151
+ }
79
152
}
80
153
81
154
/// Physical memory protection configuration
0 commit comments