Skip to content

Commit 2de250f

Browse files
authored
Merge pull request rustsbi#40 from rustsbi/instance-rustsbi
rustsbi-qemu: instance based RustSBI interface with separate functions for legacy stdio
2 parents 93c713f + 2813a25 commit 2de250f

File tree

7 files changed

+188
-104
lines changed

7 files changed

+188
-104
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1313

1414
### Modified
1515

16+
- Use instance based RustSBI interface, with separate functions for legacy stdio
1617
- Update sbi-testing to version 0.0.1
1718
- Use crate os-xtask-utils version 0.0.0 in xtask builder
1819

Cargo.lock

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

rustsbi-qemu/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ edition = "2021"
1717
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1818

1919
[dependencies]
20-
rustsbi = { version = "0.3.0-rc.1", features = ["legacy"] }
20+
rustsbi = "0.3.0-rc.2"
21+
sbi-spec = { version = "0.0.4", features = ["legacy"] }
2122
riscv = "0.9.0"
2223
spin = "0.9"
2324
r0 = "1"

rustsbi-qemu/src/console.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::ns16550a::Ns16550a;
2+
use core::fmt::{Arguments, Write};
3+
use spin::Once;
4+
5+
pub(crate) static STDOUT: Once<Ns16550a> = Once::new();
6+
7+
pub(crate) fn init(out: Ns16550a) {
8+
STDOUT.call_once(|| out);
9+
}
10+
11+
#[doc(hidden)]
12+
pub fn _print(args: Arguments) {
13+
STDOUT.wait().write_fmt(args).unwrap();
14+
}
15+
16+
/// Prints to the debug output.
17+
#[macro_export]
18+
macro_rules! print {
19+
($($arg:tt)*) => ($crate::console::_print(core::format_args!($($arg)*)));
20+
}
21+
22+
/// Prints to the debug output with a new line.
23+
#[macro_export]
24+
macro_rules! println {
25+
() => ($crate::print!("\r\n"));
26+
($($arg:tt)*) => {
27+
$crate::console::_print(core::format_args!($($arg)*));
28+
$crate::print!("\r\n");
29+
}
30+
}

rustsbi-qemu/src/execute.rs

Lines changed: 113 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
use crate::{clint, hart_id, qemu_hsm::QemuHsm, Supervisor};
1+
use crate::{clint, hart_id, qemu_hsm::QemuHsm, FixedRustSBI, Supervisor};
22
use core::arch::asm;
33
use riscv::register::*;
4+
use rustsbi::spec::binary::SbiRet;
45

56
#[repr(usize)]
67
pub(crate) enum Operation {
78
Stop = 0,
89
SystemReset = 1,
910
}
1011

11-
pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) -> Operation {
12-
let mut ctx = SupervisorContext::new(supervisor);
13-
mscratch::write(&mut ctx as *mut _ as _);
14-
12+
pub(crate) fn execute_supervisor(
13+
sbi: FixedRustSBI,
14+
hsm: &QemuHsm,
15+
supervisor: Supervisor,
16+
) -> Operation {
1517
clint::msip::clear();
1618
clint::mtimecmp::clear();
1719
unsafe {
@@ -26,6 +28,10 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) -> Opera
2628
mie::set_msoft();
2729
mie::set_mtimer();
2830
}
31+
let ctx = SupervisorContext::new(supervisor);
32+
33+
let mut env = Environment { ctx, sbi };
34+
mscratch::write(&mut env.ctx as *mut _ as _);
2935

3036
hsm.record_current_start_finished();
3137
loop {
@@ -34,15 +40,87 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) -> Opera
3440
use mcause::{Exception, Trap};
3541
match mcause::read().cause() {
3642
Trap::Exception(Exception::SupervisorEnvCall) => {
37-
if let Some(op) = ctx.handle_ecall() {
43+
if let Some(op) = env.handle_ecall() {
3844
break op;
3945
}
4046
}
41-
t => ctx.trap_stop(t),
47+
t => env.trap_stop(t),
4248
}
4349
}
4450
}
4551

52+
struct Environment<'a> {
53+
ctx: SupervisorContext,
54+
sbi: FixedRustSBI<'a>,
55+
}
56+
57+
impl<'a> Environment<'a> {
58+
fn handle_ecall(&mut self) -> Option<Operation> {
59+
use rustsbi::spec::{binary::*, hsm::*, srst::*};
60+
if self.ctx.sbi_extension() == sbi_spec::legacy::LEGACY_CONSOLE_PUTCHAR {
61+
let ch = self.ctx.a(0);
62+
crate::console::STDOUT.wait().putchar((ch & 0xFF) as u8);
63+
self.ctx.mepc = self.ctx.mepc.wrapping_add(4);
64+
return None;
65+
} else if self.ctx.sbi_extension() == sbi_spec::legacy::LEGACY_CONSOLE_GETCHAR {
66+
let ch = crate::console::STDOUT.wait().getchar();
67+
*self.ctx.a_mut(0) = ch as usize;
68+
self.ctx.mepc = self.ctx.mepc.wrapping_add(4);
69+
return None;
70+
}
71+
let ans = self.sbi.handle_ecall(
72+
self.ctx.sbi_extension(),
73+
self.ctx.sbi_function(),
74+
self.ctx.sbi_param(),
75+
);
76+
// 判断导致退出执行流程的调用
77+
if ans.error == RET_SUCCESS {
78+
match (self.ctx.sbi_extension(), self.ctx.sbi_function()) {
79+
// 核状态
80+
(EID_HSM, HART_STOP) => return Some(Operation::Stop),
81+
(EID_HSM, HART_SUSPEND)
82+
if matches!(
83+
u32::try_from(self.ctx.a(0)),
84+
Ok(HART_SUSPEND_TYPE_NON_RETENTIVE)
85+
) =>
86+
{
87+
return Some(Operation::Stop)
88+
}
89+
// 系统重置
90+
(EID_SRST, SYSTEM_RESET)
91+
if matches!(
92+
u32::try_from(self.ctx.a(0)),
93+
Ok(RESET_TYPE_COLD_REBOOT) | Ok(RESET_TYPE_WARM_REBOOT)
94+
) =>
95+
{
96+
return Some(Operation::SystemReset)
97+
}
98+
_ => {}
99+
}
100+
}
101+
self.ctx.fill_in(ans);
102+
self.ctx.mepc = self.ctx.mepc.wrapping_add(4);
103+
None
104+
}
105+
106+
fn trap_stop(&self, trap: mcause::Trap) -> ! {
107+
println!(
108+
"
109+
-----------------------------
110+
> trap: {trap:?}
111+
> mstatus: {:#018x}
112+
> mepc: {:#018x}
113+
> mtval: {:#018x}
114+
-----------------------------
115+
",
116+
self.ctx.mstatus,
117+
self.ctx.mepc,
118+
mtval::read()
119+
);
120+
panic!("stopped with unsupported trap")
121+
}
122+
}
123+
46124
#[repr(C)]
47125
#[derive(Debug)]
48126
struct SupervisorContext {
@@ -72,6 +150,34 @@ impl SupervisorContext {
72150
ctx
73151
}
74152

153+
#[inline]
154+
fn sbi_extension(&self) -> usize {
155+
self.a(7)
156+
}
157+
158+
#[inline]
159+
fn sbi_function(&self) -> usize {
160+
self.a(6)
161+
}
162+
163+
#[inline]
164+
fn sbi_param(&self) -> [usize; 6] {
165+
[
166+
self.a(0),
167+
self.a(1),
168+
self.a(2),
169+
self.a(3),
170+
self.a(4),
171+
self.a(5),
172+
]
173+
}
174+
175+
#[inline]
176+
fn fill_in(&mut self, ans: SbiRet) {
177+
*self.a_mut(0) = ans.error;
178+
*self.a_mut(1) = ans.value;
179+
}
180+
75181
#[inline]
76182
fn x(&self, n: usize) -> usize {
77183
self.x[n - 1]
@@ -92,60 +198,6 @@ impl SupervisorContext {
92198
self.x_mut(n + 10)
93199
}
94200

95-
fn handle_ecall(&mut self) -> Option<Operation> {
96-
use rustsbi::spec::{binary::*, hsm::*, srst::*};
97-
let extension = self.a(7);
98-
let function = self.a(6);
99-
let ans = rustsbi::ecall(
100-
extension,
101-
function,
102-
[
103-
self.a(0),
104-
self.a(1),
105-
self.a(2),
106-
self.a(3),
107-
self.a(4),
108-
self.a(5),
109-
],
110-
);
111-
// 判断导致退出执行流程的调用
112-
if ans.error == RET_SUCCESS {
113-
match extension {
114-
// 核状态
115-
EID_HSM => match function {
116-
HART_STOP => return Some(Operation::Stop),
117-
HART_SUSPEND
118-
if matches!(
119-
u32::try_from(self.a(0)),
120-
Ok(HART_SUSPEND_TYPE_NON_RETENTIVE)
121-
) =>
122-
{
123-
return Some(Operation::Stop);
124-
}
125-
_ => {}
126-
},
127-
// 系统重置
128-
EID_SRST => match function {
129-
SYSTEM_RESET
130-
if matches!(
131-
u32::try_from(self.a(0)),
132-
Ok(RESET_TYPE_COLD_REBOOT) | Ok(RESET_TYPE_WARM_REBOOT)
133-
) =>
134-
{
135-
return Some(Operation::SystemReset)
136-
}
137-
_ => {}
138-
},
139-
140-
_ => {}
141-
}
142-
}
143-
*self.a_mut(0) = ans.error;
144-
*self.a_mut(1) = ans.value;
145-
self.mepc = self.mepc.wrapping_add(4);
146-
None
147-
}
148-
149201
#[allow(unused)]
150202
fn do_transfer_trap(&mut self, cause: scause::Trap) {
151203
unsafe {
@@ -178,23 +230,6 @@ impl SupervisorContext {
178230
self.mepc = stvec::read().address();
179231
}
180232
}
181-
182-
fn trap_stop(&self, trap: mcause::Trap) -> ! {
183-
println!(
184-
"
185-
-----------------------------
186-
> trap: {trap:?}
187-
> mstatus: {:#018x}
188-
> mepc: {:#018x}
189-
> mtval: {:#018x}
190-
-----------------------------
191-
",
192-
self.mstatus,
193-
self.mepc,
194-
mtval::read()
195-
);
196-
panic!("stopped with unsupported trap")
197-
}
198233
}
199234

200235
/// M 态转到 S 态。

0 commit comments

Comments
 (0)