From e3e5cf6d34284a84489ea4f81301af1c81cd163f Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 30 Jan 2013 03:13:24 +0100 Subject: [PATCH] arm: make signal handlers work A few kernel and calling convention adjustments to make sigsend and sigreturn work for arm. . provide a arch_proc_setcontext for earm in kernel . set LR in context of signal handler to provide a proper return address (to __sigreturn) . change __sigreturn to retrieve the sigcontext pointer from the sigframe struct and pass it to _sigreturn() in r0 Change-Id: Icd135a70595382c79d11d8dd9876f6a6f1df41f8 --- kernel/arch/earm/arch_system.c | 13 +++++++++++++ kernel/system/do_sigsend.c | 7 +++++++ lib/libc/arch/arm/sys-minix/__sigreturn.S | 5 +++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kernel/arch/earm/arch_system.c b/kernel/arch/earm/arch_system.c index 4db5fdbe3..7d8357361 100644 --- a/kernel/arch/earm/arch_system.c +++ b/kernel/arch/earm/arch_system.c @@ -52,6 +52,19 @@ void arch_proc_reset(struct proc *pr) void arch_proc_setcontext(struct proc *p, struct stackframe_s *state, int isuser, int trapstyle) { + assert(sizeof(p->p_reg) == sizeof(*state)); + memcpy(&p->p_reg, state, sizeof(*state)); + + /* further code is instructed to not touch the context + * any more + */ + p->p_misc_flags |= MF_CONTEXT_SET; + + if(!(p->p_rts_flags)) { + printf("WARNINIG: setting full context of runnable process\n"); + print_proc(p); + util_stacktrace(); + } } void arch_set_secondary_ipc_return(struct proc *p, u32_t val) diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index bbf21149d..ddb8db93c 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -81,6 +81,13 @@ int do_sigsend(struct proc * caller, message * m_ptr) fr.sf_signo = smsg.sm_signo; fr.sf_retadr = (void (*)()) smsg.sm_sigreturn; +#if defined(__arm__) + /* use the ARM link register to set the return address from the signal + * handler + */ + rp->p_reg.lr = (reg_t) fr.sf_retadr; +#endif + /* Copy the sigframe structure to the user's stack. */ if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &fr, m_ptr->SIG_ENDPT, (vir_bytes) frp, diff --git a/lib/libc/arch/arm/sys-minix/__sigreturn.S b/lib/libc/arch/arm/sys-minix/__sigreturn.S index 9d3f26170..9eee41635 100644 --- a/lib/libc/arch/arm/sys-minix/__sigreturn.S +++ b/lib/libc/arch/arm/sys-minix/__sigreturn.S @@ -5,5 +5,6 @@ IMPORT(_sigreturn) ENTRY(__sigreturn) - add sp, sp, #16 - b _C_LABEL(_sigreturn) + add sp, sp, #24 /* make sp point to sigframe.sf_scpcopy */ + pop {r0} /* load it into r0 as parameter */ + b _C_LABEL(_sigreturn) /* _sigreturn(struct sigcontext *sf_scpcopy) */ -- 2.11.4.GIT