mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 05:46:48 +00:00
Implement should_panic for ktest and clear the codebase
This commit is contained in:
parent
bb0560530f
commit
45a6b2f46c
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -478,6 +478,12 @@ dependencies = [
|
|||||||
"syn 2.0.29",
|
"syn 2.0.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -647,6 +653,7 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
"tdx-guest",
|
"tdx-guest",
|
||||||
"trapframe",
|
"trapframe",
|
||||||
|
"unwinding",
|
||||||
"volatile",
|
"volatile",
|
||||||
"x86",
|
"x86",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
@ -1446,6 +1453,15 @@ version = "1.0.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unwinding"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
12
Cargo.toml
12
Cargo.toml
@ -17,6 +17,18 @@ x86_64 = "0.14.2"
|
|||||||
jinux-time = { path = "services/comps/time" }
|
jinux-time = { path = "services/comps/time" }
|
||||||
jinux-framebuffer = { path = "services/comps/framebuffer" }
|
jinux-framebuffer = { path = "services/comps/framebuffer" }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 0
|
||||||
|
debug = true
|
||||||
|
lto = false
|
||||||
|
panic = "unwind"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = 3
|
||||||
|
debug = false
|
||||||
|
lto = false
|
||||||
|
panic = "unwind"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
21
build.rs
21
build.rs
@ -1,16 +1,19 @@
|
|||||||
use std::{error::Error, path::PathBuf};
|
use std::{error::Error, path::PathBuf};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let linker_script_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
|
let target = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||||
.join("framework")
|
let linker_script_path = if target == "x86_64" {
|
||||||
.join("jinux-frame")
|
PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
|
||||||
.join("src")
|
.join("framework")
|
||||||
.join("arch")
|
.join("jinux-frame")
|
||||||
.join("x86")
|
.join("src")
|
||||||
.join("boot")
|
.join("arch")
|
||||||
.join("linker.ld");
|
.join("x86")
|
||||||
|
.join("linker.ld")
|
||||||
|
} else {
|
||||||
|
panic!("Unsupported target arch: {}", target);
|
||||||
|
};
|
||||||
println!("cargo:rerun-if-changed={}", linker_script_path.display());
|
println!("cargo:rerun-if-changed={}", linker_script_path.display());
|
||||||
println!("cargo:rustc-link-arg=-T{}", linker_script_path.display());
|
println!("cargo:rustc-link-arg=-T{}", linker_script_path.display());
|
||||||
println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,25 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.3"
|
|
||||||
cfg-if = "1.0"
|
|
||||||
spin = "0.9.4"
|
|
||||||
volatile = { version = "0.4.5", features = ["unstable"] }
|
|
||||||
buddy_system_allocator = "0.9.0"
|
|
||||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "d7dba56" }
|
|
||||||
align_ext = { path = "../libs/align_ext" }
|
align_ext = { path = "../libs/align_ext" }
|
||||||
ktest = { path = "../libs/ktest" }
|
|
||||||
intrusive-collections = "0.9.5"
|
|
||||||
log = "0.4"
|
|
||||||
lazy_static = { version = "1.0", features = ["spin_no_std"] }
|
|
||||||
trapframe = { git = "https://github.com/jinzhao-dev/trapframe-rs", rev = "9758a83" }
|
|
||||||
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
|
||||||
tdx-guest = { path = "../libs/tdx-guest", optional = true }
|
|
||||||
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
|
||||||
static_assertions = "1.1.0"
|
|
||||||
int-to-c-enum = { path = "../../services/libs/int-to-c-enum" }
|
|
||||||
bit_field = "0.10.1"
|
bit_field = "0.10.1"
|
||||||
|
bitflags = "1.3"
|
||||||
|
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||||
|
buddy_system_allocator = "0.9.0"
|
||||||
|
cfg-if = "1.0"
|
||||||
|
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
||||||
|
int-to-c-enum = { path = "../../services/libs/int-to-c-enum" }
|
||||||
|
intrusive-collections = "0.9.5"
|
||||||
|
ktest = { path = "../libs/ktest" }
|
||||||
|
lazy_static = { version = "1.0", features = ["spin_no_std"] }
|
||||||
|
log = "0.4"
|
||||||
|
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "d7dba56" }
|
||||||
|
spin = "0.9.4"
|
||||||
|
static_assertions = "1.1.0"
|
||||||
|
tdx-guest = { path = "../libs/tdx-guest", optional = true }
|
||||||
|
trapframe = { git = "https://github.com/jinzhao-dev/trapframe-rs", rev = "9758a83" }
|
||||||
|
unwinding = { version = "0.2.1", default-features = false, features = ["fde-static", "hide-trace", "panic", "personality", "unwinder"] }
|
||||||
|
volatile = { version = "0.4.5", features = ["unstable"] }
|
||||||
|
|
||||||
[target.x86_64-custom.dependencies]
|
[target.x86_64-custom.dependencies]
|
||||||
x86_64 = "0.14.2"
|
x86_64 = "0.14.2"
|
||||||
|
@ -21,20 +21,23 @@ SECTIONS
|
|||||||
|
|
||||||
. += KERNEL_VMA;
|
. += KERNEL_VMA;
|
||||||
|
|
||||||
.text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) }
|
.text : AT(ADDR(.text) - KERNEL_VMA) {
|
||||||
|
*(.text .text.*)
|
||||||
|
PROVIDE(__etext = .);
|
||||||
|
}
|
||||||
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) }
|
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) }
|
||||||
|
|
||||||
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) {
|
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) {
|
||||||
__eh_frame_hdr = .;
|
KEEP(*(.eh_frame_hdr .eh_frame_hdr.*))
|
||||||
KEEP(*(.eh_frame_hdr))
|
|
||||||
__eh_frame_hdr_end = .;
|
|
||||||
}
|
}
|
||||||
|
. = ALIGN(8);
|
||||||
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) {
|
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) {
|
||||||
__eh_frame = .;
|
PROVIDE(__eh_frame = .);
|
||||||
KEEP(*(.eh_frame))
|
KEEP(*(.eh_frame .eh_frame.*))
|
||||||
__eh_frame_end = .;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
|
||||||
.data.rel.ro : AT(ADDR(.data.rel.ro) - KERNEL_VMA) { *(.data.rel.ro .data.rel.ro.*) }
|
.data.rel.ro : AT(ADDR(.data.rel.ro) - KERNEL_VMA) { *(.data.rel.ro .data.rel.ro.*) }
|
||||||
.dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) }
|
.dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) }
|
||||||
|
|
@ -7,6 +7,7 @@ pub(crate) mod irq;
|
|||||||
pub(crate) mod kernel;
|
pub(crate) mod kernel;
|
||||||
pub(crate) mod mm;
|
pub(crate) mod mm;
|
||||||
pub(crate) mod pci;
|
pub(crate) mod pci;
|
||||||
|
pub mod qemu;
|
||||||
#[cfg(feature = "intel_tdx")]
|
#[cfg(feature = "intel_tdx")]
|
||||||
pub(crate) mod tdx_guest;
|
pub(crate) mod tdx_guest;
|
||||||
pub(crate) mod timer;
|
pub(crate) mod timer;
|
||||||
|
23
framework/jinux-frame/src/arch/x86/qemu.rs
Normal file
23
framework/jinux-frame/src/arch/x86/qemu.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//! QEMU isa debug device.
|
||||||
|
|
||||||
|
/// The exit code of x86 QEMU isa debug device. In `qemu-system-x86_64` the
|
||||||
|
/// exit code will be `(code << 1) | 1`. So you could never let QEMU invoke
|
||||||
|
/// `exit(0)`. We also need to check if the exit code is returned by the
|
||||||
|
/// kernel, so we couldn't use 0 as exit_success because this may conflict
|
||||||
|
/// with QEMU return value 1, which indicates that QEMU itself fails.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum QemuExitCode {
|
||||||
|
Success = 0x10,
|
||||||
|
Failed = 0x20,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
|
||||||
|
use x86_64::instructions::port::Port;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut port = Port::new(0xf4);
|
||||||
|
port.write(exit_code as u32);
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
@ -1,21 +1,22 @@
|
|||||||
//! The framework part of Jinux.
|
//! The framework part of Jinux.
|
||||||
#![no_std]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
#![feature(negative_impls)]
|
|
||||||
#![feature(fn_traits)]
|
|
||||||
#![feature(const_maybe_uninit_zeroed)]
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(const_maybe_uninit_zeroed)]
|
||||||
#![feature(new_uninit)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(strict_provenance)]
|
#![feature(const_ptr_sub_ptr)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(fn_traits)]
|
||||||
#![feature(generators)]
|
#![feature(generators)]
|
||||||
#![feature(iter_from_generator)]
|
#![feature(iter_from_generator)]
|
||||||
#![feature(const_mut_refs)]
|
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
#![feature(negative_impls)]
|
||||||
|
#![feature(new_uninit)]
|
||||||
|
#![feature(panic_info_message)]
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
#![feature(const_ptr_sub_ptr)]
|
#![feature(strict_provenance)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -32,6 +33,7 @@ pub mod cpu;
|
|||||||
mod error;
|
mod error;
|
||||||
pub mod io_mem;
|
pub mod io_mem;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
|
pub mod panicking;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
@ -44,14 +46,8 @@ pub mod vm;
|
|||||||
pub use self::cpu::CpuLocal;
|
pub use self::cpu::CpuLocal;
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use self::prelude::Result;
|
pub use self::prelude::Result;
|
||||||
use alloc::vec::Vec;
|
|
||||||
use arch::irq::{IrqCallbackHandle, IrqLine};
|
|
||||||
use core::{mem, panic::PanicInfo};
|
|
||||||
#[cfg(feature = "intel_tdx")]
|
#[cfg(feature = "intel_tdx")]
|
||||||
use tdx_guest::init_tdx;
|
use tdx_guest::init_tdx;
|
||||||
use trapframe::TrapFrame;
|
|
||||||
|
|
||||||
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
arch::before_all_init();
|
arch::before_all_init();
|
||||||
@ -69,19 +65,10 @@ pub fn init() {
|
|||||||
trap::init();
|
trap::init();
|
||||||
arch::after_all_init();
|
arch::after_all_init();
|
||||||
bus::init();
|
bus::init();
|
||||||
register_irq_common_callback();
|
invoke_ffi_init_funcs();
|
||||||
invoke_c_init_funcs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_irq_common_callback() {
|
fn invoke_ffi_init_funcs() {
|
||||||
unsafe {
|
|
||||||
for i in 0..256 {
|
|
||||||
IRQ_CALLBACK_LIST.push(IrqLine::acquire(i as u8).on_active(general_handler))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn invoke_c_init_funcs() {
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn __sinit_array();
|
fn __sinit_array();
|
||||||
fn __einit_array();
|
fn __einit_array();
|
||||||
@ -95,86 +82,17 @@ fn invoke_c_init_funcs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn general_handler(trap_frame: &TrapFrame) {
|
/// Unit test for the ktest framework and functions of the frame.
|
||||||
// info!("general handler");
|
|
||||||
// println!("{:#x?}", trap_frame);
|
|
||||||
// println!("rip = 0x{:x}", trap_frame.rip);
|
|
||||||
// println!("rsp = 0x{:x}", trap_frame.rsp);
|
|
||||||
// println!("cr2 = 0x{:x}", trap_frame.cr2);
|
|
||||||
// // println!("rbx = 0x{:x}", trap_frame.)
|
|
||||||
// panic!("couldn't handler trap right now");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) const fn zero<T>() -> T {
|
|
||||||
unsafe { mem::MaybeUninit::zeroed().assume_init() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The panic handler provided by Jinux Frame.
|
|
||||||
///
|
|
||||||
/// The definition of the real panic handler is located at the kernel binary
|
|
||||||
/// crate with the `#[panic_handler]` attribute. This function provides a
|
|
||||||
/// default implementation of the panic handler, which can forwarded to by the
|
|
||||||
/// kernel binary crate.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// extern crate jinux_frame;
|
|
||||||
/// #[panic_handler]
|
|
||||||
/// fn panic(info: &PanicInfo) -> ! {
|
|
||||||
/// jinux_frame::panic_handler(info);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn panic_handler(info: &PanicInfo) -> ! {
|
|
||||||
println!("[panic]:{:#?}", info);
|
|
||||||
// let mut fp: usize;
|
|
||||||
// let stop = unsafe{
|
|
||||||
// Task::current().kstack.get_top()
|
|
||||||
// };
|
|
||||||
// info!("stop:{:x}",stop);
|
|
||||||
// unsafe{
|
|
||||||
// asm!("mov rbp, {}", out(reg) fp);
|
|
||||||
// info!("fp:{:x}",fp);
|
|
||||||
// println!("---START BACKTRACE---");
|
|
||||||
// for i in 0..10 {
|
|
||||||
// if fp == stop {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// println!("#{}:ra={:#x}", i, *((fp - 8) as *const usize));
|
|
||||||
// info!("fp target:{:x}",*((fp ) as *const usize));
|
|
||||||
// fp = *((fp - 16) as *const usize);
|
|
||||||
// }
|
|
||||||
// println!("---END BACKTRACE---");
|
|
||||||
// }
|
|
||||||
exit_qemu(QemuExitCode::Failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The exit code of x86 QEMU isa debug device. In `qemu-system-x86_64` the
|
|
||||||
/// exit code will be `(code << 1) | 1`. So you could never let QEMU invoke
|
|
||||||
/// `exit(0)`. We also need to check if the exit code is returned by the
|
|
||||||
/// kernel, so we couldn't use 0 as exit_success because this may conflict
|
|
||||||
/// with QEMU return value 1, which indicates that QEMU itself fails.
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(u32)]
|
|
||||||
pub enum QemuExitCode {
|
|
||||||
Success = 0x10,
|
|
||||||
Failed = 0x20,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
|
|
||||||
use x86_64::instructions::port::Port;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let mut port = Port::new(0xf4);
|
|
||||||
port.write(exit_code as u32);
|
|
||||||
}
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[if_cfg_ktest]
|
#[if_cfg_ktest]
|
||||||
mod test {
|
mod test {
|
||||||
#[ktest]
|
#[ktest]
|
||||||
fn trivial_assertion() {
|
fn trivial_assertion() {
|
||||||
assert_eq!(0, 0);
|
assert_eq!(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ktest]
|
||||||
|
#[should_panic]
|
||||||
|
fn failing_assertion() {
|
||||||
|
assert_eq!(0, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
38
framework/jinux-frame/src/panicking.rs
Normal file
38
framework/jinux-frame/src/panicking.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//! Panic support in Jinux Frame.
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
|
||||||
|
use crate::arch::qemu::{exit_qemu, QemuExitCode};
|
||||||
|
use crate::println;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PanicInfo {
|
||||||
|
pub message: String,
|
||||||
|
pub file: String,
|
||||||
|
pub line: usize,
|
||||||
|
pub col: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for PanicInfo {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
writeln!(f, "Panicked at {}:{}:{}", self.file, self.line, self.col)?;
|
||||||
|
writeln!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
pub fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
let throw_info = PanicInfo {
|
||||||
|
message: info.message().unwrap().to_string(),
|
||||||
|
file: info.location().unwrap().file().to_string(),
|
||||||
|
line: info.location().unwrap().line() as usize,
|
||||||
|
col: info.location().unwrap().column() as usize,
|
||||||
|
};
|
||||||
|
// Throw an exception and expecting it to be caught.
|
||||||
|
unwinding::panic::begin_panic(Box::new(throw_info.clone()));
|
||||||
|
// If the exception is not caught (e.g. by ktest), then print the information
|
||||||
|
// and exit failed using the debug device.
|
||||||
|
println!("[uncaught panic] {}", info);
|
||||||
|
exit_qemu(QemuExitCode::Failed);
|
||||||
|
}
|
@ -21,6 +21,11 @@
|
|||||||
//! fn trivial_assertion() {
|
//! fn trivial_assertion() {
|
||||||
//! assert_eq!(0, 0);
|
//! assert_eq!(0, 0);
|
||||||
//! }
|
//! }
|
||||||
|
//! #[ktest]
|
||||||
|
//! #[should_panic]
|
||||||
|
//! fn failing_assertion() {
|
||||||
|
//! assert_eq!(0, 1);
|
||||||
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -54,8 +59,8 @@
|
|||||||
//! a default conditional compilation setting:
|
//! a default conditional compilation setting:
|
||||||
//! `#[cfg(all(ktest, any(ktest = "all", ktest = #crate_name)))]`
|
//! `#[cfg(all(ktest, any(ktest = "all", ktest = #crate_name)))]`
|
||||||
//!
|
//!
|
||||||
//! Currently we do not support `#[should_panic]` attribute, and this feature will
|
//! We do not support `#[should_panic]` attribute, but the implementation is quite
|
||||||
//! be added in the future.
|
//! slow currently. Use it with cautious.
|
||||||
//!
|
//!
|
||||||
//! Doctest is not taken into consideration yet, and the interface is subject to
|
//! Doctest is not taken into consideration yet, and the interface is subject to
|
||||||
//! change.
|
//! change.
|
||||||
@ -128,27 +133,43 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
proc_macro2::Span::call_site(),
|
proc_macro2::Span::call_site(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let should_panic = input.attrs.iter().any(|attr| {
|
||||||
|
attr.path()
|
||||||
|
.segments
|
||||||
|
.iter()
|
||||||
|
.any(|segment| segment.ident == "should_panic")
|
||||||
|
});
|
||||||
|
|
||||||
|
let package_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
||||||
let span = proc_macro::Span::call_site();
|
let span = proc_macro::Span::call_site();
|
||||||
let source = span.source_file();
|
let source = span.source_file().path();
|
||||||
let crate_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
let source = source.to_str().unwrap();
|
||||||
let hint_str = format!(
|
let line = span.line();
|
||||||
"[{}] {}: {}()",
|
let col = span.column();
|
||||||
crate_name,
|
|
||||||
source.path().to_str().unwrap(),
|
|
||||||
fn_name
|
|
||||||
);
|
|
||||||
|
|
||||||
let register = quote! {
|
let register = quote! {
|
||||||
struct #ktest_item_struct {
|
struct #ktest_item_struct {
|
||||||
fn_: fn() -> (),
|
fn_: fn() -> (),
|
||||||
hint: &'static str,
|
should_panic: bool,
|
||||||
|
module_path: &'static str,
|
||||||
|
fn_name: &'static str,
|
||||||
|
package: &'static str,
|
||||||
|
source: &'static str,
|
||||||
|
line: usize,
|
||||||
|
col: usize,
|
||||||
}
|
}
|
||||||
#[cfg(ktest)]
|
#[cfg(ktest)]
|
||||||
#[used]
|
#[used]
|
||||||
#[link_section = ".ktest_array"]
|
#[link_section = ".ktest_array"]
|
||||||
static #fn_ktest_item_name: #ktest_item_struct = #ktest_item_struct {
|
static #fn_ktest_item_name: #ktest_item_struct = #ktest_item_struct {
|
||||||
fn_: #fn_name,
|
fn_: #fn_name,
|
||||||
hint: #hint_str,
|
should_panic: #should_panic,
|
||||||
|
module_path: module_path!(),
|
||||||
|
fn_name: stringify!(#fn_name),
|
||||||
|
package: #package_name,
|
||||||
|
source: #source,
|
||||||
|
line: #line,
|
||||||
|
col: #col,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -165,27 +186,70 @@ pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn do_ktests(_item: TokenStream) -> TokenStream {
|
pub fn do_ktests(_item: TokenStream) -> TokenStream {
|
||||||
let body = quote! {
|
let body = quote! {
|
||||||
|
use crate::arch::qemu::{exit_qemu, QemuExitCode};
|
||||||
|
|
||||||
struct KtestItem {
|
struct KtestItem {
|
||||||
fn_: fn() -> (),
|
fn_: fn() -> (),
|
||||||
hint: &'static str,
|
should_panic: bool,
|
||||||
|
module_path: &'static str,
|
||||||
|
fn_name: &'static str,
|
||||||
|
package: &'static str,
|
||||||
|
source: &'static str,
|
||||||
|
line: usize,
|
||||||
|
col: usize,
|
||||||
};
|
};
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn __ktest_array();
|
fn __ktest_array();
|
||||||
fn __ktest_array_end();
|
fn __ktest_array_end();
|
||||||
}
|
};
|
||||||
let item_size = core::mem::size_of::<KtestItem>() as u64;
|
let item_size = core::mem::size_of::<KtestItem>() as u64;
|
||||||
let l = (__ktest_array_end as u64 - __ktest_array as u64) / item_size;
|
let l = (__ktest_array_end as u64 - __ktest_array as u64) / item_size;
|
||||||
crate::println!("Running {} tests", l);
|
crate::println!("Running {} tests", l);
|
||||||
for i in 0..l {
|
for i in 0..l {
|
||||||
unsafe {
|
unsafe {
|
||||||
let address = (__ktest_array as u64 + item_size * i) as *const u64;
|
let item_ptr = (__ktest_array as u64 + item_size * i) as *const u64;
|
||||||
let item = address as *const KtestItem;
|
let item = item_ptr as *const KtestItem;
|
||||||
crate::print!("{} ...", (*item).hint);
|
crate::print!("[{}] test {}::{} ...", (*item).package, (*item).module_path, (*item).fn_name);
|
||||||
((*item).fn_)();
|
let test_result = unwinding::panic::catch_unwind((*item).fn_);
|
||||||
|
let print_failure_heading = || {
|
||||||
|
crate::println!("\nfailures:\n");
|
||||||
|
crate::println!("---- {}:{}:{} - {} ----", (*item).source, (*item).line, (*item).col, (*item).fn_name);
|
||||||
|
};
|
||||||
|
if !(*item).should_panic {
|
||||||
|
match test_result {
|
||||||
|
Ok(()) => {
|
||||||
|
crate::println!(" ok");
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
crate::println!(" FAILED");
|
||||||
|
print_failure_heading();
|
||||||
|
match e.downcast::<crate::panicking::PanicInfo>() {
|
||||||
|
Ok(s) => {
|
||||||
|
crate::println!("[caught panic] {}", s);
|
||||||
|
},
|
||||||
|
Err(payload) => {
|
||||||
|
crate::println!("[caught panic] unknown panic payload: {:#?}", payload);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
exit_qemu(QemuExitCode::Failed);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match test_result {
|
||||||
|
Ok(()) => {
|
||||||
|
crate::println!(" FAILED");
|
||||||
|
print_failure_heading();
|
||||||
|
crate::println!("test did not panic as expected");
|
||||||
|
exit_qemu(QemuExitCode::Failed);
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
crate::println!(" ok");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
crate::println!(" Ok!");
|
|
||||||
}
|
}
|
||||||
crate::exit_qemu(crate::QemuExitCode::Success);
|
exit_qemu(QemuExitCode::Success);
|
||||||
};
|
};
|
||||||
|
|
||||||
TokenStream::from(body)
|
TokenStream::from(body)
|
||||||
|
@ -1,23 +1,17 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
// The `no_mangle`` attribute for the `jinux_main` entrypoint requires the removal of safety check.
|
// The `export_name` attribute for the `jinux_main` entrypoint requires the removal of safety check.
|
||||||
// Please be aware that the kernel is not allowed to introduce any other unsafe operations.
|
// Please be aware that the kernel is not allowed to introduce any other unsafe operations.
|
||||||
// #![forbid(unsafe_code)]
|
// #![forbid(unsafe_code)]
|
||||||
extern crate jinux_frame;
|
extern crate jinux_frame;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
use jinux_frame::println;
|
use jinux_frame::println;
|
||||||
|
|
||||||
#[no_mangle]
|
#[export_name = "jinux_main"]
|
||||||
pub fn jinux_main() -> ! {
|
pub fn main() -> ! {
|
||||||
jinux_frame::init();
|
jinux_frame::init();
|
||||||
println!("[kernel] finish init jinux_frame");
|
println!("[kernel] finish init jinux_frame");
|
||||||
component::init_all(component::parse_metadata!()).unwrap();
|
component::init_all(component::parse_metadata!()).unwrap();
|
||||||
jinux_std::init();
|
jinux_std::init();
|
||||||
jinux_std::run_first_process();
|
jinux_std::run_first_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::panic_handler(info);
|
|
||||||
}
|
|
||||||
|
@ -27,7 +27,10 @@ use crate::{
|
|||||||
Thread,
|
Thread,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use jinux_frame::{boot, exit_qemu, QemuExitCode};
|
use jinux_frame::{
|
||||||
|
arch::qemu::{exit_qemu, QemuExitCode},
|
||||||
|
boot,
|
||||||
|
};
|
||||||
use process::Process;
|
use process::Process;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
@ -531,9 +531,6 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[ktest]
|
#[ktest]
|
||||||
// FIXME: should_panic doesn't work with ktest, two negative makes a positive...
|
|
||||||
#[should_panic]
|
|
||||||
/// FIXME: alloc continuous frames is not supported now
|
|
||||||
fn alloc_continuous_vmo() {
|
fn alloc_continuous_vmo() {
|
||||||
let vmo = VmoOptions::<Full>::new(10 * PAGE_SIZE)
|
let vmo = VmoOptions::<Full>::new(10 * PAGE_SIZE)
|
||||||
.flags(VmoFlags::CONTIGUOUS)
|
.flags(VmoFlags::CONTIGUOUS)
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
"executables": true,
|
"executables": true,
|
||||||
"linker-flavor": "ld.lld",
|
"linker-flavor": "ld.lld",
|
||||||
"linker": "rust-lld",
|
"linker": "rust-lld",
|
||||||
"panic-strategy": "abort",
|
|
||||||
"disable-redzone": true,
|
"disable-redzone": true,
|
||||||
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
|
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user