mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-24 10:26:25 +04:00
update rustsbi-qemu.bin :: PMP set RW for [base: 0x10_0000, len: 0x2000], and os kernel supports VIRT_TEST based qemu exit
This commit is contained in:
parent
09299aabb0
commit
017dbcbd79
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
//! The panic handler
|
//! The panic handler
|
||||||
|
|
||||||
use crate::sbi::shutdown;
|
//use crate::sbi::shutdown;
|
||||||
|
use crate::qemu_exit::{QEMUExit,QEMU_EXIT_HANDLE};
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
@ -15,5 +16,7 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
} else {
|
} else {
|
||||||
println!("[kernel] Panicked: {}", info.message().unwrap());
|
println!("[kernel] Panicked: {}", info.message().unwrap());
|
||||||
}
|
}
|
||||||
shutdown()
|
//shutdown()
|
||||||
|
// QEMU_EXIT_HANDLE.exit(13)
|
||||||
|
QEMU_EXIT_HANDLE.exit_success()
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ use core::arch::global_asm;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod console;
|
mod console;
|
||||||
mod lang_items;
|
mod lang_items;
|
||||||
|
mod qemu_exit;
|
||||||
mod sbi;
|
mod sbi;
|
||||||
|
use crate::qemu_exit::{QEMUExit, QEMU_EXIT_HANDLE};
|
||||||
|
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
|
|
||||||
@ -35,26 +37,29 @@ pub fn clear_bss() {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn rust_main() -> ! {
|
pub fn rust_main() -> ! {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn stext(); // begin addr of text segment
|
fn stext(); // begin addr of text segment
|
||||||
fn etext(); // end addr of text segment
|
fn etext(); // end addr of text segment
|
||||||
fn srodata(); // start addr of Read-Only data segment
|
fn srodata(); // start addr of Read-Only data segment
|
||||||
fn erodata(); // end addr of Read-Only data ssegment
|
fn erodata(); // end addr of Read-Only data ssegment
|
||||||
fn sdata(); // start addr of data segment
|
fn sdata(); // start addr of data segment
|
||||||
fn edata(); // end addr of data segment
|
fn edata(); // end addr of data segment
|
||||||
fn sbss(); // start addr of BSS segment
|
fn sbss(); // start addr of BSS segment
|
||||||
fn ebss(); // end addr of BSS segment
|
fn ebss(); // end addr of BSS segment
|
||||||
fn boot_stack(); // stack bottom
|
fn boot_stack(); // stack bottom
|
||||||
fn boot_stack_top(); // stack top
|
fn boot_stack_top(); // stack top
|
||||||
}
|
}
|
||||||
clear_bss();
|
clear_bss();
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
println!(".text [{:#x}, {:#x})", stext as usize, etext as usize);
|
println!(".text [{:#x}, {:#x})", stext as usize, etext as usize);
|
||||||
println!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize);
|
println!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize);
|
||||||
println!(".data [{:#x}, {:#x})", sdata as usize, edata as usize);
|
println!(".data [{:#x}, {:#x})", sdata as usize, edata as usize);
|
||||||
println!(
|
println!(
|
||||||
"boot_stack [{:#x}, {:#x})",
|
"boot_stack [{:#x}, {:#x})",
|
||||||
boot_stack as usize, boot_stack_top as usize
|
boot_stack as usize, boot_stack_top as usize
|
||||||
);
|
);
|
||||||
println!(".bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
|
println!(".bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
|
||||||
panic!("Shutdown machine!");
|
|
||||||
|
QEMU_EXIT_HANDLE.exit_success(); //need successful qemu exit
|
||||||
|
//QEMU_EXIT_HANDLE.exit_failure(); //need failed qemu exit
|
||||||
|
//panic!("Shutdown machine!");
|
||||||
}
|
}
|
||||||
|
83
os/src/qemu_exit.rs
Normal file
83
os/src/qemu_exit.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020-2022 Esteban Blanc <estblcsk@gmail.com>
|
||||||
|
|
||||||
|
//! RISCV64.
|
||||||
|
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
const EXIT_SUCCESS: u32 = 0x5555; // Equals `exit(0)`.
|
||||||
|
|
||||||
|
const EXIT_FAILURE_FLAG: u32 = 0x3333;
|
||||||
|
const EXIT_FAILURE: u32 = exit_code_encode(1); // Equals `exit(1)`.
|
||||||
|
const EXIT_RESET: u32 = 0x7777;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const QEMU_EXIT_HANDLE: RISCV64 = RISCV64::new(0x100000);
|
Loading…
Reference in New Issue
Block a user