diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 3179463..373d666 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -42,4 +42,5 @@ uintr = { path = "../crates/uintr" } default = ["oscomp", "test"] test = [] oscomp = [] -uintr = [] \ No newline at end of file +uintr = [] +sleeplock = [] \ No newline at end of file diff --git a/kernel/src/arch/riscv64/trap/mod.rs b/kernel/src/arch/riscv64/trap/mod.rs index ff6f5b6..6c6086f 100644 --- a/kernel/src/arch/riscv64/trap/mod.rs +++ b/kernel/src/arch/riscv64/trap/mod.rs @@ -55,6 +55,9 @@ pub fn enable_timer_intr() { /// 2. Handles page fault caused by Instruction Fetch, Load or Store. #[no_mangle] pub fn user_trap_handler() -> ! { + #[cfg(feature = "uintr")] + uintr_save(); + set_kernel_trap(); let scause = scause::read(); @@ -136,7 +139,8 @@ pub fn user_trap_handler() -> ! { /// current task. We must drop them before changing the control flow without unwinding. #[no_mangle] pub fn user_trap_return() -> ! { - // crate::tests::sleeplock::test(); + #[cfg(feature = "sleeplock")] + crate::tests::sleeplock::test(); #[cfg(feature = "uintr")] uintr_return(); diff --git a/kernel/src/arch/riscv64/uintr.rs b/kernel/src/arch/riscv64/uintr.rs index 54f2115..517abfd 100644 --- a/kernel/src/arch/riscv64/uintr.rs +++ b/kernel/src/arch/riscv64/uintr.rs @@ -182,6 +182,9 @@ pub struct TaskUIntrInner { /// User interrupt handler pub uscratch: usize, + + /// User error pc + pub uepc: usize, } impl TaskUIntrInner { @@ -192,6 +195,7 @@ impl TaskUIntrInner { mask: 0, utvec: 0, uscratch: 0, + uepc: 0, } } @@ -355,7 +359,11 @@ mod syscall { /// Synchronize receiver status to UINTC and raise user interrupt if kernel returns to /// a receiver with pending interrupt requests. - pub unsafe fn uirs_sync() { + /// + /// Each time a receiver traps into a U-mode trap handler, it can be migrated to another hart + /// caused by U-ecall or other exceptions thus we must save and restore CPU-local registers such + /// as `upec`, `utvec` and `uscratch`. + pub unsafe fn uirs_restore() { let uintr_inner = cpu().curr.as_ref().unwrap().uintr_inner(); if let Some(uirs) = &uintr_inner.uirs { let index = uirs.0; @@ -364,9 +372,10 @@ mod syscall { uirs.mode |= 0x2; // 64 bits uirs.sync(index); - log::trace!("uirs_sync {:x} {:x?}", index, uirs); + log::trace!("uirs_restore {:x} {:x?}", index, uirs); // user configurations + uepc::write(uintr_inner.uepc); utvec::write(uintr_inner.utvec, utvec::TrapMode::Direct); uscratch::write(uintr_inner.uscratch); uie::set_usoft(); @@ -400,12 +409,19 @@ mod syscall { /// Called during trap return. pub fn uintr_return() { // receiver - unsafe { uirs_sync() }; + unsafe { uirs_restore() }; // sender uist_init(); } + /// Called when task traps into kernel. + pub fn uintr_save() { + let curr = cpu().curr.as_ref().unwrap(); + + curr.uintr_inner().uepc = uepc::read(); + } + pub struct UIntrFile { pub uirs_index: usize, pub vector: usize, diff --git a/kernel/src/cons/logger.rs b/kernel/src/cons/logger.rs index 3a01b19..9c564d7 100644 --- a/kernel/src/cons/logger.rs +++ b/kernel/src/cons/logger.rs @@ -18,7 +18,7 @@ impl Log for Logger { Level::Warn => 93, // BrightYellow Level::Info => 34, // Blue Level::Debug => 32, // Green - Level::Trace => 90, // BrightBlack + Level::Trace => 33, // BrightBlack }; let cpu_id = get_cpu_id(); println!( diff --git a/kernel/src/main.rs b/kernel/src/main.rs index fa50f36..2f5cda9 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -76,9 +76,11 @@ pub extern "C" fn rust_main(hartid: usize) -> ! { #[no_mangle] pub extern "C" fn rust_main_others(hartid: usize) -> ! { // Other initializations. - arch::init(hartid, false); info!("(Secondary) Start executing tasks."); + // Enable timer interrupt + arch::trap::enable_timer_intr(); + timer::set_next_trigger(); // IDLE loop unsafe { task::idle() }; } diff --git a/test b/test index 71f0659..cbfb47f 160000 --- a/test +++ b/test @@ -1 +1 @@ -Subproject commit 71f0659875208374c445ac03b93be22c06fca610 +Subproject commit cbfb47f3c231613cf0fc74b3dd4d393c5fadbeaf