diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index ccfadba8..ebb07b47 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -2,6 +2,7 @@ mod context; mod manager; mod pid; mod processor; +mod signal; mod switch; mod task; @@ -18,6 +19,7 @@ pub use pid::{pid_alloc, KernelStack, PidHandle}; pub use processor::{ current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task, }; +pub use signal::SignalFlags; pub fn suspend_current_and_run_next() { // There must be an application running. @@ -83,3 +85,15 @@ lazy_static! { pub fn add_initproc() { add_task(INITPROC.clone()); } + +pub fn check_signals_of_current() -> Option<(i32, &'static str)> { + let task = current_task().unwrap(); + let task_inner = task.inner_exclusive_access(); + task_inner.signals.check_error() +} + +pub fn current_add_signal(signal: SignalFlags) { + let task = current_task().unwrap(); + let mut task_inner = task.inner_exclusive_access(); + task_inner.signals |= signal; +} diff --git a/os/src/task/signal.rs b/os/src/task/signal.rs new file mode 100644 index 00000000..2da01399 --- /dev/null +++ b/os/src/task/signal.rs @@ -0,0 +1,29 @@ +use bitflags::*; + +bitflags! { + pub struct SignalFlags: u32 { + const SIGINT = 1 << 2; + const SIGILL = 1 << 4; + const SIGABRT = 1 << 6; + const SIGFPE = 1 << 8; + const SIGSEGV = 1 << 11; + } +} + +impl SignalFlags { + pub fn check_error(&self) -> Option<(i32, &'static str)> { + if self.contains(Self::SIGINT) { + Some((-2, "Killed, SIGINT=2")) + } else if self.contains(Self::SIGILL) { + Some((-4, "Illegal Instruction, SIGILL=4")) + } else if self.contains(Self::SIGABRT) { + Some((-6, "Aborted, SIGABRT=6")) + } else if self.contains(Self::SIGFPE) { + Some((-8, "Erroneous Arithmetic Operation, SIGFPE=8")) + } else if self.contains(Self::SIGSEGV) { + Some((-11, "Segmentation Fault, SIGSEGV=11")) + } else { + None + } + } +} diff --git a/os/src/task/task.rs b/os/src/task/task.rs index e0567ccb..e156638a 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,5 +1,5 @@ use super::TaskContext; -use super::{pid_alloc, KernelStack, PidHandle}; +use super::{pid_alloc, KernelStack, PidHandle, SignalFlags}; use crate::config::TRAP_CONTEXT; use crate::fs::{File, Stdin, Stdout}; use crate::mm::{translated_refmut, MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE}; @@ -29,6 +29,7 @@ pub struct TaskControlBlockInner { pub children: Vec>, pub exit_code: i32, pub fd_table: Vec>>, + pub signals: SignalFlags, } impl TaskControlBlockInner { @@ -90,6 +91,7 @@ impl TaskControlBlock { // 2 -> stderr Some(Arc::new(Stdout)), ], + signals: SignalFlags::empty(), }) }, }; @@ -191,6 +193,7 @@ impl TaskControlBlock { children: Vec::new(), exit_code: 0, fd_table: new_fd_table, + signals: SignalFlags::empty(), }) }, }); diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 4c9a1128..eb534b85 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -3,7 +3,7 @@ mod context; use crate::config::{TRAMPOLINE, TRAP_CONTEXT}; use crate::syscall::syscall; use crate::task::{ - current_trap_cx, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, + current_trap_cx, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, current_add_signal, SignalFlags, check_signals_of_current, }; use crate::timer::set_next_trigger; use core::arch::{asm, global_asm}; @@ -59,19 +59,18 @@ pub fn trap_handler() -> ! { | Trap::Exception(Exception::InstructionPageFault) | Trap::Exception(Exception::LoadFault) | Trap::Exception(Exception::LoadPageFault) => { + /* println!( "[kernel] {:?} in application, bad addr = {:#x}, bad instruction = {:#x}, kernel killed it.", scause.cause(), stval, current_trap_cx().sepc, ); - // page fault exit code - exit_current_and_run_next(-2); + */ + current_add_signal(SignalFlags::SIGSEGV); } Trap::Exception(Exception::IllegalInstruction) => { - println!("[kernel] IllegalInstruction in application, kernel killed it."); - // illegal instruction exit code - exit_current_and_run_next(-3); + current_add_signal(SignalFlags::SIGILL); } Trap::Interrupt(Interrupt::SupervisorTimer) => { set_next_trigger(); @@ -85,7 +84,11 @@ pub fn trap_handler() -> ! { ); } } - //println!("before trap_return"); + // check signals + if let Some((errno, msg)) = check_signals_of_current() { + println!("[kernel] {}", msg); + exit_current_and_run_next(errno); + } trap_return(); } diff --git a/user/Cargo.toml b/user/Cargo.toml index d50a0ba0..f522c9e9 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" [dependencies] buddy_system_allocator = "0.6" -bitflags = "1.2.1" \ No newline at end of file +bitflags = "1.2.1" +riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } diff --git a/user/src/bin/priv_csr.rs b/user/src/bin/priv_csr.rs new file mode 100644 index 00000000..fbd678f7 --- /dev/null +++ b/user/src/bin/priv_csr.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use riscv::register::sstatus::{self, SPP}; + +#[no_mangle] +fn main() -> i32 { + println!("Try to access privileged CSR in U Mode"); + println!("Kernel should kill this application!"); + unsafe { + sstatus::set_spp(SPP::User); + } + 0 +} diff --git a/user/src/bin/priv_inst.rs b/user/src/bin/priv_inst.rs new file mode 100644 index 00000000..04dac37e --- /dev/null +++ b/user/src/bin/priv_inst.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use core::arch::asm; + +#[no_mangle] +fn main() -> i32 { + println!("Try to execute privileged instruction in U Mode"); + println!("Kernel should kill this application!"); + unsafe { + asm!("sret"); + } + 0 +} diff --git a/user/src/bin/store_fault.rs b/user/src/bin/store_fault.rs new file mode 100644 index 00000000..f8023eb7 --- /dev/null +++ b/user/src/bin/store_fault.rs @@ -0,0 +1,15 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +#[no_mangle] +fn main() -> i32 { + println!("Into Test store_fault, we will insert an invalid store operation..."); + println!("Kernel should kill this application!"); + unsafe { + core::ptr::null_mut::().write_volatile(0); + } + 0 +}