diff --git a/.gitattributes b/.gitattributes index 39e2684c8..512faf1f9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,4 +5,5 @@ src/kxos-user/execve/execve filter=lfs diff=lfs merge=lfs -text src/kxos-user/execve/hello filter=lfs diff=lfs merge=lfs -text src/kxos-user/fork_c/fork filter=lfs diff=lfs merge=lfs -text src/kxos-user/signal_c/divide_zero filter=lfs diff=lfs merge=lfs -text -src/kxos-user/signal_c/sig_procmask filter=lfs diff=lfs merge=lfs -text \ No newline at end of file +src/kxos-user/signal_c/sig_procmask filter=lfs diff=lfs merge=lfs -text +src/kxos-user/signal_c/sig_action filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/src/Cargo.lock b/src/Cargo.lock index 6d3c457b8..1f64b119b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.63" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a" +checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" [[package]] name = "autocfg" diff --git a/src/kxos-frame/src/lib.rs b/src/kxos-frame/src/lib.rs index f59e5c414..be481f248 100644 --- a/src/kxos-frame/src/lib.rs +++ b/src/kxos-frame/src/lib.rs @@ -23,7 +23,7 @@ pub mod prelude; pub mod sync; pub mod task; pub mod timer; -pub(crate) mod trap; +pub mod trap; pub mod user; mod util; #[macro_use] diff --git a/src/kxos-frame/src/trap/handler.rs b/src/kxos-frame/src/trap/handler.rs index d7e30cee1..c6fbf5cbc 100644 --- a/src/kxos-frame/src/trap/handler.rs +++ b/src/kxos-frame/src/trap/handler.rs @@ -19,24 +19,29 @@ pub(crate) extern "C" fn syscall_handler(f: &'static mut SyscallFrame) -> isize -1 } -const DIVIDE_BY_ZERO: usize = 0; -const INVALID_OPCODE: usize = 6; -const SEGMENT_NOT_PRESENT: usize = 11; -const STACK_SEGMENT_FAULT: usize = 12; -const GENERAL_PROTECTION_FAULT: usize = 13; -const PAGE_FAULT: usize = 14; -const TIMER: usize = 32; - #[no_mangle] pub(crate) extern "C" fn trap_handler(f: &'static mut TrapFrame) { if !is_from_kernel(f.cs) { let current = Task::current(); current.inner_exclusive_access().is_from_trap = true; - } - let irq_line = IRQ_LIST.get(f.id as usize).unwrap(); - let callback_functions = irq_line.callback_list(); - for callback_function in callback_functions.iter() { - callback_function.call(f.clone()); + *current.trap_frame() = *SWITCH_TO_USER_SPACE_TASK.trap_frame(); + if is_cpu_fault(current.trap_frame()) { + // if is cpu fault, we will pass control to trap handler in kxos std + unsafe { + context_switch( + get_idle_task_cx_ptr() as *mut TaskContext, + &Task::current().inner_ctx() as *const TaskContext, + ) + } + } else { + let irq_line = IRQ_LIST.get(f.id as usize).unwrap(); + let callback_functions = irq_line.callback_list(); + for callback_function in callback_functions.iter() { + callback_function.call(f.clone()); + } + } + } else { + panic!("cannot handle kernel exception now"); } } @@ -47,3 +52,36 @@ fn is_from_kernel(cs: u64) -> bool { false } } + +/// As Osdev Wiki defines(https://wiki.osdev.org/Exceptions): +/// CPU exceptions are classified as: + +/// Faults: These can be corrected and the program may continue as if nothing happened. +/// Traps: Traps are reported immediately after the execution of the trapping instruction. +/// Aborts: Some severe unrecoverable error. + +/// This function will determine a trap is a CPU faults. +/// We will pass control to kxos-std if the trap is **faults**. +pub fn is_cpu_fault(trap_frame: &TrapFrame) -> bool { + match trap_frame.id { + DIVIDE_BY_ZERO + | DEBUG + | BOUND_RANGE_EXCEEDED + | INVALID_OPCODE + | DEVICE_NOT_AVAILABLE + | INVAILD_TSS + | SEGMENT_NOT_PRESENT + | STACK_SEGMENT_FAULT + | GENERAL_PROTECTION_FAULT + | PAGE_FAULT + | X87_FLOATING_POINT_EXCEPTION + | ALIGNMENT_CHECK + | SIMD_FLOATING_POINT_EXCEPTION + | VIRTUALIZATION_EXCEPTION + | CONTROL_PROTECTION_EXCEPTION + | HYPERVISOR_INJECTION_EXCEPTION + | VMM_COMMUNICATION_EXCEPTION + | SECURITY_EXCEPTION => true, + _ => false, + } +} diff --git a/src/kxos-frame/src/trap/mod.rs b/src/kxos-frame/src/trap/mod.rs index 1d3ebf954..453cb151f 100644 --- a/src/kxos-frame/src/trap/mod.rs +++ b/src/kxos-frame/src/trap/mod.rs @@ -144,3 +144,40 @@ pub(crate) fn init() { }) } } + +macro_rules! define_cpu_exception { + ( $( $name: ident = $exception_num: expr ),* ) => { + $( + pub const $name : u64 = $exception_num; + )* + } +} + +define_cpu_exception!( + DIVIDE_BY_ZERO = 0, + DEBUG = 1, + NON_MASKABLE_INTERRUPT = 2, + BREAKPOINT = 3, + OVERFLOW = 4, + BOUND_RANGE_EXCEEDED = 5, + INVALID_OPCODE = 6, + DEVICE_NOT_AVAILABLE = 7, + DOUBLE_FAULT = 8, + COPROCESSOR_SEGMENT_OVERRUN = 9, + INVAILD_TSS = 10, + SEGMENT_NOT_PRESENT = 11, + STACK_SEGMENT_FAULT = 12, + GENERAL_PROTECTION_FAULT = 13, + PAGE_FAULT = 14, + // 15 reserved + X87_FLOATING_POINT_EXCEPTION = 16, + ALIGNMENT_CHECK = 17, + MACHINE_CHECK = 18, + SIMD_FLOATING_POINT_EXCEPTION = 19, + VIRTUALIZATION_EXCEPTION = 20, + CONTROL_PROTECTION_EXCEPTION = 21, + // 22-27 reserved + HYPERVISOR_INJECTION_EXCEPTION = 28, + VMM_COMMUNICATION_EXCEPTION = 29, + SECURITY_EXCEPTION = 30 // 31 reserved +); diff --git a/src/kxos-std/src/process/exception.rs b/src/kxos-std/src/process/exception.rs new file mode 100644 index 000000000..86cd1a4ca --- /dev/null +++ b/src/kxos-std/src/process/exception.rs @@ -0,0 +1,13 @@ +use kxos_frame::cpu::CpuContext; + +use crate::{prelude::*, process::signal::signals::fault::FaultSignal}; + +/// We can't handle most exceptions, just send self a signal to force the process exit before return to user space. +pub fn handle_exception(context: &mut CpuContext) { + let trap_info = context.trap_information.clone(); + let current = current!(); + let pid = current.pid(); + debug!("trap info = {:x?}", trap_info); + let signal = Box::new(FaultSignal::new(&trap_info)); + current.sig_queues().lock().enqueue(signal); +} diff --git a/src/kxos-std/src/process/mod.rs b/src/kxos-std/src/process/mod.rs index b34fca73c..05187c07d 100644 --- a/src/kxos-std/src/process/mod.rs +++ b/src/kxos-std/src/process/mod.rs @@ -9,14 +9,17 @@ use self::process_group::ProcessGroup; use self::process_vm::mmap_area::MmapArea; use self::process_vm::user_heap::UserHeap; use self::process_vm::UserVm; +use self::signal::constants::SIGCHLD; use self::signal::sig_disposition::SigDispositions; use self::signal::sig_mask::SigMask; use self::signal::sig_queues::SigQueues; +use self::signal::signals::kernel::KernelSignal; use self::status::ProcessStatus; use self::task::create_user_task_from_elf; pub mod clone; pub mod elf; +pub mod exception; pub mod fifo_scheduler; pub mod process_filter; pub mod process_group; @@ -272,8 +275,11 @@ impl Process { } } - // wake up parent waiting children, if any if let Some(parent) = current_process.parent() { + // set parent sig child + let signal = Box::new(KernelSignal::new(SIGCHLD)); + parent.sig_queues().lock().enqueue(signal); + // wake up parent waiting children, if any parent .waiting_children() .wake_all_on_condition(¤t_process.pid(), |filter, pid| { @@ -341,12 +347,17 @@ impl Process { None } - /// free zombie child with pid, returns the exit code of child process - /// We current just remove the child from the children map. + /// free zombie child with pid, returns the exit code of child process. + /// remove process from process group. pub fn reap_zombie_child(&self, pid: Pid) -> i32 { let child_process = self.children.lock().remove(&pid).unwrap(); assert!(child_process.status().lock().is_zombie()); table::remove_process(child_process.pid()); + if let Some(process_group) = child_process.process_group().lock().as_ref() { + if let Some(process_group) = process_group.upgrade() { + process_group.remove_process(child_process.pid); + } + } child_process.exit_code() } diff --git a/src/kxos-std/src/process/process_group.rs b/src/kxos-std/src/process/process_group.rs index 8444fe683..1a422f692 100644 --- a/src/kxos-std/src/process/process_group.rs +++ b/src/kxos-std/src/process/process_group.rs @@ -1,4 +1,4 @@ -use super::{Pgid, Pid, Process}; +use super::{table, Pgid, Pid, Process}; use crate::prelude::*; pub struct ProcessGroup { @@ -44,7 +44,15 @@ impl ProcessGroup { } pub fn remove_process(&self, pid: Pid) { - self.inner.lock().processes.remove(&pid); + let mut inner_lock = self.inner.lock(); + inner_lock.processes.remove(&pid); + let len = inner_lock.processes.len(); + let pgid = inner_lock.pgid; + // if self contains no process, remove self from table + if len == 0 { + // this must be the last statement + table::remove_process_group(pgid); + } } pub fn pgid(&self) -> Pgid { diff --git a/src/kxos-std/src/process/signal/constants.rs b/src/kxos-std/src/process/signal/constants.rs index 7f2a3752c..9c4593e1a 100644 --- a/src/kxos-std/src/process/signal/constants.rs +++ b/src/kxos-std/src/process/signal/constants.rs @@ -55,3 +55,49 @@ define_std_signums! { SIGPWR = 30, // Power failure (System V) SIGSYS = 31, // Bad system call (SVr4); see also seccomp(2) } + +pub const SI_ASYNCNL: i32 = -60; +pub const SI_TKILL: i32 = -6; +pub const SI_SIGIO: i32 = -5; +pub const SI_ASYNCIO: i32 = -4; +pub const SI_MESGQ: i32 = -3; +pub const SI_TIMER: i32 = -2; +pub const SI_QUEUE: i32 = -1; +pub const SI_USER: i32 = 0; +pub const SI_KERNEL: i32 = 128; + +pub const FPE_INTDIV: i32 = 1; +pub const FPE_INTOVF: i32 = 2; +pub const FPE_FLTDIV: i32 = 3; +pub const FPE_FLTOVF: i32 = 4; +pub const FPE_FLTUND: i32 = 5; +pub const FPE_FLTRES: i32 = 6; +pub const FPE_FLTINV: i32 = 7; +pub const FPE_FLTSUB: i32 = 8; + +pub const ILL_ILLOPC: i32 = 1; +pub const ILL_ILLOPN: i32 = 2; +pub const ILL_ILLADR: i32 = 3; +pub const ILL_ILLTRP: i32 = 4; +pub const ILL_PRVOPC: i32 = 5; +pub const ILL_PRVREG: i32 = 6; +pub const ILL_COPROC: i32 = 7; +pub const ILL_BADSTK: i32 = 8; + +pub const SEGV_MAPERR: i32 = 1; +pub const SEGV_ACCERR: i32 = 2; +pub const SEGV_BNDERR: i32 = 3; +pub const SEGV_PKUERR: i32 = 4; + +pub const BUS_ADRALN: i32 = 1; +pub const BUS_ADRERR: i32 = 2; +pub const BUS_OBJERR: i32 = 3; +pub const BUS_MCEERR_AR: i32 = 4; +pub const BUS_MCEERR_AO: i32 = 5; + +pub const CLD_EXITED: i32 = 1; +pub const CLD_KILLED: i32 = 2; +pub const CLD_DUMPED: i32 = 3; +pub const CLD_TRAPPED: i32 = 4; +pub const CLD_STOPPED: i32 = 5; +pub const CLD_CONTINUED: i32 = 6; diff --git a/src/kxos-std/src/process/signal/mod.rs b/src/kxos-std/src/process/signal/mod.rs index 2743e79b3..bacf7daab 100644 --- a/src/kxos-std/src/process/signal/mod.rs +++ b/src/kxos-std/src/process/signal/mod.rs @@ -6,6 +6,8 @@ pub mod sig_num; pub mod sig_queues; pub mod signals; +use kxos_frame::task::Task; + use crate::{ prelude::*, process::signal::sig_action::{SigAction, SigDefaultAction}, @@ -14,13 +16,16 @@ use crate::{ /// Handle pending signal for current process pub fn handle_pending_signal() { let current = current!(); + let pid = current.pid(); + let process_name = current.filename().unwrap(); let sig_queues = current.sig_queues(); let mut sig_queues_guard = sig_queues.lock(); let sig_mask = current.sig_mask().lock().clone(); if let Some(signal) = sig_queues_guard.dequeue(&sig_mask) { let sig_num = signal.num(); - debug!("sig_num = {:?}", sig_num); + debug!("sig_num = {:?}, sig_name = {}", sig_num, sig_num.sig_name()); let sig_action = current.sig_dispositions().lock().get(sig_num); + debug!("sig action: {:?}", sig_action); match sig_action { SigAction::Ign => { debug!("Ignore signal {:?}", sig_num); @@ -28,10 +33,18 @@ pub fn handle_pending_signal() { SigAction::User { .. } => todo!(), SigAction::Dfl => { let sig_default_action = SigDefaultAction::from_signum(sig_num); + debug!("sig_default_action: {:?}", sig_default_action); match sig_default_action { SigDefaultAction::Core | SigDefaultAction::Term => { + error!( + "{:?}: terminating on signal {}", + process_name, + sig_num.sig_name() + ); // FIXME: How to set correct status if process is terminated current.exit(1); + // We should exit current here, since we cannot restore a valid status from trap now. + Task::current().exit(); } SigDefaultAction::Ign => {} SigDefaultAction::Stop => { diff --git a/src/kxos-std/src/process/signal/sig_mask.rs b/src/kxos-std/src/process/signal/sig_mask.rs index 301cc9f90..d80f971bc 100644 --- a/src/kxos-std/src/process/signal/sig_mask.rs +++ b/src/kxos-std/src/process/signal/sig_mask.rs @@ -40,7 +40,7 @@ impl SigMask { self.bits &= !unblock_sets; } - pub fn set(&mut self, new_set:u64) { + pub fn set(&mut self, new_set: u64) { self.bits = new_set; } diff --git a/src/kxos-std/src/process/signal/sig_num.rs b/src/kxos-std/src/process/signal/sig_num.rs index 27963f9ee..2c7329fc0 100644 --- a/src/kxos-std/src/process/signal/sig_num.rs +++ b/src/kxos-std/src/process/signal/sig_num.rs @@ -37,4 +37,41 @@ impl SigNum { pub fn is_real_time(&self) -> bool { self.sig_num >= MIN_RT_SIG_NUM } + + pub const fn sig_name(&self) -> &'static str { + match *self { + SIGHUP => "SIGHUP", + SIGINT => "SIGINT", + SIGQUIT => "SIGQUIT", + SIGILL => "SIGILL", + SIGTRAP => "SIGTRAP", + SIGABRT => "SIGABRT", + SIGBUS => "SIGBUS", + SIGFPE => "SIGFPE", + SIGKILL => "SIGKILL", + SIGUSR1 => "SIGUSR1", + SIGSEGV => "SIGSEGV", + SIGUSR2 => "SIGUSR2", + SIGPIPE => "SIGPIPE", + SIGALRM => "SIGALRM", + SIGTERM => "SIGTERM", + SIGSTKFLT => "SIGSTKFLT", + SIGCHLD => "SIGCHLD", + SIGCONT => "SIGCONT", + SIGSTOP => "SIGSTOP", + SIGTSTP => "SIGTSTP", + SIGTTIN => "SIGTTIN", + SIGTTOU => "SIGTTOU", + SIGURG => "SIGURG", + SIGXCPU => "SIGXCPU", + SIGXFSZ => "SIGXFSZ", + SIGVTALRM => "SIGVTALRM", + SIGPROF => "SIGPROF", + SIGWINCH => "SIGWINCH", + SIGIO => "SIGIO", + SIGPWR => "SIGPWR", + SIGSYS => "SIGSYS", + _ => "Realtime Signal", + } + } } diff --git a/src/kxos-std/src/process/signal/signals/fault.rs b/src/kxos-std/src/process/signal/signals/fault.rs new file mode 100644 index 000000000..71477cb65 --- /dev/null +++ b/src/kxos-std/src/process/signal/signals/fault.rs @@ -0,0 +1,51 @@ +use kxos_frame::cpu::TrapInformation; +use kxos_frame::trap::{ + ALIGNMENT_CHECK, BOUND_RANGE_EXCEEDED, DIVIDE_BY_ZERO, GENERAL_PROTECTION_FAULT, + INVALID_OPCODE, PAGE_FAULT, SIMD_FLOATING_POINT_EXCEPTION, X87_FLOATING_POINT_EXCEPTION, +}; + +use crate::prelude::*; +use crate::process::signal::constants::*; +use crate::process::signal::sig_num::SigNum; + +use super::Signal; +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct FaultSignal { + num: SigNum, + code: i32, + addr: Option, +} + +impl FaultSignal { + pub fn new(trap_info: &TrapInformation) -> FaultSignal { + debug!("Trap id: {}", trap_info.id); + let (num, code, addr) = match trap_info.id { + DIVIDE_BY_ZERO => (SIGFPE, FPE_INTDIV, None), + X87_FLOATING_POINT_EXCEPTION | SIMD_FLOATING_POINT_EXCEPTION => { + (SIGFPE, FPE_FLTDIV, None) + } + BOUND_RANGE_EXCEEDED => (SIGSEGV, SEGV_BNDERR, None), + ALIGNMENT_CHECK => (SIGBUS, BUS_ADRALN, None), + INVALID_OPCODE => (SIGILL, ILL_ILLOPC, None), + GENERAL_PROTECTION_FAULT => (SIGBUS, BUS_ADRERR, None), + PAGE_FAULT => { + const PF_ERR_FLAG_PRESENT: u64 = 1u64 << 0; + let code = if trap_info.err & PF_ERR_FLAG_PRESENT != 0 { + SEGV_ACCERR + } else { + SEGV_MAPERR + }; + let addr = Some(trap_info.cr2); + (SIGSEGV, code, addr) + } + _ => panic!("Exception cannnot be a signal"), + }; + FaultSignal { num, code, addr } + } +} + +impl Signal for FaultSignal { + fn num(&self) -> SigNum { + self.num + } +} diff --git a/src/kxos-std/src/process/signal/signals/kernel.rs b/src/kxos-std/src/process/signal/signals/kernel.rs new file mode 100644 index 000000000..c0cec7527 --- /dev/null +++ b/src/kxos-std/src/process/signal/signals/kernel.rs @@ -0,0 +1,20 @@ +use crate::process::signal::sig_num::SigNum; + +use super::Signal; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct KernelSignal { + num: SigNum, +} + +impl KernelSignal { + pub const fn new(num: SigNum) -> Self { + Self { num } + } +} + +impl Signal for KernelSignal { + fn num(&self) -> SigNum { + self.num + } +} diff --git a/src/kxos-std/src/process/signal/signals/mod.rs b/src/kxos-std/src/process/signal/signals/mod.rs index 064f1c127..71452ea2b 100644 --- a/src/kxos-std/src/process/signal/signals/mod.rs +++ b/src/kxos-std/src/process/signal/signals/mod.rs @@ -1,3 +1,5 @@ +pub mod fault; +pub mod kernel; pub mod user; use core::fmt::Debug; diff --git a/src/kxos-std/src/process/task.rs b/src/kxos-std/src/process/task.rs index 286e4eea6..8c6b886d9 100644 --- a/src/kxos-std/src/process/task.rs +++ b/src/kxos-std/src/process/task.rs @@ -7,9 +7,12 @@ use kxos_frame::{ vm::VmSpace, }; -use crate::{prelude::*, process::signal::handle_pending_signal}; +use crate::{ + prelude::*, + process::{exception::handle_exception, signal::handle_pending_signal}, +}; -use crate::syscall::syscall_handler; +use crate::syscall::handle_syscall; use super::{elf::load_elf_to_vm_space, Process}; @@ -56,6 +59,7 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< } handle_pending_signal(); if current.status().lock().is_zombie() { + debug!("exit due to signal"); break; } // If current is suspended, wait for a signal to wake up self @@ -65,6 +69,7 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< handle_pending_signal(); } } + debug!("exit user loop"); } Task::new(user_task_entry, parent, Some(userspace)).expect("spawn task failed") @@ -72,8 +77,8 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) { match user_event { - UserEvent::Syscall => syscall_handler(context), + UserEvent::Syscall => handle_syscall(context), UserEvent::Fault => todo!(), - UserEvent::Exception => todo!(), + UserEvent::Exception => handle_exception(context), } } diff --git a/src/kxos-std/src/syscall/access.rs b/src/kxos-std/src/syscall/access.rs index 452fb65e9..cc066ecb1 100644 --- a/src/kxos-std/src/syscall/access.rs +++ b/src/kxos-std/src/syscall/access.rs @@ -1,13 +1,12 @@ use super::constants::*; -use super::SyscallResult; use crate::{memory::read_bytes_from_user, prelude::*, syscall::SYS_ACCESS}; -pub fn sys_access(filename_ptr: Vaddr, file_mode: u64) -> SyscallResult { +pub fn sys_access(filename_ptr: Vaddr, file_mode: u64) -> Result { debug!("[syscall][id={}][SYS_ACCESS]", SYS_ACCESS); let mut filename_buffer = vec![0u8; MAX_FILENAME_LEN]; read_bytes_from_user(filename_ptr, &mut filename_buffer); let filename = CString::from(CStr::from_bytes_until_nul(&filename_buffer).unwrap()); debug!("filename: {:?}", filename); warn!("access currenly does not check and just return success"); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/arch_prctl.rs b/src/kxos-std/src/syscall/arch_prctl.rs index 09accf2a4..8aeccbcb2 100644 --- a/src/kxos-std/src/syscall/arch_prctl.rs +++ b/src/kxos-std/src/syscall/arch_prctl.rs @@ -1,7 +1,7 @@ use kxos_frame::cpu::CpuContext; use crate::prelude::*; -use crate::syscall::{SyscallResult, SYS_ARCH_PRCTL}; +use crate::syscall::SYS_ARCH_PRCTL; #[allow(non_camel_case_types)] #[derive(Debug)] @@ -26,17 +26,19 @@ impl TryFrom for ArchPrctlCode { } } -pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> SyscallResult { +pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> Result { debug!("[syscall][id={}][SYS_ARCH_PRCTL]", SYS_ARCH_PRCTL); - let arch_prctl_code = ArchPrctlCode::try_from(code); + let arch_prctl_code = ArchPrctlCode::try_from(code)?; debug!("arch_prctl_code: {:?}", arch_prctl_code); - match arch_prctl_code { - Err(_) => SyscallResult::Return(-1), - Ok(code) => { - let res = do_arch_prctl(code, addr, context).unwrap(); - SyscallResult::Return(res as _) - } - } + let res = do_arch_prctl(arch_prctl_code, addr, context).unwrap(); + Ok(res as _) + // match arch_prctl_code { + // Err(_) => SyscallResult::Return(-1), + // Ok(code) => { + // let res = do_arch_prctl(code, addr, context).unwrap(); + // SyscallResult::Return(res as _) + // } + // } } pub fn do_arch_prctl(code: ArchPrctlCode, addr: u64, context: &mut CpuContext) -> Result { diff --git a/src/kxos-std/src/syscall/brk.rs b/src/kxos-std/src/syscall/brk.rs index 906570377..b9dd71e53 100644 --- a/src/kxos-std/src/syscall/brk.rs +++ b/src/kxos-std/src/syscall/brk.rs @@ -1,12 +1,9 @@ use crate::prelude::*; -use crate::{ - process::Process, - syscall::{SyscallResult, SYS_BRK}, -}; +use crate::{process::Process, syscall::SYS_BRK}; /// expand the user heap to new heap end, returns the new heap end if expansion succeeds. -pub fn sys_brk(heap_end: u64) -> SyscallResult { +pub fn sys_brk(heap_end: u64) -> Result { debug!("[syscall][id={}][SYS_BRK]", SYS_BRK); let current = Process::current(); let new_heap_end = if heap_end == 0 { @@ -23,5 +20,5 @@ pub fn sys_brk(heap_end: u64) -> SyscallResult { .expect("brk should work on process with user space"); let new_heap_end = user_heap.brk(new_heap_end, vm_space); - SyscallResult::Return(new_heap_end as _) + Ok(new_heap_end as _) } diff --git a/src/kxos-std/src/syscall/clone.rs b/src/kxos-std/src/syscall/clone.rs index f52fbefc1..e60b0b4bf 100644 --- a/src/kxos-std/src/syscall/clone.rs +++ b/src/kxos-std/src/syscall/clone.rs @@ -1,6 +1,5 @@ use kxos_frame::cpu::CpuContext; -use super::SyscallResult; use crate::process::clone::{clone_child, CloneArgs, CloneFlags}; use crate::{prelude::*, syscall::SYS_CLONE}; @@ -13,7 +12,7 @@ pub fn sys_clone( child_tidptr: Vaddr, tls: usize, parent_context: CpuContext, -) -> SyscallResult { +) -> Result { debug!("[syscall][id={}][SYS_CLONE]", SYS_CLONE); debug!("flags = {}", clone_flags); let clone_flags = CloneFlags::from(clone_flags); @@ -29,5 +28,5 @@ pub fn sys_clone( debug!("*********schedule child process, pid = {}**********", pid); child_process.send_to_scheduler(); debug!("*********return to parent process, pid = {}*********", pid); - SyscallResult::Return(child_pid as _) + Ok(child_pid as _) } diff --git a/src/kxos-std/src/syscall/execve.rs b/src/kxos-std/src/syscall/execve.rs index fb2f6e1d1..240dbff2f 100644 --- a/src/kxos-std/src/syscall/execve.rs +++ b/src/kxos-std/src/syscall/execve.rs @@ -1,7 +1,6 @@ use kxos_frame::cpu::CpuContext; use super::constants::*; -use super::SyscallResult; use crate::process::elf::load_elf_to_vm_space; use crate::{memory::read_bytes_from_user, prelude::*, process::Process, syscall::SYS_EXECVE}; @@ -10,7 +9,7 @@ pub fn sys_execve( argv_ptr_ptr: Vaddr, envp_ptr_ptr: Vaddr, context: &mut CpuContext, -) -> SyscallResult { +) -> Result { debug!("[syscall][id={}][SYS_EXECVE]", SYS_EXECVE); let mut filename_buffer = vec![0u8; MAX_FILENAME_LEN]; read_bytes_from_user(filename_ptr, &mut filename_buffer); @@ -47,5 +46,5 @@ pub fn sys_execve( // set new user stack top context.gp_regs.rsp = elf_load_info.user_stack_top(); debug!("user stack top: 0x{:x}", elf_load_info.user_stack_top()); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/exit.rs b/src/kxos-std/src/syscall/exit.rs index 3d0682ff6..3c8a11c0c 100644 --- a/src/kxos-std/src/syscall/exit.rs +++ b/src/kxos-std/src/syscall/exit.rs @@ -2,10 +2,8 @@ use crate::prelude::*; use crate::syscall::SYS_EXIT; -use super::SyscallResult; - -pub fn sys_exit(exit_code: i32) -> SyscallResult { +pub fn sys_exit(exit_code: i32) -> Result { debug!("[syscall][id={}][SYS_EXIT]", SYS_EXIT); current!().exit(exit_code); - SyscallResult::NotReturn + Ok(0) } diff --git a/src/kxos-std/src/syscall/exit_group.rs b/src/kxos-std/src/syscall/exit_group.rs index 1ac7bd7cb..0d8ee732a 100644 --- a/src/kxos-std/src/syscall/exit_group.rs +++ b/src/kxos-std/src/syscall/exit_group.rs @@ -1,9 +1,9 @@ use crate::prelude::*; -use crate::syscall::{SyscallResult, SYS_EXIT_GROUP}; +use crate::syscall::SYS_EXIT_GROUP; -pub fn sys_exit_group(exit_code: u64) -> SyscallResult { +pub fn sys_exit_group(exit_code: u64) -> Result { debug!("[syscall][id={}][SYS_EXIT_GROUP]", SYS_EXIT_GROUP); current!().exit(exit_code as _); - SyscallResult::NotReturn + Ok(0) } diff --git a/src/kxos-std/src/syscall/fork.rs b/src/kxos-std/src/syscall/fork.rs index 6a8ac24d5..37fe5961b 100644 --- a/src/kxos-std/src/syscall/fork.rs +++ b/src/kxos-std/src/syscall/fork.rs @@ -6,12 +6,10 @@ use kxos_frame::cpu::CpuContext; use crate::{process::Process, syscall::SYS_FORK}; -use super::SyscallResult; - -pub fn sys_fork(parent_context: CpuContext) -> SyscallResult { +pub fn sys_fork(parent_context: CpuContext) -> Result { debug!("[syscall][id={}][SYS_FORK]", SYS_FORK); let child_process = fork(parent_context); - SyscallResult::Return(child_process.pid() as _) + Ok(child_process.pid() as _) } /// Fork a child process diff --git a/src/kxos-std/src/syscall/fstat.rs b/src/kxos-std/src/syscall/fstat.rs index 1581ad7c4..934e7cac9 100644 --- a/src/kxos-std/src/syscall/fstat.rs +++ b/src/kxos-std/src/syscall/fstat.rs @@ -3,9 +3,9 @@ use kxos_frame::vm::VmIo; use crate::fs::stat::Stat; use crate::prelude::*; -use crate::syscall::{SyscallResult, SYS_FSTAT}; +use crate::syscall::SYS_FSTAT; -pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> SyscallResult { +pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> Result { debug!("[syscall][id={}][SYS_FSTAT]", SYS_FSTAT); debug!("fd = {}", fd); debug!("stat_buf_addr = 0x{:x}", stat_buf_ptr); @@ -19,8 +19,8 @@ pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> SyscallResult { vm_space .write_val(stat_buf_ptr, &stat) .expect("Write value failed"); - return SyscallResult::Return(0); + return Ok(0); } warn!("TODO: fstat only returns fake result now."); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/futex.rs b/src/kxos-std/src/syscall/futex.rs index 9f4aa452a..b71f153e4 100644 --- a/src/kxos-std/src/syscall/futex.rs +++ b/src/kxos-std/src/syscall/futex.rs @@ -1,6 +1,5 @@ use crate::{memory::read_val_from_user, syscall::SYS_FUTEX}; -use super::SyscallResult; use crate::prelude::*; use kxos_frame::{cpu::num_cpus, sync::WaitQueue}; @@ -18,7 +17,7 @@ pub fn sys_futex( utime_addr: u64, futex_new_addr: u64, bitset: u64, -) -> SyscallResult { +) -> Result { debug!("[syscall][id={}][SYS_FUTEX]", SYS_FUTEX); // FIXME: we current ignore futex flags let (futex_op, futex_flags) = futex_op_and_flags_from_u32(futex_op as _).unwrap(); @@ -70,7 +69,7 @@ pub fn sys_futex( } .unwrap(); - SyscallResult::Return(res as _) + Ok(res as _) } /// do futex wait diff --git a/src/kxos-std/src/syscall/getpid.rs b/src/kxos-std/src/syscall/getpid.rs index 136760824..1b5ab04d6 100644 --- a/src/kxos-std/src/syscall/getpid.rs +++ b/src/kxos-std/src/syscall/getpid.rs @@ -2,11 +2,9 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETPID}; -use super::SyscallResult; - -pub fn sys_getpid() -> SyscallResult { +pub fn sys_getpid() -> Result { debug!("[syscall][id={}][SYS_GETPID]", SYS_GETPID); let pid = Process::current().pid(); info!("[sys_getpid]: pid = {}", pid); - SyscallResult::Return(pid as _) + Ok(pid as _) } diff --git a/src/kxos-std/src/syscall/gettid.rs b/src/kxos-std/src/syscall/gettid.rs index 1f5b7bd7d..c1d8e9622 100644 --- a/src/kxos-std/src/syscall/gettid.rs +++ b/src/kxos-std/src/syscall/gettid.rs @@ -2,11 +2,9 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETTID}; -use super::SyscallResult; - -pub fn sys_gettid() -> SyscallResult { +pub fn sys_gettid() -> Result { debug!("[syscall][id={}][SYS_GETTID]", SYS_GETTID); // For single-thread process, tid is equal to pid let tid = Process::current().pid(); - SyscallResult::Return(tid as _) + Ok(tid as _) } diff --git a/src/kxos-std/src/syscall/kill.rs b/src/kxos-std/src/syscall/kill.rs index 96ab2bac3..90e347c4e 100644 --- a/src/kxos-std/src/syscall/kill.rs +++ b/src/kxos-std/src/syscall/kill.rs @@ -7,14 +7,12 @@ use crate::{ syscall::SYS_KILL, }; -use super::SyscallResult; - -pub fn sys_kill(process_filter: u64, sig_num: u64) -> SyscallResult { +pub fn sys_kill(process_filter: u64, sig_num: u64) -> Result { debug!("[syscall][id={}][SYS_KILL]", SYS_KILL); let process_filter = ProcessFilter::from_id(process_filter as _); let sig_num = SigNum::try_from(sig_num as u8).unwrap(); - let _ = do_sys_kill(process_filter, sig_num); - SyscallResult::Return(0) + do_sys_kill(process_filter, sig_num)?; + Ok(0) } pub fn do_sys_kill(process_filter: ProcessFilter, sig_num: SigNum) -> Result<()> { diff --git a/src/kxos-std/src/syscall/mmap.rs b/src/kxos-std/src/syscall/mmap.rs index 64fad283b..073862b82 100644 --- a/src/kxos-std/src/syscall/mmap.rs +++ b/src/kxos-std/src/syscall/mmap.rs @@ -6,8 +6,6 @@ use kxos_frame::vm::VmPerm; use crate::{process::Process, syscall::SYS_MMAP}; -use super::SyscallResult; - pub fn sys_mmap( addr: u64, len: u64, @@ -15,7 +13,7 @@ pub fn sys_mmap( flags: u64, fd: u64, offset: u64, -) -> SyscallResult { +) -> Result { debug!("[syscall][id={}][SYS_MMAP]", SYS_MMAP); let perms = VmPerm::try_from(perms).unwrap(); let flags = MMapFlags::try_from(flags).unwrap(); @@ -27,7 +25,7 @@ pub fn sys_mmap( fd as usize, offset as usize, ); - SyscallResult::Return(res as _) + Ok(res as _) } pub fn do_sys_mmap( diff --git a/src/kxos-std/src/syscall/mod.rs b/src/kxos-std/src/syscall/mod.rs index 1c17291a0..bf62fa450 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -46,6 +46,7 @@ mod kill; mod mmap; mod mprotect; mod readlink; +mod rt_sigprocmask; mod sched_yield; mod tgkill; mod uname; @@ -53,7 +54,6 @@ mod wait4; mod waitid; mod write; mod writev; -mod rt_sigprocmask; const SYS_WRITE: u64 = 1; const SYS_FSTAT: u64 = 5; @@ -90,11 +90,6 @@ pub struct SyscallArgument { args: [u64; 6], } -pub enum SyscallResult { - Return(i32), - NotReturn, -} - impl SyscallArgument { fn new_from_context(context: &CpuContext) -> Self { let syscall_number = context.gp_regs.rax; @@ -112,22 +107,31 @@ impl SyscallArgument { } } -pub fn syscall_handler(context: &mut CpuContext) { +pub fn handle_syscall(context: &mut CpuContext) { let syscall_frame = SyscallArgument::new_from_context(context); let syscall_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args, context); - if let SyscallResult::Return(return_value) = syscall_return { - // FIXME: set return value? - context.gp_regs.rax = return_value as u64; + match syscall_return { + Ok(return_value) => { + context.gp_regs.rax = return_value as u64; + } + Err(err) => { + let errno = err.error() as i32; + context.gp_regs.rax = (-errno) as u64 + } } + // if let Syscal(return_value) = syscall_return { + // // FIXME: set return value? + // context.gp_regs.rax = return_value as u64; + // } } pub fn syscall_dispatch( syscall_number: u64, args: [u64; 6], context: &mut CpuContext, -) -> SyscallResult { +) -> Result { match syscall_number { SYS_WRITE => sys_write(args[0], args[1], args[2]), SYS_FSTAT => sys_fstat(args[0], args[1] as _), @@ -135,7 +139,9 @@ pub fn syscall_dispatch( SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]), SYS_BRK => sys_brk(args[0]), SYS_RT_SIGACTION => sys_rt_sigaction(), - SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(args[0] as _, args[1] as _, args[2] as _, args[3] as _), + SYS_RT_SIGPROCMASK => { + sys_rt_sigprocmask(args[0] as _, args[1] as _, args[2] as _, args[3] as _) + } SYS_WRITEV => sys_writev(args[0], args[1], args[2]), SYS_ACCESS => sys_access(args[0] as _, args[1]), SYS_GETPID => sys_getpid(), @@ -168,32 +174,32 @@ pub fn syscall_dispatch( } } -pub fn sys_rt_sigaction() -> SyscallResult { +pub fn sys_rt_sigaction() -> Result { debug!("[syscall][id={}][SYS_RT_SIGACTION]", SYS_RT_SIGACTION); warn!("TODO: rt_sigaction only return a fake result"); - SyscallResult::Return(0) + Ok(0) } -pub fn sys_getuid() -> SyscallResult { +pub fn sys_getuid() -> Result { debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID); warn!("TODO: getuid only return a fake uid now"); - SyscallResult::Return(0) + Ok(0) } -pub fn sys_getgid() -> SyscallResult { - debug!("[syscall][id={}][SYS_GETGID]", SYS_GETUID); +pub fn sys_getgid() -> Result { + debug!("[syscall][id={}][SYS_GETGID]", SYS_GETGID); warn!("TODO: getgid only return a fake gid now"); - SyscallResult::Return(0) + Ok(0) } -pub fn sys_geteuid() -> SyscallResult { +pub fn sys_geteuid() -> Result { debug!("[syscall][id={}][SYS_GETEUID]", SYS_GETEUID); warn!("TODO: geteuid only return a fake euid now"); - SyscallResult::Return(0) + Ok(0) } -pub fn sys_getegid() -> SyscallResult { +pub fn sys_getegid() -> Result { debug!("[syscall][id={}][SYS_GETEGID]", SYS_GETEGID); warn!("TODO: getegid only return a fake egid now"); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/mprotect.rs b/src/kxos-std/src/syscall/mprotect.rs index 259f10a53..23b101858 100644 --- a/src/kxos-std/src/syscall/mprotect.rs +++ b/src/kxos-std/src/syscall/mprotect.rs @@ -4,13 +4,11 @@ use crate::prelude::*; use crate::syscall::SYS_MPROTECT; -use super::SyscallResult; - -pub fn sys_mprotect(vaddr: u64, len: u64, perms: u64) -> SyscallResult { +pub fn sys_mprotect(vaddr: u64, len: u64, perms: u64) -> Result { debug!("[syscall][id={}][SYS_MPROTECT]", SYS_MPROTECT); let perms = VmPerm::try_from(perms).unwrap(); do_sys_mprotect(vaddr as Vaddr, len as usize, perms); - SyscallResult::Return(0) + Ok(0) } pub fn do_sys_mprotect(addr: Vaddr, len: usize, perms: VmPerm) -> isize { diff --git a/src/kxos-std/src/syscall/readlink.rs b/src/kxos-std/src/syscall/readlink.rs index c9ae7da13..de76fca8e 100644 --- a/src/kxos-std/src/syscall/readlink.rs +++ b/src/kxos-std/src/syscall/readlink.rs @@ -6,18 +6,16 @@ use crate::{ syscall::SYS_READLINK, }; -use super::SyscallResult; - const MAX_FILENAME_LEN: usize = 128; -pub fn sys_readlink(filename_ptr: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult { +pub fn sys_readlink(filename_ptr: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result { debug!("[syscall][id={}][SYS_READLINK]", SYS_READLINK); let res = do_sys_readlink( filename_ptr as Vaddr, user_buf_ptr as Vaddr, user_buf_len as usize, ); - SyscallResult::Return(res as _) + Ok(res as _) } /// do sys readlink diff --git a/src/kxos-std/src/syscall/rt_sigprocmask.rs b/src/kxos-std/src/syscall/rt_sigprocmask.rs index 2da276635..ee2052d12 100644 --- a/src/kxos-std/src/syscall/rt_sigprocmask.rs +++ b/src/kxos-std/src/syscall/rt_sigprocmask.rs @@ -2,8 +2,12 @@ use kxos_frame::vm::VmIo; use crate::{prelude::*, syscall::SYS_RT_SIGPROCMASK}; -use super::SyscallResult; -pub fn sys_rt_sigprocmask(how: u32, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_size: usize) -> SyscallResult { +pub fn sys_rt_sigprocmask( + how: u32, + set_ptr: Vaddr, + oldset_ptr: Vaddr, + sigset_size: usize, +) -> Result { debug!("[syscall][id={}][SYS_RT_SIGPROCMASK]", SYS_RT_SIGPROCMASK); let mask_op = MaskOp::try_from(how).unwrap(); debug!("mask op = {:?}", mask_op); @@ -14,10 +18,15 @@ pub fn sys_rt_sigprocmask(how: u32, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_si warn!("sigset size is not equal to 8"); } do_rt_sigprocmask(mask_op, set_ptr, oldset_ptr, sigset_size).unwrap(); - SyscallResult::Return(0) + Ok(0) } -fn do_rt_sigprocmask(mask_op: MaskOp, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_size: usize) -> Result<()>{ +fn do_rt_sigprocmask( + mask_op: MaskOp, + set_ptr: Vaddr, + oldset_ptr: Vaddr, + sigset_size: usize, +) -> Result<()> { let current = current!(); let vm_space = current.vm_space().unwrap(); let mut sig_mask = current.sig_mask().lock(); @@ -30,7 +39,7 @@ fn do_rt_sigprocmask(mask_op: MaskOp, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_ let new_set = vm_space.read_val::(set_ptr)?; debug!("new set = 0x{:x}", new_set); match mask_op { - MaskOp::Block => sig_mask.block(new_set ), + MaskOp::Block => sig_mask.block(new_set), MaskOp::Unblock => sig_mask.unblock(new_set), MaskOp::SetMask => sig_mask.set(new_set), } @@ -60,4 +69,4 @@ impl TryFrom for MaskOp { }; Ok(op) } -} \ No newline at end of file +} diff --git a/src/kxos-std/src/syscall/sched_yield.rs b/src/kxos-std/src/syscall/sched_yield.rs index d58217f84..2768661f3 100644 --- a/src/kxos-std/src/syscall/sched_yield.rs +++ b/src/kxos-std/src/syscall/sched_yield.rs @@ -2,10 +2,8 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_SCHED_YIELD}; -use super::SyscallResult; - -pub fn sys_sched_yield() -> SyscallResult { +pub fn sys_sched_yield() -> Result { debug!("[syscall][id={}][SYS_SCHED_YIELD]", SYS_SCHED_YIELD); Process::yield_now(); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/tgkill.rs b/src/kxos-std/src/syscall/tgkill.rs index de9e419cc..0bdd713b6 100644 --- a/src/kxos-std/src/syscall/tgkill.rs +++ b/src/kxos-std/src/syscall/tgkill.rs @@ -1,11 +1,11 @@ use crate::prelude::*; -use crate::syscall::{SyscallResult, SYS_TGKILL}; +use crate::syscall::SYS_TGKILL; -pub fn sys_tgkill(tgid: u64, pid: u64, signal: u64) -> SyscallResult { +pub fn sys_tgkill(tgid: u64, pid: u64, signal: u64) -> Result { debug!("[syscall][id={}][SYS_TGKILL]", SYS_TGKILL); debug!("tgid = {}", tgid); debug!("pid = {}", pid); warn!("TODO: tgkill do nothing now"); - SyscallResult::Return(0) + Ok(0) } diff --git a/src/kxos-std/src/syscall/uname.rs b/src/kxos-std/src/syscall/uname.rs index 5bcb08eaa..6d6140216 100644 --- a/src/kxos-std/src/syscall/uname.rs +++ b/src/kxos-std/src/syscall/uname.rs @@ -1,9 +1,6 @@ use crate::prelude::*; -use crate::{ - memory::write_val_to_user, - syscall::{SyscallResult, SYS_UNAME}, -}; +use crate::{memory::write_val_to_user, syscall::SYS_UNAME}; // We don't use the real name and version of our os here. Instead, we pick up fake values witch is the same as the ones of linux. // The values are used to fool glibc since glibc will check the version and os name. @@ -59,10 +56,10 @@ fn copy_cstring_to_u8_slice(src: &CStr, dst: &mut [u8]) { dst[..len].copy_from_slice(&src[..len]); } -pub fn sys_uname(old_uname_addr: u64) -> SyscallResult { +pub fn sys_uname(old_uname_addr: u64) -> Result { debug!("[syscall][id={}][SYS_UNAME]", SYS_UNAME); do_sys_uname(old_uname_addr as Vaddr); - SyscallResult::Return(0) + Ok(0) } pub fn do_sys_uname(old_uname_addr: Vaddr) -> usize { diff --git a/src/kxos-std/src/syscall/wait4.rs b/src/kxos-std/src/syscall/wait4.rs index 71f9d7b87..41dabeebe 100644 --- a/src/kxos-std/src/syscall/wait4.rs +++ b/src/kxos-std/src/syscall/wait4.rs @@ -4,11 +4,10 @@ use crate::{ syscall::SYS_WAIT4, }; -use super::SyscallResult; use crate::prelude::*; use crate::process::wait::WaitOptions; -pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> SyscallResult { +pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> Result { debug!("[syscall][id={}][SYS_WAIT4]", SYS_WAIT4); let wait_options = WaitOptions::from_bits(wait_options as u32).expect("Unknown wait options"); debug!("pid = {}", wait_pid as isize); @@ -20,5 +19,5 @@ pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> Sysc write_val_to_user(exit_status_ptr as _, &exit_code); } - SyscallResult::Return(return_pid as _) + Ok(return_pid as _) } diff --git a/src/kxos-std/src/syscall/waitid.rs b/src/kxos-std/src/syscall/waitid.rs index f7e1d77f7..04dbc5486 100644 --- a/src/kxos-std/src/syscall/waitid.rs +++ b/src/kxos-std/src/syscall/waitid.rs @@ -1,6 +1,6 @@ +use crate::prelude::*; use crate::process::{process_filter::ProcessFilter, wait::wait_child_exit}; -use super::SyscallResult; use crate::process::wait::WaitOptions; pub fn sys_waitid( @@ -9,10 +9,10 @@ pub fn sys_waitid( infoq_addr: u64, options: u64, rusage_addr: u64, -) -> SyscallResult { +) -> Result { // FIXME: what does infoq and rusage use for? let process_filter = ProcessFilter::from_which_and_id(which, upid); let wait_options = WaitOptions::from_bits(options as u32).expect("Unknown wait options"); let (exit_code, pid) = wait_child_exit(process_filter, wait_options); - SyscallResult::Return(pid) + Ok(pid as _) } diff --git a/src/kxos-std/src/syscall/write.rs b/src/kxos-std/src/syscall/write.rs index 1d13d2551..f2aed5df6 100644 --- a/src/kxos-std/src/syscall/write.rs +++ b/src/kxos-std/src/syscall/write.rs @@ -2,12 +2,10 @@ use crate::prelude::*; use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE}; -use super::SyscallResult; - const STDOUT: u64 = 1; const STDERR: u64 = 2; -pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult { +pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result { // only suppprt STDOUT now. debug!("[syscall][id={}][SYS_WRITE]", SYS_WRITE); @@ -21,7 +19,7 @@ pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult info!("Error message from user mode: {:?}", content); } - SyscallResult::Return(user_buf_len as _) + Ok(user_buf_len as _) } else { panic!("Unsupported fd number {}", fd); } diff --git a/src/kxos-std/src/syscall/writev.rs b/src/kxos-std/src/syscall/writev.rs index ae3c1d9f9..f70ab37b5 100644 --- a/src/kxos-std/src/syscall/writev.rs +++ b/src/kxos-std/src/syscall/writev.rs @@ -5,8 +5,6 @@ use crate::{ syscall::SYS_WRITEV, }; -use super::SyscallResult; - const IOVEC_MAX: usize = 256; #[repr(C)] @@ -16,10 +14,10 @@ pub struct IoVec { len: usize, } -pub fn sys_writev(fd: u64, io_vec_ptr: u64, io_vec_count: u64) -> SyscallResult { +pub fn sys_writev(fd: u64, io_vec_ptr: u64, io_vec_count: u64) -> Result { debug!("[syscall][id={}][SYS_WRITEV]", SYS_WRITEV); let res = do_sys_writev(fd, io_vec_ptr as Vaddr, io_vec_count as usize); - SyscallResult::Return(res as _) + Ok(res as _) } pub fn do_sys_writev(fd: u64, io_vec_ptr: Vaddr, io_vec_count: usize) -> usize { diff --git a/src/kxos-std/src/user_apps.rs b/src/kxos-std/src/user_apps.rs index f91fe1360..10ad61f9c 100644 --- a/src/kxos-std/src/user_apps.rs +++ b/src/kxos-std/src/user_apps.rs @@ -49,9 +49,17 @@ pub fn get_all_apps() -> Vec { res.push(app5); // Set sig procmask - let app6 = UserApp::new("/sig_procmask", read_sig_procmask()); + let app6 = UserApp::new("/sig_procmask", read_sig_procmask_content()); res.push(app6); + // divide zero + let app7 = UserApp::new("/divide_zero", read_divide_zero_content()); + res.push(app7); + + // sig_action + let app8 = UserApp::new("/sig_action", read_sig_action_content()); + res.push(app8); + res } @@ -79,6 +87,14 @@ fn read_fork_c_content() -> &'static [u8] { include_bytes!("../../kxos-user/fork_c/fork") } -fn read_sig_procmask() -> &'static [u8] { +fn read_sig_procmask_content() -> &'static [u8] { include_bytes!("../../kxos-user/signal_c/sig_procmask") } + +fn read_divide_zero_content() -> &'static [u8] { + include_bytes!("../../kxos-user/signal_c/divide_zero") +} + +fn read_sig_action_content() -> &'static [u8] { + include_bytes!("../../kxos-user/signal_c/sig_action") +} diff --git a/src/kxos-user/signal_c/Makefile b/src/kxos-user/signal_c/Makefile index bc903b97f..090aaaf3d 100644 --- a/src/kxos-user/signal_c/Makefile +++ b/src/kxos-user/signal_c/Makefile @@ -1,9 +1,10 @@ .PHONY: build clean run -build: divide_zero.c sig_procmask.c +build: divide_zero.c sig_procmask.c sig_action.c @gcc -static divide_zero.c -o divide_zero @gcc -static sig_procmask.c -o sig_procmask + @gcc -static sig_action.c -o sig_action clean: - @rm divide_zero sig_procmask + @rm divide_zero sig_procmask sig_action run: build @./sig_procmask - @./divide_zero + @./sig_action diff --git a/src/kxos-user/signal_c/sig_action b/src/kxos-user/signal_c/sig_action new file mode 100755 index 000000000..42d39e3a8 --- /dev/null +++ b/src/kxos-user/signal_c/sig_action @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08b21d340c8d144c1bfb86097e46ceda6d690041269cf56fee5bd8918e8253fa +size 877544 diff --git a/src/kxos-user/signal_c/sig_action.c b/src/kxos-user/signal_c/sig_action.c index e69de29bb..c1927c1f7 100644 --- a/src/kxos-user/signal_c/sig_action.c +++ b/src/kxos-user/signal_c/sig_action.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int sigchld = 0; + +void proc_exit() { + sigchld = 999; +} + +int main() { + signal(SIGCHLD, proc_exit); + printf("Run a parent process has pid = %d\n", getpid()); + fflush(stdout); + int pid = fork(); + if(pid == 0) { + // child process + printf("create a new proces successfully (pid = %d)\n", getpid()); + fflush(stdout); + } else { + // parent process + wait(NULL); + printf("sigchld = %d\n", sigchld); + fflush(stdout); + } + return 0; +} \ No newline at end of file