Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MOD] fix sbi_shutdown problem in Issue#127 #128

Open
wants to merge 1 commit into
base: lab-1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions os/src/panic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! 代替 std 库,实现 panic 和 abort 的功能

use crate::sbi::shutdown;
use crate::sbi::sbi_hart_stop;
use core::panic::PanicInfo;

/// 打印 panic 的信息并 [`shutdown`]
Expand All @@ -23,7 +23,14 @@ fn panic_handler(info: &PanicInfo) -> ! {
} else {
println!("\x1b[1;31mpanic: '{}'\x1b[0m", info.message().unwrap());
}
shutdown()

// This call is not expected to return under normal conditions.
// Returns SBI_ERR_FAILED through sbiret.error only if it fails,
// where SBI_ERR_FAILED = -1.
let sbiret = sbi_hart_stop();
println!("sbiret.error = {}, sbiret.value = {}", sbiret.error, sbiret.value);

unreachable!()
}

/// 终止程序
Expand Down
53 changes: 34 additions & 19 deletions os/src/sbi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,64 @@

/// SBI 调用
#[inline(always)]
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
let mut ret;
fn sbi_call(eid: i32,fid: i32, arg0: usize, arg1: usize, arg2: usize) -> Sbiret {
let mut error;
let mut value;
unsafe {
llvm_asm!("ecall"
: "={x10}" (ret)
: "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which)
: "={x10}" (error), "={x11}" (value)
: "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (eid), "{x16}" (fid)
: "memory" // 如果汇编可能改变内存,则需要加入 memory 选项
: "volatile"); // 防止编译器做激进的优化(如调换指令顺序等破坏 SBI 调用行为的优化)
}
ret
Sbiret{error, value}
}

const SBI_SET_TIMER: usize = 0;
const SBI_CONSOLE_PUTCHAR: usize = 1;
const SBI_CONSOLE_GETCHAR: usize = 2;
const SBI_CLEAR_IPI: usize = 3;
const SBI_SEND_IPI: usize = 4;
const SBI_REMOTE_FENCE_I: usize = 5;
const SBI_REMOTE_SFENCE_VMA: usize = 6;
const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;
const SBI_SHUTDOWN: usize = 8;
pub struct Sbiret {
pub error: i64,
pub value: i64,
}

const SBI_HSM_STOP_EID:i32 = 0x48534D;
const SBI_HSM_STOP_FID:i32 = 1;

const SBI_SET_TIMER: i32 = 0;
const SBI_CONSOLE_PUTCHAR: i32 = 1;
const SBI_CONSOLE_GETCHAR: i32 = 2;
const SBI_CLEAR_IPI: i32 = 3;
const SBI_SEND_IPI: i32 = 4;
const SBI_REMOTE_FENCE_I: i32 = 5;
const SBI_REMOTE_SFENCE_VMA: i32 = 6;
const SBI_REMOTE_SFENCE_VMA_ASID: i32 = 7;
const SBI_SHUTDOWN: i32 = 8;

/// 向控制台输出一个字符
///
/// 需要注意我们不能直接使用 Rust 中的 char 类型
pub fn console_putchar(c: usize) {
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
sbi_call(SBI_CONSOLE_PUTCHAR, 0, c, 0, 0);
}

/// 从控制台中读取一个字符
///
/// 没有读取到字符则返回 -1
pub fn console_getchar() -> usize {
sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
pub fn console_getchar() -> Sbiret {
sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0, 0)
}

/// 调用 SBI_SHUTDOWN 来关闭操作系统(直接退出 QEMU)
pub fn shutdown() -> ! {
sbi_call(SBI_SHUTDOWN, 0, 0, 0);
sbi_call(SBI_SHUTDOWN, 0, 0, 0,0);
unreachable!()
}

/// 设置下一次时钟中断的时间
pub fn set_timer(time: usize) {
sbi_call(SBI_SET_TIMER, time, 0, 0);
sbi_call(SBI_SET_TIMER, 0, time, 0,0);
}

/// 关闭 hart ,等价于 SBI_SHUTDOWN ?
/// TODO: need to verify
pub fn sbi_hart_stop() -> Sbiret {
sbi_call(SBI_HSM_STOP_EID, SBI_HSM_STOP_FID, 0, 0, 0)
}