From patchwork Thu Sep 4 17:19:53 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 385930 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 0082F14018B for ; Fri, 5 Sep 2014 03:28:00 +1000 (EST) Received: from localhost ([::1]:52904 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XPapB-0008VK-K5 for incoming@patchwork.ozlabs.org; Thu, 04 Sep 2014 13:27:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39615) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XPaiK-00043Z-HO for qemu-devel@nongnu.org; Thu, 04 Sep 2014 13:21:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XPaiA-0005hs-Su for qemu-devel@nongnu.org; Thu, 04 Sep 2014 13:20:52 -0400 Received: from cantor2.suse.de ([195.135.220.15]:43883 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XPaiA-0005gZ-FP; Thu, 04 Sep 2014 13:20:42 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3A7FFAD1B; Thu, 4 Sep 2014 17:20:41 +0000 (UTC) From: Alexander Graf To: qemu-ppc@nongnu.org Date: Thu, 4 Sep 2014 19:19:53 +0200 Message-Id: <1409851240-48126-6-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1409851240-48126-1-git-send-email-agraf@suse.de> References: <1409851240-48126-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-Received-From: 195.135.220.15 Cc: peter.maydell@linaro.org, qemu-devel@nongnu.org, Tom Musta Subject: [Qemu-devel] [PULL 05/52] linux-user: Enable Signal Handlers on PPC64 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Tom Musta Enable the 64-bit PowerPC signal handling code that was previously disabled via #ifdefs. Specifically: - Move the target_mcontext (register save area) structure and append it to the 64-bit target_sigcontext structure. This provides the space on the stack for saving and restoring context. - Define the target_rt_sigframe for 64-bit. - Adjust the setup_frame and setup_rt_frame routines to properly select the target_mcontext area and trampoline within the stack frame; tthis is different for 32-bit and 64-bit implementations. - Adjust the do_setcontext stub for 64-bit so that it compiles without warnings. The 64-bit signal handling code is still not functional after this change; but the 32-bit code is. Subsequent changes will address specific issues with the 64-bit code. Signed-off-by: Tom Musta [agraf: fix build on 32bit hosts] Signed-off-by: Alexander Graf --- linux-user/signal.c | 119 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 47 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 7365d5d..6f77d4d 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4325,15 +4325,7 @@ badframe: return 0; } -#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) - -/* FIXME: Many of the structures are defined for both PPC and PPC64, but - the signal handling is different enough that we haven't implemented - support for PPC64 yet. Hence the restriction above. - - There are various #if'd blocks for code for TARGET_PPC64. These - blocks should go away so that we can successfully run 32-bit and - 64-bit binaries on a QEMU configured for PPC64. */ +#elif defined(TARGET_PPC) /* Size of dummy stack frame allocated when calling signal handler. See arch/powerpc/include/asm/ptrace.h. */ @@ -4343,6 +4335,33 @@ badframe: #define SIGNAL_FRAMESIZE 64 #endif +/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC; + on 64-bit PPC, sigcontext and mcontext are one and the same. */ +struct target_mcontext { + target_ulong mc_gregs[48]; + /* Includes fpscr. */ + uint64_t mc_fregs[33]; + target_ulong mc_pad[2]; + /* We need to handle Altivec and SPE at the same time, which no + kernel needs to do. Fortunately, the kernel defines this bit to + be Altivec-register-large all the time, rather than trying to + twiddle it based on the specific platform. */ + union { + /* SPE vector registers. One extra for SPEFSCR. */ + uint32_t spe[33]; + /* Altivec vector registers. The packing of VSCR and VRSAVE + varies depending on whether we're PPC64 or not: PPC64 splits + them apart; PPC32 stuffs them together. */ +#if defined(TARGET_PPC64) +#define QEMU_NVRREG 34 +#else +#define QEMU_NVRREG 33 +#endif + ppc_avr_t altivec[QEMU_NVRREG]; +#undef QEMU_NVRREG + } mc_vregs __attribute__((__aligned__(16))); +}; + /* See arch/powerpc/include/asm/sigcontext.h. */ struct target_sigcontext { target_ulong _unused[4]; @@ -4353,7 +4372,9 @@ struct target_sigcontext { target_ulong handler; target_ulong oldmask; target_ulong regs; /* struct pt_regs __user * */ - /* TODO: PPC64 includes extra bits here. */ +#if defined(TARGET_PPC64) + struct target_mcontext mcontext; +#endif }; /* Indices for target_mcontext.mc_gregs, below. @@ -4408,32 +4429,6 @@ enum { TARGET_PT_REGS_COUNT = 44 }; -/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC; - on 64-bit PPC, sigcontext and mcontext are one and the same. */ -struct target_mcontext { - target_ulong mc_gregs[48]; - /* Includes fpscr. */ - uint64_t mc_fregs[33]; - target_ulong mc_pad[2]; - /* We need to handle Altivec and SPE at the same time, which no - kernel needs to do. Fortunately, the kernel defines this bit to - be Altivec-register-large all the time, rather than trying to - twiddle it based on the specific platform. */ - union { - /* SPE vector registers. One extra for SPEFSCR. */ - uint32_t spe[33]; - /* Altivec vector registers. The packing of VSCR and VRSAVE - varies depending on whether we're PPC64 or not: PPC64 splits - them apart; PPC32 stuffs them together. */ -#if defined(TARGET_PPC64) -#define QEMU_NVRREG 34 -#else -#define QEMU_NVRREG 33 -#endif - ppc_avr_t altivec[QEMU_NVRREG]; -#undef QEMU_NVRREG - } mc_vregs __attribute__((__aligned__(16))); -}; struct target_ucontext { target_ulong tuc_flags; @@ -4447,7 +4442,7 @@ struct target_ucontext { target_sigset_t tuc_sigmask; #if defined(TARGET_PPC64) target_sigset_t unused[15]; /* Allow for uc_sigmask growth */ - struct target_sigcontext tuc_mcontext; + struct target_sigcontext tuc_sigcontext; #else int32_t tuc_maskext[30]; int32_t tuc_pad2[3]; @@ -4462,12 +4457,32 @@ struct target_sigframe { int32_t abigap[56]; }; +#if defined(TARGET_PPC64) + +#define TARGET_TRAMP_SIZE 6 + +struct target_rt_sigframe { + /* sys_rt_sigreturn requires the ucontext be the first field */ + struct target_ucontext uc; + target_ulong _unused[2]; + uint32_t trampoline[TARGET_TRAMP_SIZE]; + target_ulong pinfo; /* struct siginfo __user * */ + target_ulong puc; /* void __user * */ + struct target_siginfo info; + /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ + char abigap[288]; +} __attribute__((aligned(16))); + +#else + struct target_rt_sigframe { struct target_siginfo info; struct target_ucontext uc; int32_t abigap[56]; }; +#endif + /* We use the mc_pad field for the signal return trampoline. */ #define tramp mc_pad @@ -4717,7 +4732,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUPPCState *env) { struct target_rt_sigframe *rt_sf; - struct target_mcontext *frame; + uint32_t *trampptr = 0; + struct target_mcontext *mctx = 0; target_ulong rt_sf_addr, newsp = 0; int i, err = 0; int signal; @@ -4738,19 +4754,28 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, &rt_sf->uc.tuc_stack.ss_flags); __put_user(target_sigaltstack_used.ss_size, &rt_sf->uc.tuc_stack.ss_size); +#if !defined(TARGET_PPC64) __put_user(h2g (&rt_sf->uc.tuc_mcontext), &rt_sf->uc.tuc_regs); +#endif for(i = 0; i < TARGET_NSIG_WORDS; i++) { __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]); } - frame = &rt_sf->uc.tuc_mcontext; - save_user_regs(env, frame); - encode_trampoline(TARGET_NR_rt_sigreturn, (uint32_t *)&frame->tramp); +#if defined(TARGET_PPC64) + mctx = &rt_sf->uc.tuc_sigcontext.mcontext; + trampptr = &rt_sf->trampoline[0]; +#else + mctx = &rt_sf->uc.tuc_mcontext; + trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp; +#endif + + save_user_regs(env, mctx); + encode_trampoline(TARGET_NR_rt_sigreturn, trampptr); /* The kernel checks for the presence of a VDSO here. We don't emulate a vdso, so use a sigreturn system call. */ - env->lr = (target_ulong) h2g(frame->tramp); + env->lr = (target_ulong) h2g(trampptr); /* Turn off all fp exceptions. */ env->fpscr = 0; @@ -4795,7 +4820,7 @@ long do_sigreturn(CPUPPCState *env) goto sigsegv; #if defined(TARGET_PPC64) - set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32); + set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32); #else __get_user(set.sig[0], &sc->oldmask); __get_user(set.sig[1], &sc->_unused[3]); @@ -4823,6 +4848,10 @@ sigsegv: /* See arch/powerpc/kernel/signal_32.c. */ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) { +#if defined(TARGET_PPC64) + fprintf(stderr, "do_setcontext: not implemented\n"); + return 0; +#else struct target_mcontext *mcp; target_ulong mcp_addr; sigset_t blocked; @@ -4832,10 +4861,6 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) sizeof (set))) return 1; -#if defined(TARGET_PPC64) - fprintf (stderr, "do_setcontext: not implemented\n"); - return 0; -#else __get_user(mcp_addr, &ucp->tuc_regs); if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))