Skip to content

Commit be2927e

Browse files
Merge #58
58: Add detail to pmpcfgx.rs to return the individual pmp[x]cfg register … r=almindor a=dkhayes117 I wrote this about a dozen different ways. Check it out and let me know what you think. I didn't implement this for pmpcfg1 - pmpcfg3 as they will be identical setups as pmpcfg0 (well not quite identical). Once I get pmpcfg0 satisfactory, I will add the rest to match. Thanks, Daniel Co-authored-by: dkhayes117 <[email protected]> Co-authored-by: dkhayes117 <[email protected]>
2 parents 5f386ef + 1ab92c5 commit be2927e

File tree

4 files changed

+162
-10
lines changed

4 files changed

+162
-10
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
9+
### Added
10+
- Add `#[cfg(riscv32)]` to `pmpcfg1` and `pmpcfg3` modules
11+
- Add enums `Range`, `Permission` for PMP configuration
12+
- Add `set_pmp()` and `clear_pmp()` functions to pmpcfg(x) modules
13+
- Add struct `Pmpcsr` and is returned from `pmpcfgx::read()`
914

1015
### Changed
1116

1217
- Use new `asm!` instead of `llvm_asm!`
18+
- Change `pmpcfgx::read()` macro to `read_csr_as!()` from `read_csr_as_usize!()`
1319

1420
## [v0.7.0] - 2020-07-29
1521

src/register/macros.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ macro_rules! set_csr {
229229
pub unsafe fn $set_field() {
230230
_set($e);
231231
}
232-
}
232+
};
233233
}
234234

235235
macro_rules! clear_csr {
@@ -239,7 +239,7 @@ macro_rules! clear_csr {
239239
pub unsafe fn $clear_field() {
240240
_clear($e);
241241
}
242-
}
242+
};
243243
}
244244

245245
macro_rules! set_clear_csr {
@@ -270,3 +270,40 @@ macro_rules! read_composite_csr {
270270
}
271271
};
272272
}
273+
274+
macro_rules! set_pmp {
275+
() => {
276+
/// Set the pmp configuration corresponding to the index
277+
#[inline]
278+
pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
279+
#[cfg(riscv32)]
280+
assert!(index < 4);
281+
282+
#[cfg(riscv64)]
283+
assert!(index < 8);
284+
285+
let mut value = _read();
286+
let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
287+
value.set_bits(8 * index..=8 * index + 7, byte);
288+
_write(value);
289+
}
290+
};
291+
}
292+
293+
macro_rules! clear_pmp {
294+
() => {
295+
/// Clear the pmp configuration corresponding to the index
296+
#[inline]
297+
pub unsafe fn clear_pmp(index: usize) {
298+
#[cfg(riscv32)]
299+
assert!(index < 4);
300+
301+
#[cfg(riscv64)]
302+
assert!(index < 8);
303+
304+
let mut value = _read();
305+
value.set_bits(8 * index..=8 * index + 7, 0);
306+
_write(value);
307+
}
308+
};
309+
}

src/register/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
//! - cycleh
66
//! - timeh
77
//! - instreth
8-
//! - hpmcounter[3-31]h
8+
//! - hpmcounter<3-31>h
99
//! - mcycleh
1010
//! - minstreth
11-
//! - mhpmcounter[3-31]h
11+
//! - mhpmcounter<3-31>h
1212
1313
#[macro_use]
1414
mod macros;

src/register/pmpcfgx.rs

Lines changed: 115 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,132 @@
11
/// Physical memory protection configuration
2+
use bit_field::BitField;
3+
4+
/// Permission enum contains all possible permission modes for pmp registers
5+
#[derive(Clone, Copy, Debug)]
6+
pub enum Permission {
7+
NONE = 0b000,
8+
R = 0b001,
9+
W = 0b010,
10+
RW = 0b011,
11+
X = 0b100,
12+
RX = 0b101,
13+
WX = 0b110,
14+
RWX = 0b111,
15+
}
16+
17+
/// Range enum contains all possible addressing modes for pmp registers
18+
#[derive(Clone, Copy, Debug)]
19+
pub enum Range {
20+
OFF = 0b00,
21+
TOR = 0b01,
22+
NA4 = 0b10,
23+
NAPOT = 0b11,
24+
}
25+
26+
/// Pmp struct holds a high-level representation of a single pmp configuration
27+
#[derive(Clone, Copy, Debug)]
28+
pub struct Pmp {
29+
/// raw bits
30+
pub byte: u8,
31+
/// Current PMP Permission
32+
pub permission: Permission,
33+
/// Current PMP Range
34+
pub range: Range,
35+
/// Is PMP locked?
36+
pub locked: bool,
37+
}
38+
39+
pub struct Pmpcsr {
40+
/// Holds the raw contents of a PMP CSR Register
41+
pub bits: usize,
42+
}
43+
44+
impl Pmpcsr {
45+
/// Take the register contents and translate into a Pmp configuration struct
46+
#[inline]
47+
pub fn into_config(&self, index: usize) -> Pmp {
48+
#[cfg(riscv32)]
49+
assert!(index < 4);
50+
51+
#[cfg(riscv64)]
52+
assert!(index < 8);
53+
54+
let byte = self.bits.get_bits(8 * index..=8 * index + 7) as u8;
55+
Pmp {
56+
byte,
57+
permission: match byte.get_bits(0..=2) {
58+
0 => Permission::NONE,
59+
1 => Permission::R,
60+
2 => Permission::W,
61+
3 => Permission::RW,
62+
4 => Permission::X,
63+
5 => Permission::RX,
64+
6 => Permission::WX,
65+
7 => Permission::RWX,
66+
_ => unreachable!(),
67+
},
68+
range: match byte.get_bits(3..=4) {
69+
0 => Range::OFF,
70+
1 => Range::TOR,
71+
2 => Range::NA4,
72+
3 => Range::NAPOT,
73+
_ => unreachable!(),
74+
},
75+
locked: byte.get_bit(7) as bool,
76+
}
77+
}
78+
}
79+
80+
/// Physical memory protection configuration
81+
/// pmpcfg0 struct contains pmp0cfg - pmp3cfg for RV32, and pmp0cfg - pmp7cfg for RV64
282
pub mod pmpcfg0 {
3-
read_csr_as_usize!(0x3A0, __read_pmpcfg0);
83+
use super::{Permission, Pmpcsr, Range};
84+
use bit_field::BitField;
85+
86+
read_csr_as!(Pmpcsr, 0x3A0, __read_pmpcfg0);
487
write_csr_as_usize!(0x3A0, __write_pmpcfg0);
88+
89+
set_pmp!();
90+
clear_pmp!();
591
}
692

7-
/// Physical memory protection configuration, RV32 only
93+
/// Physical memory protection configuration
94+
/// pmpcfg1 struct contains pmp4cfg - pmp7cfg for RV32 only
95+
#[cfg(riscv32)]
896
pub mod pmpcfg1 {
9-
read_csr_as_usize_rv32!(0x3A1, __read_pmpcfg1);
97+
use super::{Permission, Pmpcsr, Range};
98+
use bit_field::BitField;
99+
100+
read_csr_as!(Pmpcsr, 0x3A1, __read_pmpcfg1);
10101
write_csr_as_usize_rv32!(0x3A1, __write_pmpcfg1);
102+
103+
set_pmp!();
104+
clear_pmp!();
11105
}
12106

13107
/// Physical memory protection configuration
108+
/// pmpcfg2 struct contains pmp8cfg - pmp11cfg for RV32, or pmp8cfg - pmp15cfg for RV64
14109
pub mod pmpcfg2 {
15-
read_csr_as_usize!(0x3A2, __read_pmpcfg2);
110+
use super::{Permission, Pmpcsr, Range};
111+
use bit_field::BitField;
112+
113+
read_csr_as!(Pmpcsr, 0x3A2, __read_pmpcfg2);
16114
write_csr_as_usize!(0x3A2, __write_pmpcfg2);
115+
116+
set_pmp!();
117+
clear_pmp!();
17118
}
18119

19-
/// Physical memory protection configuration, RV32 only
120+
/// Physical memory protection configuration
121+
/// pmpcfg3 struct contains pmp12cfg - pmp15cfg for RV32 only
122+
#[cfg(riscv32)]
20123
pub mod pmpcfg3 {
21-
read_csr_as_usize_rv32!(0x3A3, __read_pmpcfg3);
124+
use super::{Permission, Pmpcsr, Range};
125+
use bit_field::BitField;
126+
127+
read_csr_as!(Pmpcsr, 0x3A3, __read_pmpcfg3);
22128
write_csr_as_usize_rv32!(0x3A3, __write_pmpcfg3);
129+
130+
set_pmp!();
131+
clear_pmp!();
23132
}

0 commit comments

Comments
 (0)