Skip to content

Commit 197386e

Browse files
bors[bot]luojia65
andauthored
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>
2 parents 4145e4a + 14991c3 commit 197386e

File tree

13 files changed

+141
-14
lines changed

13 files changed

+141
-14
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ matrix:
2323
language: bash
2424
if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
2525

26-
- env: RUSTFMT=1
26+
- env: CHECK_RUSTFMT=1
2727
rust: stable
2828
if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
2929

ci/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ if [ -n "${CHECK_BLOBS:-}" ]; then
1313
fi
1414
fi
1515

16-
if [ -n "${RUSTFMT:-}" ]; then
16+
if [ -n "${CHECK_RUSTFMT:-}" ]; then
1717
rustup component add rustfmt
1818
fi

ci/script.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ if [ -n "${CHECK_BLOBS:-}" ]; then
1515
./check-blobs.sh
1616
fi
1717

18-
if [ -n "${RUSTFMT:-}" ]; then
18+
if [ -n "${CHECK_RUSTFMT:-}" ]; then
1919
cargo fmt -- --check
2020
fi

src/register/cycle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! cycle register
2+
//!
23
//! Shadow of mcycle register
34
//! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
45
//! S-mode is implemented or not

src/register/cycleh.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! cycleh register
2+
//!
23
//! Shadow of mcycleh register (rv32)
34
//! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
45
//! S-mode is implemented or not

src/register/instret.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! instret register
2+
//!
23
//! Shadow of minstret register
34
//! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
45
//! S-mode is implemented or not

src/register/instreth.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! instreth register
2+
//!
23
//! Shadow of minstreth register (rv32)
34
//! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
45
//! S-mode is implemented or not

src/register/mstatus.rs

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
//! mstatus register
2-
// TODO: Virtualization, Memory Privilege and Extension Context Fields
2+
3+
// FIXME: in 1.12 spec there will be `SBE` and `MBE` bits.
4+
// They allows to execute supervisor in given big endian,
5+
// they would be in a new register `mstatush` in RV32; we should implement `mstatush`
6+
// at that time.
7+
// FIXME: `SXL` and `UXL` bits require a structure interpreting XLEN,
8+
// which would be the best way we implement this using Rust?
39

410
use bit_field::BitField;
511
use core::mem::size_of;
@@ -136,6 +142,59 @@ impl Mstatus {
136142
}
137143
}
138144

145+
/// Permit Supervisor User Memory access
146+
#[inline]
147+
pub fn sum(&self) -> bool {
148+
self.bits.get_bit(18)
149+
}
150+
151+
/// Make eXecutable Readable
152+
#[inline]
153+
pub fn mxr(&self) -> bool {
154+
self.bits.get_bit(19)
155+
}
156+
157+
/// Trap Virtual Memory
158+
///
159+
/// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma`
160+
/// instruction when in S-mode will raise an illegal instruction exception.
161+
///
162+
/// TVM is hard-wired to 0 when S-mode is not supported.
163+
#[inline]
164+
pub fn tvm(&self) -> bool {
165+
self.bits.get_bit(20)
166+
}
167+
168+
/// Timeout Wait
169+
///
170+
/// Indicates that if WFI instruction should be intercepted.
171+
///
172+
/// If this bit is set, when WFI is executed in S-mode, and it does not complete
173+
/// within an implementation specific, bounded time limit, the WFI instruction will cause
174+
/// an illegal instruction trap; or could always cause trap then the time limit is zero.
175+
///
176+
/// TW is hard-wired to 0 when S-mode is not supported.
177+
#[inline]
178+
pub fn tw(&self) -> bool {
179+
self.bits.get_bit(21)
180+
}
181+
182+
/// Trap SRET
183+
///
184+
/// Indicates that if SRET instruction should be trapped to raise illegal
185+
/// instruction exception.
186+
///
187+
/// If S-mode is not supported, TSR bit is hard-wired to 0.
188+
#[inline]
189+
pub fn tsr(&self) -> bool {
190+
self.bits.get_bit(22)
191+
}
192+
193+
/*
194+
FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12
195+
is ratified, there should be read functions of these bits as well.
196+
*/
197+
139198
/// Whether either the FS field or XS field
140199
/// signals the presence of some dirty state
141200
#[inline]
@@ -152,26 +211,36 @@ clear!(0x300, __clear_mstatus);
152211
set_clear_csr!(
153212
/// User Interrupt Enable
154213
, set_uie, clear_uie, 1 << 0);
155-
156214
set_clear_csr!(
157215
/// Supervisor Interrupt Enable
158216
, set_sie, clear_sie, 1 << 1);
159-
160217
set_clear_csr!(
161218
/// Machine Interrupt Enable
162219
, set_mie, clear_mie, 1 << 3);
163-
164220
set_csr!(
165221
/// User Previous Interrupt Enable
166222
, set_upie, 1 << 4);
167-
168223
set_csr!(
169224
/// Supervisor Previous Interrupt Enable
170225
, set_spie, 1 << 5);
171-
172226
set_csr!(
173227
/// Machine Previous Interrupt Enable
174228
, set_mpie, 1 << 7);
229+
set_clear_csr!(
230+
/// Permit Supervisor User Memory access
231+
, set_sum, clear_sum, 1 << 18);
232+
set_clear_csr!(
233+
/// Make eXecutable Readable
234+
, set_mxr, clear_mxr, 1 << 19);
235+
set_clear_csr!(
236+
/// Trap Virtual Memory
237+
, set_tvm, clear_tvm, 1 << 20);
238+
set_clear_csr!(
239+
/// Timeout Wait
240+
, set_tw, clear_tw, 1 << 21);
241+
set_clear_csr!(
242+
/// Trap SRET
243+
, set_tsr, clear_tsr, 1 << 22);
175244

176245
/// Supervisor Previous Privilege Mode
177246
#[inline]

src/register/scause.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,41 @@ impl Scause {
115115
}
116116

117117
read_csr_as!(Scause, 0x142, __read_scause);
118+
write_csr!(0x142, __write_scause);
119+
120+
/// Writes the CSR
121+
pub unsafe fn write(bits: usize) {
122+
_write(bits)
123+
}
124+
125+
/// Set supervisor cause register to corresponding cause.
126+
pub unsafe fn set(cause: Trap) {
127+
let bits = match cause {
128+
Trap::Interrupt(i) => match i {
129+
Interrupt::UserSoft => 0,
130+
Interrupt::SupervisorSoft => 1,
131+
Interrupt::UserTimer => 4,
132+
Interrupt::SupervisorTimer => 5,
133+
Interrupt::UserExternal => 8,
134+
Interrupt::SupervisorExternal => 9,
135+
Interrupt::Unknown => panic!("unknown interrupt"),
136+
},
137+
Trap::Exception(e) => {
138+
(match e {
139+
Exception::InstructionMisaligned => 0,
140+
Exception::InstructionFault => 1,
141+
Exception::IllegalInstruction => 2,
142+
Exception::Breakpoint => 3,
143+
Exception::LoadFault => 5,
144+
Exception::StoreMisaligned => 6,
145+
Exception::StoreFault => 7,
146+
Exception::UserEnvCall => 8,
147+
Exception::InstructionPageFault => 12,
148+
Exception::LoadPageFault => 13,
149+
Exception::StorePageFault => 15,
150+
Exception::Unknown => panic!("unknown exception"),
151+
} | (1 << (size_of::<usize>() * 8 - 1)))
152+
}
153+
};
154+
_write(bits);
155+
}

src/register/sstatus.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,15 @@ set_csr!(
113113
set_csr!(
114114
/// Supervisor Previous Interrupt Enable
115115
, set_spie, 1 << 5);
116-
set_clear_csr!(
117-
/// Make eXecutable Readable
118-
, set_mxr, clear_mxr, 1 << 19);
119116
set_clear_csr!(
120117
/// Permit Supervisor User Memory access
121118
, set_sum, clear_sum, 1 << 18);
119+
set_clear_csr!(
120+
/// Make eXecutable Readable
121+
, set_mxr, clear_mxr, 1 << 19);
122122

123123
/// Supervisor Previous Privilege Mode
124124
#[inline]
125-
#[cfg(riscv)]
126125
pub unsafe fn set_spp(spp: SPP) {
127126
match spp {
128127
SPP::Supervisor => _set(1 << 8),
@@ -132,7 +131,6 @@ pub unsafe fn set_spp(spp: SPP) {
132131

133132
/// The status of the floating-point unit
134133
#[inline]
135-
#[cfg(riscv)]
136134
pub unsafe fn set_fs(fs: FS) {
137135
let mut value = _read();
138136
value.set_bits(13..15, fs as usize);

0 commit comments

Comments
 (0)