qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64
@ 2014-06-30 13:13 Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame Tom Musta
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

Signal handler support exists for 32-bit PowerPC Linux User Mode (target ppc-linux-user) and is
scaffolded, but disabled for 64-bit PowerPC.  This series completes much of the work that was left
undone in the scaffolding and enables suport for signal handlers in the 64-bit PowerPC targets
(ppc64-linux-user, ppc64le-linux-user).

Tom Musta (7):
  linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame
  linux-user: Split PPC Trampoline Encoding from Register Save
  linux-user: Enable Signal Handlers on PPC64
  linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer
  linux-user: Implement do_setcontext for PPC64
  linux-user: Move get_ppc64_abi
  linux-user: Handle PPC64 ELFv2 Function Pointers

 linux-user/elfload.c        |    9 --
 linux-user/ppc/target_cpu.h |   10 +++
 linux-user/signal.c         |  180 +++++++++++++++++++++++++++++++------------
 3 files changed, 140 insertions(+), 59 deletions(-)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 2/7] linux-user: Split PPC Trampoline Encoding from Register Save Tom Musta
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

The code that sets the stack frame back pointer is incorrect for
the setup_rt_frame() code; qemu will abort (SIGSEGV) in some
environments.  The setup_frame code  was fixed in commit
beb526b12134a6b6744125deec5a7fe24a8f92e3 but the setup_rt_frame
code was not.

Make the setup_rt_frame code consistent with the setup_frame
code.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/signal.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index f3b4378..256f9b9 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4740,7 +4740,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     /* Create a stack frame for the caller of the handler.  */
     newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
-    __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
+    err |= put_user(env->gpr[1], newsp, target_ulong);
 
     if (err)
         goto sigsegv;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 2/7] linux-user: Split PPC Trampoline Encoding from Register Save
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64 Tom Musta
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

Split the encoding of the PowerPC sigreturn trampoline from the saving of
register state onto the signal handler stack.  This will make it easier
in subsequent patches to deal with variations in the stack frame layouts between
32 and 64 bit PowerPC.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/signal.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 256f9b9..00c99b1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4480,8 +4480,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
     return newsp;
 }
 
-static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
-                          int sigret)
+static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
 {
     target_ulong msr = env->msr;
     int i;
@@ -4548,11 +4547,14 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
 
     /* Store MSR.  */
     __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
+}
 
+static void encode_trampoline(int sigret, uint32_t *tramp)
+{
     /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
     if (sigret) {
-        __put_user(0x38000000UL | sigret, &frame->tramp[0]);
-        __put_user(0x44000002UL, &frame->tramp[1]);
+        __put_user(0x38000000 | sigret, &tramp[0]);
+        __put_user(0x44000002, &tramp[1]);
     }
 }
 
@@ -4663,7 +4665,10 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     __put_user(sig, &sc->signal);
 
     /* Save user regs.  */
-    save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
+    save_user_regs(env, &frame->mctx);
+
+    /* Construct the trampoline code on the stack. */
+    encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
 
     /* The kernel checks for the presence of a VDSO here.  We don't
        emulate a vdso, so use a sigreturn system call.  */
@@ -4729,7 +4734,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     }
 
     frame = &rt_sf->uc.tuc_mcontext;
-    save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
+    save_user_regs(env, frame);
+    encode_trampoline(TARGET_NR_rt_sigreturn, (uint32_t *)&frame->tramp);
 
     /* The kernel checks for the presence of a VDSO here.  We don't
        emulate a vdso, so use a sigreturn system call.  */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 2/7] linux-user: Split PPC Trampoline Encoding from Register Save Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 4/7] linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer Tom Musta
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

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 <tommusta@gmail.com>
---
 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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 4/7] linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
                   ` (2 preceding siblings ...)
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64 Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 5/7] linux-user: Implement do_setcontext for PPC64 Tom Musta
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

Properly dereference 64-bit PPC ELF V1 ABIT function pointers to signal handlers.
On this platform, function pointers are pointers to structures and the first 64
bits of such a structure contains the function's entry point.  The second 64 bits
contains the TOC pointer, which must be placed into GPR 2.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/signal.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 83bfcd6..7bd9a43 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4472,6 +4472,15 @@ struct target_rt_sigframe {
 
 #endif
 
+#if defined(TARGET_PPC64)
+
+struct target_func_ptr {
+    target_ulong entry;
+    target_ulong toc;
+};
+
+#endif
+
 /* We use the mc_pad field for the signal return trampoline.  */
 #define tramp mc_pad
 
@@ -4703,7 +4712,17 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     env->gpr[1] = newsp;
     env->gpr[3] = signal;
     env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
+
+#if defined(TARGET_PPC64)
+    /* PPC64 function pointers are pointers to OPD entries. */
+    struct target_func_ptr *handler =
+        (struct target_func_ptr *)g2h(ka->_sa_handler);
+    env->nip = tswapl(handler->entry);
+    env->gpr[2] = tswapl(handler->toc);
+#else
     env->nip = (target_ulong) ka->_sa_handler;
+#endif
+
     /* Signal handlers are entered in big-endian mode.  */
     env->msr &= ~MSR_LE;
 
@@ -4782,7 +4801,17 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
     env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
     env->gpr[6] = (target_ulong) h2g(rt_sf);
+
+#if defined(TARGET_PPC64)
+    /* PPC64 function pointers are pointers to OPD entries.  */
+    struct target_func_ptr *handler =
+        (struct target_func_ptr *)g2h(ka->_sa_handler);
+    env->nip = tswapl(handler->entry);
+    env->gpr[2] = tswapl(handler->toc);
+#else
     env->nip = (target_ulong) ka->_sa_handler;
+#endif
+
     /* Signal handlers are entered in big-endian mode.  */
     env->msr &= ~MSR_LE;
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 5/7] linux-user: Implement do_setcontext for PPC64
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
                   ` (3 preceding siblings ...)
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 4/7] linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 6/7] linux-user: Move get_ppc64_abi Tom Musta
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

Eliminate the stub for the do_setcontext() function for TARGET_PPC64.  The
implementation re-uses the existing TARGET_PPC32 code with the only change
being the computation of the address of the register save area.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/signal.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7bd9a43..9f04a20 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4866,10 +4866,6 @@ 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;
@@ -4879,7 +4875,12 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
                        sizeof (set)))
         return 1;
 
+#if defined(TARGET_PPC64)
+    mcp_addr = h2g(ucp) +
+        offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
+#else
     __get_user(mcp_addr, &ucp->tuc_regs);
+#endif
 
     if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
         return 1;
@@ -4890,7 +4891,6 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
 
     unlock_user_struct(mcp, mcp_addr, 1);
     return 0;
-#endif
 }
 
 long do_rt_sigreturn(CPUPPCState *env)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 6/7] linux-user: Move get_ppc64_abi
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
                   ` (4 preceding siblings ...)
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 5/7] linux-user: Implement do_setcontext for PPC64 Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 7/7] linux-user: Handle PPC64 ELFv2 Function Pointers Tom Musta
  2014-07-03 12:59 ` [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Alexander Graf
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

The get_ppc64_abi is used to determine the ELF ABI (i.e. V1 or V2). This
routine is currently implemented in the linux-user/elfload.c file but
is useful in other scenarios.  Move the routine to a more generally
available location (linux-user/ppc/target_cpu.h).

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/elfload.c        |    9 ---------
 linux-user/ppc/target_cpu.h |   10 ++++++++++
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 60777fe..bea803b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -824,8 +824,6 @@ static uint32_t get_elf_hwcap2(void)
         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
     } while (0)
 
-static inline uint32_t get_ppc64_abi(struct image_info *infop);
-
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
     _regs->gpr[1] = infop->start_stack;
@@ -1205,13 +1203,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #include "elf.h"
 
-#ifdef TARGET_PPC
-static inline uint32_t get_ppc64_abi(struct image_info *infop)
-{
-  return infop->elf_flags & EF_PPC64_ABI;
-}
-#endif
-
 struct exec
 {
     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h
index 9cc0c3b..26f4ba2 100644
--- a/linux-user/ppc/target_cpu.h
+++ b/linux-user/ppc/target_cpu.h
@@ -38,4 +38,14 @@ static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
 #endif
 }
 
+#ifndef EF_PPC64_ABI
+#define EF_PPC64_ABI           0x3
+#endif
+
+static inline uint32_t get_ppc64_abi(struct image_info *infop)
+{
+  return infop->elf_flags & EF_PPC64_ABI;
+}
+
+
 #endif
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 7/7] linux-user: Handle PPC64 ELFv2 Function Pointers
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
                   ` (5 preceding siblings ...)
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 6/7] linux-user: Move get_ppc64_abi Tom Musta
@ 2014-06-30 13:13 ` Tom Musta
  2014-07-03 12:59 ` [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Alexander Graf
  7 siblings, 0 replies; 9+ messages in thread
From: Tom Musta @ 2014-06-30 13:13 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Tom Musta, riku.voipio, agraf

Function pointers in the 64-bit ELFv2 PowerPC ABI are actual (internal)
entry point addresses.  However, when invoking a function via a function
pointer, GPR 12 must also be set to this address so that the TOC may be
handled properly.

Add this support to the invocation of a signal handler.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 linux-user/signal.c |   40 ++++++++++++++++++++++++++++++----------
 1 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9f04a20..770e7f7 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4670,6 +4670,9 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     target_ulong frame_addr, newsp;
     int err = 0;
     int signal;
+#if defined(TARGET_PPC64)
+    struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
+#endif
 
     frame_addr = get_sigframe(ka, env, sizeof(*frame));
     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
@@ -4714,11 +4717,18 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
 
 #if defined(TARGET_PPC64)
-    /* PPC64 function pointers are pointers to OPD entries. */
-    struct target_func_ptr *handler =
-        (struct target_func_ptr *)g2h(ka->_sa_handler);
-    env->nip = tswapl(handler->entry);
-    env->gpr[2] = tswapl(handler->toc);
+    if (get_ppc64_abi(image) < 2) {
+        /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
+        struct target_func_ptr *handler =
+            (struct target_func_ptr *)g2h(ka->_sa_handler);
+        env->nip = tswapl(handler->entry);
+        env->gpr[2] = tswapl(handler->toc);
+    } else {
+        /* ELFv2 PPC64 function pointers are entry points, but R12
+         * must also be set */
+        env->nip = tswapl((target_ulong) ka->_sa_handler);
+        env->gpr[12] = env->nip;
+    }
 #else
     env->nip = (target_ulong) ka->_sa_handler;
 #endif
@@ -4745,6 +4755,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     target_ulong rt_sf_addr, newsp = 0;
     int i, err = 0;
     int signal;
+#if defined(TARGET_PPC64)
+    struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
+#endif
 
     rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
     if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
@@ -4803,11 +4816,18 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->gpr[6] = (target_ulong) h2g(rt_sf);
 
 #if defined(TARGET_PPC64)
-    /* PPC64 function pointers are pointers to OPD entries.  */
-    struct target_func_ptr *handler =
-        (struct target_func_ptr *)g2h(ka->_sa_handler);
-    env->nip = tswapl(handler->entry);
-    env->gpr[2] = tswapl(handler->toc);
+    if (get_ppc64_abi(image) < 2) {
+        /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
+        struct target_func_ptr *handler =
+            (struct target_func_ptr *)g2h(ka->_sa_handler);
+        env->nip = tswapl(handler->entry);
+        env->gpr[2] = tswapl(handler->toc);
+    } else {
+        /* ELFv2 PPC64 function pointers are entry points, but R12
+         * must also be set */
+        env->nip = tswapl((target_ulong) ka->_sa_handler);
+        env->gpr[12] = env->nip;
+    }
 #else
     env->nip = (target_ulong) ka->_sa_handler;
 #endif
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64
  2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
                   ` (6 preceding siblings ...)
  2014-06-30 13:13 ` [Qemu-devel] [PATCH 7/7] linux-user: Handle PPC64 ELFv2 Function Pointers Tom Musta
@ 2014-07-03 12:59 ` Alexander Graf
  7 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2014-07-03 12:59 UTC (permalink / raw)
  To: Tom Musta, qemu-devel, qemu-ppc; +Cc: riku.voipio


On 30.06.14 15:13, Tom Musta wrote:
> Signal handler support exists for 32-bit PowerPC Linux User Mode (target ppc-linux-user) and is
> scaffolded, but disabled for 64-bit PowerPC.  This series completes much of the work that was left
> undone in the scaffolding and enables suport for signal handlers in the 64-bit PowerPC targets
> (ppc64-linux-user, ppc64le-linux-user).

Thanks, applied all to ppc-next-2.2.


Alex

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-07-03 13:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-30 13:13 [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 1/7] linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 2/7] linux-user: Split PPC Trampoline Encoding from Register Save Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 3/7] linux-user: Enable Signal Handlers on PPC64 Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 4/7] linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 5/7] linux-user: Implement do_setcontext for PPC64 Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 6/7] linux-user: Move get_ppc64_abi Tom Musta
2014-06-30 13:13 ` [Qemu-devel] [PATCH 7/7] linux-user: Handle PPC64 ELFv2 Function Pointers Tom Musta
2014-07-03 12:59 ` [Qemu-devel] [PATCH 0/7] linux-user: Support for Signal Handlers on PPC64 Alexander Graf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).