|
@@ -4,121 +4,93 @@ use bit_field::BitField;
|
|
|
/// Permission enum contains all possible permission modes for pmp registers
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
pub enum Permission {
|
|
|
- NONE = 0b_000,
|
|
|
- R = 0b_001,
|
|
|
- W = 0b_010,
|
|
|
- RW = 0b_011,
|
|
|
- X = 0b_100,
|
|
|
- RX = 0b_101,
|
|
|
- WX = 0b_110,
|
|
|
- RWX = 0b_111,
|
|
|
+ NONE = 0b000,
|
|
|
+ R = 0b001,
|
|
|
+ W = 0b010,
|
|
|
+ RW = 0b011,
|
|
|
+ X = 0b100,
|
|
|
+ RX = 0b101,
|
|
|
+ WX = 0b110,
|
|
|
+ RWX = 0b111,
|
|
|
}
|
|
|
|
|
|
/// Range enum contains all possible addressing modes for pmp registers
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
pub enum Range {
|
|
|
- OFF = 0b_00,
|
|
|
- TOR = 0b_01,
|
|
|
- NA4 = 0b_10,
|
|
|
- NAPOT = 0b_11,
|
|
|
+ OFF = 0b00,
|
|
|
+ TOR = 0b01,
|
|
|
+ NA4 = 0b10,
|
|
|
+ NAPOT = 0b11,
|
|
|
}
|
|
|
|
|
|
+/// RV64 Pmpcfg holds the entire register (8 Pmp configurations)
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
-pub struct Pmpcfg {
|
|
|
- pub bits: usize,
|
|
|
+pub struct Pmp {
|
|
|
+ /// raw bits
|
|
|
+ pub byte: u8,
|
|
|
+ /// Current PMP Permission
|
|
|
+ pub permission: Permission,
|
|
|
+ /// Current PMP Range
|
|
|
+ pub range: Range,
|
|
|
+ /// Is PMP locked?
|
|
|
+ pub locked: bool,
|
|
|
}
|
|
|
|
|
|
-/// PmpByte holds the a single pmp configuration
|
|
|
-#[derive(Clone, Copy, Debug)]
|
|
|
-pub struct PmpEntry {
|
|
|
- pub byte: usize,
|
|
|
- pub index: usize,
|
|
|
- pub permission: Option<Permission>,
|
|
|
- pub range: Option<Range>,
|
|
|
- pub locked: bool,
|
|
|
+pub struct Pmpcsr {
|
|
|
+ /// Holds the raw contents of the PMP CSR
|
|
|
+ pub bits: usize,
|
|
|
}
|
|
|
|
|
|
-impl Pmpcfg {
|
|
|
+impl Pmpcsr {
|
|
|
+ /// Take the register contents and translate into configurations held in a Pmpcfg struct
|
|
|
+ /// Takes `self` as a parameter and destroys the current Pmpcsr struct
|
|
|
#[inline]
|
|
|
- pub fn get_config(&self, index: usize) -> PmpEntry {
|
|
|
+ pub fn into_config(&self, index: usize) -> Pmp {
|
|
|
#[cfg(riscv32)]
|
|
|
assert!(index < 4);
|
|
|
|
|
|
#[cfg(riscv64)]
|
|
|
assert!(index < 8);
|
|
|
|
|
|
- PmpEntry {
|
|
|
- byte: self.get_byte(index),
|
|
|
- index,
|
|
|
- permission: self.get_permission(index),
|
|
|
- range: self.get_range(index),
|
|
|
- locked: self.is_locked(index),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// PmpByte methods to get a pmp configuration attributes
|
|
|
- pub fn get_byte(&self, index: usize) -> usize {
|
|
|
- self.bits.get_bits(8 * index..=(8 * index) + 7) as usize
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub fn is_locked(&self, index: usize) -> bool {
|
|
|
- self.bits.get_bit(7 + 8 * index)
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub fn get_permission(&self, index: usize) -> Option<Permission> {
|
|
|
- match self.bits.get_bits(8 * index..=8 * index + 2) {
|
|
|
- 0 => Some(Permission::NONE),
|
|
|
- 1 => Some(Permission::R),
|
|
|
- 2 => Some(Permission::W),
|
|
|
- 3 => Some(Permission::RW),
|
|
|
- 4 => Some(Permission::X),
|
|
|
- 5 => Some(Permission::RX),
|
|
|
- 6 => Some(Permission::WX),
|
|
|
- 7 => Some(Permission::RWX),
|
|
|
- _ => unreachable!(),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub fn get_range(&self, index: usize) -> Option<Range> {
|
|
|
- match self.bits.get_bits(8 * index + 3..=8 * index + 4) {
|
|
|
- 0 => Some(Range::OFF),
|
|
|
- 1 => Some(Range::TOR),
|
|
|
- 2 => Some(Range::NA4),
|
|
|
- 3 => Some(Range::NAPOT),
|
|
|
- _ => unreachable!(),
|
|
|
+ let byte = self.bits.get_bits(8 * index..=8 * index + 7) as u8;
|
|
|
+ Pmp {
|
|
|
+ byte,
|
|
|
+ permission: match byte.get_bits(0..=2) {
|
|
|
+ 0 => Permission::NONE,
|
|
|
+ 1 => Permission::R,
|
|
|
+ 2 => Permission::W,
|
|
|
+ 3 => Permission::RW,
|
|
|
+ 4 => Permission::X,
|
|
|
+ 5 => Permission::RX,
|
|
|
+ 6 => Permission::WX,
|
|
|
+ 7 => Permission::RWX,
|
|
|
+ _ => unreachable!(),
|
|
|
+ },
|
|
|
+ range: match byte.get_bits(3..=4) {
|
|
|
+ 0 => Range::OFF,
|
|
|
+ 1 => Range::TOR,
|
|
|
+ 2 => Range::NA4,
|
|
|
+ 3 => Range::NAPOT,
|
|
|
+ _ => unreachable!(),
|
|
|
+ },
|
|
|
+ locked: byte.get_bit(7) as bool,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
/// Physical memory protection configuration
|
|
|
-/// Pmpcfg0 struct contains pmp0cfg - pmp3cfg for RV32, or pmp0cfg - pmp7cfg for RV64
|
|
|
-/// get_byte() method retrieves a single pmp<x>cfg held in a PmpByte struct
|
|
|
-pub mod pmpcfg0 {
|
|
|
- use super::{Permission, Pmpcfg, Range};
|
|
|
+/// pmpcfg0 struct contains pmp0cfg - pmp3cfg for RV32, and pmp0cfg - pmp7cfg for RV64
|
|
|
+mod pmpcfg0 {
|
|
|
+ use super::{Permission, Pmpcsr, Range};
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
- read_csr_as!(Pmpcfg, 0x3A0, __read_pmpcfg0);
|
|
|
- write_csr!(0x3A0, __write_pmpcfg0);
|
|
|
+ read_csr_as!(Pmpcsr, 0x3A0, __read_pmpcfg0);
|
|
|
+ write_csr_as_usize!(0x3A0, __write_pmpcfg0);
|
|
|
set!(0x3A0, __set_pmpcfg0);
|
|
|
clear!(0x3A0, __clear_pmpcfg0);
|
|
|
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_permissions(permission: Permission, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- let mut value = _read();
|
|
|
- value.set_bits(8 * index..=8 * index + 2, permission as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_range(range: Range, index: usize) {
|
|
|
+ /// set the configuration for pmp(x)
|
|
|
+ pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
|
|
|
#[cfg(riscv32)]
|
|
|
assert!(index < 4);
|
|
|
|
|
@@ -126,86 +98,48 @@ pub mod pmpcfg0 {
|
|
|
assert!(index < 8);
|
|
|
|
|
|
let mut value = _read();
|
|
|
- value.set_bits(8 * index + 3..=8 * index + 4, range as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_lock(index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- _set(1 << (7 + index * 8));
|
|
|
+ let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
|
|
|
+ value.set_bits(8 * index..=8 * index + 7, byte);
|
|
|
+ _set(value)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// Physical memory protection configuration
|
|
|
-/// Pmpcfg1 struct contains pmp4cfg - pmp7cfg for RV32 only
|
|
|
-/// get_byte() method retrieves a single pmp<x>cfg held in a PmpByte struct
|
|
|
-pub mod pmpcfg1 {
|
|
|
- use super::{Permission, Pmpcfg, Range};
|
|
|
+/// pmpcfg1 struct contains pmp4cfg - pmp7cfg for RV32 only
|
|
|
+#[cfg(riscv32)]
|
|
|
+mod pmpcfg1 {
|
|
|
+ use super::{Permission, Pmpcsr, Range};
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
- read_csr_as!(Pmpcfg, 0x3A1, __read_pmpcfg1);
|
|
|
- write_csr!(0x3A1, __write_pmpcfg1);
|
|
|
+ read_csr_as!(Pmpcsr, 0x3A1, __read_pmpcfg1);
|
|
|
+ write_csr_as_usize_rv32!(0x3A1, __write_pmpcfg1);
|
|
|
set!(0x3A1, __set_pmpcfg1);
|
|
|
clear!(0x3A1, __clear_pmpcfg1);
|
|
|
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_permissions(permission: Permission, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
+ /// set the configuration for pmp(x)
|
|
|
+ pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
|
|
|
assert!(index < 4);
|
|
|
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- let mut value = _read();
|
|
|
- value.set_bits(8 * index..=8 * index + 2, permission as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_range(range: Range, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
let mut value = _read();
|
|
|
- value.set_bits(8 * index + 3..=8 * index + 4, range as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_lock(index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- _set(1 << (7 + index * 8));
|
|
|
+ let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
|
|
|
+ value.set_bits(8 * index..=8 * index + 7, byte);
|
|
|
+ _set(value)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// Physical memory protection configuration
|
|
|
-/// Pmpcfg0 struct contains pmp8cfg - pmp11cfg for RV32, or pmp8cfg - pmp15cfg for RV64
|
|
|
-/// get_byte() method retrieves a single pmp<x>cfg held in a PmpByte struct
|
|
|
+/// pmpcfg2 struct contains pmp8cfg - pmp11cfg for RV32, or pmp8cfg - pmp15cfg for RV64
|
|
|
pub mod pmpcfg2 {
|
|
|
- use super::{Permission, Pmpcfg, Range};
|
|
|
+ use super::{Permission, Pmpcsr, Range};
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
- read_csr_as!(Pmpcfg, 0x3A2, __read_pmpcfg2);
|
|
|
- write_csr!(0x3A2, __write_pmpcfg2);
|
|
|
+ read_csr_as!(Pmpcsr, 0x3A2, __read_pmpcfg2);
|
|
|
+ write_csr_as_usize!(0x3A2, __write_pmpcfg2);
|
|
|
set!(0x3A2, __set_pmpcfg2);
|
|
|
clear!(0x3A2, __clear_pmpcfg2);
|
|
|
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_permissions(permission: Permission, index: usize) {
|
|
|
+ /// set the configuration for pmp(x)
|
|
|
+ pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
|
|
|
#[cfg(riscv32)]
|
|
|
assert!(index < 4);
|
|
|
|
|
@@ -213,81 +147,31 @@ pub mod pmpcfg2 {
|
|
|
assert!(index < 8);
|
|
|
|
|
|
let mut value = _read();
|
|
|
- value.set_bits(8 * index..=8 * index + 2, permission as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_range(range: Range, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- let mut value = _read();
|
|
|
- value.set_bits(8 * index + 3..=8 * index + 4, range as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_lock(index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- _set(1 << (7 + index * 8));
|
|
|
+ let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
|
|
|
+ value.set_bits(8 * index..=8 * index + 7, byte);
|
|
|
+ _set(value)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// Physical memory protection configuration
|
|
|
-/// Pmpcfg0 struct contains pmp12cfg - pmp15cfg for RV32 only
|
|
|
-/// get_byte() method retrieves a single pmp<x>cfg held in a PmpByte struct
|
|
|
+/// pmpcfg3 struct contains pmp12cfg - pmp15cfg for RV32 only
|
|
|
+#[cfg(riscv32)]
|
|
|
pub mod pmpcfg3 {
|
|
|
- use super::{Permission, Pmpcfg, Range};
|
|
|
+ use super::{Permission, Pmpcsr, Range};
|
|
|
use bit_field::BitField;
|
|
|
|
|
|
- read_csr_as!(Pmpcfg, 0x3A3, __read_pmpcfg3);
|
|
|
- write_csr!(0x3A3, __write_pmpcfg3);
|
|
|
+ read_csr_as!(Pmpcsr, 0x3A3, __read_pmpcfg3);
|
|
|
+ write_csr_as_usize_rv32!(0x3A3, __read_pmpcfg3);
|
|
|
set!(0x3A3, __set_pmpcfg3);
|
|
|
clear!(0x3A3, __clear_pmpcfg3);
|
|
|
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_permissions(permission: Permission, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- let mut value = _read();
|
|
|
- value.set_bits(8 * index..=8 * index + 2, permission as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_range(range: Range, index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
+ /// set the configuration for pmp(x)
|
|
|
+ pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
|
|
|
assert!(index < 4);
|
|
|
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
let mut value = _read();
|
|
|
- value.set_bits(8 * index + 3..=8 * index + 4, range as usize);
|
|
|
- _write(value);
|
|
|
- }
|
|
|
-
|
|
|
- #[inline]
|
|
|
- pub unsafe fn set_lock(index: usize) {
|
|
|
- #[cfg(riscv32)]
|
|
|
- assert!(index < 4);
|
|
|
-
|
|
|
- #[cfg(riscv64)]
|
|
|
- assert!(index < 8);
|
|
|
-
|
|
|
- _set(1 << (7 + index * 8));
|
|
|
+ let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
|
|
|
+ value.set_bits(8 * index..=8 * index + 7, byte);
|
|
|
+ _set(value)
|
|
|
}
|
|
|
}
|