From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:45553) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RgIMa-0000Sf-1l for qemu-devel@nongnu.org; Thu, 29 Dec 2011 10:57:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RgIMX-0003eR-0R for qemu-devel@nongnu.org; Thu, 29 Dec 2011 10:57:51 -0500 Received: from cantor2.suse.de ([195.135.220.15]:59567 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RgIMW-0003da-Ow for qemu-devel@nongnu.org; Thu, 29 Dec 2011 10:57:48 -0500 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 29 Dec 2011 16:55:49 +0100 Message-Id: <1325174149-8077-12-git-send-email-afaerber@suse.de> In-Reply-To: <1325174149-8077-1-git-send-email-afaerber@suse.de> References: <1325174149-8077-1-git-send-email-afaerber@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [RFC 11/11] linux-user: Implement signal handling for mipsn32 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Riku Voipio , Khansa Butt , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Richard Henderson Mostly adapted from o32. Linux no longer seems to have sf_code/rs_code for any of the ABIs. It's u32 {sf,rt}_pad[2] /* Was: signal trampoline */ now... Signed-off-by: Andreas F=C3=A4rber Cc: Richard Henderson Cc: Khansa Butt --- linux-user/signal.c | 104 +++++++++++++++++++++++++++++++++++++++++++++= ++++-- 1 files changed, 100 insertions(+), 4 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index b33f8cb..82ce4ac 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2673,7 +2673,20 @@ long do_rt_sigreturn(CPUState *env) =20 #elif defined(TARGET_ABI_MIPSN32) =20 -# warning signal handling not implemented +struct target_ucontext { + uint32_t tuc_flags; + int32_t tuc_link; + target_stack_t tuc_stack; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + uint32_t rs_ass[4]; /* argument save space for o32 */ + uint32_t rs_pad[2]; /* Was: signal trampoline */ + struct target_siginfo rs_info; + struct target_ucontext rs_uc; +}; =20 static void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUState *env) @@ -2685,7 +2698,61 @@ static void setup_rt_frame(int sig, struct target_= sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUState *env) { - fprintf(stderr, "setup_rt_frame: not implemented\n"); + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + int i; + + frame_addr =3D get_sigframe(ka, env, sizeof(*frame)); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + goto give_sigsegv; + + //install_sigtramp(frame->rs_pad, TARGET_NR_rt_sigreturn); + + /* Create siginfo. */ + copy_siginfo_to_user(&frame->rs_info, info); + + /* Create the ucontext. */ + __put_user(0, &frame->rs_uc.tuc_flags); + __put_user(0, &frame->rs_uc.tuc_link); + __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss= _sp); + __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.= ss_size); + __put_user(sas_ss_flags(get_sp_from_cpustate(env)), + &frame->rs_uc.tuc_stack.ss_flags); + + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + for(i =3D 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); + } + + /* + * Arguments to signal handler: + * + * a0 =3D signal number + * a1 =3D pointer to struct siginfo + * a2 =3D pointer to struct ucontext + * + * $25 and PC point to the signal handler, $29 points to the + * struct sigframe. + */ + env->active_tc.gpr[ 4] =3D sig; + env->active_tc.gpr[ 5] =3D frame_addr + + offsetof(struct target_rt_sigframe, rs_in= fo); + env->active_tc.gpr[ 6] =3D frame_addr + + offsetof(struct target_rt_sigframe, rs_uc= ); + env->active_tc.gpr[29] =3D frame_addr; + //env->active_tc.gpr[31] =3D frame_addr + // + offsetof(struct target_rt_sigframe, rs_= pad); + /* The original kernel code sets CP0_EPC to the handler + * since it returns to userland using eret + * we cannot do this here, and we must set PC directly */ + env->active_tc.PC =3D env->active_tc.gpr[25] =3D ka->_sa_handler; + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sig(TARGET_SIGSEGV/*, current*/); } =20 long do_sigreturn(CPUState *env) @@ -2696,8 +2763,37 @@ long do_sigreturn(CPUState *env) =20 long do_rt_sigreturn(CPUState *env) { - fprintf(stderr, "do_rt_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + sigset_t blocked; + +#if defined(DEBUG_SIGNAL) + fprintf(stderr, "do_rt_sigreturn\n"); +#endif + frame_addr =3D env->active_tc.gpr[29]; + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); + sigprocmask(SIG_SETMASK, &blocked, NULL); + + if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext)) + goto badframe; + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), + 0, get_sp_from_cpustate(env)) =3D=3D -EFAULT) + goto badframe; + + env->active_tc.PC =3D env->CP0_EPC; + /* I am not sure this is right, but it seems to work + * maybe a problem with nested signals ? */ + env->CP0_EPC =3D 0; + return -TARGET_QEMU_ESIGRETURN; + +badframe: + force_sig(TARGET_SIGSEGV/*, current*/); + return 0; } =20 #elif defined(TARGET_ABI_MIPSO32) --=20 1.7.7