[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64
From: |
Tom Musta |
Subject: |
[Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64 |
Date: |
Mon, 30 Jun 2014 08:13:38 -0500 |
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 <address@hidden>
---
linux-user/signal.c | 117 +++++++++++++++++++++++++++++++--------------------
1 files changed, 71 insertions(+), 46 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 00c99b1..83bfcd6 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4314,15 +4314,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. */
@@ -4332,6 +4324,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];
@@ -4342,7 +4361,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.
@@ -4397,32 +4418,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;
@@ -4436,7 +4431,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];
@@ -4451,12 +4446,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
@@ -4706,7 +4721,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;
@@ -4727,19 +4743,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;
@@ -4812,6 +4837,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;
@@ -4821,10 +4850,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))
--
1.7.1
- [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64,
Tom Musta <=
- [Qemu-devel] [PATCH 2/7] linux-user: Split PPC Trampoline Encoding from Register Save, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 4/7] linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 6/7] linux-user: Move get_ppc64_abi, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 5/7] linux-user: Implement do_setcontext for PPC64, Tom Musta, 2014/06/30
- [Qemu-devel] [PATCH 7/7] linux-user: Handle PPC64 ELFv2 Function Pointers, Tom Musta, 2014/06/30