From patchwork Thu Aug 13 20:06:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 31353 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id 432B8B7099 for ; Fri, 14 Aug 2009 06:07:31 +1000 (EST) Received: from localhost ([127.0.0.1]:41399 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mbga7-00040f-UK for incoming@patchwork.ozlabs.org; Thu, 13 Aug 2009 16:07:27 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MbgZG-0003uP-E5 for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:34 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MbgZD-0003px-3Y for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:31 -0400 Received: from [199.232.76.173] (port=50651 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MbgZC-0003pI-Jp for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:30 -0400 Received: from [84.20.150.76] (port=34673 helo=naru.obs2.net) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MbgZB-0000pL-Dy for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:29 -0400 Received: from kos.to (localhost.localdomain [127.0.0.1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by narury.org (Postfix) with ESMTP id C58683274064; Thu, 13 Aug 2009 23:06:25 +0300 (EEST) Received: by kos.to (Postfix, from userid 573) id 35254EE8319; Thu, 13 Aug 2009 23:06:25 +0300 (EEST) From: riku.voipio@iki.fi To: qemu-devel@nongnu.org Date: Thu, 13 Aug 2009 23:06:15 +0300 Message-Id: X-Mailer: git-send-email 1.6.2.1 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.4-2.6 Cc: Riku Voipio , Laurent Vivier Subject: [Qemu-devel] [PATCH 02/11] m68k,linux-user: add setup_frame X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Laurent Vivier This patch adds signals management for linux-user. It implements setup_frame() which allows to call the user signal handler. setup_rt_frame() is always unimplemented. Signed-off-by: Laurent Vivier Signed-off-by: Riku Voipio --- linux-user/signal.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 183 insertions(+), 0 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index b2c0623..0756380 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4028,6 +4028,189 @@ sigsegv: return 0; } +#elif defined(TARGET_M68K) + +struct target_sigcontext { + abi_ulong sc_mask; + abi_ulong sc_usp; + abi_ulong sc_d0; + abi_ulong sc_d1; + abi_ulong sc_a0; + abi_ulong sc_a1; + unsigned short sc_sr; + abi_ulong sc_pc; +}; + +struct target_sigframe +{ + abi_ulong pretcode; + int sig; + int code; + abi_ulong psc; + char retcode[8]; + abi_ulong extramask[TARGET_NSIG_WORDS-1]; + struct target_sigcontext sc; +}; + +static int +setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask) +{ + int err = 0; + + err |= __put_user(mask, &sc->sc_mask); + err |= __put_user(env->aregs[7], &sc->sc_usp); + err |= __put_user(env->dregs[0], &sc->sc_d0); + err |= __put_user(env->dregs[1], &sc->sc_d1); + err |= __put_user(env->aregs[0], &sc->sc_a0); + err |= __put_user(env->aregs[1], &sc->sc_a1); + err |= __put_user(env->sr, &sc->sc_sr); + err |= __put_user(env->pc, &sc->sc_pc); + + return err; +} + +static int +restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0) +{ + int err = 0; + int temp; + + err |= __get_user(env->aregs[7], &sc->sc_usp); + err |= __get_user(env->dregs[1], &sc->sc_d1); + err |= __get_user(env->aregs[0], &sc->sc_a0); + err |= __get_user(env->aregs[1], &sc->sc_a1); + err |= __get_user(env->pc, &sc->sc_pc); + err |= __get_user(temp, &sc->sc_sr); + env->sr = (env->sr & 0xff00) | (temp & 0xff); + + *pd0 = tswapl(sc->sc_d0); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size) +{ + unsigned long sp; + + sp = regs->aregs[7]; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + + return ((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct target_sigaction *ka, + target_sigset_t *set, CPUState *env) +{ + struct target_sigframe *frame; + abi_ulong frame_addr; + abi_ulong retcode_addr; + abi_ulong sc_addr; + int err = 0; + int i; + + frame_addr = get_sigframe(ka, env, sizeof *frame); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + goto give_sigsegv; + + err |= __put_user(sig, &frame->sig); + + sc_addr = frame_addr + offsetof(struct target_sigframe, sc); + err |= __put_user(sc_addr, &frame->psc); + + err |= setup_sigcontext(&frame->sc, env, set->sig[0]); + if (err) + goto give_sigsegv; + + for(i = 1; i < TARGET_NSIG_WORDS; i++) { + if (__put_user(set->sig[i], &frame->extramask[i - 1])) + goto give_sigsegv; + } + + /* Set up to return from userspace. */ + + retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); + err |= __put_user(retcode_addr, &frame->pretcode); + + /* moveq #,d0; trap #0 */ + + err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), + (long *)(frame->retcode)); + + if (err) + goto give_sigsegv; + + /* Set up to return from userspace */ + + env->aregs[7] = frame_addr; + env->pc = ka->_sa_handler; + + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sig(SIGSEGV); +} + +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"); +} + +long do_sigreturn(CPUState *env) +{ + struct target_sigframe *frame; + abi_ulong frame_addr = env->aregs[7] - 4; + target_sigset_t target_set; + sigset_t set; + int d0, i; + + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + /* set blocked signals */ + + if (__get_user(target_set.sig[0], &frame->sc.sc_mask)) + goto badframe; + + for(i = 1; i < TARGET_NSIG_WORDS; i++) { + if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) + goto badframe; + } + + target_to_host_sigset_internal(&set, &target_set); + sigprocmask(SIG_SETMASK, &set, NULL); + + /* restore registers */ + + if (restore_sigcontext(env, &frame->sc, &d0)) + goto badframe; + + unlock_user_struct(frame, frame_addr, 0); + return d0; + +badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return 0; +} + +long do_rt_sigreturn(CPUState *env) +{ + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); + return -TARGET_ENOSYS; +} + #else static void setup_frame(int sig, struct target_sigaction *ka,