Skip to content

Commit

Permalink
riscv: add fallible functions to pmpcfgx
Browse files Browse the repository at this point in the history
Adds fallible conversion functions for `Pmpcfgx` permission and range
fields.
  • Loading branch information
rmsyn committed Jun 29, 2024
1 parent f6a5d52 commit c2e12f7
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions riscv/src/register/pmpcfgx.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Physical memory protection configuration

use crate::result::{Error, Result};

/// Permission enum contains all possible permission modes for pmp registers
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Permission {
Expand All @@ -13,6 +15,28 @@ pub enum Permission {
RWX = 0b111,
}

impl TryFrom<u8> for Permission {
type Error = Error;

fn try_from(val: u8) -> Result<Self> {
match val {
0b000 => Ok(Self::NONE),
0b001 => Ok(Self::R),
0b010 => Ok(Self::W),
0b011 => Ok(Self::RW),
0b100 => Ok(Self::X),
0b101 => Ok(Self::RX),
0b110 => Ok(Self::WX),
0b111 => Ok(Self::RWX),
_ => Err(Error::InvalidValue {
field: "permission",
value: val as usize,
bitmask: 0b111,
}),
}
}
}

/// Range enum contains all possible addressing modes for pmp registers
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Range {
Expand All @@ -22,6 +46,24 @@ pub enum Range {
NAPOT = 0b11,
}

impl TryFrom<u8> for Range {
type Error = Error;

fn try_from(val: u8) -> Result<Self> {
match val {
0b00 => Ok(Self::OFF),
0b01 => Ok(Self::TOR),
0b10 => Ok(Self::NA4),
0b11 => Ok(Self::NAPOT),
_ => Err(Error::InvalidValue {
field: "range",
value: val as usize,
bitmask: 0b11,
}),
}
}
}

/// Pmp struct holds a high-level representation of a single pmp configuration
#[derive(Clone, Copy, Debug)]
pub struct Pmp {
Expand Down Expand Up @@ -76,6 +118,37 @@ impl Pmpcsr {
locked: (byte & (1 << 7)) != 0,
}
}

/// Attempts to take the register contents, and translate into a Pmp configuration struct.
#[inline]
pub fn try_into_config(&self, index: usize) -> Result<Pmp> {
let max = if cfg!(riscv32) {
Ok(4usize)
} else if cfg!(riscv64) {
Ok(8usize)
} else {
Err(Error::Unimplemented)
}?;

if index < max {
let byte = (self.bits >> (8 * index)) as u8; // move config to LSB and drop the rest
let permission = byte & 0x7; // bits 0-2
let range = (byte >> 3) & 0x3; // bits 3-4

Ok(Pmp {
byte,
permission: permission.try_into()?,
range: range.try_into()?,
locked: (byte & (1 << 7)) != 0,
})
} else {
Err(Error::OutOfBounds {
index,
min: 0,
max: max - 1,
})
}
}
}

/// Physical memory protection configuration
Expand Down

0 comments on commit c2e12f7

Please sign in to comment.