goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub
- already in userspace. */
+ already in userspace. The first words of tramp are used to
+ save the previous sigrestartblock trampoline that might be
+ on the stack. We start the sigreturn trampoline at
+ SIGRESTARTBLOCK_TRAMP+X. */
err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
- &frame->tramp[SIGRETURN_TRAMP+0]);
- err |= __put_user(INSN_LDI_R20, &frame->tramp[SIGRETURN_TRAMP+1]);
- err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[SIGRETURN_TRAMP+2]);
- err |= __put_user(INSN_NOP, &frame->tramp[SIGRETURN_TRAMP+3]);
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
+ err |= __put_user(INSN_LDI_R20,
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
+ err |= __put_user(INSN_BLE_SR2_R0,
+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
+ err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
#if DEBUG_SIG
/* Assert that we're flushing in the correct space... */
}
#endif
- flush_user_dcache_range((unsigned long) &frame->tramp[SIGRETURN_TRAMP],
+ flush_user_dcache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[TRAMP_SIZE]);
- flush_user_icache_range((unsigned long) &frame->tramp[SIGRETURN_TRAMP],
+ flush_user_icache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[TRAMP_SIZE]);
- rp = (unsigned long) &frame->tramp[SIGRETURN_TRAMP];
+ /* TRAMP Words 0-4, Lenght 5 = SIGRESTARTBLOCK_TRAMP
+ * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
+ * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
+ */
+ rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
if (err)
goto give_sigsegv;