Bladeren bron

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 <dkhayes117@yahoo.com>
Co-authored-by: dkhayes117 <59458913+dkhayes117@users.noreply.github.com>
bors[bot] 3 jaren geleden
bovenliggende
commit
be2927e248
4 gewijzigde bestanden met toevoegingen van 162 en 10 verwijderingen
  1. 6 0
      CHANGELOG.md
  2. 39 2
      src/register/macros.rs
  3. 2 2
      src/register/mod.rs
  4. 115 6
      src/register/pmpcfgx.rs

+ 6 - 0
CHANGELOG.md

@@ -6,10 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
+### Added
+- Add `#[cfg(riscv32)]` to `pmpcfg1` and `pmpcfg3` modules
+- Add enums `Range`, `Permission` for PMP configuration
+- Add `set_pmp()` and `clear_pmp()` functions to pmpcfg(x) modules
+- Add struct `Pmpcsr` and is returned from `pmpcfgx::read()`
 
 ### Changed
 
 - Use new `asm!` instead of `llvm_asm!`
+- Change `pmpcfgx::read()` macro to `read_csr_as!()` from `read_csr_as_usize!()` 
 
 ## [v0.7.0] - 2020-07-29
 

+ 39 - 2
src/register/macros.rs

@@ -229,7 +229,7 @@ macro_rules! set_csr {
         pub unsafe fn $set_field() {
             _set($e);
         }
-    }
+    };
 }
 
 macro_rules! clear_csr {
@@ -239,7 +239,7 @@ macro_rules! clear_csr {
         pub unsafe fn $clear_field() {
             _clear($e);
         }
-    }
+    };
 }
 
 macro_rules! set_clear_csr {
@@ -270,3 +270,40 @@ macro_rules! read_composite_csr {
         }
     };
 }
+
+macro_rules! set_pmp {
+    () => {
+        /// Set the pmp configuration corresponding to the index
+        #[inline]
+        pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) {
+            #[cfg(riscv32)]
+            assert!(index < 4);
+
+            #[cfg(riscv64)]
+            assert!(index < 8);
+
+            let mut value = _read();
+            let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize);
+            value.set_bits(8 * index..=8 * index + 7, byte);
+            _write(value);
+        }
+    };
+}
+
+macro_rules! clear_pmp {
+    () => {
+        /// Clear the pmp configuration corresponding to the index
+        #[inline]
+        pub unsafe fn clear_pmp(index: usize) {
+            #[cfg(riscv32)]
+            assert!(index < 4);
+
+            #[cfg(riscv64)]
+            assert!(index < 8);
+
+            let mut value = _read();
+            value.set_bits(8 * index..=8 * index + 7, 0);
+            _write(value);
+        }
+    };
+}

+ 2 - 2
src/register/mod.rs

@@ -5,10 +5,10 @@
 //! - cycleh
 //! - timeh
 //! - instreth
-//! - hpmcounter[3-31]h
+//! - hpmcounter<3-31>h
 //! - mcycleh
 //! - minstreth
-//! - mhpmcounter[3-31]h
+//! - mhpmcounter<3-31>h
 
 #[macro_use]
 mod macros;

+ 115 - 6
src/register/pmpcfgx.rs

@@ -1,23 +1,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 {
-    read_csr_as_usize!(0x3A0, __read_pmpcfg0);
+    use super::{Permission, Pmpcsr, Range};
+    use bit_field::BitField;
+
+    read_csr_as!(Pmpcsr, 0x3A0, __read_pmpcfg0);
     write_csr_as_usize!(0x3A0, __write_pmpcfg0);
+
+    set_pmp!();
+    clear_pmp!();
 }
 
-/// Physical memory protection configuration, RV32 only
+/// Physical memory protection configuration
+/// pmpcfg1 struct contains pmp4cfg - pmp7cfg for RV32 only
+#[cfg(riscv32)]
 pub mod pmpcfg1 {
-    read_csr_as_usize_rv32!(0x3A1, __read_pmpcfg1);
+    use super::{Permission, Pmpcsr, Range};
+    use bit_field::BitField;
+
+    read_csr_as!(Pmpcsr, 0x3A1, __read_pmpcfg1);
     write_csr_as_usize_rv32!(0x3A1, __write_pmpcfg1);
+
+    set_pmp!();
+    clear_pmp!();
 }
 
 /// Physical memory protection configuration
+/// pmpcfg2 struct contains pmp8cfg - pmp11cfg for RV32, or pmp8cfg - pmp15cfg for RV64
 pub mod pmpcfg2 {
-    read_csr_as_usize!(0x3A2, __read_pmpcfg2);
+    use super::{Permission, Pmpcsr, Range};
+    use bit_field::BitField;
+
+    read_csr_as!(Pmpcsr, 0x3A2, __read_pmpcfg2);
     write_csr_as_usize!(0x3A2, __write_pmpcfg2);
+
+    set_pmp!();
+    clear_pmp!();
 }
 
-/// Physical memory protection configuration, RV32 only
+/// Physical memory protection configuration
+/// pmpcfg3 struct contains pmp12cfg - pmp15cfg for RV32 only
+#[cfg(riscv32)]
 pub mod pmpcfg3 {
-    read_csr_as_usize_rv32!(0x3A3, __read_pmpcfg3);
+    use super::{Permission, Pmpcsr, Range};
+    use bit_field::BitField;
+
+    read_csr_as!(Pmpcsr, 0x3A3, __read_pmpcfg3);
     write_csr_as_usize_rv32!(0x3A3, __write_pmpcfg3);
+
+    set_pmp!();
+    clear_pmp!();
 }