patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / parisc / kernel / signal.c
index 1aed89d..b220bb2 100644 (file)
@@ -353,12 +353,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                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... */
@@ -370,12 +375,16 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        }
 #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;