Skip to content

Commit 1533a8f

Browse files
committed
feat: 实现 hsm
Signed-off-by: YdrMaster <[email protected]>
1 parent cb3388b commit 1533a8f

File tree

3 files changed

+85
-280
lines changed

3 files changed

+85
-280
lines changed

hsm-cell/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ impl<T> LocalHsmCell<'_, T> {
6565
Ordering::Relaxed,
6666
) {
6767
Ok(_) => break Ok(unsafe { (*self.0.val.get()).take().unwrap() }),
68+
Err(HART_STATE_SUSPENDED) => {
69+
self.0.status.store(HART_STATE_STARTED, Ordering::Relaxed);
70+
break Ok(unsafe { (*self.0.val.get()).take().unwrap() });
71+
}
6872
Err(HART_STATE_START_PENDING_EXT) => spin_loop(),
6973
Err(s) => break Err(s),
7074
}
@@ -76,6 +80,25 @@ impl<T> LocalHsmCell<'_, T> {
7680
pub fn stop(&self) {
7781
self.0.status.store(HART_STATE_STOPPED, Ordering::Release)
7882
}
83+
84+
/// 关闭。
85+
#[inline]
86+
pub fn suspend_non_retentive(&self, t: T) {
87+
unsafe { *self.0.val.get() = Some(t) };
88+
self.0.status.store(HART_STATE_SUSPENDED, Ordering::Relaxed)
89+
}
90+
91+
/// 关闭。
92+
#[inline]
93+
pub fn suspend(&self) {
94+
self.0.status.store(HART_STATE_SUSPENDED, Ordering::Relaxed)
95+
}
96+
97+
/// 关闭。
98+
#[inline]
99+
pub fn resume(&self) {
100+
self.0.status.store(HART_STATE_STARTED, Ordering::Relaxed)
101+
}
79102
}
80103

81104
impl<T> RemoteHsmCell<'_, T> {

rustsbi-qemu/src/main.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ unsafe extern "C" fn _stop() -> ! {
8787
/// rust 入口。
8888
extern "C" fn rust_main(_hartid: usize, opaque: usize) {
8989
static GENESIS: AtomicBool = AtomicBool::new(true);
90+
static DONE: AtomicBool = AtomicBool::new(true);
9091
static BOARD_INFO: Once<BoardInfo> = Once::new();
9192

9293
// 全局初始化过程
@@ -134,6 +135,7 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
134135
rustsbi::Builder::new_machine()
135136
.with_ipi(&clint::Clint)
136137
.with_timer(&clint::Clint)
138+
.with_hsm(Hsm)
137139
.with_reset(qemu_test::get())
138140
.build(),
139141
);
@@ -154,11 +156,15 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
154156
opaque,
155157
});
156158
}
159+
DONE.store(false, Ordering::SeqCst);
157160
} else {
158161
// 设置 pmp
159162
set_pmp(BOARD_INFO.wait());
160163
// 设置陷入栈
161164
unsafe { ROOT_STACK[hart_id()].load_as_stack() };
165+
while DONE.load(Ordering::SeqCst) {
166+
core::hint::spin_loop();
167+
}
162168
}
163169
// 清理 clint
164170
clint::msip::clear();
@@ -171,9 +177,6 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
171177
asm!("csrw mcounteren, {}", in(reg) !0);
172178
medeleg::clear_supervisor_env_call();
173179
medeleg::clear_machine_env_call();
174-
mie::set_mext();
175-
mie::set_msoft();
176-
mie::set_mtimer();
177180
}
178181
}
179182

@@ -232,6 +235,7 @@ extern "C" fn fast_handler(
232235
mtvec::write(trap_vec::trap_vec as _, mtvec::TrapMode::Vectored);
233236
mstatus::set_mpie();
234237
mstatus::set_mpp(mstatus::MPP::Supervisor);
238+
asm!("csrw mie, {}", in(reg) (1<<3)|(1<<7)|(1<<11));
235239
}
236240
hart_ctx.trap.a[0] = hart_id;
237241
hart_ctx.trap.a[1] = supervisor.opaque;
@@ -240,6 +244,9 @@ extern "C" fn fast_handler(
240244
Err(_state) => {
241245
unsafe {
242246
mtvec::write(trap_vec::trap_vec as _, mtvec::TrapMode::Direct);
247+
mstatus::set_mpie();
248+
mstatus::set_mpp(mstatus::MPP::Machine);
249+
asm!("csrw mie, {}", in(reg) 1<<3);
243250
};
244251
hart_ctx.trap.pc = _stop as usize;
245252
}
@@ -249,20 +256,31 @@ extern "C" fn fast_handler(
249256
match cause.cause() {
250257
// SBI call
251258
T::Exception(E::SupervisorEnvCall) => {
259+
use sbi_spec::hsm;
252260
let ret = unsafe { SBI.assume_init_mut() }.handle_ecall(
253261
a7,
254262
a6,
255263
[ctx.a0(), a1, a2, a3, a4, a5],
256264
);
257-
if ret.is_ok() && a7 == sbi_spec::hsm::EID_HSM {
258-
match a6 {
259-
sbi_spec::hsm::HART_STOP => unsafe {
265+
if ret.is_ok() && a7 == hsm::EID_HSM {
266+
if a6 == hsm::HART_STOP {
267+
unsafe {
260268
mtvec::write(trap_vec::trap_vec as _, mtvec::TrapMode::Direct);
261269
mstatus::set_mpp(mstatus::MPP::Machine);
270+
asm!("csrw mie, {}", in(reg) 1<<3);
262271
ROOT_STACK[hart_id()].hart_context().trap.pc = _stop as usize;
263-
return ctx.call(0);
264-
},
265-
_ => {}
272+
}
273+
return ctx.call(0);
274+
}
275+
if a6 == hsm::HART_SUSPEND
276+
&& ctx.a0() == hsm::HART_SUSPEND_TYPE_NON_RETENTIVE as usize
277+
{
278+
unsafe {
279+
mtvec::write(trap_vec::trap_vec as _, mtvec::TrapMode::Direct);
280+
mstatus::set_mpp(mstatus::MPP::Machine);
281+
ROOT_STACK[hart_id()].hart_context().trap.pc = _stop as usize;
282+
}
283+
return ctx.call(0);
266284
}
267285
}
268286
mepc::write(mepc::read() + 4);
@@ -399,7 +417,7 @@ type FixedRustSBI<'a> = RustSBI<
399417
&'a clint::Clint,
400418
&'a clint::Clint,
401419
Infallible,
402-
Infallible,
420+
Hsm,
403421
&'a qemu_test::QemuTest,
404422
Infallible,
405423
>;
@@ -435,9 +453,40 @@ impl rustsbi::Hsm for Hsm {
435453
}
436454
}
437455

438-
#[inline]
439456
fn hart_suspend(&self, suspend_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
440-
let _ = (suspend_type, resume_addr, opaque);
441-
SbiRet::not_supported()
457+
use sbi_spec::hsm as spec;
458+
match suspend_type {
459+
spec::HART_SUSPEND_TYPE_NON_RETENTIVE => unsafe {
460+
ROOT_STACK[hart_id()]
461+
.hart_context()
462+
.hsm
463+
.local()
464+
.suspend_non_retentive(Supervisor {
465+
start_addr: resume_addr,
466+
opaque,
467+
});
468+
SbiRet::success(0)
469+
},
470+
spec::HART_SUSPEND_TYPE_RETENTIVE => unsafe {
471+
ROOT_STACK[hart_id()].hart_context().hsm.local().suspend();
472+
asm!(
473+
" la {0}, 1f
474+
csrrw {0}, mtvec, {0}
475+
csrrw {1}, mepc, {1}
476+
csrrw {2}, mstatus, {2}
477+
wfi
478+
1: csrrw {2}, mstatus, {2}
479+
csrrw {1}, mepc, {1}
480+
csrrw {0}, mtvec, {0}
481+
",
482+
out(reg) _,
483+
out(reg) _,
484+
out(reg) _,
485+
);
486+
ROOT_STACK[hart_id()].hart_context().hsm.local().resume();
487+
SbiRet::success(0)
488+
},
489+
_ => SbiRet::not_supported(),
490+
}
442491
}
443492
}

0 commit comments

Comments
 (0)