Skip to content
Snippets Groups Projects
Verified Commit a2ab86d2 authored by Jacob Lorentzon's avatar Jacob Lorentzon
Browse files

Implement signal selection in asm, for SA_ONSTACK.

parent d45adade
No related branches found
No related tags found
1 merge request!480Refactor redox runtime and impl signals in userspace
......@@ -16,6 +16,7 @@ pub struct SigArea {
altstack_top: usize,
altstack_bottom: usize,
tmp: usize,
pub onstack: u64,
pub disable_signals_depth: u64,
}
......@@ -128,18 +129,41 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: ["
"] <= []);
asmfunction!(__relibc_internal_sigentry: ["
// Get offset to TCB
mov rax, gs:[0]
// First, select signal, always pick first available bit
// Read first signal word
mov rdx, fs:[{tcb_sc_off} + {sc_word}]
mov rcx, rdx
shr rcx, 32
and edx, ecx
bsf edx, edx
jnz 2f
// Read second signal word
mov rdx, fs:[{tcb_sc_off} + {sc_word} + 8]
mov rcx, rdx
shr rcx, 32
and edx, ecx
bsf edx, edx
jnz 4f
add edx, 32
2:
// By now we have selected a signal, stored in edx (6-bit). We now need to choose whether or
// not to switch to the alternate signal stack. If SA_ONSTACK is clear for this signal, then
// skip the sigaltstack logic.
bt fs:[{tcb_sa_off} + {sa_onstack}], edx
jc 3f
// If current RSP is above altstack region, switch to altstack
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_top}]
mov rdx, fs:[{tcb_sa_off} + {sa_altstack_top}]
cmp rdx, rsp
cmova rsp, rdx
// If current RSP is below altstack region, also switch to altstack
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_bottom}]
cmp rdx, rax
mov rdx, fs:[{tcb_sa_off} + {sa_altstack_bottom}]
cmp rdx, rsp
cmovbe rsp, rdx
3:
// Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent
// to setting 'top' to usize::MAX and 'bottom' to 0.
......@@ -147,16 +171,16 @@ asmfunction!(__relibc_internal_sigentry: ["
// Now that we have a stack, we can finally start initializing the signal stack!
push 0 // SS
push [rax + {tcb_sc_off} + {sc_saved_rsp}]
push [rax + {tcb_sc_off} + {sc_saved_rflags}]
push fs:[{tcb_sc_off} + {sc_saved_rsp}]
push fs:[{tcb_sc_off} + {sc_saved_rflags}]
push 0 // CS
push [rax + {tcb_sc_off} + {sc_saved_rip}]
push fs:[{tcb_sc_off} + {sc_saved_rip}]
push rdi
push rsi
push [rax + {tcb_sc_off} + {sc_saved_rdx}]
push fs:[{tcb_sc_off} + {sc_saved_rdx}]
push rcx
push [rax + {tcb_sc_off} + {sc_saved_rax}]
push fs:[{tcb_sc_off} + {sc_saved_rax}]
push r8
push r9
push r10
......@@ -168,12 +192,14 @@ asmfunction!(__relibc_internal_sigentry: ["
push r14
push r15
sub rsp, 4096 + 32
push rdx // selected signal
sub rsp, 4096 + 24
cld
mov rdi, rsp
xor eax, eax
mov ecx, 4096 + 32
mov ecx, 4096 + 24
rep stosb
// TODO: self-modifying?
......@@ -191,7 +217,7 @@ asmfunction!(__relibc_internal_sigentry: ["
mov edx, eax
xrstor [rsp]
add rsp, 4096 + 32
add rsp, 4096 + 24
2:
pop r15
pop r14
......@@ -209,11 +235,11 @@ asmfunction!(__relibc_internal_sigentry: ["
pop rsi
pop rdi
pop qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
pop qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
add rsp, 8
popfq
pop rsp
jmp qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
jmp qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
3:
fxsave64 [rsp]
......@@ -222,16 +248,20 @@ asmfunction!(__relibc_internal_sigentry: ["
fxrstor64 [rsp]
jmp 2b
4:
// Spurious signal
"] <= [
inner = sym inner_c,
sa_tmp = const offset_of!(SigArea, tmp),
sa_altstack_top = const offset_of!(SigArea, altstack_top),
sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
sa_onstack = const offset_of!(SigArea, onstack),
sc_saved_rax = const offset_of!(Sigcontrol, saved_scratch_a),
sc_saved_rdx = const offset_of!(Sigcontrol, saved_scratch_b),
sc_saved_rflags = const offset_of!(Sigcontrol, saved_flags),
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
sc_saved_rsp = const offset_of!(Sigcontrol, saved_sp),
sc_word = const offset_of!(Sigcontrol, word),
tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch),
tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
supports_xsave = sym SUPPORTS_XSAVE,
......
......@@ -2,7 +2,7 @@ use core::cell::Cell;
use core::ffi::c_int;
use core::sync::atomic::{AtomicU64, Ordering};
use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
use crate::{arch::*, Tcb};
use crate::sync::Mutex;
......@@ -104,16 +104,24 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
Ok(())
}
#[derive(Clone, Copy)]
pub enum Sigaction {
#[derive(Clone, Copy, Default)]
pub enum SigactionKind {
#[default]
Default,
Ignore,
Handled {
handler: SignalHandler,
mask: u64,
flags: SigactionFlags,
},
}
#[derive(Clone, Copy, Default)]
pub struct Sigaction {
pub kind: SigactionKind,
pub mask: u64,
pub flags: SigactionFlags,
}
pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
return Err(Error::new(EINVAL));
......@@ -125,39 +133,59 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
let old_ignmask = IGNMASK.load(Ordering::Relaxed);
if let Some(old) = old {
// TODO
}
let Some(new) = new else {
return Ok(());
};
match (usize::from(signal), new) {
(_, Sigaction::Ignore) | (SIGCHLD | SIGURG | SIGWINCH, Sigaction::Default) => {
let sig_group = usize::from(signal) / 32;
let sig_bit32 = 1 << ((signal - 1) % 32);
match (usize::from(signal), new.kind) {
(_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => {
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
// mark the signal as masked
ctl.word[usize::from(signal) / 32].fetch_or(1 << ((signal - 1) % 32), Ordering::Relaxed);
ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
// POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
// sigaction.
// TODO: handle tmp_disable_signals
}
// TODO: Handle pending signals before these flags are set.
(SIGTSTP, Sigaction::Default) => {
(SIGTSTP, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGTTIN, Sigaction::Default) => {
(SIGTTIN, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGTTOU, Sigaction::Default) => {
(SIGTTOU, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGCHLD, SigactionKind::Default) => {
if new.flags.contains(SigactionFlags::NOCLDSTOP) {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
} else {
PROC_CONTROL_STRUCT.word[0].fetch_and(!SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
}
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
// mark the signal as masked
ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
}
(_, SigactionKind::Default) => {
IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed);
(_, Sigaction::Default) => (),
(_, Sigaction::Handled { .. }) => (),
// TODO: update mask
//ctl.word[usize::from(signal)].fetch_or();
},
(_, SigactionKind::Handled { .. }) => (),
}
todo!()
Ok(())
}
fn current_sigctl() -> &'static Sigcontrol {
......@@ -192,7 +220,7 @@ impl Drop for TmpDisableSignalsGuard {
bitflags::bitflags! {
// Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Default)]
pub struct SigactionFlags: u32 {
const NOCLDSTOP = 1;
const NOCLDWAIT = 2;
......@@ -226,7 +254,7 @@ struct TheDefault {
ignmask: u64,
}
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction::Default; 64]);
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction { flags: SigactionFlags::empty(), mask: 0, kind: SigactionKind::Default }; 64]);
static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
......
use core::mem;
use redox_rt::signal::{Sigaction, SigactionFlags, SignalHandler};
use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, SignalHandler};
use syscall::{self, Result};
use super::{
......@@ -111,49 +111,53 @@ impl PalSignal for Sys {
let new_action = c_act.map(|c_act| {
let handler = c_act.sa_handler.map_or(0, |f| f as usize);
if handler == SIG_DFL {
Sigaction::Default
let kind = if handler == SIG_DFL {
SigactionKind::Default
} else if handler == SIG_IGN {
Sigaction::Ignore
SigactionKind::Ignore
} else {
Sigaction::Handled {
SigactionKind::Handled {
handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 {
SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } }
} else {
SignalHandler { handler: c_act.sa_handler }
},
mask: c_act.sa_mask,
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
}
};
Sigaction {
kind,
mask: c_act.sa_mask,
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
}
});
let mut old_action = c_oact.as_ref().map(|_| Sigaction::Default);
let mut old_action = c_oact.as_ref().map(|_| Sigaction::default());
redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
*c_oact = match old_action {
Sigaction::Ignore => sigaction {
*c_oact = match old_action.kind {
SigactionKind::Ignore => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
Sigaction::Default => sigaction {
SigactionKind::Default => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
Sigaction::Handled { handler, mask, flags } => sigaction {
sa_handler: if flags.contains(SigactionFlags::SIGINFO) {
SigactionKind::Handled { handler } => sigaction {
sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
unsafe { core::mem::transmute(handler.sigaction) }
} else {
unsafe { handler.handler }
},
sa_restorer: None,
sa_flags: flags.bits().into(),
sa_mask: mask,
sa_flags: old_action.flags.bits().into(),
sa_mask: old_action.mask,
},
};
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment