add CI autotest, update README

This commit is contained in:
Yu Chen 2022-06-24 01:26:26 +08:00
parent f79bb085a6
commit 39037a97ca
11 changed files with 386 additions and 72 deletions

View file

@ -37,6 +37,9 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64
# Disassembly
DISASM ?= -x
# Run usertests or usershell
TEST ?=
build: env switch-check $(KERNEL_BIN) fs-img
switch-check:
@ -61,7 +64,7 @@ $(KERNEL_BIN): kernel
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
fs-img: $(APPS)
@cd ../user && make build
@cd ../user && make build TEST=$(TEST)
@rm -f $(FS_IMG)
@cd ../easy-fs-fuse && cargo run --release -- -s ../user/src/bin/ -t ../user/target/riscv64gc-unknown-none-elf/release/

View file

@ -1,4 +1,5 @@
pub const CLOCK_FREQ: usize = 403000000 / 62;
pub const MEMORY_END: usize = 0x80600000;
pub const MMIO: &[(usize, usize)] = &[
// we don't need clint in S priv when running

View file

@ -1,5 +1,89 @@
pub const CLOCK_FREQ: usize = 12500000;
pub const MEMORY_END: usize = 0x801000000;
pub const MMIO: &[(usize, usize)] = &[(0x10001000, 0x1000)];
pub const MMIO: &[(usize, usize)] = &[
(0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine
(0x1000_1000, 0x00_1000), // Virtio Block in virt machine
];
pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock;
//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);

View file

@ -4,11 +4,11 @@
pub const USER_STACK_SIZE: usize = 4096 * 2;
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
pub const KERNEL_HEAP_SIZE: usize = 0x20_0000;
pub const MEMORY_END: usize = 0x80800000;
pub const PAGE_SIZE: usize = 0x1000;
pub const PAGE_SIZE_BITS: usize = 0xc;
pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE;
pub use crate::board::{CLOCK_FREQ, MMIO};
pub use crate::board::{CLOCK_FREQ, MEMORY_END, MMIO};

View file

@ -55,10 +55,35 @@ pub fn suspend_current_and_run_next() {
// jump to scheduling cycle
schedule(task_cx_ptr);
}
/// pid of usertests app in make run TEST=1
pub const IDLE_PID: usize = 0;
#[cfg(feature = "board_qemu")]
use crate::board::QEMUExit;
/// Exit the current 'Running' task and run the next task in task list.
pub fn exit_current_and_run_next(exit_code: i32) {
// take from Processor
let task = take_current_task().unwrap();
#[cfg(feature = "board_qemu")]
let pid = task.getpid();
#[cfg(feature = "board_qemu")]
if pid == IDLE_PID {
println!(
"[kernel] Idle process exit with exit_code {} ...",
exit_code
);
if exit_code != 0 {
//crate::sbi::shutdown(255); //255 == -1 for err hint
crate::board::QEMU_EXIT_HANDLE.exit_failure();
} else {
//crate::sbi::shutdown(0); //0 for success hint
crate::board::QEMU_EXIT_HANDLE.exit_success();
}
}
// **** access current TCB exclusively
let mut inner = task.inner_exclusive_access();
// Change status to Zombie