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 6ff98661..9c2a7d30 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -12,6 +12,8 @@ lazy_static = { version = "1.4.0", features = ["spin_no_std"] } buddy_system_allocator = "0.6" bitflags = "1.2.1" xmas-elf = "0.7.0" +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 df564eb8..05527add 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -5,83 +5,3 @@ pub const CLOCK_FREQ: usize = 12500000; pub const MMIO: &[(usize, usize)] = &[ (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine ]; - -//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 e8cf681a..6e711164 100644 --- a/os/src/lang_items.rs +++ b/os/src/lang_items.rs @@ -16,5 +16,5 @@ fn panic(info: &PanicInfo) -> ! { } else { println!("[kernel] Panicked: {}", info.message().unwrap()); } - shutdown() + shutdown(true) } diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 269581f3..5a2eed2b 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -1,51 +1,23 @@ //! SBI call wrappers -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)] -/// general sbi call -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { - let mut ret; - unsafe { - asm!( - "li x16, 0", - "ecall", - inlateout("x10") arg0 => ret, - in("x11") arg1, - in("x12") arg2, - in("x17") which, - ); - } - ret +/// use sbi call to putchar in console (qemu uart handler) +pub fn console_putchar(c: usize) { + #[allow(deprecated)] + sbi_rt::legacy::console_putchar(c); } /// use sbi call to set timer pub fn set_timer(timer: usize) { - sbi_call(SBI_SET_TIMER, timer, 0, 0); + sbi_rt::set_timer(timer as _); } -/// use sbi call to putchar in console (qemu uart handler) -pub fn console_putchar(c: usize) { - sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0); -} - -/// use sbi call to getchar from console (qemu uart handler) -// pub fn console_getchar() -> usize { -// sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) -// } -use crate::board::QEMUExit; /// use sbi call to shutdown the kernel -pub fn shutdown() -> ! { - crate::board::QEMU_EXIT_HANDLE.exit_failure(); +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!() }