|
@@ -41,7 +41,7 @@ struct target_ucontext {
|
|
|
};
|
|
|
|
|
|
struct target_rt_sigframe {
|
|
|
- abi_uint tramp[9];
|
|
|
+ abi_uint tramp[2]; /* syscall restart return address */
|
|
|
target_siginfo_t info;
|
|
|
struct target_ucontext uc;
|
|
|
/* hidden location of upper halves of pa2.0 64-bit gregs */
|
|
@@ -101,9 +101,15 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
|
|
|
__get_user(env->cr[CR_SAR], &sc->sc_sar);
|
|
|
}
|
|
|
|
|
|
-/* No, this doesn't look right, but it's copied straight from the kernel. */
|
|
|
+#if TARGET_ABI_BITS == 32
|
|
|
+#define SIGFRAME 64
|
|
|
+#define FUNCTIONCALLFRAME 48
|
|
|
+#else
|
|
|
+#define SIGFRAME 128
|
|
|
+#define FUNCTIONCALLFRAME 96
|
|
|
+#endif
|
|
|
#define PARISC_RT_SIGFRAME_SIZE32 \
|
|
|
- ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64)
|
|
|
+ ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
|
|
|
|
|
|
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
|
|
target_siginfo_t *info,
|
|
@@ -118,7 +124,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
|
|
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
|
|
|
sp = (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
|
|
|
}
|
|
|
- frame_addr = QEMU_ALIGN_UP(sp, 64);
|
|
|
+ frame_addr = QEMU_ALIGN_UP(sp, SIGFRAME);
|
|
|
sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
|
|
|
|
|
|
trace_user_setup_rt_frame(env, frame_addr);
|
|
@@ -139,14 +145,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
|
|
|
|
|
setup_sigcontext(&frame->uc.tuc_mcontext, env);
|
|
|
|
|
|
- __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
|
|
|
- __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
|
|
|
- __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
|
|
|
- __put_user(0x08000240, frame->tramp + 3); /* nop */
|
|
|
-
|
|
|
unlock_user_struct(frame, frame_addr, 1);
|
|
|
|
|
|
- env->gr[2] = h2g(frame->tramp);
|
|
|
+ env->gr[2] = default_rt_sigreturn;
|
|
|
env->gr[30] = sp;
|
|
|
env->gr[26] = sig;
|
|
|
env->gr[25] = h2g(&frame->info);
|
|
@@ -197,3 +198,23 @@ long do_rt_sigreturn(CPUArchState *env)
|
|
|
force_sig(TARGET_SIGSEGV);
|
|
|
return -QEMU_ESIGRETURN;
|
|
|
}
|
|
|
+
|
|
|
+void setup_sigtramp(abi_ulong sigtramp_page)
|
|
|
+{
|
|
|
+ uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6*4, 0);
|
|
|
+ abi_ulong SIGFRAME_CONTEXT_REGS32;
|
|
|
+ assert(tramp != NULL);
|
|
|
+
|
|
|
+ SIGFRAME_CONTEXT_REGS32 = offsetof(struct target_rt_sigframe, uc.tuc_mcontext);
|
|
|
+ SIGFRAME_CONTEXT_REGS32 -= PARISC_RT_SIGFRAME_SIZE32;
|
|
|
+
|
|
|
+ __put_user(SIGFRAME_CONTEXT_REGS32, tramp + 0);
|
|
|
+ __put_user(0x08000240, tramp + 1); /* nop - b/c dwarf2 unwind routines */
|
|
|
+ __put_user(0x34190000, tramp + 2); /* ldi 0, %r25 (in_syscall=0) */
|
|
|
+ __put_user(0x3414015a, tramp + 3); /* ldi __NR_rt_sigreturn, %r20 */
|
|
|
+ __put_user(0xe4008200, tramp + 4); /* ble 0x100(%sr2, %r0) */
|
|
|
+ __put_user(0x08000240, tramp + 5); /* nop */
|
|
|
+
|
|
|
+ default_rt_sigreturn = (sigtramp_page + 8) | 3;
|
|
|
+ unlock_user(tramp, sigtramp_page, 6*4);
|
|
|
+}
|