Skip to content

Commit ff79ee0

Browse files
committed
feat(sbi): 处理 mtimer 和非法指令
1 parent f2133fd commit ff79ee0

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed

rustsbi-qemu/src/execute/mod.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,31 @@ struct Context {
99
mepc: usize,
1010
}
1111

12+
impl Context {
13+
#[inline]
14+
fn a(&self, n: usize) -> usize {
15+
self.x[n + 9]
16+
}
17+
18+
#[inline]
19+
fn a_mut(&mut self, n: usize) -> &mut usize {
20+
&mut self.x[n + 9]
21+
}
22+
23+
#[inline]
24+
fn x(&self, n: usize) -> usize {
25+
self.x[n - 1]
26+
}
27+
28+
#[inline]
29+
fn x_mut(&mut self, n: usize) -> &mut usize {
30+
&mut self.x[n - 1]
31+
}
32+
}
33+
1234
pub(crate) fn execute_supervisor(supervisor: Supervisor) {
1335
use core::arch::asm;
14-
use riscv::register::{medeleg, mie, mip, mstatus};
36+
use riscv::register::{medeleg, mie, mstatus};
1537

1638
unsafe {
1739
mstatus::set_mpp(mstatus::MPP::Supervisor);
@@ -67,11 +89,51 @@ pub(crate) fn execute_supervisor(supervisor: Supervisor) {
6789
ctx.mepc = ctx.mepc.wrapping_add(4);
6890
}
6991
T::Interrupt(I::MachineTimer) => unsafe {
92+
use riscv::register::mip;
7093
mip::clear_mtimer();
7194
mip::set_stimer();
7295
},
7396
T::Exception(E::IllegalInstruction) => {
74-
println!("TODO emulate or forward illegal instruction");
97+
use riscv::register::mtval;
98+
99+
const OPCODE_MASK: usize = (1 << 7) - 1;
100+
const REG_MASK: usize = (1 << 5) - 1;
101+
const OPCODE_CSR: usize = 0b1110011;
102+
const CSR_TIME: usize = 0xc01;
103+
let instruction = mtval::read();
104+
// 标准 20191213 的表 24.3 列出了一些特殊的 CSR,SBI 软件负责将它们模拟出来
105+
if let OPCODE_CSR = instruction & OPCODE_MASK {
106+
if instruction >> 20 == CSR_TIME {
107+
match (instruction >> 7) & REG_MASK {
108+
0 => {}
109+
rd => *ctx.x_mut(rd) = crate::clint::get().get_mtime() as _,
110+
}
111+
continue;
112+
}
113+
}
114+
// 如果不是可修正的指令,且不是 M 态本身发出的,转交给 S 态处理
115+
// mpp != machine
116+
if (ctx.mstatus >> 11) & 0b11 != 0b11 {
117+
use riscv::register::{
118+
scause::{self, Exception, Trap},
119+
sepc, stval, stvec,
120+
};
121+
unsafe {
122+
scause::set(Trap::Exception(Exception::IllegalInstruction));
123+
stval::write(instruction);
124+
sepc::write(ctx.mepc);
125+
mstatus::set_mpp(mstatus::MPP::Supervisor);
126+
mstatus::set_spp(mstatus::SPP::Supervisor);
127+
if mstatus::read().sie() {
128+
mstatus::set_spie()
129+
}
130+
mstatus::clear_sie();
131+
core::arch::asm!("csrr {}, mstatus", out(reg) ctx.mstatus);
132+
ctx.mepc = stvec::read().address();
133+
}
134+
continue;
135+
}
136+
println!("{:?}", E::IllegalInstruction);
75137
break;
76138
}
77139
t => {
@@ -85,18 +147,6 @@ pub(crate) fn execute_supervisor(supervisor: Supervisor) {
85147
}
86148
}
87149

88-
impl Context {
89-
#[inline]
90-
fn a(&self, n: usize) -> usize {
91-
self.x[9 + n]
92-
}
93-
94-
#[inline]
95-
fn a_mut(&mut self, n: usize) -> &mut usize {
96-
&mut self.x[9 + n]
97-
}
98-
}
99-
100150
/// M 态转到 S 态。
101151
///
102152
/// # Safety

test-kernel/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ extern "C" fn primary_rust_main(hartid: usize, dtb_pa: usize) -> ! {
109109
test::base_extension();
110110
test::sbi_ins_emulation();
111111

112-
// unsafe { stvec::write(start_trap as usize, TrapMode::Direct) };
113-
// test::trap_delegate(hartid);
112+
unsafe { stvec::write(start_trap as usize, TrapMode::Direct) };
113+
test::trap_delegate(hartid);
114114

115115
println!();
116116
STARTED.fetch_add(1, Ordering::SeqCst);

0 commit comments

Comments
 (0)