1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/// Physical memory protection configuration
use bit_field::BitField;
/// Permission enum contains all possible permission modes for pmp registers
#[derive(Clone, Copy, Debug)]
pub enum Permission {
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 = 0b00,
TOR = 0b01,
NA4 = 0b10,
NAPOT = 0b11,
}
/// Pmp struct holds a high-level representation of a single pmp configuration
#[derive(Clone, Copy, Debug)]
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,
}
pub struct Pmpcsr {
/// Holds the raw contents of a PMP CSR Register
pub bits: usize,
}
impl Pmpcsr {
/// Take the register contents and translate into a Pmp configuration struct
#[inline]
pub fn into_config(&self, index: usize) -> Pmp {
#[cfg(riscv32)]
assert!(index < 4);
#[cfg(riscv64)]
assert!(index < 8);
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, and pmp0cfg - pmp7cfg for RV64
pub mod pmpcfg0 {
use super::{Permission, Pmpcsr, Range};
use bit_field::BitField;
read_csr_as!(Pmpcsr, 0x3A0);
write_csr_as_usize!(0x3A0);
set_pmp!();
clear_pmp!();
}
/// Physical memory protection configuration
/// pmpcfg1 struct contains pmp4cfg - pmp7cfg for RV32 only
#[cfg(riscv32)]
pub mod pmpcfg1 {
use super::{Permission, Pmpcsr, Range};
use bit_field::BitField;
read_csr_as!(Pmpcsr, 0x3A1);
write_csr_as_usize_rv32!(0x3A1);
set_pmp!();
clear_pmp!();
}
/// Physical memory protection configuration
/// pmpcfg2 struct contains pmp8cfg - pmp11cfg for RV32, or pmp8cfg - pmp15cfg for RV64
pub mod pmpcfg2 {
use super::{Permission, Pmpcsr, Range};
use bit_field::BitField;
read_csr_as!(Pmpcsr, 0x3A2);
write_csr_as_usize!(0x3A2);
set_pmp!();
clear_pmp!();
}
/// Physical memory protection configuration
/// pmpcfg3 struct contains pmp12cfg - pmp15cfg for RV32 only
#[cfg(riscv32)]
pub mod pmpcfg3 {
use super::{Permission, Pmpcsr, Range};
use bit_field::BitField;
read_csr_as!(Pmpcsr, 0x3A3);
write_csr_as_usize_rv32!(0x3A3);
set_pmp!();
clear_pmp!();
}