Skip to content

Commit 77b692f

Browse files
committed
riscv: add fallible functions to pmpcfgx
Adds fallible conversion functions for `Pmpcfgx` permission and range fields.
1 parent 54bdc4e commit 77b692f

File tree

1 file changed

+80
-30
lines changed

1 file changed

+80
-30
lines changed

riscv/src/register/pmpcfgx.rs

+80-30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Physical memory protection configuration
22
3+
use crate::result::{Error, Result};
4+
35
/// Permission enum contains all possible permission modes for pmp registers
46
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
57
pub enum Permission {
@@ -13,6 +15,28 @@ pub enum Permission {
1315
RWX = 0b111,
1416
}
1517

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+
1640
/// Range enum contains all possible addressing modes for pmp registers
1741
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1842
pub enum Range {
@@ -22,6 +46,24 @@ pub enum Range {
2246
NAPOT = 0b11,
2347
}
2448

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+
2567
/// Pmp struct holds a high-level representation of a single pmp configuration
2668
#[derive(Clone, Copy, Debug)]
2769
pub struct Pmp {
@@ -42,38 +84,46 @@ pub struct Pmpcsr {
4284

4385
impl Pmpcsr {
4486
/// 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
4593
#[inline]
4694
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+
})
77127
}
78128
}
79129
}

0 commit comments

Comments
 (0)