tg_sbi/
lib.rs

1//! # tg-sbi
2//!
3//! 为 rCore 教学操作系统提供的 SBI (Supervisor Binary Interface) 调用封装。
4//!
5//! ## Features
6//!
7//! - `nobios`: 启用内置的 M-Mode SBI 实现,用于 `-bios none` 启动模式。
8//!   启用此 feature 后,crate 将提供自己的 M-Mode 陷阱处理程序和基本 SBI 服务。
9//!
10//! ## 支持的 SBI 扩展
11//!
12//! - Legacy 控制台 I/O (EID 0x01, 0x02)
13//! - Timer 扩展 (EID 0x54494D45)
14//! - System Reset 扩展 (EID 0x53525354)
15//!
16//! ## Example
17//!
18//! ```ignore
19//! use tg_sbi::{console_putchar, set_timer, shutdown};
20//!
21//! // 输出字符
22//! console_putchar(b'H');
23//!
24//! // 设置定时器中断
25//! set_timer(1000000);
26//!
27//! // 关闭系统
28//! shutdown(false);
29//! ```
30
31#![no_std]
32#![deny(warnings, missing_docs)]
33
34// M-Mode SBI 实现(用于 -bios none 启动)
35#[cfg(all(feature = "nobios", target_arch = "riscv64"))]
36pub mod msbi;
37// M-Mode SBI 入口点(用于 -bios none 启动)
38#[cfg(all(feature = "nobios", target_arch = "riscv64"))]
39core::arch::global_asm!(include_str!("m_entry.asm"));
40
41// Legacy SBI 调用号(用于兼容性)
42const SBI_CONSOLE_PUTCHAR: usize = 1;
43const SBI_CONSOLE_GETCHAR: usize = 2;
44
45// SBI 扩展 ID
46const SBI_EXT_TIMER: usize = 0x54494D45;
47const SBI_EXT_SRST: usize = 0x53525354;
48
49/// 通用 SBI 调用。
50#[cfg(all(target_arch = "riscv64", not(feature = "nobios")))]
51#[inline(always)]
52fn sbi_call(eid: usize, fid: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
53    let ret;
54    // SAFETY: 执行 SBI ecall,这是 S-mode 软件向 SBI 固件请求服务的标准接口。
55    // ecall 指令定义明确,寄存器约定遵循 RISC-V SBI 规范。
56    unsafe {
57        core::arch::asm!(
58            "ecall",
59            inlateout("x10") arg0 => ret,
60            in("x11") arg1,
61            in("x12") arg2,
62            in("x16") fid,
63            in("x17") eid,
64        );
65    }
66    ret
67}
68
69/// 通用 SBI 调用(nobios 模式,使用自定义 M-mode 处理程序)。
70#[cfg(all(target_arch = "riscv64", feature = "nobios"))]
71#[inline(always)]
72fn sbi_call(eid: usize, fid: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
73    let ret1: isize;
74    let ret2: usize;
75    // SAFETY: 执行 ecall 调用自定义的 M-mode SBI 处理程序。
76    // 处理程序在 m_entry.asm 中设置,在 msbi.rs 中实现。
77    // 寄存器约定遵循 RISC-V SBI 规范。
78    unsafe {
79        core::arch::asm!(
80            "ecall",
81            inlateout("x10") arg0 => ret1,
82            inlateout("x11") arg1 => ret2,
83            in("x12") arg2,
84            in("x16") fid,
85            in("x17") eid
86        );
87    }
88    if ret1 < 0 {
89        panic!("SBI call failed: {}", ret1);
90    }
91    ret2
92}
93
94/// 非 riscv64 架构处理。
95#[cfg(not(target_arch = "riscv64"))]
96#[inline(always)]
97fn sbi_call(_eid: usize, _fid: usize, _arg0: usize, _arg1: usize, _arg2: usize) -> usize {
98    unimplemented!("SBI calls are only supported on riscv64")
99}
100
101/// 设置下一次定时器中断的时间。
102pub fn set_timer(timer: u64) {
103    sbi_call(SBI_EXT_TIMER, 0, timer as usize, 0, 0);
104}
105
106/// 向调试控制台输出一个字符。
107pub fn console_putchar(c: u8) {
108    sbi_call(SBI_CONSOLE_PUTCHAR, 0, c as usize, 0, 0);
109}
110
111/// 从调试控制台读取一个字符。
112pub fn console_getchar() -> usize {
113    sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0, 0)
114}
115
116/// 关闭系统。
117pub fn shutdown(failure: bool) -> ! {
118    if failure {
119        sbi_call(SBI_EXT_SRST, 0, 1, 0, 0);
120    } else {
121        sbi_call(SBI_EXT_SRST, 0, 0, 0, 0);
122    }
123    panic!("It should shutdown!");
124}