Skip to content

Commit 5721e34

Browse files
committed
Non-retentive resume
1 parent 034cc60 commit 5721e34

File tree

3 files changed

+48
-41
lines changed

3 files changed

+48
-41
lines changed

rustsbi-qemu/src/execute.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,22 @@ pub fn execute_supervisor(supervisor_mepc: usize, a0: usize, a1: usize, hsm: Qem
1616
let ctx = rt.context_mut();
1717
let param = [ctx.a0, ctx.a1, ctx.a2, ctx.a3, ctx.a4, ctx.a5];
1818
let ans = rustsbi::ecall(ctx.a7, ctx.a6, param);
19-
ctx.a0 = ans.error;
20-
ctx.a1 = ans.value;
21-
ctx.mepc = ctx.mepc.wrapping_add(4);
19+
if ans.error == 0x233 { // hart non-retentive resume
20+
if let Some(HsmCommand::Start(start_paddr, opaque)) = hsm.last_command() {
21+
unsafe {
22+
riscv::register::satp::write(0);
23+
riscv::register::sstatus::clear_sie();
24+
}
25+
hsm.record_current_start_finished();
26+
ctx.mstatus = riscv::register::mstatus::read(); // get from modified sstatus
27+
ctx.a0 = opaque;
28+
ctx.mepc = start_paddr;
29+
}
30+
} else {
31+
ctx.a0 = ans.error;
32+
ctx.a1 = ans.value;
33+
ctx.mepc = ctx.mepc.wrapping_add(4);
34+
}
2235
}
2336
GeneratorState::Yielded(MachineTrap::IllegalInstruction()) => {
2437
let ctx = rt.context_mut();

rustsbi-qemu/src/qemu_hsm.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -248,31 +248,11 @@ impl rustsbi::Hsm for QemuHsm {
248248
// retentive suspend
249249
suspend_current_hart(&self);
250250
// begin wake process
251-
unsafe {
252-
riscv::register::satp::write(0);
253-
riscv::register::sstatus::clear_sie();
254-
}
255-
// when wake, mark current hart as started
256-
let mut state_lock = self.state.lock();
257-
state_lock.entry(hart_id).insert(AtomicU8::new(HsmState::Started as u8));
258-
drop(state_lock);
259-
match () {
260-
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
261-
() => unsafe {
262-
asm!(
263-
"csrr a0, mhartid",
264-
"jr {resume_addr}",
265-
resume_addr = in(reg) resume_addr,
266-
in("a1") opaque,
267-
options(noreturn)
268-
)
269-
},
270-
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
271-
() => {
272-
drop((resume_addr, opaque));
273-
unimplemented!("not RISC-V instruction set architecture")
274-
}
275-
};
251+
// send start command to runtime of current hart
252+
let mut config_lock = self.last_command.lock();
253+
config_lock.entry(hart_id).insert(HsmCommand::Start(resume_addr, opaque));
254+
drop(config_lock);
255+
SbiRet { error: 0x233, value: 0x0 } // unreachable, the runtime identifies start command and perform the hart resume
276256
},
277257
// There could be other platform specific suspend types; RustSBI-QEMU does not define any
278258
// platform suspend types. It gives SBI return value as not supported.

test-kernel/src/main.rs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,32 +37,46 @@ pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
3737
let sbi_ret = sbi::hart_get_status(i);
3838
println!(">> Hart {} state return value: {:?}", i, sbi_ret);
3939
}
40-
} else if hartid == 1 || hartid == 2 {
40+
} else if hartid == 1 {
4141
let sbi_ret = sbi::hart_suspend(0x00000000, 0, 0);
42-
println!(">> Start test for hart {}, suspend return value {:?}", hartid, sbi_ret);
42+
println!(">> Start test for hart {}, retentive suspend return value {:?}", hartid, sbi_ret);
43+
} else if hartid == 2 {
44+
/* resume_addr should be physical address, and here pa == va */
45+
let sbi_ret = sbi::hart_suspend(0x80000000, hart_2_resume as usize, 0x4567890a);
46+
println!(">> Error for non-retentive suspend: {:?}", sbi_ret);
47+
loop {}
4348
} else { // hartid == 3
4449
loop {}
4550
}
46-
if hartid == 0 || hartid == 1 {
51+
if hartid == 0 {
4752
println!("<< Test-kernel: test for hart {} success, wake another hart", hartid);
4853
let bv: usize = 0b10;
4954
let sbi_ret = sbi::send_ipi(&bv as *const _ as usize, hartid); // wake hartid + 1
50-
println!(">> Wake, sbi return value {:?}", sbi_ret);
55+
println!(">> Wake hart 1, sbi return value {:?}", sbi_ret);
5156
loop {} // wait for machine shutdown
52-
} else if hartid == 2 {
53-
let param = 0x12345678;
54-
println!(">> Start hart 3 with parameter {:#x}", param);
55-
/* start_addr should be physical address, and here pa == va */
56-
let sbi_ret = sbi::hart_start(3, hart_3_start as usize, param);
57-
println!(">> SBI return value: {:?}", sbi_ret);
58-
loop {} // wait for machine shutdown
59-
} else { // hartid == 3
57+
} else if hartid == 1 {
58+
// send software IPI to activate hart 2
59+
let bv: usize = 0b10;
60+
let sbi_ret = sbi::send_ipi(&bv as *const _ as usize, hartid); // wake hartid + 1
61+
println!(">> Wake hart 2, sbi return value {:?}", sbi_ret);
62+
loop {}
63+
} else { // hartid == 2 || hartid == 3
6064
unreachable!()
6165
}
6266
}
6367

68+
extern "C" fn hart_2_resume(param: usize) {
69+
println!("<< The parameter passed to hart 2 resume is: {:#x}", param);
70+
let param = 0x12345678;
71+
println!(">> Start hart 3 with parameter {:#x}", param);
72+
/* start_addr should be physical address, and here pa == va */
73+
let sbi_ret = sbi::hart_start(3, hart_3_start as usize, param);
74+
println!(">> SBI return value: {:?}", sbi_ret);
75+
loop {} // wait for machine shutdown
76+
}
77+
6478
extern "C" fn hart_3_start(param: usize) {
65-
println!("<< The parameter passed to hart start is: {:#x}", param);
79+
println!("<< The parameter passed to hart 3 start is: {:#x}", param);
6680
println!("<< Test-kernel: All hart SBI test SUCCESS, shutdown");
6781
sbi::shutdown()
6882
}

0 commit comments

Comments
 (0)