Skip to content

Commit 999e355

Browse files
luojia65duskmoon314
andcommitted
rustsbi-qemu: supervisor IPI delegation
Try to resolve pull request #6 Co-authored-by: Campbell He <campbell.he@icloud.com> Signed-off-by: luojia65 <me@luojia.cc>
1 parent 301acab commit 999e355

File tree

6 files changed

+148
-37
lines changed

6 files changed

+148
-37
lines changed

Cargo.lock

Lines changed: 50 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustsbi-qemu/src/execute.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::{
44
};
55

66
use riscv::register::{mcause, mie, mip, scause::{Exception, Trap}};
7+
use riscv::register::scause::Interrupt;
78

89
use crate::feature;
910
use crate::prv_mem::{self, SupervisorPointer};
@@ -95,9 +96,20 @@ pub fn execute_supervisor(supervisor_mepc: usize, hart_id: usize, a1: usize, hsm
9596
ctx.mepc = start_paddr;
9697
}
9798
}
98-
None => panic!(
99-
"rustsbi-qemu: machine soft interrupt with no hart state monitor command"
100-
),
99+
None => unsafe {
100+
// machine software interrupt but no HSM commands - delegate to S mode;
101+
let ctx = rt.context_mut();
102+
let clint = crate::clint::Clint::new(0x2000000 as *mut u8);
103+
clint.clear_soft(hart_id); // Clear IPI
104+
if feature::should_transfer_trap(ctx) {
105+
feature::do_transfer_trap(
106+
ctx,
107+
Trap::Interrupt(Interrupt::SupervisorSoft),
108+
)
109+
} else {
110+
panic!("rustsbi-qemu: machine soft interrupt with no hart state monitor command")
111+
}
112+
},
101113
},
102114
GeneratorState::Complete(()) => {
103115
use rustsbi::Reset;

rustsbi-qemu/src/feature/transfer_trap.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use crate::runtime::SupervisorContext;
21
use riscv::register::{
32
mstatus::{self, MPP, SPP},
43
mtval, scause, sepc, stval, stvec,
54
};
65

6+
use crate::runtime::SupervisorContext;
7+
78
#[inline]
89
pub unsafe fn should_transfer_trap(ctx: &mut SupervisorContext) -> bool {
910
ctx.mstatus.mpp() != MPP::Machine
@@ -15,7 +16,7 @@ pub unsafe fn do_transfer_trap(ctx: &mut SupervisorContext, cause: scause::Trap)
1516
scause::set(cause);
1617
// 填写异常指令的指令内容
1718
stval::write(mtval::read());
18-
// 填写S层需要返回到的地址,这里的mepc会被随后的代码覆盖掉
19+
// 填写S层需要返回到的地址,这里的mepc会被随后的代码覆盖掉。mepc已经处理了中断向量的问题
1920
sepc::write(ctx.mepc);
2021
// 设置中断位
2122
mstatus::set_mpp(MPP::Supervisor);

test-kernel/src/main.rs

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77
use core::arch::asm;
88
use core::panic::PanicInfo;
99

10-
use riscv::register::{
11-
scause::{self, Exception, Trap},
12-
sepc,
13-
stvec::{self, TrapMode},
14-
};
10+
use riscv::register::{scause::{self, Exception, Trap}, sepc, /*sie, sstatus, */stvec::{self, TrapMode}};
11+
use riscv::register::scause::Interrupt;
1512

1613
#[macro_use]
1714
mod console;
1815
mod mm;
1916
mod sbi;
2017

2118
pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
19+
unsafe { asm!("mv tp, {}", in(reg) hartid, options(nomem, nostack)) }; // tp == hartid
20+
let mut start_trap_addr = start_trap as usize;
21+
if start_trap_addr & 0b10 != 0 {
22+
start_trap_addr += 0b10;
23+
}
2224
if hartid == 0 {
2325
// initialization
2426
mm::init_heap();
@@ -30,14 +32,14 @@ pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
3032
);
3133
test_base_extension();
3234
test_sbi_ins_emulation();
33-
unsafe { stvec::write(start_trap as usize, TrapMode::Direct) };
35+
unsafe { stvec::write(start_trap_addr, TrapMode::Direct) };
3436
println!(">> Test-kernel: Trigger illegal exception");
3537
unsafe { asm!("csrw mcycle, x0") }; // mcycle cannot be written, this is always a 4-byte illegal instruction
3638
}
3739
if hartid == 0 {
3840
let sbi_ret = sbi::hart_stop(3);
3941
println!(">> Stop hart 3, return value {:?}", sbi_ret);
40-
for i in 0..4 {
42+
for i in 0..5 {
4143
let sbi_ret = sbi::hart_get_status(i);
4244
println!(">> Hart {} state return value: {:?}", i, sbi_ret);
4345
}
@@ -52,6 +54,14 @@ pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
5254
let sbi_ret = sbi::hart_suspend(0x80000000, hart_2_resume as usize, 0x4567890a);
5355
println!(">> Error for non-retentive suspend: {:?}", sbi_ret);
5456
loop {}
57+
} else if hartid == 4 {
58+
// unsafe { stvec::write(start_trap_addr, TrapMode::Direct) };
59+
// unsafe { sstatus::set_sie() };
60+
// unsafe { sie::set_ssoft() };
61+
// loop {} // wait for S-IPI
62+
// println!(">> Test-kernel: SBI S-IPI delegation success");
63+
// println!("<< Test-kernel: All hart SBI test SUCCESS, shutdown");
64+
loop {} // todo: S-IPI
5565
} else {
5666
// hartid == 3
5767
loop {}
@@ -70,7 +80,7 @@ pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
7080
println!(">> Wake hart 2, sbi return value {:?}", sbi_ret);
7181
loop {}
7282
} else {
73-
// hartid == 2 || hartid == 3
83+
// hartid == 2 || hartid == 3 || hartid == 4
7484
unreachable!()
7585
}
7686
}
@@ -95,6 +105,10 @@ extern "C" fn hart_3_start(hart_id: usize, param: usize) {
95105
);
96106
println!("<< Test-kernel: All hart SBI test SUCCESS, shutdown");
97107
sbi::shutdown()
108+
// todo: S-IPI
109+
// println!(">> Send IPI to hart 4, should delegate IPI to S-level");
110+
// let _ = sbi::send_ipi(0b1, 4); // IPI to hart 4
111+
// loop {} // wait for machine shutdown
98112
}
99113

100114
fn test_base_extension() {
@@ -142,15 +156,26 @@ fn test_sbi_ins_emulation() {
142156
}
143157
}
144158

145-
pub extern "C" fn rust_trap_exception() {
146-
let cause = scause::read().cause();
147-
println!("<< Test-kernel: Value of scause: {:?}", cause);
148-
if cause != Trap::Exception(Exception::IllegalInstruction) {
149-
println!("!! Test-kernel: Wrong cause associated to illegal instruction");
159+
extern "C" fn rust_trap_exception(trap_frame: &mut TrapFrame) {
160+
if trap_frame.tp == 0 {
161+
let cause = scause::read().cause();
162+
println!("<< Test-kernel: Value of scause: {:?}", cause);
163+
if cause != Trap::Exception(Exception::IllegalInstruction) {
164+
println!("!! Test-kernel: Wrong cause associated to illegal instruction");
165+
sbi::shutdown()
166+
}
167+
println!("<< Test-kernel: Illegal exception delegate success");
168+
sepc::write(sepc::read().wrapping_add(4));
169+
} else if trap_frame.tp == 4 {
170+
if scause::read().cause() != Trap::Interrupt(Interrupt::SupervisorSoft) {
171+
println!("!! Test-kernel: Wrong cause associated to S-IPI delegation");
172+
sbi::shutdown()
173+
}
174+
} else {
175+
println!("!! Test-kernel: hart {} should not trap", trap_frame.tp);
176+
println!("!! Test-kernel: SBI test FAILED for this hart should not trap");
150177
sbi::shutdown()
151178
}
152-
println!("<< Test-kernel: Illegal exception delegate success");
153-
sepc::write(sepc::read().wrapping_add(4));
154179
}
155180

156181
#[cfg_attr(not(test), panic_handler)]
@@ -233,7 +258,7 @@ macro_rules! define_store_load {
233258
unsafe extern "C" fn start_trap() {
234259
asm!(define_store_load!(), "
235260
.p2align 2
236-
addi sp, sp, -16 * {REGBYTES}
261+
addi sp, sp, -17 * {REGBYTES}
237262
STORE ra, 0
238263
STORE t0, 1
239264
STORE t1, 2
@@ -250,6 +275,7 @@ unsafe extern "C" fn start_trap() {
250275
STORE a5, 13
251276
STORE a6, 14
252277
STORE a7, 15
278+
STORE tp, 16
253279
mv a0, sp
254280
call {rust_trap_exception}
255281
LOAD ra, 0
@@ -268,10 +294,32 @@ unsafe extern "C" fn start_trap() {
268294
LOAD a5, 13
269295
LOAD a6, 14
270296
LOAD a7, 15
271-
addi sp, sp, 16 * {REGBYTES}
297+
LOAD tp, 16
298+
addi sp, sp, 17 * {REGBYTES}
272299
sret
273300
",
274301
REGBYTES = const core::mem::size_of::<usize>(),
275302
rust_trap_exception = sym rust_trap_exception,
276303
options(noreturn))
277304
}
305+
306+
#[repr(C)]
307+
struct TrapFrame {
308+
ra: usize,
309+
t0: usize,
310+
t1: usize,
311+
t2: usize,
312+
t3: usize,
313+
t4: usize,
314+
t5: usize,
315+
t6: usize,
316+
a0: usize,
317+
a1: usize,
318+
a2: usize,
319+
a3: usize,
320+
a4: usize,
321+
a5: usize,
322+
a6: usize,
323+
a7: usize,
324+
tp: usize,
325+
}

xtask/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ publish = false
1010

1111
[dependencies]
1212
clap = "2"
13+
ctrlc = "3.2"

xtask/src/main.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
#[macro_use]
2+
extern crate clap;
3+
14
use std::{
25
env,
36
path::{Path, PathBuf},
47
process::{self, Command, Stdio},
58
};
69

7-
#[macro_use]
8-
extern crate clap;
910

1011
// 不要修改DEFAULT_TARGET;如果你需要编译到别的目标,请使用--target编译选项!
1112
const DEFAULT_TARGET: &'static str = "riscv64imac-unknown-none-elf";
@@ -246,16 +247,19 @@ fn xtask_qemu_debug(xtask_env: &XtaskEnv) {
246247
}
247248

248249
fn xtask_gdb(xtask_env: &XtaskEnv) {
249-
let status = Command::new("riscv64-unknown-elf-gdb")
250-
.current_dir(dist_dir(xtask_env))
251-
.args(&["--eval-command", "file rustsbi-qemu"])
252-
.args(&["--eval-command", "target remote localhost:1234"])
253-
.arg("-q")
254-
.status()
255-
.unwrap();
250+
let mut command = Command::new("riscv64-unknown-elf-gdb");
251+
command.current_dir(dist_dir(xtask_env));
252+
command.args(&["--eval-command", "file rustsbi-qemu"]);
253+
command.args(&["--eval-command", "target remote localhost:1234"]);
254+
command.arg("-q");
256255

256+
ctrlc::set_handler(move || {
257+
// when ctrl-c, don't exit gdb
258+
}).expect("disable Ctrl-C exit");
259+
260+
let status = command.status().expect("run program");
257261
if !status.success() {
258-
println!("qemu failed");
262+
println!("debug failed");
259263
process::exit(1);
260264
}
261265
}

0 commit comments

Comments
 (0)