Skip to content

Commit a008b8b

Browse files
committed
temp
1 parent 644b894 commit a008b8b

File tree

2 files changed

+354
-245
lines changed

2 files changed

+354
-245
lines changed

rustsbi-qemu/src/execute/mod.rs

Lines changed: 202 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,225 @@
1-
use crate::{
2-
hart_id,
3-
qemu_hsm::{EID_HSM, FID_HART_STOP, FID_HART_SUSPEND, SUSPEND_NON_RETENTIVE},
4-
Supervisor,
5-
};
6-
use core::{
7-
ops::{Generator, GeneratorState},
8-
pin::Pin,
9-
};
10-
use riscv::register::{
11-
mcause,
12-
scause::{Exception, Interrupt, Trap},
13-
};
1+
use crate::{clint, hart_id, Supervisor};
142

15-
mod feature;
16-
mod prv_mem;
17-
mod runtime;
18-
19-
use prv_mem::SupervisorPointer;
20-
use runtime::{MachineTrap, Runtime, SupervisorContext};
3+
#[repr(C)]
4+
#[derive(Default)]
5+
struct Context {
6+
msp: usize,
7+
x: [usize; 31],
8+
mstatus: usize,
9+
mepc: usize,
10+
}
2111

2212
pub(crate) fn execute_supervisor(supervisor: Supervisor) {
23-
let mut rt = Runtime::new(supervisor);
13+
use core::arch::asm;
14+
use riscv::register::{medeleg, mie, mstatus};
15+
16+
unsafe {
17+
mstatus::set_mpp(mstatus::MPP::Supervisor);
18+
mstatus::set_mie();
19+
};
20+
21+
let mut ctx = Context {
22+
msp: 0,
23+
x: [0; 31],
24+
mstatus: 0,
25+
mepc: supervisor.start_addr,
26+
};
27+
28+
*ctx.a_mut(0) = hart_id();
29+
*ctx.a_mut(1) = supervisor.opaque;
30+
31+
clint::get().clear_soft(hart_id());
32+
unsafe {
33+
asm!("csrr {}, mstatus", out(reg) ctx.mstatus);
34+
asm!("csrw mip, {}", in(reg) 0);
35+
asm!("csrw mideleg, {}", in(reg) usize::MAX);
36+
asm!("csrw medeleg, {}", in(reg) usize::MAX);
37+
mstatus::clear_mie();
38+
medeleg::clear_illegal_instruction();
39+
medeleg::clear_supervisor_env_call();
40+
medeleg::clear_machine_env_call();
41+
42+
crate::set_mtcev(s_to_m as usize);
43+
mie::set_mext();
44+
mie::set_msoft();
45+
}
46+
2447
loop {
25-
match Pin::new(&mut rt).resume(()) {
26-
GeneratorState::Yielded(MachineTrap::SbiCall()) => {
27-
let ctx = rt.context_mut();
28-
let param = [ctx.a0, ctx.a1, ctx.a2, ctx.a3, ctx.a4, ctx.a5];
29-
let ans = rustsbi::ecall(ctx.a7, ctx.a6, param);
30-
if ctx.a7 == EID_HSM && ans.error == 0 {
31-
if ctx.a6 == FID_HART_STOP {
48+
use crate::qemu_hsm::{EID_HSM, FID_HART_STOP, FID_HART_SUSPEND, SUSPEND_NON_RETENTIVE};
49+
use riscv::register::mcause::{self, Exception as E, Trap as T};
50+
51+
unsafe { m_to_s(&mut ctx) };
52+
53+
match mcause::read().cause() {
54+
T::Exception(E::SupervisorEnvCall) => {
55+
let param = [ctx.a(0), ctx.a(1), ctx.a(2), ctx.a(3), ctx.a(4), ctx.a(5)];
56+
let ans = rustsbi::ecall(ctx.a(7), ctx.a(6), param);
57+
if ctx.a(7) == EID_HSM && ans.error == 0 {
58+
if ctx.a(6) == FID_HART_STOP {
3259
return;
3360
}
34-
if ctx.a6 == FID_HART_SUSPEND && ctx.a0 == SUSPEND_NON_RETENTIVE as usize {
61+
if ctx.a(6) == FID_HART_SUSPEND && ctx.a(0) == SUSPEND_NON_RETENTIVE as usize {
3562
return;
3663
}
3764
}
38-
ctx.a0 = ans.error;
39-
ctx.a1 = ans.value;
65+
*ctx.a_mut(0) = ans.error;
66+
*ctx.a_mut(1) = ans.value;
4067
ctx.mepc = ctx.mepc.wrapping_add(4);
4168
}
42-
GeneratorState::Yielded(MachineTrap::IllegalInstruction()) => {
43-
let ctx = rt.context_mut();
44-
let ptr: SupervisorPointer<usize> = SupervisorPointer::cast(ctx.mepc);
45-
let deref_ans = unsafe { prv_mem::try_read(ptr) };
46-
let ins = match deref_ans {
47-
Ok(ins) => ins,
48-
Err(e) => fail_cant_read_exception_address(ctx, e),
49-
};
50-
if !emulate_illegal_instruction(ctx, ins) {
51-
unsafe {
52-
if feature::should_transfer_trap(ctx) {
53-
feature::do_transfer_trap(
54-
ctx,
55-
Trap::Exception(Exception::IllegalInstruction),
56-
)
57-
} else {
58-
fail_illegal_instruction(ctx, ins)
59-
}
60-
}
69+
t => {
70+
println!("{t:?}");
71+
loop {
72+
core::hint::spin_loop();
6173
}
6274
}
63-
GeneratorState::Yielded(MachineTrap::MachineTimer()) => unsafe {
64-
use riscv::register::{mie, mip};
65-
mip::set_stimer();
66-
mie::clear_mtimer();
67-
},
68-
GeneratorState::Yielded(MachineTrap::MachineSoft()) => {
69-
// machine software interrupt but no HSM commands - delegate to S mode;
70-
let ctx = rt.context_mut();
71-
crate::clint::get().clear_soft(hart_id()); // Clear IPI
72-
unsafe {
73-
if feature::should_transfer_trap(ctx) {
74-
feature::do_transfer_trap(ctx, Trap::Interrupt(Interrupt::SupervisorSoft));
75-
} else {
76-
println!("rustsbi-qemu: machine soft interrupt with no hart state monitor command");
77-
}
78-
}
79-
}
80-
GeneratorState::Complete(()) => {
81-
use rustsbi::{
82-
reset::{RESET_REASON_NO_REASON, RESET_TYPE_SHUTDOWN},
83-
Reset,
84-
};
85-
crate::test_device::get().system_reset(RESET_TYPE_SHUTDOWN, RESET_REASON_NO_REASON);
86-
}
8775
}
8876
}
8977
}
9078

91-
#[inline]
92-
fn emulate_illegal_instruction(ctx: &mut SupervisorContext, ins: usize) -> bool {
93-
if feature::emulate_rdtime(ctx, ins) {
94-
return true;
79+
impl Context {
80+
#[inline]
81+
fn a(&self, n: usize) -> usize {
82+
self.x[9 + n]
83+
}
84+
85+
#[inline]
86+
fn a_mut(&mut self, n: usize) -> &mut usize {
87+
&mut self.x[9 + n]
9588
}
96-
false
9789
}
9890

99-
// Illegal instruction occurred in M level
100-
fn fail_illegal_instruction(ctx: &mut SupervisorContext, ins: usize) -> ! {
101-
#[cfg(target_pointer_width = "64")]
102-
panic!("invalid instruction from machine level, mepc: {:016x?}, instruction: {:016x?}, context: {:016x?}", ctx.mepc, ins, ctx);
103-
#[cfg(target_pointer_width = "32")]
104-
panic!("invalid instruction from machine level, mepc: {:08x?}, instruction: {:08x?}, context: {:08x?}", ctx.mepc, ins, ctx);
91+
/// M 态转到 S 态。
92+
///
93+
/// # Safety
94+
///
95+
/// 裸函数,手动保存所有上下文环境。
96+
/// 为了写起来简单,占 32 * usize 空间,循环 31 次保存 31 个通用寄存器。
97+
/// 实际 x0(zero) 和 x2(sp) 不需要保存在这里。
98+
#[naked]
99+
unsafe extern "C" fn m_to_s(ctx: &mut Context) {
100+
core::arch::asm!(
101+
r"
102+
.altmacro
103+
.macro SAVE_M n
104+
sd x\n, \n*8(sp)
105+
.endm
106+
.macro LOAD_S n
107+
ld x\n, \n*8(sp)
108+
.endm
109+
",
110+
// 入栈
111+
"
112+
addi sp, sp, -32*8
113+
",
114+
// 保存 x[1..31]
115+
"
116+
.set n, 1
117+
.rept 31
118+
SAVE_M %n
119+
.set n, n+1
120+
.endr
121+
",
122+
// M sp 保存到 S ctx
123+
"
124+
sd sp, 0(a0)
125+
mv sp, a0
126+
",
127+
// 利用 tx 恢复 csr
128+
// S ctx.x[2](sp) => mscratch
129+
// S ctx.mstatus => mstatus
130+
// S ctx.mepc => mepc
131+
"
132+
ld t0, 2*8(sp)
133+
ld t1, 32*8(sp)
134+
ld t2, 33*8(sp)
135+
csrw mscratch, t0
136+
csrw mstatus, t1
137+
csrw mepc, t2
138+
",
139+
// 从 S ctx 恢复 x[1,3..32]
140+
"
141+
ld x1, 1*8(sp)
142+
.set n, 3
143+
.rept 29
144+
LOAD_S %n
145+
.set n, n+1
146+
.endr
147+
",
148+
// 换栈:
149+
// sp : S sp
150+
// mscratch: S ctx
151+
"
152+
csrrw sp, mscratch, sp
153+
mret
154+
",
155+
options(noreturn)
156+
)
105157
}
106158

107-
fn fail_cant_read_exception_address(ctx: &mut SupervisorContext, cause: mcause::Exception) -> ! {
108-
#[cfg(target_pointer_width = "64")]
109-
panic!(
110-
"can't read exception address, cause: {:?}, mepc: {:016x?}, context: {:016x?}",
111-
cause, ctx.mepc, ctx
112-
);
113-
#[cfg(target_pointer_width = "32")]
114-
panic!(
115-
"can't read exception address, cause: {:?}, mepc: {:08x?}, context: {:08x?}",
116-
cause, ctx.mepc, ctx
117-
);
159+
/// S 态陷入 M 态。
160+
///
161+
/// # Safety
162+
///
163+
/// 裸函数。
164+
/// 利用恢复的 ra 回到 [`m_to_s`] 的返回地址。
165+
#[naked]
166+
#[link_section = ".text.trap_handler"]
167+
unsafe extern "C" fn s_to_m() {
168+
core::arch::asm!(
169+
r"
170+
.altmacro
171+
.macro SAVE_S n
172+
sd x\n, \n*8(sp)
173+
.endm
174+
.macro LOAD_M n
175+
ld x\n, \n*8(sp)
176+
.endm
177+
",
178+
// 换栈:
179+
// sp : S ctx
180+
// mscratch: S sp
181+
"
182+
csrrw sp, mscratch, sp
183+
",
184+
// 保存 x[1,3..32] 到 S ctx
185+
"
186+
sd x1, 1*8(sp)
187+
.set n, 3
188+
.rept 29
189+
SAVE_S %n
190+
.set n, n+1
191+
.endr
192+
",
193+
// 利用 tx 保存 csr
194+
// mscratch => S ctx.x[2](sp)
195+
// mstatus => S ctx.mstatus
196+
// mepc => S ctx.mepc
197+
"
198+
csrr t0, mscratch
199+
csrr t1, mstatus
200+
csrr t2, mepc
201+
sd t0, 2*8(sp)
202+
sd t1, 32*8(sp)
203+
sd t2, 33*8(sp)
204+
",
205+
// 从 S ctx 恢复 M sp
206+
"
207+
ld sp, 0(sp)
208+
",
209+
// 恢复 s[0..12]
210+
"
211+
.set n, 1
212+
.rept 31
213+
LOAD_M %n
214+
.set n, n+1
215+
.endr
216+
",
217+
// 出栈完成,栈指针归位
218+
// 返回
219+
"
220+
addi sp, sp, 32*8
221+
ret
222+
",
223+
options(noreturn)
224+
)
118225
}

0 commit comments

Comments
 (0)