Parcourir la source

Merge #65

65: Small fixes according to RISC-V privileged specification r=Disasm a=luojia65

This patch contains following parts: 

1. RISC-V privileged specification v1.10 defined `TVM`, `TW` and `TSR` bits in `mstatus`, implement them in Rust.
2. Make `scause`, `stval`, `ucause` and `utval` writable. 
3. Add some comments for instructions when we need to update this crate into privileged version v1.12.

For part 2, these registers are defined read-write in specification, and are typically read in supervisor S-level. However in M-level there are some situations we should write values into them. This feature is used when M-level environment are transfering exception to S-level kernel.

Function `scause::set` contains somehow lots of code here, we need to write a `Trap` struct into it, but I don't know which way is the best to implement this function.

Co-authored-by: luojia65 <me@luojia.cc>
bors[bot] il y a 4 ans
Parent
commit
197386eb92

+ 1 - 1
.travis.yml

@@ -23,7 +23,7 @@ matrix:
       language: bash
       if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
 
-    - env: RUSTFMT=1
+    - env: CHECK_RUSTFMT=1
       rust: stable
       if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
 

+ 1 - 1
ci/install.sh

@@ -13,6 +13,6 @@ if [ -n "${CHECK_BLOBS:-}" ]; then
     fi
 fi
 
-if [ -n "${RUSTFMT:-}" ]; then
+if [ -n "${CHECK_RUSTFMT:-}" ]; then
     rustup component add rustfmt
 fi

+ 1 - 1
ci/script.sh

@@ -15,6 +15,6 @@ if [ -n "${CHECK_BLOBS:-}" ]; then
     ./check-blobs.sh
 fi
 
-if [ -n "${RUSTFMT:-}" ]; then
+if [ -n "${CHECK_RUSTFMT:-}" ]; then
     cargo fmt -- --check
 fi

+ 1 - 0
src/register/cycle.rs

@@ -1,4 +1,5 @@
 //! cycle register
+//!
 //! Shadow of mcycle register
 //! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/cycleh.rs

@@ -1,4 +1,5 @@
 //! cycleh register
+//!
 //! Shadow of mcycleh register (rv32)
 //! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/instret.rs

@@ -1,4 +1,5 @@
 //! instret register
+//!
 //! Shadow of minstret register
 //! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/instreth.rs

@@ -1,4 +1,5 @@
 //! instreth register
+//!
 //! Shadow of minstreth register (rv32)
 //! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
 //! S-mode is implemented or not

+ 75 - 6
src/register/mstatus.rs

@@ -1,5 +1,11 @@
 //! mstatus register
-// TODO: Virtualization, Memory Privilege and Extension Context Fields
+
+// FIXME: in 1.12 spec there will be `SBE` and `MBE` bits.
+// They allows to execute supervisor in given big endian,
+// they would be in a new register `mstatush` in RV32; we should implement `mstatush`
+// at that time.
+// FIXME: `SXL` and `UXL` bits require a structure interpreting XLEN,
+// which would be the best way we implement this using Rust?
 
 use bit_field::BitField;
 use core::mem::size_of;
@@ -136,6 +142,59 @@ impl Mstatus {
         }
     }
 
+    /// Permit Supervisor User Memory access
+    #[inline]
+    pub fn sum(&self) -> bool {
+        self.bits.get_bit(18)
+    }
+
+    /// Make eXecutable Readable
+    #[inline]
+    pub fn mxr(&self) -> bool {
+        self.bits.get_bit(19)
+    }
+
+    /// Trap Virtual Memory
+    ///
+    /// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma`
+    /// instruction when in S-mode will raise an illegal instruction exception.
+    ///
+    /// TVM is hard-wired to 0 when S-mode is not supported.
+    #[inline]
+    pub fn tvm(&self) -> bool {
+        self.bits.get_bit(20)
+    }
+
+    /// Timeout Wait
+    ///
+    /// Indicates that if WFI instruction should be intercepted.
+    ///
+    /// If this bit is set, when WFI is executed in S-mode, and it does not complete
+    /// within an implementation specific, bounded time limit, the WFI instruction will cause
+    /// an illegal instruction trap; or could always cause trap then the time limit is zero.
+    ///
+    /// TW is hard-wired to 0 when S-mode is not supported.
+    #[inline]
+    pub fn tw(&self) -> bool {
+        self.bits.get_bit(21)
+    }
+
+    /// Trap SRET
+    ///
+    /// Indicates that if SRET instruction should be trapped to raise illegal
+    /// instruction exception.
+    ///
+    /// If S-mode is not supported, TSR bit is hard-wired to 0.
+    #[inline]
+    pub fn tsr(&self) -> bool {
+        self.bits.get_bit(22)
+    }
+
+    /*
+        FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12
+        is ratified, there should be read functions of these bits as well.
+    */
+
     /// Whether either the FS field or XS field
     /// signals the presence of some dirty state
     #[inline]
@@ -152,26 +211,36 @@ clear!(0x300, __clear_mstatus);
 set_clear_csr!(
     /// User Interrupt Enable
     , set_uie, clear_uie, 1 << 0);
-
 set_clear_csr!(
     /// Supervisor Interrupt Enable
     , set_sie, clear_sie, 1 << 1);
-
 set_clear_csr!(
     /// Machine Interrupt Enable
     , set_mie, clear_mie, 1 << 3);
-
 set_csr!(
     /// User Previous Interrupt Enable
     , set_upie, 1 << 4);
-
 set_csr!(
     /// Supervisor Previous Interrupt Enable
     , set_spie, 1 << 5);
-
 set_csr!(
     /// Machine Previous Interrupt Enable
     , set_mpie, 1 << 7);
+set_clear_csr!(
+    /// Permit Supervisor User Memory access
+    , set_sum, clear_sum, 1 << 18);
+set_clear_csr!(
+    /// Make eXecutable Readable
+    , set_mxr, clear_mxr, 1 << 19);
+set_clear_csr!(
+    /// Trap Virtual Memory
+    , set_tvm, clear_tvm, 1 << 20);
+set_clear_csr!(
+    /// Timeout Wait
+    , set_tw, clear_tw, 1 << 21);
+set_clear_csr!(
+    /// Trap SRET
+    , set_tsr, clear_tsr, 1 << 22);
 
 /// Supervisor Previous Privilege Mode
 #[inline]

+ 38 - 0
src/register/scause.rs

@@ -115,3 +115,41 @@ impl Scause {
 }
 
 read_csr_as!(Scause, 0x142, __read_scause);
+write_csr!(0x142, __write_scause);
+
+/// Writes the CSR
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}
+
+/// Set supervisor cause register to corresponding cause.
+pub unsafe fn set(cause: Trap) {
+    let bits = match cause {
+        Trap::Interrupt(i) => match i {
+            Interrupt::UserSoft => 0,
+            Interrupt::SupervisorSoft => 1,
+            Interrupt::UserTimer => 4,
+            Interrupt::SupervisorTimer => 5,
+            Interrupt::UserExternal => 8,
+            Interrupt::SupervisorExternal => 9,
+            Interrupt::Unknown => panic!("unknown interrupt"),
+        },
+        Trap::Exception(e) => {
+            (match e {
+                Exception::InstructionMisaligned => 0,
+                Exception::InstructionFault => 1,
+                Exception::IllegalInstruction => 2,
+                Exception::Breakpoint => 3,
+                Exception::LoadFault => 5,
+                Exception::StoreMisaligned => 6,
+                Exception::StoreFault => 7,
+                Exception::UserEnvCall => 8,
+                Exception::InstructionPageFault => 12,
+                Exception::LoadPageFault => 13,
+                Exception::StorePageFault => 15,
+                Exception::Unknown => panic!("unknown exception"),
+            } | (1 << (size_of::<usize>() * 8 - 1)))
+        }
+    };
+    _write(bits);
+}

+ 3 - 5
src/register/sstatus.rs

@@ -113,16 +113,15 @@ set_csr!(
 set_csr!(
     /// Supervisor Previous Interrupt Enable
     , set_spie, 1 << 5);
-set_clear_csr!(
-    /// Make eXecutable Readable
-    , set_mxr, clear_mxr, 1 << 19);
 set_clear_csr!(
     /// Permit Supervisor User Memory access
     , set_sum, clear_sum, 1 << 18);
+set_clear_csr!(
+    /// Make eXecutable Readable
+    , set_mxr, clear_mxr, 1 << 19);
 
 /// Supervisor Previous Privilege Mode
 #[inline]
-#[cfg(riscv)]
 pub unsafe fn set_spp(spp: SPP) {
     match spp {
         SPP::Supervisor => _set(1 << 8),
@@ -132,7 +131,6 @@ pub unsafe fn set_spp(spp: SPP) {
 
 /// The status of the floating-point unit
 #[inline]
-#[cfg(riscv)]
 pub unsafe fn set_fs(fs: FS) {
     let mut value = _read();
     value.set_bits(13..15, fs as usize);

+ 6 - 0
src/register/stval.rs

@@ -1,3 +1,9 @@
 //! stval register
 
 read_csr_as_usize!(0x143, __read_stval);
+write_csr!(0x143, __write_stval);
+
+/// Writes the CSR
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}

+ 6 - 0
src/register/ucause.rs

@@ -15,3 +15,9 @@ impl Ucause {
 }
 
 read_csr_as!(Ucause, 0x042, __read_ucause);
+write_csr!(0x042, __write_ucause);
+
+/// Writes the CSR
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}

+ 6 - 0
src/register/utval.rs

@@ -1,3 +1,9 @@
 //! utval register
 
 read_csr_as_usize!(0x043, __read_utval);
+write_csr!(0x043, __write_utval);
+
+/// Writes the CSR
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}