mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 01:16:26 +04:00
Using sbi-rt instead of asm && update rustsbi-qemu to latest
rustsbi-qemu version: a4f0bbe44d9f2f1069a9e5becd09f291e542852c
This commit is contained in:
parent
7b7df6a759
commit
386d783525
Binary file not shown.
@ -9,7 +9,8 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
|
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
|
||||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||||
|
log = "0.4"
|
||||||
|
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
//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);
|
|
@ -15,5 +15,5 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
} else {
|
} else {
|
||||||
println!("[kernel] Panicked: {}", info.message().unwrap());
|
println!("[kernel] Panicked: {}", info.message().unwrap());
|
||||||
}
|
}
|
||||||
shutdown()
|
shutdown(true)
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,6 @@
|
|||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
|
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
|
|
||||||
#[path = "boards/qemu.rs"]
|
|
||||||
mod board;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod console;
|
mod console;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -1,47 +1,25 @@
|
|||||||
//! SBI call wrappers
|
//! SBI call wrappers
|
||||||
|
|
||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
const SBI_CONSOLE_PUTCHAR: usize = 1;
|
|
||||||
|
|
||||||
// const SBI_SET_TIMER: usize = 0;
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/// handle SBI call with `which` SBI_id and other arguments
|
|
||||||
#[inline(always)]
|
|
||||||
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)
|
/// use sbi call to putchar in console (qemu uart handler)
|
||||||
pub fn console_putchar(c: usize) {
|
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)
|
/// use sbi call to getchar from console (qemu uart handler)
|
||||||
// pub fn console_getchar() -> usize {
|
#[allow(unused)]
|
||||||
// sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
|
pub fn console_getchar() -> usize {
|
||||||
// }
|
#[allow(deprecated)]
|
||||||
|
sbi_rt::legacy::console_getchar()
|
||||||
use crate::board::QEMUExit;
|
}
|
||||||
/// use sbi call to shutdown the kernel
|
|
||||||
pub fn shutdown() -> ! {
|
/// use sbi call to shutdown the kernel
|
||||||
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!()
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ mod task;
|
|||||||
|
|
||||||
use crate::config::MAX_APP_NUM;
|
use crate::config::MAX_APP_NUM;
|
||||||
use crate::loader::{get_num_app, init_app_cx};
|
use crate::loader::{get_num_app, init_app_cx};
|
||||||
|
use crate::sbi::shutdown;
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use switch::__switch;
|
use switch::__switch;
|
||||||
@ -134,8 +135,7 @@ impl TaskManager {
|
|||||||
// go back to user mode
|
// go back to user mode
|
||||||
} else {
|
} else {
|
||||||
println!("All applications completed!");
|
println!("All applications completed!");
|
||||||
use crate::board::QEMUExit;
|
shutdown(false);
|
||||||
crate::board::QEMU_EXIT_HANDLE.exit_success();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user