Skip to content

Commit 8bffbd7

Browse files
bors[bot]wangrunji0408Disasm
committed
Merge #12 #14
12: Add some S-Mode CSRs r=dvc94ch a=wangrunji0408 Add these S-Mode CSRs: - `sstatus` - `stvec` - `sie` - `sip` - `scause` - `stval` - `sscratch` - `sepc` - `satp` as well as: - `time` - `timeh` and S-Mode instructions: - `sfence.vma` Most of the code have been tested in the [RustOS](https://github.com/wangrunji0408/RustOS) project. 14: Remove ecall and *ret instructions from riscv::asm r=dvc94ch a=Disasm * *ret instructions should not be used directly in Rust code, they should be used in handlers, written in asm ([example](https://github.com/rust-embedded/riscv-rt/blob/273f0d4f70418a7602678632dcc78dbe24208fe2/src/lib.rs#L294-L340)). * ecall instruction should be wrapped into something like syscall(), which should be declared in another platform-specific crate. Co-authored-by: WangRunji <[email protected]> Co-authored-by: Vadim Kaushan <[email protected]>
3 parents ca737e7 + 8776d30 + 9550fe0 commit 8bffbd7

File tree

16 files changed

+723
-4
lines changed

16 files changed

+723
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ license = "ISC"
1010

1111
[dependencies]
1212
bare-metal = "0.2.0"
13+
bit_field = "0.9.0"
1314

1415
[features]
1516
inline-asm = []

src/asm.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@ macro_rules! instruction {
1616

1717

1818
/// Priviledged ISA Instructions
19-
instruction!(ecall, "ecall");
2019
instruction!(ebreak, "ebreak");
21-
instruction!(uret, "uret");
22-
instruction!(sret, "sret");
23-
instruction!(mret, "mret");
2420
instruction!(wfi, "wfi");
21+
instruction!(sfence_vma_all, "sfence.vma");
22+
23+
24+
#[inline]
25+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
26+
pub unsafe fn sfence_vma(asid: usize, addr: usize) {
27+
asm!("sfence.vma $0, $1" :: "r"(asid), "r"(addr) :: "volatile");
28+
}
29+
30+
#[inline]
31+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
32+
pub fn sfence_vma(_asid: usize, _addr: usize) {}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#![feature(const_fn)]
1313

1414
extern crate bare_metal;
15+
extern crate bit_field;
1516

1617
pub mod asm;
1718
pub mod interrupt;

src/register/macros.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
macro_rules! read_csr {
2+
($csr_number:expr) => {
3+
/// Reads the CSR
4+
#[inline]
5+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
6+
unsafe fn _read() -> usize {
7+
let r: usize;
8+
asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
9+
r
10+
}
11+
12+
#[inline]
13+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
14+
unsafe fn _read() -> usize {
15+
unimplemented!()
16+
}
17+
};
18+
}
19+
20+
macro_rules! read_csr_as {
21+
($register:ident, $csr_number:expr) => {
22+
read_csr!($csr_number);
23+
24+
/// Reads the CSR
25+
#[inline]
26+
pub fn read() -> $register {
27+
$register { bits: unsafe{ _read() } }
28+
}
29+
};
30+
}
31+
macro_rules! read_csr_as_usize {
32+
($csr_number:expr) => {
33+
read_csr!($csr_number);
34+
35+
/// Reads the CSR
36+
#[inline]
37+
pub fn read() -> usize {
38+
unsafe{ _read() }
39+
}
40+
};
41+
}
42+
43+
macro_rules! write_csr {
44+
($csr_number:expr) => {
45+
/// Writes the CSR
46+
#[inline]
47+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
48+
unsafe fn _write(bits: usize) {
49+
asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
50+
}
51+
52+
#[inline]
53+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
54+
unsafe fn _write(_bits: usize) {
55+
unimplemented!()
56+
}
57+
};
58+
}
59+
60+
macro_rules! write_csr_as_usize {
61+
($csr_number:expr) => {
62+
write_csr!($csr_number);
63+
64+
/// Writes the CSR
65+
#[inline]
66+
pub fn write(bits: usize) {
67+
unsafe{ _write(bits) }
68+
}
69+
};
70+
}
71+
72+
macro_rules! set {
73+
($csr_number:expr) => {
74+
/// Set the CSR
75+
#[inline]
76+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
77+
unsafe fn _set(bits: usize) {
78+
asm!("csrrs x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
79+
}
80+
81+
#[inline]
82+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
83+
unsafe fn _set(_bits: usize) {
84+
unimplemented!()
85+
}
86+
};
87+
}
88+
89+
macro_rules! clear {
90+
($csr_number:expr) => {
91+
/// Clear the CSR
92+
#[inline]
93+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
94+
unsafe fn _clear(bits: usize) {
95+
asm!("csrrc x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
96+
}
97+
98+
#[inline]
99+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
100+
unsafe fn _clear(_bits: usize) {
101+
unimplemented!()
102+
}
103+
};
104+
}
105+
106+
macro_rules! set_csr {
107+
($set_field:ident, $e:expr) => {
108+
#[inline]
109+
pub unsafe fn $set_field() {
110+
_set($e);
111+
}
112+
}
113+
}
114+
115+
macro_rules! clear_csr {
116+
($clear_field:ident, $e:expr) => {
117+
#[inline]
118+
pub unsafe fn $clear_field() {
119+
_clear($e);
120+
}
121+
}
122+
}
123+
124+
macro_rules! set_clear_csr {
125+
($set_field:ident, $clear_field:ident, $e:expr) => {
126+
set_csr!($set_field, $e);
127+
clear_csr!($clear_field, $e);
128+
}
129+
}

src/register/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
//! - minstreth
1111
//! - mhpmcounter[3-31]h
1212
13+
#[macro_use]
14+
mod macros;
15+
1316
pub mod mcause;
1417
pub mod mcycle;
1518
pub mod mcycleh;
@@ -22,3 +25,16 @@ pub mod misa;
2225
pub mod mstatus;
2326
pub mod mtvec;
2427
pub mod mvendorid;
28+
29+
pub mod sstatus;
30+
pub mod stvec;
31+
pub mod sie;
32+
pub mod sip;
33+
pub mod scause;
34+
pub mod stval;
35+
pub mod satp;
36+
pub mod sscratch;
37+
pub mod sepc;
38+
39+
pub mod time;
40+
pub mod timeh;

src/register/satp.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//! satp register
2+
3+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
4+
use bit_field::BitField;
5+
6+
/// satp register
7+
#[derive(Clone, Copy, Debug)]
8+
pub struct Satp {
9+
bits: usize,
10+
}
11+
12+
impl Satp {
13+
/// Returns the contents of the register as raw bits
14+
#[inline]
15+
pub fn bits(&self) -> usize {
16+
self.bits
17+
}
18+
19+
/// Current address-translation scheme
20+
#[inline]
21+
#[cfg(target_arch = "riscv32")]
22+
pub fn mode(&self) -> Mode {
23+
match self.bits.get_bit(31) {
24+
false => Mode::Bare,
25+
true => Mode::Sv32,
26+
}
27+
}
28+
29+
/// Current address-translation scheme
30+
#[inline]
31+
#[cfg(target_arch = "riscv64")]
32+
pub fn mode(&self) -> Mode {
33+
match self.bits.get_bits(60..64) {
34+
0 => Mode::Bare,
35+
8 => Mode::Sv39,
36+
9 => Mode::Sv48,
37+
10 => Mode::Sv57,
38+
11 => Mode::Sv64,
39+
_ => unreachable!(),
40+
}
41+
}
42+
43+
/// Address space identifier
44+
#[inline]
45+
#[cfg(target_arch = "riscv32")]
46+
pub fn asid(&self) -> usize {
47+
self.bits.get_bits(22..31)
48+
}
49+
50+
/// Address space identifier
51+
#[inline]
52+
#[cfg(target_arch = "riscv64")]
53+
pub fn asid(&self) -> usize {
54+
self.bits.get_bits(44..60)
55+
}
56+
57+
/// Physical page number
58+
#[inline]
59+
#[cfg(target_arch = "riscv32")]
60+
pub fn ppn(&self) -> usize {
61+
self.bits.get_bits(0..22)
62+
}
63+
64+
/// Physical page number
65+
#[inline]
66+
#[cfg(target_arch = "riscv64")]
67+
pub fn ppn(&self) -> usize {
68+
self.bits.get_bits(0..44)
69+
}
70+
}
71+
72+
#[cfg(target_arch = "riscv32")]
73+
pub enum Mode {
74+
Bare = 0,
75+
Sv32 = 1,
76+
}
77+
78+
#[cfg(target_arch = "riscv64")]
79+
pub enum Mode {
80+
Bare = 0,
81+
Sv39 = 8,
82+
Sv48 = 9,
83+
Sv57 = 10,
84+
Sv64 = 11,
85+
}
86+
87+
read_csr_as!(Satp, 0x180);
88+
write_csr!(0x180);
89+
90+
#[inline]
91+
#[cfg(target_arch = "riscv32")]
92+
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
93+
let mut bits = 0usize;
94+
bits.set_bits(31..32, mode as usize);
95+
bits.set_bits(22..31, asid);
96+
bits.set_bits(0..22, ppn);
97+
_write(bits);
98+
}
99+
100+
#[inline]
101+
#[cfg(target_arch = "riscv64")]
102+
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
103+
let mut bits = 0usize;
104+
bits.set_bits(60..64, mode as usize);
105+
bits.set_bits(44..60, asid);
106+
bits.set_bits(0..44, ppn);
107+
_write(bits);
108+
}

0 commit comments

Comments
 (0)