diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 07d8ae05b7..d8a6ced45a 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -1,9 +1,10 @@ use core::mem::offset_of; +use core::sync::atomic::Ordering; use syscall::*; use crate::proc::{fork_inner, FdGuard}; -use crate::signal::{inner_fastcall, RtSigarea, SigStack}; +use crate::signal::{inner_fastcall, PROC_CONTROL_STRUCT, RtSigarea, SigStack}; // Setup a stack starting from the very end of the address space, and then growing downwards. pub(crate) const STACK_TOP: usize = 1 << 31; @@ -18,7 +19,6 @@ pub struct SigArea { pub tmp_esp: usize, pub tmp_eax: usize, pub tmp_edx: usize, - pub onstack: u64, pub disable_signals_depth: u64, } #[derive(Debug, Default)] @@ -144,7 +144,10 @@ asmfunction!(__relibc_internal_sigentry: [" add eax, 32 2: and esp, -{STACK_ALIGN} - bt gs:[{tcb_sa_off} + {sa_onstack}], eax + + mov edx, eax + add edx, edx + bt dword ptr [{pctl} + {pctl_off_actions} + edx * 8 + 4], 28 jnc 4f mov edx, gs:[{tcb_sa_off} + {sa_altstack_top}] @@ -209,15 +212,14 @@ __relibc_internal_sigentry_crit_second: sa_tmp_edx = const offset_of!(SigArea, tmp_edx), 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_eflags = const offset_of!(Sigcontrol, saved_archdep_reg), sc_saved_eip = const offset_of!(Sigcontrol, saved_ip), 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), - SIGW0_PENDING_MASK = const !( - SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | SIGW0_NOCLDSTOP_BIT | SIGW0_UNUSED1 | SIGW0_UNUSED2 - ), + pctl_off_actions = const offset_of!(SigProcControl, actions), + pctl = sym PROC_CONTROL_STRUCT, + SIGW0_PENDING_MASK = const !0, SIGW1_PENDING_MASK = const !0, STACK_ALIGN = const 16, ]); @@ -253,3 +255,20 @@ pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) { stack.regs.eip = area.tmp_eip; } } +pub unsafe fn manually_enter_trampoline() { + let c = &crate::Tcb::current().unwrap().os_specific.control; + c.control_flags.store(c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release); + c.saved_archdep_reg.set(0); // TODO: Just reset DF on x86? + + core::arch::asm!(" + call 2f + jmp 3f + 2: + pop dword ptr gs:[{tcb_sc_off} + {sc_saved_eip}] + jmp __relibc_internal_sigentry + 3: + ", + tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control), + sc_saved_eip = const offset_of!(Sigcontrol, saved_ip), + ); +} diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 67a3600c65..4a921169c9 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -1,5 +1,5 @@ use core::mem::offset_of; -use core::sync::atomic::AtomicU8; +use core::sync::atomic::{AtomicU8, Ordering}; use syscall::data::{Sigcontrol, SigProcControl}; use syscall::error::*; @@ -360,10 +360,9 @@ pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) { static SUPPORTS_XSAVE: AtomicU8 = AtomicU8::new(1); // FIXME pub unsafe fn manually_enter_trampoline() { - let _g = tmp_disable_signals(); - - let a = &Tcb::current().unwrap().os_specific.control; - a.saved_archdep_reg.set(0); // TODO: Just reset DF on x86? + let c = &Tcb::current().unwrap().os_specific.control; + c.control_flags.store(c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release); + c.saved_archdep_reg.set(0); // TODO: Just reset DF on x86? core::arch::asm!(" lea rax, [rip + 2f] diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 2cb8da5329..5fff5ae39a 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -111,10 +111,13 @@ unsafe fn inner(stack: &mut SigStack) { // Call handler, either sa_handler or sa_siginfo depending on flag. if sigaction.flags.contains(SigactionFlags::SIGINFO) && let Some(sigaction) = handler.sigaction { + //let _ = syscall::write(1, alloc::format!("SIGACTION {:p}\n", sigaction).as_bytes()); sigaction(stack.sig_num as c_int, core::ptr::null_mut(), core::ptr::null_mut()); } else if let Some(handler) = handler.handler { + //let _ = syscall::write(1, alloc::format!("HANDLER {:p}\n", handler).as_bytes()); handler(stack.sig_num as c_int); } + //let _ = syscall::write(1, alloc::format!("RETURNED HANDLER\n").as_bytes()); // Disable signals while we modify the sigmask again control_flags.store(control_flags.load(Ordering::Relaxed) | SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release); @@ -129,6 +132,8 @@ unsafe fn inner(stack: &mut SigStack) { // TODO: If resetting the sigmask caused signals to be unblocked, then should they be delivered // here? And would it be possible to tail-call-optimize that? + //let _ = syscall::write(1, alloc::format!("will return to {:x?}\n", stack.regs.eip).as_bytes()); + // And re-enable them again control_flags.store(control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release); core::sync::atomic::compiler_fence(Ordering::Acquire); @@ -388,7 +393,10 @@ pub fn setup_sighandler(area: &RtSigarea) { // equivalent to not using any altstack at all (the default). arch.altstack_top = usize::MAX; arch.altstack_bottom = 0; - arch.pctl = core::ptr::addr_of!(PROC_CONTROL_STRUCT) as usize; + #[cfg(not(target_arch = "x86"))] + { + arch.pctl = core::ptr::addr_of!(PROC_CONTROL_STRUCT) as usize; + } } #[cfg(target_arch = "x86_64")]