From patchwork Thu Aug 13 20:06:16 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 31356 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 A7C1CB7087 for ; Fri, 14 Aug 2009 06:13:55 +1000 (EST) Received: from localhost ([127.0.0.1]:46295 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MbggJ-0000N2-Uf for incoming@patchwork.ozlabs.org; Thu, 13 Aug 2009 16:13:51 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MbgZF-0003vD-Kq for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:33 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MbgZD-0003qD-1o for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:31 -0400 Received: from [199.232.76.173] (port=50647 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MbgZC-0003oa-JP for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:30 -0400 Received: from [84.20.150.76] (port=34679 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-0000pT-Dm for qemu-devel@nongnu.org; Thu, 13 Aug 2009 16:06:30 -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 2A1F8327406A; Thu, 13 Aug 2009 23:06:26 +0300 (EEST) Received: by kos.to (Postfix, from userid 573) id 97050EE831A; 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:16 +0300 Message-Id: <8eac7f34102981addc3ad1a192cfa6624278d223.1250193231.git.riku.voipio@iki.fi> 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 03/11] m68k, linux-user: add setup_rt_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 implements setup_rt_frame(). Signed-off-by: Laurent Vivier Signed-off-by: Riku Voipio --- linux-user/signal.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 202 insertions(+), 3 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 0756380..2df17aa 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4051,6 +4051,43 @@ struct target_sigframe abi_ulong extramask[TARGET_NSIG_WORDS-1]; struct target_sigcontext sc; }; + +typedef int target_greg_t; +#define TARGET_NGREG 18 +typedef target_greg_t target_gregset_t[TARGET_NGREG]; + +typedef struct target_fpregset { + int f_fpcntl[3]; + int f_fpregs[8*3]; +} target_fpregset_t; + +struct target_mcontext { + int version; + target_gregset_t gregs; + target_fpregset_t fpregs; +}; + +#define TARGET_MCONTEXT_VERSION 2 + +struct target_ucontext { + abi_ulong uc_flags; + abi_ulong uc_link; + target_stack_t uc_stack; + struct target_mcontext uc_mcontext; + abi_long uc_filler[80]; + target_sigset_t uc_sigmask; +}; + +struct target_rt_sigframe +{ + abi_ulong pretcode; + int sig; + abi_ulong pinfo; + abi_ulong puc; + char retcode[8]; + struct target_siginfo info; + struct target_ucontext uc; +}; static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask) @@ -4160,11 +4197,146 @@ give_sigsegv: force_sig(SIGSEGV); } +static inline int target_rt_setup_ucontext(struct target_ucontext *uc, + CPUState *env) +{ + target_greg_t *gregs = uc->uc_mcontext.gregs; + int err; + + err = __put_user(TARGET_MCONTEXT_VERSION, &uc->uc_mcontext.version); + err |= __put_user(env->dregs[0], &gregs[0]); + err |= __put_user(env->dregs[1], &gregs[1]); + err |= __put_user(env->dregs[2], &gregs[2]); + err |= __put_user(env->dregs[3], &gregs[3]); + err |= __put_user(env->dregs[4], &gregs[4]); + err |= __put_user(env->dregs[5], &gregs[5]); + err |= __put_user(env->dregs[6], &gregs[6]); + err |= __put_user(env->dregs[7], &gregs[7]); + err |= __put_user(env->aregs[0], &gregs[8]); + err |= __put_user(env->aregs[1], &gregs[9]); + err |= __put_user(env->aregs[2], &gregs[10]); + err |= __put_user(env->aregs[3], &gregs[11]); + err |= __put_user(env->aregs[4], &gregs[12]); + err |= __put_user(env->aregs[5], &gregs[13]); + err |= __put_user(env->aregs[6], &gregs[14]); + err |= __put_user(env->aregs[7], &gregs[15]); + err |= __put_user(env->pc, &gregs[16]); + err |= __put_user(env->sr, &gregs[17]); + + return err; +} + +static inline int target_rt_restore_ucontext(CPUState *env, + struct target_ucontext *uc, + int *pd0) +{ + int temp; + int err; + target_greg_t *gregs = uc->uc_mcontext.gregs; + + err = __get_user(temp, &uc->uc_mcontext.version); + if (temp != TARGET_MCONTEXT_VERSION) + goto badframe; + + /* restore passed registers */ + err |= __get_user(env->dregs[0], &gregs[0]); + err |= __get_user(env->dregs[1], &gregs[1]); + err |= __get_user(env->dregs[2], &gregs[2]); + err |= __get_user(env->dregs[3], &gregs[3]); + err |= __get_user(env->dregs[4], &gregs[4]); + err |= __get_user(env->dregs[5], &gregs[5]); + err |= __get_user(env->dregs[6], &gregs[6]); + err |= __get_user(env->dregs[7], &gregs[7]); + err |= __get_user(env->aregs[0], &gregs[8]); + err |= __get_user(env->aregs[1], &gregs[9]); + err |= __get_user(env->aregs[2], &gregs[10]); + err |= __get_user(env->aregs[3], &gregs[11]); + err |= __get_user(env->aregs[4], &gregs[12]); + err |= __get_user(env->aregs[5], &gregs[13]); + err |= __get_user(env->aregs[6], &gregs[14]); + err |= __get_user(env->aregs[7], &gregs[15]); + err |= __get_user(env->pc, &gregs[16]); + err |= __get_user(temp, &gregs[17]); + env->sr = (env->sr & 0xff00) | (temp & 0xff); + + *pd0 = env->dregs[0]; + return err; + +badframe: + return 1; +} + 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; + abi_ulong retcode_addr; + abi_ulong info_addr; + abi_ulong uc_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); + + info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); + err |= __put_user(info_addr, &frame->pinfo); + + uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); + err |= __put_user(uc_addr, &frame->puc); + + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext */ + + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(target_sigaltstack_used.ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(env->aregs[7]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(target_sigaltstack_used.ss_size, + &frame->uc.uc_stack.ss_size); + err |= target_rt_setup_ucontext(&frame->uc, env); + + if (err) + goto give_sigsegv; + + for(i = 0; i < TARGET_NSIG_WORDS; i++) { + if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i])) + 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; notb d0; trap #0 */ + + err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16), + (long *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); + + 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); } long do_sigreturn(CPUState *env) @@ -4207,8 +4379,35 @@ badframe: 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 = env->aregs[7] - 4; + target_sigset_t target_set; + sigset_t set; + int d0; + + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + target_to_host_sigset_internal(&set, &target_set); + sigprocmask(SIG_SETMASK, &set, NULL); + + /* restore registers */ + + if (target_rt_restore_ucontext(env, &frame->uc, &d0)) + goto badframe; + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, uc.uc_stack), + 0, get_sp_from_cpustate(env)) == -EFAULT) + 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; } #else