Skip to content

Commit c2e12f7

Browse files
committed
riscv: add fallible functions to pmpcfgx
Adds fallible conversion functions for `Pmpcfgx` permission and range fields.
1 parent f6a5d52 commit c2e12f7

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

riscv/src/register/pmpcfgx.rs

Lines changed: 73 additions & 0 deletions
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 {
@@ -76,6 +118,37 @@ impl Pmpcsr {
76118
locked: (byte & (1 << 7)) != 0,
77119
}
78120
}
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+
}
79152
}
80153

81154
/// Physical memory protection configuration

0 commit comments

Comments
 (0)