diff --git a/ch2/os/src/main.rs b/ch2/os/src/main.rs index 38b837a..5dbc93a 100644 --- a/ch2/os/src/main.rs +++ b/ch2/os/src/main.rs @@ -11,6 +11,7 @@ pub mod sbi; pub mod batch; pub mod sync; pub mod trap; +pub mod syscall; // 汇编脚本引入, 调整内核的内存布局之后, 会跳入到 rust_main中执行 global_asm!(include_str!("entry.asm")); @@ -35,6 +36,7 @@ pub fn rust_main(){ println!("sbss: {:#x}, ebss: {:#x}", sbss as usize, ebss as usize); println!("boot_stack_top_bound: {:#x}, boot_stack_lower_bound: {:#x}", boot_stack_top_bound as usize, boot_stack_lower_bound as usize); + trap::init(); batch::init(); batch::run_next_app(); } diff --git a/ch2/os/src/trap/mod.rs b/ch2/os/src/trap/mod.rs index bc6c71e..79418b8 100644 --- a/ch2/os/src/trap/mod.rs +++ b/ch2/os/src/trap/mod.rs @@ -1,2 +1,66 @@ mod context; + +use core::arch::global_asm; +use riscv::register::{ + mtvec::TrapMode, + scause::{self, Exception, Trap}, + stval, stvec, +}; pub use context::TrapContext; +use crate::batch::run_next_app; +use crate::println; +use crate::syscall::syscall; + + + +// 引入陷入保存寄存器需要的汇编代码 +global_asm!(include_str!("trap.S")); + +/// 初始化stvec 寄存器, 这个寄存器保存陷入时, 入口函数的地址 +pub fn init() { + extern "C" { + fn __alltraps(); + } + unsafe { + stvec::write(__alltraps as usize, TrapMode::Direct); + } +} + + +// 这个函数是 trap.S 中__alltraps 保存完所有寄存器在内核栈 之后会进入到这里 +#[no_mangle] +pub fn trap_handler(trap_context: &mut TrapContext) -> &mut TrapContext { + let scause = scause::read(); // trap 发生的原因 + let stval = stval::read(); // trap的附加信息 + + // 根据发生的原因判断是那种类别 + match scause.cause() { + // 用户态发出的系统调用 + Trap::Exception(Exception::UserEnvCall) => { + trap_context.sepc += 4; // +4 是因为我们需要返回 ecall指令的下一个指令 + trap_context.x[10] = syscall(trap_context.x[17], [trap_context.x[10], trap_context.x[11], trap_context.x[12]]) as usize; + } + // 访问不允许的内存 + Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { + println!("[kernel] PageFault in application, kernel killed it."); + run_next_app(); + } + // 非法指令 + Trap::Exception(Exception::IllegalInstruction) => { + println!("[kernel] IllegalInstruction in application, kernel killed it."); + run_next_app(); + } + // 未知错误 + _ => { + panic!( + "Unsupported trap {:?}, stval = {:#x}!", + scause.cause(), + stval + ); + } + } + trap_context +} + + + diff --git a/ch2/os/src/trap/trap.S b/ch2/os/src/trap/trap.S index 804e782..be27631 100644 --- a/ch2/os/src/trap/trap.S +++ b/ch2/os/src/trap/trap.S @@ -38,7 +38,7 @@ __alltraps: # __alltraps 符号的实现 sd t2, 2*8(sp) # 保存用户栈的地址到内核栈 trap context中 # 设置 trap_handler(cx: &mut TrapContext) 的输入参数 mv a0, sp # 将 TrapContext 的地址赋值给 a0 - call trap_handler # 调用 trap_handler 函# 数 + call trap_handler # 调用 trap_handler 分发函数 __restore: # __restore 符号的实现 # case1: 开始运行应用程序