1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 08:06:17 +04:00
This commit is contained in:
function2-llx 2020-06-04 19:15:06 +08:00
parent 98d3f83a12
commit bee5a77e2b
10 changed files with 231 additions and 58 deletions

View File

@ -69,6 +69,8 @@ use super::TrapFrame;
use crate::drivers::IRQ_MANAGER;
use bitflags::*;
use log::*;
use crate::process::current_thread;
use crate::processor;
global_asm!(include_str!("trap.asm"));
global_asm!(include_str!("vector.asm"));
@ -81,6 +83,9 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
tf.trap_num,
super::super::cpu::id()
);
if processor().tid_option().is_some() {
unsafe { current_thread().ustack_top = tf.rsp; }
}
// Dispatch
match tf.trap_num as u8 {
Breakpoint => breakpoint(),

View File

@ -5,6 +5,7 @@ use num::FromPrimitive;
use rcore_thread::std_thread::current;
use crate::signal::*;
use alloc::vec::Vec;
use crate::arch::get_sp;
#[derive(Clone)]
#[repr(C)]
@ -160,27 +161,44 @@ impl Context {
push r13
push r14
push r15
"::::"intel" "volatile");
asm!("
// save page table
mov r15, cr3
push r15
push r15"::::"intel" "volatile"
);
asm!(
"
// Switch stacks
mov [rdi], rsp // rdi = from_rsp
mov rsp, [rsi] // rsi = to_rsp
"::::"intel" "volatile");
asm!("mov r15, cr3"::::"intel" "volatile"); // debug
asm!(
"
// restore page table
pop r15
mov cr3, r15
"::::"intel" "volatile");
asm!("
// restore old callee-save registers
pop r15
": : : : "intel" "volatile"
);
asm!("
pop r14
pop r13
pop r12
pop r12": : : : "intel" "volatile");
asm!("
pop rbp
pop rbx
": : : : "intel" "volatile");
// info!("wang!");
handle_signal();
}

View File

@ -92,3 +92,19 @@ fn other_start() -> ! {
// call the first main function in kernel.
crate::kmain();
}
pub fn get_sp() -> usize {
let sp: usize;
unsafe {
asm!("mov %rsp, $0" : "=r"(sp));
}
sp
}
pub fn set_sp(sp: usize) {
unsafe {
asm!("mov $0, %rsp" :: "r" (sp) : "memory");
}
}

View File

@ -13,6 +13,7 @@ use crate::signal::{send_signal, Signal};
use crate::sync::Condvar;
use crate::sync::SpinNoIrqLock as Mutex;
use spin::RwLock;
use crate::processor;
#[derive(Default)]
pub struct Stdin {
@ -31,8 +32,12 @@ impl Stdin {
match c as i32 {
// INTR
0o3 => {
for proc in foregroud_processes {
send_signal(proc, -1, SIGINT);
if processor().tid_option().is_none() {
for proc in foregroud_processes {
send_signal(proc, -1, SIGINT);
}
} else {
info!("ignored");
}
}
_ => warn!("special char {} is unimplented", c),

View File

@ -25,7 +25,7 @@ use crate::sync::{Condvar, SpinLock, SpinNoIrqLock as Mutex};
use super::abi::{self, ProcInitInfo};
use crate::process::thread_manager;
use crate::signal::{SIGRTMAX, SigAction, Sigset};
use crate::signal::{SIGRTMAX, SignalAction, SigSet, SignalStack};
use bitflags::_core::cell::Ref;
use core::mem::MaybeUninit;
use pc_keyboard::KeyCode::BackTick;
@ -42,9 +42,11 @@ pub struct Thread {
// This is same as `proc.vm`
pub vm: Arc<Mutex<MemorySet>>,
pub proc: Arc<Mutex<Process>>,
pub sig_mask: Sigset,
pub sig_mask: SigSet,
// if syscall or library function was interrupted by a signal
pub int: bool,
// this field is set from trap for convenience
pub ustack_top: usize,
}
/// Pid type
@ -94,7 +96,8 @@ pub struct Process {
// delivered signals, tid specified thread, -1 stands for any thread
pub signals: [Option<isize>; SIGRTMAX + 1],
pub dispositions: [SigAction; SIGRTMAX + 1],
pub dispositions: [SignalAction; SIGRTMAX + 1],
pub sigaltstack: SignalStack,
}
lazy_static! {
@ -193,11 +196,13 @@ impl Thread {
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new(),
signals: [None; SIGRTMAX + 1],
dispositions: [SigAction::default(); SIGRTMAX + 1],
dispositions: [SignalAction::default(); SIGRTMAX + 1],
sigaltstack: SignalStack::default(),
}
.add_to_table(),
sig_mask: Sigset::default(),
sig_mask: SigSet::default(),
int: false,
ustack_top: 0,
})
}
@ -388,11 +393,13 @@ impl Thread {
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new(),
signals: [None; SIGRTMAX + 1],
dispositions: [SigAction::default(); SIGRTMAX + 1],
dispositions: [SignalAction::default(); SIGRTMAX + 1],
sigaltstack: SignalStack::default(),
}
.add_to_table(),
sig_mask: Sigset::default(),
sig_mask: SigSet::default(),
int: false,
ustack_top: 0,
})
}
@ -422,6 +429,7 @@ impl Thread {
child_exit_code: BTreeMap::new(),
signals: [None; SIGRTMAX + 1],
dispositions: proc.dispositions.clone(),
sigaltstack: SignalStack::default(),
}
.add_to_table();
// link to parent
@ -440,6 +448,7 @@ impl Thread {
proc: new_proc,
sig_mask: self.sig_mask,
int: false,
ustack_top: 0,
})
}
@ -461,6 +470,7 @@ impl Thread {
proc: self.proc.clone(),
sig_mask: self.sig_mask,
int: false,
ustack_top: 0,
})
}
}

View File

@ -5,26 +5,52 @@ pub const SIG_DFL: usize = 0;
pub const SIG_IGN: usize = 1;
// yet there's a bug because of mismatching bits: https://sourceware.org/bugzilla/show_bug.cgi?id=25657
pub type Sigset = u64; // just support 64bits size sigset
pub type SigSet = u64; // just support 64bits size sigset
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct SigAction {
pub struct SignalAction {
pub handler: usize, // this field may be an union
pub mask: Sigset,
pub mask: SigSet,
pub flags: u32,
pub _restorer: usize,
}
bitflags! {
pub struct Flags : u32 {
const SA_NOCLDSTOP = 1;
const SA_NOCLDWAIT = 2;
const SA_SIGINFO = 4;
const SA_ONSTACK = 0x08000000;
const SA_RESTART = 0x10000000;
const SA_NODEFER = 0x40000000;
const SA_RESETHAND = 0x80000000;
const SA_RESTORER = 0x04000000;
#[repr(C)]
pub union SigInfoFields {
pad: [u8; Self::PAD_SIZE],
// TODO: fill this union
}
impl SigInfoFields {
const PAD_SIZE: usize = 128 - 2 * core::mem::size_of::<i32>() - core::mem::size_of::<usize>();
}
impl Default for SigInfoFields {
fn default() -> Self {
SigInfoFields {
pad: [0; Self::PAD_SIZE]
}
}
}
#[repr(C)]
pub struct SigInfo {
pub signo: i32,
pub errno: i32,
pub code: i32,
pub field: SigInfoFields,
}
bitflags! {
pub struct SignalActionFlags : u32 {
const NOCLDSTOP = 1;
const NOCLDWAIT = 2;
const SIGINFO = 4;
const ONSTACK = 0x08000000;
const RESTART = 0x10000000;
const NODEFER = 0x40000000;
const RESETHAND = 0x80000000;
const RESTORER = 0x04000000;
}
}

View File

@ -11,6 +11,9 @@ use rcore_thread::std_thread::{current, yield_now};
use alloc::vec::Vec;
use crate::processor;
use crate::syscall::{SysError, SysResult};
use crate::arch::{get_sp, set_sp};
use crate::signal::SigInfo;
use alloc::alloc::handle_alloc_error;
#[derive(Eq, PartialEq, FromPrimitive, Debug, Copy, Clone)]
pub enum Signal {
@ -108,6 +111,8 @@ pub fn send_signal(process: Arc<Mutex<Process>>, tid: isize, signal: Signal) {
}
}
// must be called with = user stack
// FIXME: set user mode?
#[inline(never)]
pub(crate) fn handle_signal() {
let signals = unsafe { current_thread() }.proc.lock().signals.iter().enumerate().filter_map(|(signum, tid)| {
@ -123,28 +128,29 @@ pub(crate) fn handle_signal() {
}
}).collect::<Vec<_>>();
unsafe { current_thread() }.int = false;
unsafe { current_thread().int = false; }
for signum in signals {
use crate::signal::Flags;
use crate::signal::SignalActionFlags;
use Signal::*;
let signal = <Signal as num::FromPrimitive>::from_usize(signum).unwrap();
info!("received signal: {:?}", signal);
let action = {
let mut process = unsafe { current_thread() }.proc.lock();
let mut process = unsafe { current_thread().proc.lock() };
process.signals[signum] = None;
process.dispositions[signum]
};
let flags = Flags::from_bits_truncate(action.flags);
let action_flags = SignalActionFlags::from_bits_truncate(action.flags);
// enter signal handler
match action.handler {
// TODO: complete default actions
x if x == SIG_DFL => {
match signal {
SIGALRM | SIGHUP | SIGINT => {
info!("default action: Term");
// FIXME: exit code ref please?
unsafe { current_thread() }.proc.lock().exit(signum + 128);
unsafe { current_thread().proc.lock().exit(signum + 128); }
yield_now();
}
_ => (),
@ -156,21 +162,82 @@ pub(crate) fn handle_signal() {
unimplemented!();
}
_ => {
unsafe { current_thread() }.int = true;
if flags.contains(Flags::SA_SIGINFO) {
// TODO
unimplemented!();
unsafe { current_thread().int = true; }
let sig_sp = {
if action_flags.contains(SignalActionFlags::ONSTACK) {
let stack = unsafe { current_thread().proc.lock().sigaltstack };
let stack_flags = SignalStackFlags::from_bits_truncate(stack.flags);
if !stack_flags.contains(SignalStackFlags::DISABLE) {
stack.sp + stack.size
} else {
unsafe {
current_thread().ustack_top
}
}
} else {
unsafe {
current_thread().ustack_top
}
}
};
if action_flags.contains(SignalActionFlags::SIGINFO) {
unsafe {
let action: extern "C" fn(i32, *mut SigInfo, usize) = core::mem::transmute(action.handler);
// TODO: complete info
let mut info = SigInfo {
signo: signum as i32,
errno: 0,
code: 0,
field: Default::default(),
};
// TODO: complete ucontext
// let mut sp = get_sp();
// sp = get_sp();
// set_sp(sig_sp);
action(signum as i32, &mut info as *mut SigInfo, 0);
// set_sp(sp);
}
} else {
unsafe {
let handler: extern "C" fn(i32) = core::mem::transmute(action.handler);
let mut sp = get_sp();
sp = get_sp(); // get stack pointer after local variable `sp` is allocated
set_sp(sig_sp);
handler(signum as i32);
set_sp(sp);
}
}
}
}
if flags.contains(Flags::SA_RESTART) {
if action_flags.contains(SignalActionFlags::RESTART) {
// TODO: restart the syscall
warn!("unsupported flag: {:?}", Flags::SA_RESTART);
warn!("unsupported flag: {:?}", SignalActionFlags::RESTART);
}
}
}
bitflags! {
pub struct SignalStackFlags : u32 {
const ONSTACK = 1;
const DISABLE = 2;
const AUTODISARM = 0x80000000;
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct SignalStack {
pub sp: usize,
pub flags: u32,
pub size: usize,
}
impl Default for SignalStack {
fn default() -> Self {
SignalStack {
sp: 0,
flags: SignalStackFlags::DISABLE.bits,
size: 0,
}
}
}

View File

@ -44,7 +44,7 @@ use alloc::collections::BTreeMap;
use rcore_thread::std_thread::yield_now;
#[cfg(feature = "profile")]
use spin::Mutex;
use crate::signal::{SigAction, Sigset};
use crate::signal::{SignalAction, SigSet, SignalStack, Signal};
#[cfg(feature = "profile")]
lazy_static! {
@ -53,14 +53,15 @@ lazy_static! {
/// System call dispatcher
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// let thread = unsafe { current_thread() };
let mut syscall = Syscall { tf };
syscall.syscall(id, args)
let thread = unsafe { current_thread() };
let mut syscall = Syscall { thread, tf };
let ret = syscall.syscall(id, args);
ret
}
/// All context needed for syscall
struct Syscall<'a> {
// thread: &'a mut Thread,
thread: &'a mut Thread,
tf: &'a mut TrapFrame,
}
@ -68,14 +69,12 @@ impl Syscall<'_> {
/// Get current process
/// spinlock is tend to deadlock, use busy waiting
pub fn process(&self) -> MutexGuard<'_, Process, SpinNoIrq> {
unsafe { current_thread() }.proc.busy_lock()
// self.thread.proc.busy_lock()
self.thread.proc.busy_lock()
}
/// Get current virtual memory
pub fn vm(&self) -> MutexGuard<'_, MemorySet, SpinNoIrq> {
// self.thread.vm.lock()
unsafe { current_thread() }.vm.lock()
self.thread.vm.lock()
}
/// System call dispatcher
@ -213,17 +212,17 @@ impl Syscall<'_> {
// signal
SYS_RT_SIGACTION => self.sys_rt_sigaction(
args[0],
args[1] as *const SigAction,
args[2] as *mut SigAction,
args[1] as *const SignalAction,
args[2] as *mut SignalAction,
args[3],
),
SYS_RT_SIGPROCMASK => self.sys_rt_sigprocmask(
args[0],
args[1] as *const Sigset,
args[2] as *mut Sigset,
args[1] as *const SigSet,
args[2] as *mut SigSet,
args[3],
),
SYS_SIGALTSTACK => self.unimplemented("sigaltstack", Ok(0)),
SYS_SIGALTSTACK => self.sys_sigaltstack(args[0] as *const SignalStack, args[1] as *mut SignalStack),
SYS_KILL => self.sys_kill(args[0] as isize, args[1]),
// schedule

View File

@ -267,13 +267,13 @@ impl Syscall<'_> {
}
info!("setpgid: set pgid of process {} to {}", pid, pgid);
let process_table = PROCESSES.read();
// let process_table: BTreeMap<usize, Weak<Mutex<Process>>> = BTreeMap::new();
let proc = process_table.get(&pid);
if (proc.is_some()) {
// TODO: check process pid is the child of calling process
let lock = proc.unwrap().upgrade().unwrap();
let mut proc = lock.lock();
proc.pgid = pgid as i32;
if let Some(proc) = proc.unwrap().upgrade() {
let mut proc = proc.lock();
proc.pgid = pgid as i32;
}
Ok(0)
} else {
Err(ESRCH)

View File

@ -1,7 +1,7 @@
use crate::process::{PROCESSES, thread_manager, process_of, current_thread};
use crate::process::{process, process_group};
use crate::signal::*;
use crate::syscall::SysError::{EINVAL, ESRCH};
use crate::syscall::SysError::{EINVAL, ESRCH, ENOMEM, EPERM};
use crate::syscall::{SysResult, Syscall};
use crate::thread;
use num::FromPrimitive;
@ -10,8 +10,8 @@ impl Syscall<'_> {
pub fn sys_rt_sigaction(
&self,
signum: usize,
act: *const SigAction,
oldact: *mut SigAction,
act: *const SignalAction,
oldact: *mut SignalAction,
sigsetsize: usize,
) -> SysResult {
if let Some(signal) = <Signal as FromPrimitive>::from_usize(signum) {
@ -47,8 +47,8 @@ impl Syscall<'_> {
pub fn sys_rt_sigprocmask(
&mut self,
how: usize,
set: *const Sigset,
oldset: *mut Sigset,
set: *const SigSet,
oldset: *mut SigSet,
sigsetsize: usize,
) -> SysResult {
info!(
@ -144,4 +144,31 @@ impl Syscall<'_> {
Err(EINVAL)
}
}
pub fn sys_sigaltstack(&self, ss: *const SignalStack, old_ss: *mut SignalStack) -> SysResult {
const MINSIGSTKSZ: usize = 2048;
if !old_ss.is_null() {
let old_ss = unsafe { self.vm().check_write_ptr(old_ss)? };
*old_ss = self.process().sigaltstack;
}
if !ss.is_null() {
let ss = unsafe { self.vm().check_read_ptr(ss)? };
if ss.flags & 2 != 0 && ss.size < MINSIGSTKSZ {
return Err(ENOMEM);
}
// only allow SS_AUTODISARM or SS_DISABLE
if ss.flags ^ (ss.flags & 0x8000002) != 0 {
return Err(EINVAL);
}
let old_ss = &mut self.process().sigaltstack;
let flags = SignalStackFlags::from_bits_truncate(old_ss.flags);
if flags.contains(SignalStackFlags::ONSTACK) {
return Err(EPERM);
}
*old_ss = *ss;
}
Ok(0)
}
}