diff --git a/src/kxos-frame/src/sync/wait.rs b/src/kxos-frame/src/sync/wait.rs index 829292d01..ef3fd0311 100644 --- a/src/kxos-frame/src/sync/wait.rs +++ b/src/kxos-frame/src/sync/wait.rs @@ -3,7 +3,7 @@ use core::sync::atomic::{AtomicBool, Ordering}; use alloc::{collections::VecDeque, sync::Arc, vec::Vec}; use spin::mutex::Mutex; -use crate::{debug, task::Task}; +use crate::task::Task; /// A wait queue. /// @@ -214,7 +214,7 @@ impl Waiter { pub fn wait(&self) { while !self.is_woken_up.load(Ordering::Relaxed) { // yield the execution, to allow other task to contine - debug!("Waiter: wait"); + // debug!("Waiter: wait"); Task::yield_now(); } } diff --git a/src/kxos-std/src/process/exception.rs b/src/kxos-std/src/process/exception.rs index 86cd1a4ca..1c4b9b8fa 100644 --- a/src/kxos-std/src/process/exception.rs +++ b/src/kxos-std/src/process/exception.rs @@ -8,6 +8,7 @@ pub fn handle_exception(context: &mut CpuContext) { let current = current!(); let pid = current.pid(); debug!("trap info = {:x?}", trap_info); + debug!("cpu context = {:x?}", context); 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 05187c07d..6e27949c8 100644 --- a/src/kxos-std/src/process/mod.rs +++ b/src/kxos-std/src/process/mod.rs @@ -14,6 +14,7 @@ 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::signal::SigContext; use self::status::ProcessStatus; use self::task::create_user_task_from_elf; @@ -64,6 +65,8 @@ pub struct Process { sig_queues: Mutex, /// Process-level sigmask sig_mask: Mutex, + /// Signal handler Context + sig_context: Mutex>, } impl Process { @@ -116,6 +119,7 @@ impl Process { sig_dispositions: Mutex::new(sig_dispositions), sig_queues: Mutex::new(sig_queues), sig_mask: Mutex::new(sig_mask), + sig_context: Mutex::new(None), } } @@ -222,6 +226,10 @@ impl Process { &self.process_group } + pub fn sig_context(&self) -> &Mutex> { + &self.sig_context + } + /// add a child process pub fn add_child(&self, child: Arc) { debug!("process: {}, add child: {} ", self.pid(), child.pid()); diff --git a/src/kxos-std/src/process/process_filter.rs b/src/kxos-std/src/process/process_filter.rs index 4db223100..968f50d16 100644 --- a/src/kxos-std/src/process/process_filter.rs +++ b/src/kxos-std/src/process/process_filter.rs @@ -21,7 +21,7 @@ impl ProcessFilter { } // used for wait4 and kill - pub fn from_id(wait_pid: isize) -> Self { + pub fn from_id(wait_pid: i32) -> Self { // https://man7.org/linux/man-pages/man2/waitpid.2.html // https://man7.org/linux/man-pages/man2/kill.2.html if wait_pid < -1 { diff --git a/src/kxos-std/src/process/signal/c_types.rs b/src/kxos-std/src/process/signal/c_types.rs new file mode 100644 index 000000000..d30bf3def --- /dev/null +++ b/src/kxos-std/src/process/signal/c_types.rs @@ -0,0 +1,13 @@ +#![allow(non_camel_case_types)] +use crate::prelude::*; + +pub type sigset_t = u64; + +#[derive(Debug, Clone, Copy, Pod)] +#[repr(C)] +pub struct sigaction_t { + pub handler_ptr: Vaddr, + pub flags: u32, + pub restorer_ptr: Vaddr, + pub mask: sigset_t, +} diff --git a/src/kxos-std/src/process/signal/mod.rs b/src/kxos-std/src/process/signal/mod.rs index bacf7daab..dcde0ced7 100644 --- a/src/kxos-std/src/process/signal/mod.rs +++ b/src/kxos-std/src/process/signal/mod.rs @@ -1,3 +1,4 @@ +pub mod c_types; pub mod constants; pub mod sig_action; pub mod sig_disposition; @@ -6,15 +7,19 @@ pub mod sig_num; pub mod sig_queues; pub mod signals; -use kxos_frame::task::Task; +use kxos_frame::{cpu::CpuContext, task::Task}; +use self::sig_mask::SigMask; +use self::sig_num::SigNum; +use crate::memory::{write_bytes_to_user, write_val_to_user}; +use crate::process::signal::sig_action::SigActionFlags; use crate::{ prelude::*, process::signal::sig_action::{SigAction, SigDefaultAction}, }; /// Handle pending signal for current process -pub fn handle_pending_signal() { +pub fn handle_pending_signal(context: &mut CpuContext) { let current = current!(); let pid = current.pid(); let process_name = current.filename().unwrap(); @@ -25,12 +30,24 @@ pub fn handle_pending_signal() { let sig_num = signal.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); + debug!("sig action: {:x?}", sig_action); match sig_action { SigAction::Ign => { debug!("Ignore signal {:?}", sig_num); } - SigAction::User { .. } => todo!(), + SigAction::User { + handler_addr, + flags, + restorer_addr, + mask, + } => handle_user_signal_handler( + sig_num, + handler_addr, + flags, + restorer_addr, + mask, + context, + ), SigAction::Dfl => { let sig_default_action = SigDefaultAction::from_signum(sig_num); debug!("sig_default_action: {:?}", sig_default_action); @@ -70,3 +87,85 @@ pub fn handle_pending_signal() { } } } + +pub fn handle_user_signal_handler( + sig_num: SigNum, + handler_addr: Vaddr, + flags: SigActionFlags, + restorer_addr: Vaddr, + mask: SigMask, + context: &mut CpuContext, +) { + debug!("sig_num = {:?}", sig_num); + debug!("handler_addr = 0x{:x}", handler_addr); + debug!("flags = {:?}", flags); + debug!("restorer_addr = 0x{:x}", restorer_addr); + // FIXME: How to respect flags + if flags.intersects(!(SigActionFlags::SA_RESTART | SigActionFlags::SA_RESTORER)) { + panic!("Unsupported Signal flags"); + } + let current = current!(); + // block signals in sigmask when running signal handler + current.sig_mask().lock().block(mask.as_u64()); + // store context in current process + let sig_context = SigContext::new(context.clone(), mask); + *(current.sig_context().lock()) = Some(sig_context); + // set up signal stack in user stack + let mut user_rsp = context.gp_regs.rsp; + // avoid corrupt user stack, we minus 128 first. + user_rsp = user_rsp - 128; + // Copy the trampoline code. + if flags.contains(SigActionFlags::SA_RESTORER) { + // If contains SA_RESTORER flag, trampoline code is provided by libc in restorer_addr. + // We just store restorer_addr on user stack to allow user code just to trampoline code. + user_rsp = write_u64_to_user_stack(user_rsp, restorer_addr as u64); + } else { + // Otherwise we create + const TRAMPOLINE: &[u8] = &[ + 0xb8, 0x0f, 0x00, 0x00, 0x00, // mov eax, 15(syscall number of rt_sigreturn) + 0x0f, 0x05, // syscall (call rt_sigreturn) + 0x90, // nop (for alignment) + ]; + user_rsp = user_rsp - TRAMPOLINE.len() as u64; + let trampoline_rip = user_rsp; + write_bytes_to_user(user_rsp as Vaddr, TRAMPOLINE); + user_rsp = write_u64_to_user_stack(user_rsp, trampoline_rip); + } + context.gp_regs.rip = handler_addr as _; + context.gp_regs.rsp = user_rsp; + // parameters of signal handler + context.gp_regs.rdi = sig_num.as_u8() as u64; // signal number + context.gp_regs.rsi = 0; // siginfo_t* siginfo + context.gp_regs.rdx = 0; // void* ctx +} + +fn write_u64_to_user_stack(rsp: u64, value: u64) -> u64 { + let rsp = rsp - 8; + write_val_to_user(rsp as Vaddr, &value); + rsp +} + +/// Used to store process context before running signal handler. +/// In rt_sigreturn, this context is used to restore process context. +#[derive(Debug, Clone, Copy)] +pub struct SigContext { + cpu_context: CpuContext, + sig_mask: SigMask, +} + +impl SigContext { + pub const fn new(cpu_context: CpuContext, sig_mask: SigMask) -> SigContext { + Self { + cpu_context, + sig_mask, + } + } + + pub fn cpu_context(&self) -> &CpuContext { + &self.cpu_context + } + + pub fn sig_mask(&self) -> &SigMask { + &self.sig_mask + } +} diff --git a/src/kxos-std/src/process/signal/sig_action.rs b/src/kxos-std/src/process/signal/sig_action.rs index 27a9e3a2a..3c8150463 100644 --- a/src/kxos-std/src/process/signal/sig_action.rs +++ b/src/kxos-std/src/process/signal/sig_action.rs @@ -1,4 +1,5 @@ -use super::{constants::*, sig_mask::SigMask, sig_num::SigNum}; +use super::{c_types::sigaction_t, constants::*, sig_mask::SigMask, sig_num::SigNum}; +use crate::prelude::*; use bitflags::bitflags; use kxos_frame::warn; @@ -21,6 +22,58 @@ impl Default for SigAction { } } +impl TryFrom for SigAction { + type Error = Error; + + fn try_from(input: sigaction_t) -> Result { + let action = match input.handler_ptr { + SIG_DFL => SigAction::Dfl, + SIG_IGN => SigAction::Ign, + _ => { + let flags = SigActionFlags::from_bits_truncate(input.flags); + let mask = SigMask::from(input.mask); + SigAction::User { + handler_addr: input.handler_ptr, + flags, + restorer_addr: input.restorer_ptr, + mask, + } + } + }; + Ok(action) + } +} + +impl SigAction { + pub fn to_c(&self) -> sigaction_t { + match self { + SigAction::Dfl => sigaction_t { + handler_ptr: SIG_DFL, + flags: 0, + restorer_ptr: 0, + mask: 0, + }, + SigAction::Ign => sigaction_t { + handler_ptr: SIG_IGN, + flags: 0, + restorer_ptr: 0, + mask: 0, + }, + SigAction::User { + handler_addr, + flags, + restorer_addr, + mask, + } => sigaction_t { + handler_ptr: *handler_addr, + flags: flags.to_u32(), + restorer_ptr: *restorer_addr, + mask: mask.as_u64(), + }, + } + } +} + bitflags! { pub struct SigActionFlags: u32 { const SA_NOCLDSTOP = 1; @@ -35,10 +88,11 @@ bitflags! { } impl TryFrom for SigActionFlags { - type Error = &'static str; + type Error = Error; - fn try_from(bits: u32) -> Result { - let flags = SigActionFlags::from_bits(bits).ok_or_else(|| "invalid sigaction flags")?; + fn try_from(bits: u32) -> Result { + let flags = SigActionFlags::from_bits(bits) + .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid sig action flag"))?; if flags.contains(SigActionFlags::SA_RESTART) { warn!("SA_RESTART is not supported"); } diff --git a/src/kxos-std/src/process/task.rs b/src/kxos-std/src/process/task.rs index 8c6b886d9..229c312dd 100644 --- a/src/kxos-std/src/process/task.rs +++ b/src/kxos-std/src/process/task.rs @@ -57,7 +57,7 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< if current.status().lock().is_zombie() { break; } - handle_pending_signal(); + handle_pending_signal(context); if current.status().lock().is_zombie() { debug!("exit due to signal"); break; @@ -66,7 +66,7 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< while current.status().lock().is_suspend() { Process::yield_now(); debug!("{} is suspended.", current.pid()); - handle_pending_signal(); + handle_pending_signal(context); } } debug!("exit user loop"); diff --git a/src/kxos-std/src/syscall/access.rs b/src/kxos-std/src/syscall/access.rs index cc066ecb1..81319de7f 100644 --- a/src/kxos-std/src/syscall/access.rs +++ b/src/kxos-std/src/syscall/access.rs @@ -1,12 +1,12 @@ -use super::constants::*; +use super::{constants::*, SyscallReturn}; use crate::{memory::read_bytes_from_user, prelude::*, syscall::SYS_ACCESS}; -pub fn sys_access(filename_ptr: Vaddr, file_mode: u64) -> Result { +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"); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/arch_prctl.rs b/src/kxos-std/src/syscall/arch_prctl.rs index 8aeccbcb2..6be34263b 100644 --- a/src/kxos-std/src/syscall/arch_prctl.rs +++ b/src/kxos-std/src/syscall/arch_prctl.rs @@ -3,6 +3,8 @@ use kxos_frame::cpu::CpuContext; use crate::prelude::*; use crate::syscall::SYS_ARCH_PRCTL; +use super::SyscallReturn; + #[allow(non_camel_case_types)] #[derive(Debug)] pub enum ArchPrctlCode { @@ -26,19 +28,12 @@ impl TryFrom for ArchPrctlCode { } } -pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> Result { +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)?; debug!("arch_prctl_code: {:?}", arch_prctl_code); 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 _) - // } - // } + Ok(SyscallReturn::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 b9dd71e53..d9c4c83e9 100644 --- a/src/kxos-std/src/syscall/brk.rs +++ b/src/kxos-std/src/syscall/brk.rs @@ -1,9 +1,10 @@ use crate::prelude::*; +use crate::syscall::SyscallReturn; 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) -> Result { +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 { @@ -20,5 +21,5 @@ pub fn sys_brk(heap_end: u64) -> Result { .expect("brk should work on process with user space"); let new_heap_end = user_heap.brk(new_heap_end, vm_space); - Ok(new_heap_end as _) + Ok(SyscallReturn::Return(new_heap_end as _)) } diff --git a/src/kxos-std/src/syscall/clone.rs b/src/kxos-std/src/syscall/clone.rs index e60b0b4bf..80de9fa56 100644 --- a/src/kxos-std/src/syscall/clone.rs +++ b/src/kxos-std/src/syscall/clone.rs @@ -3,6 +3,8 @@ use kxos_frame::cpu::CpuContext; use crate::process::clone::{clone_child, CloneArgs, CloneFlags}; use crate::{prelude::*, syscall::SYS_CLONE}; +use super::SyscallReturn; + // The order of arguments for clone differs in different architecture. // This order we use here is the order for x86_64. See https://man7.org/linux/man-pages/man2/clone.2.html. pub fn sys_clone( @@ -12,7 +14,7 @@ pub fn sys_clone( child_tidptr: Vaddr, tls: usize, parent_context: CpuContext, -) -> Result { +) -> Result { debug!("[syscall][id={}][SYS_CLONE]", SYS_CLONE); debug!("flags = {}", clone_flags); let clone_flags = CloneFlags::from(clone_flags); @@ -28,5 +30,5 @@ pub fn sys_clone( debug!("*********schedule child process, pid = {}**********", pid); child_process.send_to_scheduler(); debug!("*********return to parent process, pid = {}*********", pid); - Ok(child_pid as _) + Ok(SyscallReturn::Return(child_pid as _)) } diff --git a/src/kxos-std/src/syscall/execve.rs b/src/kxos-std/src/syscall/execve.rs index 240dbff2f..af5592873 100644 --- a/src/kxos-std/src/syscall/execve.rs +++ b/src/kxos-std/src/syscall/execve.rs @@ -1,6 +1,6 @@ use kxos_frame::cpu::CpuContext; -use super::constants::*; +use super::{constants::*, SyscallReturn}; use crate::process::elf::load_elf_to_vm_space; use crate::{memory::read_bytes_from_user, prelude::*, process::Process, syscall::SYS_EXECVE}; @@ -9,7 +9,7 @@ pub fn sys_execve( argv_ptr_ptr: Vaddr, envp_ptr_ptr: Vaddr, context: &mut CpuContext, -) -> Result { +) -> 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); @@ -40,11 +40,12 @@ pub fn sys_execve( let defalut_content = CpuContext::default(); context.gp_regs = defalut_content.gp_regs; context.fs_base = defalut_content.fs_base; + context.fp_regs = defalut_content.fp_regs; // set new entry point context.gp_regs.rip = elf_load_info.entry_point(); debug!("entry_point: 0x{:x}", elf_load_info.entry_point()); // 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()); - Ok(0) + Ok(SyscallReturn::NoReturn) } diff --git a/src/kxos-std/src/syscall/exit.rs b/src/kxos-std/src/syscall/exit.rs index 3c8a11c0c..8e60803c1 100644 --- a/src/kxos-std/src/syscall/exit.rs +++ b/src/kxos-std/src/syscall/exit.rs @@ -1,9 +1,9 @@ use crate::prelude::*; -use crate::syscall::SYS_EXIT; +use crate::syscall::{SyscallReturn, SYS_EXIT}; -pub fn sys_exit(exit_code: i32) -> Result { +pub fn sys_exit(exit_code: i32) -> Result { debug!("[syscall][id={}][SYS_EXIT]", SYS_EXIT); current!().exit(exit_code); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/exit_group.rs b/src/kxos-std/src/syscall/exit_group.rs index 0d8ee732a..cfb084cf4 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::SYS_EXIT_GROUP; +use crate::syscall::{SyscallReturn, SYS_EXIT_GROUP}; -pub fn sys_exit_group(exit_code: u64) -> Result { +pub fn sys_exit_group(exit_code: u64) -> Result { debug!("[syscall][id={}][SYS_EXIT_GROUP]", SYS_EXIT_GROUP); current!().exit(exit_code as _); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/fork.rs b/src/kxos-std/src/syscall/fork.rs index 37fe5961b..cfc0858b4 100644 --- a/src/kxos-std/src/syscall/fork.rs +++ b/src/kxos-std/src/syscall/fork.rs @@ -6,10 +6,12 @@ use kxos_frame::cpu::CpuContext; use crate::{process::Process, syscall::SYS_FORK}; -pub fn sys_fork(parent_context: CpuContext) -> Result { +use super::SyscallReturn; + +pub fn sys_fork(parent_context: CpuContext) -> Result { debug!("[syscall][id={}][SYS_FORK]", SYS_FORK); let child_process = fork(parent_context); - Ok(child_process.pid() as _) + Ok(SyscallReturn::Return(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 934e7cac9..2ecb99ddf 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::SYS_FSTAT; +use crate::syscall::{SyscallReturn, SYS_FSTAT}; -pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> Result { +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) -> Result { vm_space .write_val(stat_buf_ptr, &stat) .expect("Write value failed"); - return Ok(0); + return Ok(SyscallReturn::Return(0)); } warn!("TODO: fstat only returns fake result now."); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/futex.rs b/src/kxos-std/src/syscall/futex.rs index b71f153e4..6103533e4 100644 --- a/src/kxos-std/src/syscall/futex.rs +++ b/src/kxos-std/src/syscall/futex.rs @@ -1,3 +1,4 @@ +use crate::syscall::SyscallReturn; use crate::{memory::read_val_from_user, syscall::SYS_FUTEX}; use crate::prelude::*; @@ -17,7 +18,7 @@ pub fn sys_futex( utime_addr: u64, futex_new_addr: u64, bitset: u64, -) -> Result { +) -> 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(); @@ -69,7 +70,7 @@ pub fn sys_futex( } .unwrap(); - Ok(res as _) + Ok(SyscallReturn::Return(res as _)) } /// do futex wait diff --git a/src/kxos-std/src/syscall/getegid.rs b/src/kxos-std/src/syscall/getegid.rs new file mode 100644 index 000000000..d1e9f2c85 --- /dev/null +++ b/src/kxos-std/src/syscall/getegid.rs @@ -0,0 +1,9 @@ +use crate::{prelude::*, syscall::SYS_GETEGID}; + +use super::SyscallReturn; + +pub fn sys_getegid() -> Result { + debug!("[syscall][id={}][SYS_GETEGID]", SYS_GETEGID); + warn!("TODO: getegid only return a fake egid now"); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/kxos-std/src/syscall/geteuid.rs b/src/kxos-std/src/syscall/geteuid.rs new file mode 100644 index 000000000..1c11f4dcc --- /dev/null +++ b/src/kxos-std/src/syscall/geteuid.rs @@ -0,0 +1,9 @@ +use crate::{prelude::*, syscall::SYS_GETEUID}; + +use super::SyscallReturn; + +pub fn sys_geteuid() -> Result { + debug!("[syscall][id={}][SYS_GETEUID]", SYS_GETEUID); + warn!("TODO: geteuid only return a fake euid now"); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/kxos-std/src/syscall/getgid.rs b/src/kxos-std/src/syscall/getgid.rs new file mode 100644 index 000000000..eefe27ed2 --- /dev/null +++ b/src/kxos-std/src/syscall/getgid.rs @@ -0,0 +1,9 @@ +use crate::{prelude::*, syscall::SYS_GETGID}; + +use super::SyscallReturn; + +pub fn sys_getgid() -> Result { + debug!("[syscall][id={}][SYS_GETGID]", SYS_GETGID); + warn!("TODO: getgid only return a fake gid now"); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/kxos-std/src/syscall/getpid.rs b/src/kxos-std/src/syscall/getpid.rs index 1b5ab04d6..493b7371f 100644 --- a/src/kxos-std/src/syscall/getpid.rs +++ b/src/kxos-std/src/syscall/getpid.rs @@ -2,9 +2,11 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETPID}; -pub fn sys_getpid() -> Result { +use super::SyscallReturn; + +pub fn sys_getpid() -> Result { debug!("[syscall][id={}][SYS_GETPID]", SYS_GETPID); let pid = Process::current().pid(); info!("[sys_getpid]: pid = {}", pid); - Ok(pid as _) + Ok(SyscallReturn::Return(pid as _)) } diff --git a/src/kxos-std/src/syscall/gettid.rs b/src/kxos-std/src/syscall/gettid.rs index c1d8e9622..028d6e891 100644 --- a/src/kxos-std/src/syscall/gettid.rs +++ b/src/kxos-std/src/syscall/gettid.rs @@ -2,9 +2,11 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETTID}; -pub fn sys_gettid() -> Result { +use super::SyscallReturn; + +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(); - Ok(tid as _) + Ok(SyscallReturn::Return(tid as _)) } diff --git a/src/kxos-std/src/syscall/getuid.rs b/src/kxos-std/src/syscall/getuid.rs new file mode 100644 index 000000000..f9bef9ddc --- /dev/null +++ b/src/kxos-std/src/syscall/getuid.rs @@ -0,0 +1,9 @@ +use crate::{prelude::*, syscall::SYS_GETUID}; + +use super::SyscallReturn; + +pub fn sys_getuid() -> Result { + debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID); + warn!("TODO: getuid only return a fake uid now"); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/kxos-std/src/syscall/kill.rs b/src/kxos-std/src/syscall/kill.rs index 90e347c4e..452e7abd1 100644 --- a/src/kxos-std/src/syscall/kill.rs +++ b/src/kxos-std/src/syscall/kill.rs @@ -7,12 +7,14 @@ use crate::{ syscall::SYS_KILL, }; -pub fn sys_kill(process_filter: u64, sig_num: u64) -> Result { +use super::SyscallReturn; + +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(); do_sys_kill(process_filter, sig_num)?; - Ok(0) + Ok(SyscallReturn::Return(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 073862b82..4af368cde 100644 --- a/src/kxos-std/src/syscall/mmap.rs +++ b/src/kxos-std/src/syscall/mmap.rs @@ -6,6 +6,8 @@ use kxos_frame::vm::VmPerm; use crate::{process::Process, syscall::SYS_MMAP}; +use super::SyscallReturn; + pub fn sys_mmap( addr: u64, len: u64, @@ -13,7 +15,7 @@ pub fn sys_mmap( flags: u64, fd: u64, offset: u64, -) -> Result { +) -> Result { debug!("[syscall][id={}][SYS_MMAP]", SYS_MMAP); let perms = VmPerm::try_from(perms).unwrap(); let flags = MMapFlags::try_from(flags).unwrap(); @@ -25,7 +27,7 @@ pub fn sys_mmap( fd as usize, offset as usize, ); - Ok(res as _) + Ok(SyscallReturn::Return(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 bf62fa450..62e055081 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -1,33 +1,38 @@ //! Read the Cpu context content then dispatch syscall to corrsponding handler //! The each sub module contains functions that handle real syscall logic. - use crate::prelude::*; -use crate::syscall::clone::sys_clone; -use crate::syscall::kill::sys_kill; -use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask; -use alloc::borrow::ToOwned; -use kxos_frame::cpu::CpuContext; - use crate::syscall::access::sys_access; use crate::syscall::arch_prctl::sys_arch_prctl; use crate::syscall::brk::sys_brk; +use crate::syscall::clone::sys_clone; use crate::syscall::execve::sys_execve; use crate::syscall::exit::sys_exit; use crate::syscall::exit_group::sys_exit_group; use crate::syscall::fork::sys_fork; use crate::syscall::fstat::sys_fstat; use crate::syscall::futex::sys_futex; +use crate::syscall::getegid::sys_getegid; +use crate::syscall::geteuid::sys_geteuid; +use crate::syscall::getgid::sys_getgid; use crate::syscall::getpid::sys_getpid; use crate::syscall::gettid::sys_gettid; +use crate::syscall::getuid::sys_getuid; +use crate::syscall::kill::sys_kill; use crate::syscall::mmap::sys_mmap; use crate::syscall::mprotect::sys_mprotect; use crate::syscall::readlink::sys_readlink; +use crate::syscall::rt_sigaction::sys_rt_sigaction; +use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask; +use crate::syscall::rt_sigreturn::sys_rt_sigreturn; +use crate::syscall::sched_yield::sys_sched_yield; use crate::syscall::tgkill::sys_tgkill; use crate::syscall::uname::sys_uname; use crate::syscall::wait4::sys_wait4; use crate::syscall::waitid::sys_waitid; use crate::syscall::write::sys_write; use crate::syscall::writev::sys_writev; +use crate::{define_syscall_nums, syscall_handler}; +use kxos_frame::cpu::CpuContext; mod access; mod arch_prctl; @@ -40,13 +45,19 @@ mod exit_group; mod fork; mod fstat; mod futex; +mod getegid; +mod geteuid; +mod getgid; mod getpid; mod gettid; +mod getuid; mod kill; mod mmap; mod mprotect; mod readlink; +mod rt_sigaction; mod rt_sigprocmask; +mod rt_sigreturn; mod sched_yield; mod tgkill; mod uname; @@ -55,41 +66,58 @@ mod waitid; mod write; mod writev; -const SYS_WRITE: u64 = 1; -const SYS_FSTAT: u64 = 5; -const SYS_MMAP: u64 = 9; -const SYS_MPROTECT: u64 = 10; -const SYS_BRK: u64 = 12; -const SYS_RT_SIGACTION: u64 = 13; -const SYS_RT_SIGPROCMASK: u64 = 14; -const SYS_WRITEV: u64 = 20; -const SYS_ACCESS: u64 = 21; -const SYS_SCHED_YIELD: u64 = 24; -const SYS_GETPID: u64 = 39; -const SYS_CLONE: u64 = 56; -const SYS_FORK: u64 = 57; -const SYS_EXECVE: u64 = 59; -const SYS_EXIT: u64 = 60; -const SYS_WAIT4: u64 = 61; -const SYS_KILL: u64 = 62; -const SYS_UNAME: u64 = 63; -const SYS_READLINK: u64 = 89; -const SYS_GETUID: u64 = 102; -const SYS_GETGID: u64 = 104; -const SYS_GETEUID: u64 = 107; -const SYS_GETEGID: u64 = 108; -const SYS_ARCH_PRCTL: u64 = 158; -const SYS_GETTID: u64 = 186; -const SYS_FUTEX: u64 = 202; -const SYS_EXIT_GROUP: u64 = 231; -const SYS_TGKILL: u64 = 234; -const SYS_WAITID: u64 = 247; +define_syscall_nums!( + SYS_WRITE = 1, + SYS_FSTAT = 5, + SYS_MMAP = 9, + SYS_MPROTECT = 10, + SYS_BRK = 12, + SYS_RT_SIGACTION = 13, + SYS_RT_SIGPROCMASK = 14, + SYS_RT_SIGRETRUN = 15, + SYS_WRITEV = 20, + SYS_ACCESS = 21, + SYS_SCHED_YIELD = 24, + SYS_IOCTL = 29, + SYS_GETPID = 39, + SYS_CLONE = 56, + SYS_FORK = 57, + SYS_EXECVE = 59, + SYS_EXIT = 60, + SYS_WAIT4 = 61, + SYS_KILL = 62, + SYS_UNAME = 63, + SYS_GETPPID = 64, + SYS_FCNTL = 72, + SYS_READLINK = 89, + SYS_GETUID = 102, + SYS_GETGID = 104, + SYS_GETEUID = 107, + SYS_GETEGID = 108, + SYS_GETPGRP = 111, + SYS_PRCTL = 157, + SYS_ARCH_PRCTL = 158, + SYS_GETCWD = 183, + SYS_GETTID = 186, + SYS_FUTEX = 202, + SYS_EXIT_GROUP = 231, + SYS_TGKILL = 234, + SYS_WAITID = 247 +); pub struct SyscallArgument { syscall_number: u64, args: [u64; 6], } +/// Syscall return +pub enum SyscallReturn { + /// return isize, this value will be used to set rax + Return(isize), + /// does not need to set rax + NoReturn, +} + impl SyscallArgument { fn new_from_context(context: &CpuContext) -> Self { let syscall_number = context.gp_regs.rax; @@ -114,92 +142,91 @@ pub fn handle_syscall(context: &mut CpuContext) { match syscall_return { Ok(return_value) => { - context.gp_regs.rax = return_value as u64; + if let SyscallReturn::Return(return_value) = 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, -) -> Result { +) -> Result { match syscall_number { - SYS_WRITE => sys_write(args[0], args[1], args[2]), - SYS_FSTAT => sys_fstat(args[0], args[1] as _), - SYS_MMAP => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]), - 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_WRITEV => sys_writev(args[0], args[1], args[2]), - SYS_ACCESS => sys_access(args[0] as _, args[1]), - SYS_GETPID => sys_getpid(), - SYS_CLONE => sys_clone( - args[0], - args[1] as _, - args[2] as _, - args[3] as _, - args[4] as _, - context.to_owned(), - ), - SYS_FORK => sys_fork(context.to_owned()), - SYS_EXECVE => sys_execve(args[0] as _, args[1] as _, args[2] as _, context), - SYS_EXIT => sys_exit(args[0] as _), - SYS_WAIT4 => sys_wait4(args[0], args[1], args[2]), - SYS_KILL => sys_kill(args[0], args[1]), - SYS_UNAME => sys_uname(args[0]), - SYS_READLINK => sys_readlink(args[0], args[1], args[2]), - SYS_GETUID => sys_getuid(), - SYS_GETGID => sys_getgid(), - SYS_GETEUID => sys_geteuid(), - SYS_GETEGID => sys_getegid(), - SYS_ARCH_PRCTL => sys_arch_prctl(args[0], args[1], context), - SYS_GETTID => sys_gettid(), - SYS_FUTEX => sys_futex(args[0], args[1], args[2], args[3], args[4], args[5]), - SYS_EXIT_GROUP => sys_exit_group(args[0]), - SYS_TGKILL => sys_tgkill(args[0], args[1], args[2]), - SYS_WAITID => sys_waitid(args[0], args[1], args[2], args[3], args[4]), + SYS_WRITE => syscall_handler!(3, sys_write, args), + SYS_FSTAT => syscall_handler!(2, sys_fstat, args), + SYS_MMAP => syscall_handler!(6, sys_mmap, args), + SYS_MPROTECT => syscall_handler!(3, sys_mprotect, args), + SYS_BRK => syscall_handler!(1, sys_brk, args), + SYS_RT_SIGACTION => syscall_handler!(4, sys_rt_sigaction, args), + SYS_RT_SIGPROCMASK => syscall_handler!(4, sys_rt_sigprocmask, args), + SYS_RT_SIGRETRUN => syscall_handler!(0, sys_rt_sigreturn, context), + SYS_WRITEV => syscall_handler!(3, sys_writev, args), + SYS_ACCESS => syscall_handler!(2, sys_access, args), + SYS_SCHED_YIELD => syscall_handler!(0, sys_sched_yield), + SYS_IOCTL => todo!(), + SYS_GETPID => syscall_handler!(0, sys_getpid), + SYS_CLONE => syscall_handler!(5, sys_clone, args, context.clone()), + SYS_FORK => syscall_handler!(0, sys_fork, context.clone()), + SYS_EXECVE => syscall_handler!(3, sys_execve, args, context), + SYS_EXIT => syscall_handler!(1, sys_exit, args), + SYS_WAIT4 => syscall_handler!(3, sys_wait4, args), + SYS_KILL => syscall_handler!(2, sys_kill, args), + SYS_UNAME => syscall_handler!(1, sys_uname, args), + SYS_GETPPID => todo!(), + SYS_FCNTL => todo!(), + SYS_READLINK => syscall_handler!(3, sys_readlink, args), + SYS_GETUID => syscall_handler!(0, sys_getuid), + SYS_GETGID => syscall_handler!(0, sys_getgid), + SYS_GETEUID => syscall_handler!(0, sys_geteuid), + SYS_GETEGID => syscall_handler!(0, sys_getegid), + SYS_GETPGRP => todo!(), + SYS_PRCTL => todo!(), + SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context), + SYS_GETCWD => todo!(), + SYS_GETTID => syscall_handler!(0, sys_gettid), + SYS_FUTEX => syscall_handler!(6, sys_futex, args), + SYS_EXIT_GROUP => syscall_handler!(1, sys_exit_group, args), + SYS_TGKILL => syscall_handler!(3, sys_tgkill, args), + SYS_WAITID => syscall_handler!(5, sys_waitid, args), _ => panic!("Unsupported syscall number: {}", syscall_number), } } -pub fn sys_rt_sigaction() -> Result { - debug!("[syscall][id={}][SYS_RT_SIGACTION]", SYS_RT_SIGACTION); - warn!("TODO: rt_sigaction only return a fake result"); - Ok(0) +/// This macro is used to define syscall handler. +/// The first param is ths number of parameters, +/// The second param is the function name of syscall handler, +/// The third is optional, means the args(if parameter number > 0), +/// The third is optional, means if cpu context is required. +#[macro_export] +macro_rules! syscall_handler { + (0, $fn_name: ident) => { $fn_name() }; + (0, $fn_name: ident, $context: expr) => { $fn_name($context) }; + (1, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _) }; + (1, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $context) }; + (2, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _)}; + (2, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $context)}; + (3, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _)}; + (3, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $context)}; + (4, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _)}; + (4, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _), $context}; + (5, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _)}; + (5, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $context)}; + (6, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _)}; + (6, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _, $context)}; } -pub fn sys_getuid() -> Result { - debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID); - warn!("TODO: getuid only return a fake uid now"); - Ok(0) -} - -pub fn sys_getgid() -> Result { - debug!("[syscall][id={}][SYS_GETGID]", SYS_GETGID); - warn!("TODO: getgid only return a fake gid now"); - Ok(0) -} - -pub fn sys_geteuid() -> Result { - debug!("[syscall][id={}][SYS_GETEUID]", SYS_GETEUID); - warn!("TODO: geteuid only return a fake euid now"); - Ok(0) -} - -pub fn sys_getegid() -> Result { - debug!("[syscall][id={}][SYS_GETEGID]", SYS_GETEGID); - warn!("TODO: getegid only return a fake egid now"); - Ok(0) +#[macro_export] +macro_rules! define_syscall_nums { + ( $( $name: ident = $num: expr ),+ ) => { + $( + const $name: u64 = $num; + )* + } } diff --git a/src/kxos-std/src/syscall/mprotect.rs b/src/kxos-std/src/syscall/mprotect.rs index 23b101858..48c9df88e 100644 --- a/src/kxos-std/src/syscall/mprotect.rs +++ b/src/kxos-std/src/syscall/mprotect.rs @@ -4,11 +4,13 @@ use crate::prelude::*; use crate::syscall::SYS_MPROTECT; -pub fn sys_mprotect(vaddr: u64, len: u64, perms: u64) -> Result { +use super::SyscallReturn; + +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); - Ok(0) + Ok(SyscallReturn::Return(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 de76fca8e..39434cd13 100644 --- a/src/kxos-std/src/syscall/readlink.rs +++ b/src/kxos-std/src/syscall/readlink.rs @@ -6,16 +6,22 @@ use crate::{ syscall::SYS_READLINK, }; +use super::SyscallReturn; + const MAX_FILENAME_LEN: usize = 128; -pub fn sys_readlink(filename_ptr: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result { +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, ); - Ok(res as _) + Ok(SyscallReturn::Return(res as _)) } /// do sys readlink diff --git a/src/kxos-std/src/syscall/rt_sigaction.rs b/src/kxos-std/src/syscall/rt_sigaction.rs new file mode 100644 index 000000000..3205fa00f --- /dev/null +++ b/src/kxos-std/src/syscall/rt_sigaction.rs @@ -0,0 +1,36 @@ +use crate::{ + memory::{read_val_from_user, write_val_to_user}, + prelude::*, + process::signal::{c_types::sigaction_t, sig_action::SigAction, sig_num::SigNum}, + syscall::SYS_RT_SIGACTION, +}; + +use super::SyscallReturn; + +pub fn sys_rt_sigaction( + sig_num: u8, + sig_action_ptr: Vaddr, + old_sig_action_ptr: Vaddr, + sigset_size: u64, +) -> Result { + debug!("[syscall][id={}][SYS_RT_SIGACTION]", SYS_RT_SIGACTION); + let sig_num = SigNum::try_from(sig_num)?; + debug!("sig_num = {}", sig_num.sig_name()); + debug!("sig_action_ptr = 0x{:x}", sig_action_ptr); + debug!("old_sig_action_ptr = 0x{:x}", old_sig_action_ptr); + debug!("sigset_size = {}", sigset_size); + let sig_action_c = read_val_from_user::(sig_action_ptr); + debug!("sig_action_c = {:?}", sig_action_c); + let sig_action = SigAction::try_from(sig_action_c).unwrap(); + debug!("sig_action = {:x?}", sig_action); + + let current = current!(); + let mut sig_dispositions = current.sig_dispositions().lock(); + let old_action = sig_dispositions.get(sig_num); + debug!("old_action = {:x?}", old_action); + let old_action_c = old_action.to_c(); + debug!("old_action_c = {:x?}", old_action_c); + sig_dispositions.set(sig_num, sig_action); + write_val_to_user(old_sig_action_ptr, &old_action_c); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/kxos-std/src/syscall/rt_sigprocmask.rs b/src/kxos-std/src/syscall/rt_sigprocmask.rs index ee2052d12..7ce7d29eb 100644 --- a/src/kxos-std/src/syscall/rt_sigprocmask.rs +++ b/src/kxos-std/src/syscall/rt_sigprocmask.rs @@ -1,13 +1,16 @@ use kxos_frame::vm::VmIo; -use crate::{prelude::*, syscall::SYS_RT_SIGPROCMASK}; +use crate::{ + prelude::*, + syscall::{SyscallReturn, SYS_RT_SIGPROCMASK}, +}; pub fn sys_rt_sigprocmask( how: u32, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_size: usize, -) -> Result { +) -> Result { debug!("[syscall][id={}][SYS_RT_SIGPROCMASK]", SYS_RT_SIGPROCMASK); let mask_op = MaskOp::try_from(how).unwrap(); debug!("mask op = {:?}", mask_op); @@ -18,7 +21,7 @@ pub fn sys_rt_sigprocmask( warn!("sigset size is not equal to 8"); } do_rt_sigprocmask(mask_op, set_ptr, oldset_ptr, sigset_size).unwrap(); - Ok(0) + Ok(SyscallReturn::Return(0)) } fn do_rt_sigprocmask( diff --git a/src/kxos-std/src/syscall/rt_sigreturn.rs b/src/kxos-std/src/syscall/rt_sigreturn.rs new file mode 100644 index 000000000..32df4110c --- /dev/null +++ b/src/kxos-std/src/syscall/rt_sigreturn.rs @@ -0,0 +1,14 @@ +use crate::prelude::*; +use kxos_frame::cpu::CpuContext; + +use super::SyscallReturn; + +pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result { + let current = current!(); + let sig_context = current.sig_context().lock().as_ref().unwrap().clone(); + *context = *sig_context.cpu_context(); + // unblock sig mask + let sig_mask = sig_context.sig_mask(); + current.sig_mask().lock().unblock(sig_mask.as_u64()); + Ok(SyscallReturn::NoReturn) +} diff --git a/src/kxos-std/src/syscall/sched_yield.rs b/src/kxos-std/src/syscall/sched_yield.rs index 2768661f3..074ba9bd7 100644 --- a/src/kxos-std/src/syscall/sched_yield.rs +++ b/src/kxos-std/src/syscall/sched_yield.rs @@ -2,8 +2,10 @@ use crate::prelude::*; use crate::{process::Process, syscall::SYS_SCHED_YIELD}; -pub fn sys_sched_yield() -> Result { +use super::SyscallReturn; + +pub fn sys_sched_yield() -> Result { debug!("[syscall][id={}][SYS_SCHED_YIELD]", SYS_SCHED_YIELD); Process::yield_now(); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/tgkill.rs b/src/kxos-std/src/syscall/tgkill.rs index 0bdd713b6..7312f7899 100644 --- a/src/kxos-std/src/syscall/tgkill.rs +++ b/src/kxos-std/src/syscall/tgkill.rs @@ -2,10 +2,12 @@ use crate::prelude::*; use crate::syscall::SYS_TGKILL; -pub fn sys_tgkill(tgid: u64, pid: u64, signal: u64) -> Result { +use super::SyscallReturn; + +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"); - Ok(0) + Ok(SyscallReturn::Return(0)) } diff --git a/src/kxos-std/src/syscall/uname.rs b/src/kxos-std/src/syscall/uname.rs index 6d6140216..5b32b8391 100644 --- a/src/kxos-std/src/syscall/uname.rs +++ b/src/kxos-std/src/syscall/uname.rs @@ -2,6 +2,8 @@ use crate::prelude::*; use crate::{memory::write_val_to_user, syscall::SYS_UNAME}; +use super::SyscallReturn; + // 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. lazy_static! { @@ -56,10 +58,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) -> Result { +pub fn sys_uname(old_uname_addr: u64) -> Result { debug!("[syscall][id={}][SYS_UNAME]", SYS_UNAME); do_sys_uname(old_uname_addr as Vaddr); - Ok(0) + Ok(SyscallReturn::Return(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 41dabeebe..8e72e8e55 100644 --- a/src/kxos-std/src/syscall/wait4.rs +++ b/src/kxos-std/src/syscall/wait4.rs @@ -7,10 +7,12 @@ use crate::{ use crate::prelude::*; use crate::process::wait::WaitOptions; -pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> Result { +use super::SyscallReturn; + +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); + debug!("pid = {}", wait_pid as i32); debug!("exit_status_ptr = {}", exit_status_ptr); debug!("wait_options: {:?}", wait_options); let process_filter = ProcessFilter::from_id(wait_pid as _); @@ -18,6 +20,5 @@ pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> Resu if return_pid != 0 && exit_status_ptr != 0 { write_val_to_user(exit_status_ptr as _, &exit_code); } - - Ok(return_pid as _) + Ok(SyscallReturn::Return(return_pid as _)) } diff --git a/src/kxos-std/src/syscall/waitid.rs b/src/kxos-std/src/syscall/waitid.rs index 04dbc5486..aa74091ed 100644 --- a/src/kxos-std/src/syscall/waitid.rs +++ b/src/kxos-std/src/syscall/waitid.rs @@ -3,16 +3,18 @@ use crate::process::{process_filter::ProcessFilter, wait::wait_child_exit}; use crate::process::wait::WaitOptions; +use super::SyscallReturn; + pub fn sys_waitid( which: u64, upid: u64, infoq_addr: u64, options: u64, rusage_addr: u64, -) -> Result { +) -> 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); - Ok(pid as _) + Ok(SyscallReturn::Return(pid as _)) } diff --git a/src/kxos-std/src/syscall/write.rs b/src/kxos-std/src/syscall/write.rs index f2aed5df6..291d582e8 100644 --- a/src/kxos-std/src/syscall/write.rs +++ b/src/kxos-std/src/syscall/write.rs @@ -2,10 +2,12 @@ use crate::prelude::*; use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE}; +use super::SyscallReturn; + const STDOUT: u64 = 1; const STDERR: u64 = 2; -pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result { +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); @@ -18,8 +20,7 @@ pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result } else { info!("Error message from user mode: {:?}", content); } - - Ok(user_buf_len as _) + Ok(SyscallReturn::Return(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 f70ab37b5..490488a54 100644 --- a/src/kxos-std/src/syscall/writev.rs +++ b/src/kxos-std/src/syscall/writev.rs @@ -5,6 +5,8 @@ use crate::{ syscall::SYS_WRITEV, }; +use super::SyscallReturn; + const IOVEC_MAX: usize = 256; #[repr(C)] @@ -14,10 +16,10 @@ pub struct IoVec { len: usize, } -pub fn sys_writev(fd: u64, io_vec_ptr: u64, io_vec_count: u64) -> Result { +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); - Ok(res as _) + Ok(SyscallReturn::Return(res as _)) } pub fn do_sys_writev(fd: u64, io_vec_ptr: Vaddr, io_vec_count: usize) -> usize { diff --git a/src/kxos-user/execve/execve b/src/kxos-user/execve/execve index 85ed4d0b3..673f205d3 100755 --- a/src/kxos-user/execve/execve +++ b/src/kxos-user/execve/execve @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f98928f25e8223fd76d5d19db68e83913b48ea8b3cf6ae8d3120971e7271c93b +oid sha256:afc9465a8ae782da4e049d2b660a27b678394e683814c29a9601bc135126a0e5 size 871952 diff --git a/src/kxos-user/execve/execve.c b/src/kxos-user/execve/execve.c index 1db4a5ab9..547d9dae7 100644 --- a/src/kxos-user/execve/execve.c +++ b/src/kxos-user/execve/execve.c @@ -5,9 +5,10 @@ int main() { char* argv[] = { NULL }; char* envp[] = { NULL }; printf("Execve a new file ./hello:\n"); - // flust the stdout content to ensure the content print to console + // flush the stdout content to ensure the content print to console fflush(stdout); execve("./hello", argv, envp); printf("Should not print\n"); + fflush(stdout); return 0; } \ No newline at end of file diff --git a/src/kxos-user/fork_c/fork b/src/kxos-user/fork_c/fork index aacd152b4..8d7f960c3 100755 --- a/src/kxos-user/fork_c/fork +++ b/src/kxos-user/fork_c/fork @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f3b6fe8b52f200c469170223ea0cb2d06dbab6a5eb757e007eb0a751c5e1e81 +oid sha256:ca7a77a72da160f11670a04a16b623944295b9059399da45f57668f121b00d11 size 877152 diff --git a/src/kxos-user/fork_c/fork.c b/src/kxos-user/fork_c/fork.c index bac7950d0..dfbfc2efc 100644 --- a/src/kxos-user/fork_c/fork.c +++ b/src/kxos-user/fork_c/fork.c @@ -5,9 +5,9 @@ int main() { printf("before fork\n"); fflush(stdout); if(fork() == 0) { - printf("after fork: Hello from parent\n"); + printf("after fork: Hello from child\n"); } else { - printf("after fork: Hello from child\n"); + printf("after fork: Hello from parent\n"); } fflush(stdout); return 0; diff --git a/src/kxos-user/signal_c/sig_action b/src/kxos-user/signal_c/sig_action index 42d39e3a8..348d203fc 100755 --- a/src/kxos-user/signal_c/sig_action +++ b/src/kxos-user/signal_c/sig_action @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08b21d340c8d144c1bfb86097e46ceda6d690041269cf56fee5bd8918e8253fa +oid sha256:1938c6e8abd70c400780dd8aa089d768a8662d54bac2a658936790d5537e868c size 877544 diff --git a/src/kxos-user/signal_c/sig_action.c b/src/kxos-user/signal_c/sig_action.c index c1927c1f7..7f33bb9e7 100644 --- a/src/kxos-user/signal_c/sig_action.c +++ b/src/kxos-user/signal_c/sig_action.c @@ -7,7 +7,7 @@ int sigchld = 0; void proc_exit() { - sigchld = 999; + sigchld = sigchld + 1; } int main() {