mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
move exception handling to kxos-std
This commit is contained in:
parent
149f72e31f
commit
288cba2832
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -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
|
||||
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
|
4
src/Cargo.lock
generated
4
src/Cargo.lock
generated
@ -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"
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
|
13
src/kxos-std/src/process/exception.rs
Normal file
13
src/kxos-std/src/process/exception.rs
Normal file
@ -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);
|
||||
}
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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 => {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
51
src/kxos-std/src/process/signal/signals/fault.rs
Normal file
51
src/kxos-std/src/process/signal/signals/fault.rs
Normal file
@ -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<u64>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
20
src/kxos-std/src/process/signal/signals/kernel.rs
Normal file
20
src/kxos-std/src/process/signal/signals/kernel.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
pub mod fault;
|
||||
pub mod kernel;
|
||||
pub mod user;
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
@ -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<UserSpace>, parent: Weak<Process>) -> 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<UserSpace>, parent: Weak<Process>) -> 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<UserSpace>, parent: Weak<Process>) -> 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),
|
||||
}
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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)
|
||||
}
|
||||
|
@ -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<u64> 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<isize> {
|
||||
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<u64> {
|
||||
|
@ -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<isize> {
|
||||
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 _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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 _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
debug!("[syscall][id={}][SYS_EXIT]", SYS_EXIT);
|
||||
current!().exit(exit_code);
|
||||
SyscallResult::NotReturn
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
debug!("[syscall][id={}][SYS_EXIT_GROUP]", SYS_EXIT_GROUP);
|
||||
current!().exit(exit_code as _);
|
||||
SyscallResult::NotReturn
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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
|
||||
|
@ -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<isize> {
|
||||
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)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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
|
||||
|
@ -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<isize> {
|
||||
debug!("[syscall][id={}][SYS_GETPID]", SYS_GETPID);
|
||||
let pid = Process::current().pid();
|
||||
info!("[sys_getpid]: pid = {}", pid);
|
||||
SyscallResult::Return(pid as _)
|
||||
Ok(pid as _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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 _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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<()> {
|
||||
|
@ -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<isize> {
|
||||
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(
|
||||
|
@ -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<isize> {
|
||||
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<isize> {
|
||||
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<isize> {
|
||||
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<isize> {
|
||||
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<isize> {
|
||||
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<isize> {
|
||||
debug!("[syscall][id={}][SYS_GETEGID]", SYS_GETEGID);
|
||||
warn!("TODO: getegid only return a fake egid now");
|
||||
SyscallResult::Return(0)
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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 {
|
||||
|
@ -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<isize> {
|
||||
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
|
||||
|
@ -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<isize> {
|
||||
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::<u64>(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<u32> for MaskOp {
|
||||
};
|
||||
Ok(op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
debug!("[syscall][id={}][SYS_SCHED_YIELD]", SYS_SCHED_YIELD);
|
||||
Process::yield_now();
|
||||
SyscallResult::Return(0)
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
debug!("[syscall][id={}][SYS_TGKILL]", SYS_TGKILL);
|
||||
debug!("tgid = {}", tgid);
|
||||
debug!("pid = {}", pid);
|
||||
warn!("TODO: tgkill do nothing now");
|
||||
SyscallResult::Return(0)
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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 {
|
||||
|
@ -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<isize> {
|
||||
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 _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
// 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 _)
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
// 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);
|
||||
}
|
||||
|
@ -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<isize> {
|
||||
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 {
|
||||
|
@ -49,9 +49,17 @@ pub fn get_all_apps() -> Vec<UserApp> {
|
||||
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")
|
||||
}
|
||||
|
@ -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
|
||||
|
3
src/kxos-user/signal_c/sig_action
Executable file
3
src/kxos-user/signal_c/sig_action
Executable file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08b21d340c8d144c1bfb86097e46ceda6d690041269cf56fee5bd8918e8253fa
|
||||
size 877544
|
@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user