diff --git a/bootloader/rustsbi-qemu.bin b/bootloader/rustsbi-qemu.bin index 022c7f27..f9015b81 100755 Binary files a/bootloader/rustsbi-qemu.bin and b/bootloader/rustsbi-qemu.bin differ diff --git a/os/Cargo.toml b/os/Cargo.toml index fbcff883..51fc1e88 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -19,6 +19,8 @@ lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "3f4 easy-fs = { path = "../easy-fs" } embedded-graphics = "0.7.1" tinybmp = "0.3.1" +log = "0.4" +sbi-rt = { version = "0.0.2", features = ["legacy"] } [profile.release] debug = true diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs index ffb88539..ad9cf096 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -103,84 +103,3 @@ pub unsafe extern "C" fn timervec() -> ! { options(noreturn) ); } - - -//ref:: https://github.com/andre-richter/qemu-exit -use core::arch::asm; - -const EXIT_SUCCESS: u32 = 0x5555; // Equals `exit(0)`. qemu successful exit - -const EXIT_FAILURE_FLAG: u32 = 0x3333; -const EXIT_FAILURE: u32 = exit_code_encode(1); // Equals `exit(1)`. qemu failed exit -const EXIT_RESET: u32 = 0x7777; // qemu reset - -pub trait QEMUExit { - /// Exit with specified return code. - /// - /// Note: For `X86`, code is binary-OR'ed with `0x1` inside QEMU. - fn exit(&self, code: u32) -> !; - - /// Exit QEMU using `EXIT_SUCCESS`, aka `0`, if possible. - /// - /// Note: Not possible for `X86`. - fn exit_success(&self) -> !; - - /// Exit QEMU using `EXIT_FAILURE`, aka `1`. - fn exit_failure(&self) -> !; -} - -/// RISCV64 configuration -pub struct RISCV64 { - /// Address of the sifive_test mapped device. - addr: u64, -} - -/// Encode the exit code using EXIT_FAILURE_FLAG. -const fn exit_code_encode(code: u32) -> u32 { - (code << 16) | EXIT_FAILURE_FLAG -} - -impl RISCV64 { - /// Create an instance. - pub const fn new(addr: u64) -> Self { - RISCV64 { addr } - } -} - -impl QEMUExit for RISCV64 { - /// Exit qemu with specified exit code. - fn exit(&self, code: u32) -> ! { - // If code is not a special value, we need to encode it with EXIT_FAILURE_FLAG. - let code_new = match code { - EXIT_SUCCESS | EXIT_FAILURE | EXIT_RESET => code, - _ => exit_code_encode(code), - }; - - unsafe { - asm!( - "sw {0}, 0({1})", - in(reg)code_new, in(reg)self.addr - ); - - // For the case that the QEMU exit attempt did not work, transition into an infinite - // loop. Calling `panic!()` here is unfeasible, since there is a good chance - // this function here is the last expression in the `panic!()` handler - // itself. This prevents a possible infinite loop. - loop { - asm!("wfi", options(nomem, nostack)); - } - } - } - - fn exit_success(&self) -> ! { - self.exit(EXIT_SUCCESS); - } - - fn exit_failure(&self) -> ! { - self.exit(EXIT_FAILURE); - } -} - -const VIRT_TEST: u64 = 0x100000; - -pub const QEMU_EXIT_HANDLE: RISCV64 = RISCV64::new(VIRT_TEST); diff --git a/os/src/lang_items.rs b/os/src/lang_items.rs index a33943a1..68d736ec 100644 --- a/os/src/lang_items.rs +++ b/os/src/lang_items.rs @@ -18,7 +18,7 @@ fn panic(info: &PanicInfo) -> ! { unsafe { backtrace(); } - shutdown(255) + shutdown(true) } unsafe fn backtrace() { diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 5113c901..326f4d63 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -1,46 +1,27 @@ -#![allow(unused)] - -use core::arch::asm; - -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; - -#[inline(always)] -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { - let mut ret; - unsafe { - core::arch::asm!( - "li x16, 0", - "ecall", - inlateout("x10") arg0 => ret, - in("x11") arg1, - in("x12") arg2, - in("x17") which, - ); - } - ret -} - -pub fn set_timer(timer: usize) { - sbi_call(SBI_SET_TIMER, timer, 0, 0); -} - +/// use sbi call to putchar in console (qemu uart handler) pub fn console_putchar(c: usize) { - sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0); + #[allow(deprecated)] + sbi_rt::legacy::console_putchar(c); } +/// use sbi call to getchar from console (qemu uart handler) pub fn console_getchar() -> usize { - sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) + #[allow(deprecated)] + sbi_rt::legacy::console_getchar() } -use crate::board::QEMUExit; -pub fn shutdown(exit_code: usize) -> ! { - crate::board::QEMU_EXIT_HANDLE.exit_failure() +/// use sbi call to set timer +pub fn set_timer(timer: usize) { + sbi_rt::set_timer(timer as _); +} + +/// use sbi call to shutdown the kernel +pub fn shutdown(failure: bool) -> ! { + use sbi_rt::{system_reset, NoReason, Shutdown, SystemFailure}; + if !failure { + system_reset(Shutdown, NoReason); + } else { + system_reset(Shutdown, SystemFailure); + } + unreachable!() }