diff --git a/.gitignore b/.gitignore index 770aba77..9fc90c58 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ easy-fs-fuse/Cargo.lock easy-fs-fuse/target/* tools/ pushall.sh +*.bak diff --git a/os/src/main.rs b/os/src/main.rs index 5ad63749..6494e1d0 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -15,6 +15,8 @@ //! We then call [`task::run_first_task()`] and for the first time go to //! userspace. +#![deny(missing_docs)] +#![deny(warnings)] #![no_std] #![no_main] #![feature(panic_info_message)] diff --git a/os/src/sync/up.rs b/os/src/sync/up.rs index 039b0397..e8ba20c8 100644 --- a/os/src/sync/up.rs +++ b/os/src/sync/up.rs @@ -24,7 +24,7 @@ impl UPSafeCell { inner: RefCell::new(value), } } - /// Panic if the data has been borrowed. + /// Exclusive access inner data in UPSafeCell. Panic if the data has been borrowed. pub fn exclusive_access(&self) -> RefMut<'_, T> { self.inner.borrow_mut() } diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 0cbd0ca0..2fe02bc6 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -5,6 +5,7 @@ use crate::task::current_user_token; const FD_STDOUT: usize = 1; +/// write buf of length `len` to a file with `fd` pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { match fd { FD_STDOUT => { diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index a26fb3fe..e5b4ad42 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -3,17 +3,20 @@ use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; use crate::timer::get_time_ms; +/// task exits and submit an exit code pub fn sys_exit(exit_code: i32) -> ! { println!("[kernel] Application exited with code {}", exit_code); exit_current_and_run_next(); panic!("Unreachable in sys_exit!"); } +/// current task gives up resources for other tasks pub fn sys_yield() -> isize { suspend_current_and_run_next(); 0 } +/// get current time pub fn sys_get_time() -> isize { get_time_ms() as isize } diff --git a/os/src/task/context.rs b/os/src/task/context.rs index 8e4f5473..d945c5e0 100644 --- a/os/src/task/context.rs +++ b/os/src/task/context.rs @@ -4,12 +4,16 @@ use crate::trap::trap_return; #[repr(C)] /// task context structure containing some registers pub struct TaskContext { + /// return address ( e.g. __restore ) of __switch ASM function ra: usize, + /// kernel stack pointer of app sp: usize, + /// callee saved registers: s 0..11 s: [usize; 12], } impl TaskContext { + /// init task context pub fn zero_init() -> Self { Self { ra: 0, @@ -17,6 +21,7 @@ impl TaskContext { s: [0; 12], } } + /// set Task Context{__restore ASM funciton: trap_return, sp: kstack_ptr, s: s_0..12} pub fn goto_trap_return(kstack_ptr: usize) -> Self { Self { ra: trap_return as usize, diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index ee36241b..0f548d0a 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -6,7 +6,7 @@ //! A single global instance of [`TaskManager`] called `TASK_MANAGER` controls //! all the tasks in the operating system. //! -//! Be careful when you see [`__switch`]. Control flow around this function +//! Be careful when you see `__switch` ASM function in `switch.S`. Control flow around this function //! might not be what you expect. mod context; @@ -49,7 +49,7 @@ struct TaskManagerInner { } lazy_static! { - /// a `TaskManager` instance through lazy_static! + /// a `TaskManager` global instance through lazy_static! pub static ref TASK_MANAGER: TaskManager = { println!("init TASK_MANAGER"); let num_app = get_num_app(); diff --git a/os/src/trap/context.rs b/os/src/trap/context.rs index 420c016b..527d1b61 100644 --- a/os/src/trap/context.rs +++ b/os/src/trap/context.rs @@ -5,18 +5,26 @@ use riscv::register::sstatus::{self, Sstatus, SPP}; #[repr(C)] /// trap context structure containing sstatus, sepc and registers pub struct TrapContext { + /// general regs[0..31] pub x: [usize; 32], + /// CSR sstatus pub sstatus: Sstatus, + /// CSR sepc pub sepc: usize, + /// Addr of Page Table pub kernel_satp: usize, + /// kernel stack pub kernel_sp: usize, + /// Addr of trap_handler function pub trap_handler: usize, } impl TrapContext { + /// set stack pointer to x_2 reg (sp) pub fn set_sp(&mut self, sp: usize) { self.x[2] = sp; } + /// init app context pub fn app_init_context( entry: usize, sp: usize, @@ -24,17 +32,17 @@ impl TrapContext { kernel_sp: usize, trap_handler: usize, ) -> Self { - let mut sstatus = sstatus::read(); - sstatus.set_spp(SPP::User); + let mut sstatus = sstatus::read(); // CSR sstatus + sstatus.set_spp(SPP::User); //previous privilege mode: user mode let mut cx = Self { x: [0; 32], sstatus, - sepc: entry, - kernel_satp, - kernel_sp, - trap_handler, + sepc: entry, // entry point of app + kernel_satp, // addr of page table + kernel_sp, // kernel stack + trap_handler,// addr of trap_handler function }; - cx.set_sp(sp); - cx + cx.set_sp(sp); // app's user stack pointer + cx // return initial Trap Context of app } } diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 56aec31a..14fb76b2 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -28,6 +28,7 @@ use riscv::register::{ global_asm!(include_str!("trap.S")); +/// initialize CSR `stvec` as the entry of `__alltraps` pub fn init() { set_kernel_trap_entry(); } @@ -44,6 +45,7 @@ fn set_user_trap_entry() { } } +/// enable timer interrupt in sie CSR pub fn enable_timer_interrupt() { unsafe { sie::set_stimer(); @@ -51,6 +53,7 @@ pub fn enable_timer_interrupt() { } #[no_mangle] +/// handle an interrupt, exception, or system call from user space pub fn trap_handler() -> ! { set_kernel_trap_entry(); let cx = current_trap_cx(); @@ -86,6 +89,9 @@ pub fn trap_handler() -> ! { } #[no_mangle] +/// set the new addr of __restore asm function in TRAMPOLINE page, +/// set the reg a0 = trap_cx_ptr, reg a1 = phy addr of usr page table, +/// finally, jump to new addr of __restore asm function pub fn trap_return() -> ! { set_user_trap_entry(); let trap_cx_ptr = TRAP_CONTEXT; @@ -98,16 +104,18 @@ pub fn trap_return() -> ! { unsafe { asm!( "fence.i", - "jr {restore_va}", + "jr {restore_va}", // jump to new addr of __restore asm function restore_va = in(reg) restore_va, - in("a0") trap_cx_ptr, - in("a1") user_satp, + in("a0") trap_cx_ptr, // a0 = virt addr of Trap Context + in("a1") user_satp, // a1 = phy addr of usr page table options(noreturn) ); } } #[no_mangle] +/// Unimplement: traps/interrupts/exceptions from kernel mode +/// Todo: Chapter 9: I/O device pub fn trap_from_kernel() -> ! { panic!("a trap from kernel!"); }