Implement OSDK functionalities and opt-in OSDK for asterinas

This commit is contained in:
Zhang Junyang
2024-02-21 16:58:40 +08:00
committed by Tate, Hongliang Tian
parent bc9bce9dea
commit f97d0f1260
103 changed files with 1663 additions and 1295 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
align_ext = { path = "../libs/align_ext" }
aster-main = { path = "../libs/aster-main" }
bit_field = "0.10.1"
bitflags = "1.3"
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }

View File

@ -1,74 +0,0 @@
ENTRY(__multiboot_boot)
OUTPUT_ARCH(i386:x86-64)
OUTPUT_FORMAT(elf64-x86-64)
KERNEL_LMA = 0x8000000;
LINUX_32_ENTRY = 0x8001000;
KERNEL_VMA = 0xffffffff80000000;
SECTIONS
{
. = KERNEL_LMA;
__kernel_start = .;
.multiboot_header : { KEEP(*(.multiboot_header)) }
.multiboot2_header : { KEEP(*(.multiboot2_header)) }
. = LINUX_32_ENTRY;
.boot : { KEEP(*(.boot)) }
. += KERNEL_VMA;
.text : AT(ADDR(.text) - KERNEL_VMA) {
*(.text .text.*)
PROVIDE(__etext = .);
}
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) }
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) {
KEEP(*(.eh_frame_hdr .eh_frame_hdr.*))
}
. = ALIGN(8);
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) {
PROVIDE(__eh_frame = .);
KEEP(*(.eh_frame .eh_frame.*))
}
.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.*) }
.dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) }
.init_array : AT(ADDR(.init_array) - KERNEL_VMA) {
__sinit_array = .;
KEEP(*(SORT(.init_array .init_array.*)))
__einit_array = .;
}
.got : AT(ADDR(.got) - KERNEL_VMA) { *(.got .got.*) }
.got.plt : AT(ADDR(.got.plt) - KERNEL_VMA) { *(.got.plt .got.plt.*) }
. = DATA_SEGMENT_RELRO_END(0, .);
.data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) }
.bss : AT(ADDR(.bss) - KERNEL_VMA) {
__bss = .;
*(.bss .bss.*) *(COMMON)
__bss_end = .;
}
.ktest_array : AT(ADDR(.ktest_array) - KERNEL_VMA) {
__ktest_array = .;
KEEP(*(SORT(.ktest_array)))
__ktest_array_end = .;
}
.tdata : AT(ADDR(.tdata) - KERNEL_VMA) { *(.tdata .tdata.*) }
.tbss : AT(ADDR(.tbss) - KERNEL_VMA) { *(.tbss .tbss.*) }
. = DATA_SEGMENT_END(.);
__kernel_end = . - KERNEL_VMA;
}

View File

@ -91,11 +91,6 @@ impl From<&str> for KCmdlineArg {
// The main parse loop. The processing steps are arranged (not very strictly)
// by the analysis over the BackusNaur form syntax tree.
for arg in split_arg(cmdline) {
// FIXME: The -kernel option in QEMU seems to add this string to the command line, which we skip for now.
if arg.starts_with("target/x86_64-custom/") {
warn!("Found kcmdline: {:?}, skipped for now.", arg);
continue;
}
// Cmdline => KernelArg "--" InitArg
// KernelArg => Arg "\s+" KernelArg | %empty
// InitArg => Arg "\s+" InitArg | %empty
@ -116,7 +111,8 @@ impl From<&str> for KCmdlineArg {
1 => (arg_pattern[0], None),
2 => (arg_pattern[0], Some(arg_pattern[1])),
_ => {
panic!("Unable to parse argument {}", arg);
warn!("Unable to parse kernel argument {}, skip for now", arg);
continue;
}
};
// Entry => Module "." ModuleOptionName | KernelOptionName
@ -125,7 +121,11 @@ impl From<&str> for KCmdlineArg {
1 => (None, entry_pattern[0]),
2 => (Some(entry_pattern[0]), entry_pattern[1]),
_ => {
panic!("Unable to parse entry {} in argument {}", entry, arg);
warn!(
"Unable to parse entry {} in argument {}, skip for now",
entry, arg
);
continue;
}
};
if let Some(modname) = node {

View File

@ -113,48 +113,38 @@ pub fn call_aster_main() -> ! {
// The entry point of kernel code, which should be defined by the package that
// uses aster-frame.
extern "Rust" {
fn aster_main() -> !;
fn __aster_main() -> !;
}
aster_main();
__aster_main();
}
#[cfg(ktest)]
{
use alloc::{boxed::Box, string::ToString};
use core::any::Any;
use crate::arch::qemu::{exit_qemu, QemuExitCode};
unsafe {
crate::init();
let fn_catch_unwind = &(unwinding::panic::catch_unwind::<(), fn()>
as fn(fn()) -> Result<(), Box<(dyn Any + Send + 'static)>>);
// Parse the whitelist from the kernel command line.
let mut paths = None;
let args = kernel_cmdline().get_module_args("ktest");
if let Some(args) = args {
for options in args {
match options {
kcmdline::ModuleArg::KeyVal(key, val) => {
if key.to_str().unwrap() == "whitelist" && val.to_str().unwrap() != "" {
let paths_str = val.to_str().unwrap();
paths = Some(
paths_str
.split(',')
.map(|s| s.to_string())
.collect::<Vec<_>>(),
);
}
}
_ => {}
}
}
}
use ktest::runner::{run_ktests, KtestResult};
match run_ktests(
&crate::console::print,
fn_catch_unwind,
paths.map(|v| v.into_iter()),
) {
KtestResult::Ok => exit_qemu(QemuExitCode::Success),
KtestResult::Failed => exit_qemu(QemuExitCode::Failed),
// The whitelists that will be generated by OSDK runner as static consts.
extern "Rust" {
static KTEST_TEST_WHITELIST: Option<&'static [&'static str]>;
static KTEST_CRATE_WHITELIST: Option<&'static [&'static str]>;
}
run_ktests(KTEST_TEST_WHITELIST, KTEST_CRATE_WHITELIST);
}
}
fn run_ktests(test_whitelist: Option<&[&str]>, crate_whitelist: Option<&[&str]>) -> ! {
use crate::arch::qemu::{exit_qemu, QemuExitCode};
use alloc::{boxed::Box, string::ToString};
use core::any::Any;
let fn_catch_unwind = &(unwinding::panic::catch_unwind::<(), fn()>
as fn(fn()) -> Result<(), Box<(dyn Any + Send + 'static)>>);
use ktest::runner::{run_ktests, KtestResult};
match run_ktests(
&crate::console::print,
fn_catch_unwind,
test_whitelist.map(|s| s.iter().map(|s| s.to_string())),
crate_whitelist,
) {
KtestResult::Ok => exit_qemu(QemuExitCode::Success),
KtestResult::Failed => exit_qemu(QemuExitCode::Failed),
};
}

View File

@ -19,6 +19,7 @@
#![no_std]
extern crate alloc;
#[cfg(ktest)]
#[macro_use]
extern crate ktest;
#[macro_use]
@ -83,7 +84,7 @@ fn invoke_ffi_init_funcs() {
}
/// Simple unit tests for the ktest framework.
#[if_cfg_ktest]
#[cfg(ktest)]
mod test {
#[ktest]
fn trivial_assertion() {

View File

@ -23,12 +23,12 @@ use unwinding::{
panic::begin_panic,
};
fn abort() -> ! {
exit_qemu(QemuExitCode::Failed);
}
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
/// The panic handler must be defined in the binary crate or in the crate that the binary
/// crate explicity declares by `extern crate`. We cannot let the base crate depend on the
/// framework due to prismatic dependencies. That's why we export this symbol and state the
/// panic handler in the binary crate.
#[export_name = "__aster_panic_handler"]
pub fn panic_handler(info: &core::panic::PanicInfo) -> ! {
let throw_info = ktest::PanicInfo {
message: info.message().unwrap().to_string(),
file: info.location().unwrap().file().to_string(),
@ -46,6 +46,10 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
abort();
}
fn abort() -> ! {
exit_qemu(QemuExitCode::Failed);
}
fn print_stack_trace() {
struct CallbackData {
counter: usize,

View File

@ -8,3 +8,7 @@ pub(crate) use alloc::{boxed::Box, sync::Arc, vec::Vec};
pub(crate) use core::any::Any;
pub use crate::vm::{Paddr, Vaddr};
pub use crate::early_print as print;
pub use crate::early_println as println;
pub use aster_main::aster_main;

View File

@ -288,7 +288,7 @@ impl fmt::Debug for AtomicBits {
}
}
#[if_cfg_ktest]
#[cfg(ktest)]
mod test {
use super::*;

View File

@ -162,7 +162,7 @@ impl HasPaddr for DmaCoherent {
}
}
#[if_cfg_ktest]
#[cfg(ktest)]
mod test {
use alloc::vec;

View File

@ -195,7 +195,7 @@ impl HasPaddr for DmaStream {
}
}
#[if_cfg_ktest]
#[cfg(ktest)]
mod test {
use alloc::vec;