Loading arch/parisc/kernel/signal.c +98 −79 Original line number Diff line number Diff line Loading @@ -471,6 +471,97 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, return 1; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { /* Check the return code */ switch (regs->gr[28]) { case -ERESTART_RESTARTBLOCK: current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); regs->gr[28] = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all * we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; break; } } static inline void insert_restart_trampoline(struct pt_regs *regs) { switch(regs->gr[28]) { case -ERESTART_RESTARTBLOCK: { /* Restart the system call - no handlers present */ unsigned int *usp = (unsigned int *)regs->gr[30]; /* Setup a trampoline to restart the syscall * with __NR_restart_syscall * * 0: <return address (orig r31)> * 4: <2nd half for 64-bit> * 8: ldw 0(%sp), %r31 * 12: be 0x100(%sr2, %r0) * 16: ldi __NR_restart_syscall, %r20 */ #ifdef CONFIG_64BIT put_user(regs->gr[31] >> 32, &usp[0]); put_user(regs->gr[31] & 0xffffffff, &usp[1]); put_user(0x0fc010df, &usp[2]); #else put_user(regs->gr[31], &usp[0]); put_user(0x0fc0109f, &usp[2]); #endif put_user(0xe0008200, &usp[3]); put_user(0x34140000, &usp[4]); /* Stack is 64-byte aligned, and we only need * to flush 1 cache line. * Flushing one cacheline is cheap. * "sync" on bigger (> 4 way) boxes is not. */ flush_icache_range(regs->gr[30], regs->gr[30] + 4); regs->gr[31] = regs->gr[30] + 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; return; } case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: { /* Hooray for delayed branching. We don't * have to restore %r20 (the system call * number) because it gets loaded in the delay * slot of the branch external instruction. */ regs->gr[31] -= 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; return; } default: break; } } /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by Loading @@ -482,7 +573,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * registers). As noted below, the syscall number gets restored for * us due to the magic of delayed branching. */ asmlinkage void do_signal(struct pt_regs *regs, long in_syscall) { Loading Loading @@ -518,36 +608,14 @@ do_signal(struct pt_regs *regs, long in_syscall) break; /* Restart a system call if necessary. */ if (in_syscall) { /* Check the return code */ switch (regs->gr[28]) { case -ERESTART_RESTARTBLOCK: current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); regs->gr[28] = -EINTR; break; if (in_syscall) syscall_restart(regs, &ka); case -ERESTARTSYS: if (!(ka.sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; break; } } /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", regs->gr[28]); if (test_thread_flag(TIF_RESTORE_SIGMASK)) Loading @@ -558,57 +626,8 @@ do_signal(struct pt_regs *regs, long in_syscall) /* end of while(1) looping forever if we can't force a signal */ /* Did we come from a system call? */ if (in_syscall) { /* Restart the system call - no handlers present */ if (regs->gr[28] == -ERESTART_RESTARTBLOCK) { unsigned int *usp = (unsigned int *)regs->gr[30]; /* Setup a trampoline to restart the syscall * with __NR_restart_syscall * * 0: <return address (orig r31)> * 4: <2nd half for 64-bit> * 8: ldw 0(%sp), %r31 * 12: be 0x100(%sr2, %r0) * 16: ldi __NR_restart_syscall, %r20 */ #ifndef __LP64__ put_user(regs->gr[31], &usp[0]); put_user(0x0fc0109f, &usp[2]); #else put_user(regs->gr[31] >> 32, &usp[0]); put_user(regs->gr[31] & 0xffffffff, &usp[1]); put_user(0x0fc010df, &usp[2]); #endif put_user(0xe0008200, &usp[3]); put_user(0x34140000, &usp[4]); /* Stack is 64-byte aligned, and we only need * to flush 1 cache line. * Flushing one cacheline is cheap. * "sync" on bigger (> 4 way) boxes is not. */ asm("fdc %%r0(%%sr3, %0)\n" "sync\n" "fic %%r0(%%sr3, %0)\n" "sync\n" : : "r"(regs->gr[30])); regs->gr[31] = regs->gr[30] + 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; } else if (regs->gr[28] == -ERESTARTNOHAND || regs->gr[28] == -ERESTARTSYS || regs->gr[28] == -ERESTARTNOINTR) { /* Hooray for delayed branching. We don't have to restore %r20 (the system call number) because it gets loaded in the delay slot of the branch external instruction. */ regs->gr[31] -= 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; } } if (in_syscall) insert_restart_trampoline(regs); DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", regs->gr[28]); Loading Loading
arch/parisc/kernel/signal.c +98 −79 Original line number Diff line number Diff line Loading @@ -471,6 +471,97 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, return 1; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { /* Check the return code */ switch (regs->gr[28]) { case -ERESTART_RESTARTBLOCK: current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); regs->gr[28] = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all * we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; break; } } static inline void insert_restart_trampoline(struct pt_regs *regs) { switch(regs->gr[28]) { case -ERESTART_RESTARTBLOCK: { /* Restart the system call - no handlers present */ unsigned int *usp = (unsigned int *)regs->gr[30]; /* Setup a trampoline to restart the syscall * with __NR_restart_syscall * * 0: <return address (orig r31)> * 4: <2nd half for 64-bit> * 8: ldw 0(%sp), %r31 * 12: be 0x100(%sr2, %r0) * 16: ldi __NR_restart_syscall, %r20 */ #ifdef CONFIG_64BIT put_user(regs->gr[31] >> 32, &usp[0]); put_user(regs->gr[31] & 0xffffffff, &usp[1]); put_user(0x0fc010df, &usp[2]); #else put_user(regs->gr[31], &usp[0]); put_user(0x0fc0109f, &usp[2]); #endif put_user(0xe0008200, &usp[3]); put_user(0x34140000, &usp[4]); /* Stack is 64-byte aligned, and we only need * to flush 1 cache line. * Flushing one cacheline is cheap. * "sync" on bigger (> 4 way) boxes is not. */ flush_icache_range(regs->gr[30], regs->gr[30] + 4); regs->gr[31] = regs->gr[30] + 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; return; } case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: { /* Hooray for delayed branching. We don't * have to restore %r20 (the system call * number) because it gets loaded in the delay * slot of the branch external instruction. */ regs->gr[31] -= 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; return; } default: break; } } /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by Loading @@ -482,7 +573,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * registers). As noted below, the syscall number gets restored for * us due to the magic of delayed branching. */ asmlinkage void do_signal(struct pt_regs *regs, long in_syscall) { Loading Loading @@ -518,36 +608,14 @@ do_signal(struct pt_regs *regs, long in_syscall) break; /* Restart a system call if necessary. */ if (in_syscall) { /* Check the return code */ switch (regs->gr[28]) { case -ERESTART_RESTARTBLOCK: current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); regs->gr[28] = -EINTR; break; if (in_syscall) syscall_restart(regs, &ka); case -ERESTARTSYS: if (!(ka.sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; break; } } /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", regs->gr[28]); if (test_thread_flag(TIF_RESTORE_SIGMASK)) Loading @@ -558,57 +626,8 @@ do_signal(struct pt_regs *regs, long in_syscall) /* end of while(1) looping forever if we can't force a signal */ /* Did we come from a system call? */ if (in_syscall) { /* Restart the system call - no handlers present */ if (regs->gr[28] == -ERESTART_RESTARTBLOCK) { unsigned int *usp = (unsigned int *)regs->gr[30]; /* Setup a trampoline to restart the syscall * with __NR_restart_syscall * * 0: <return address (orig r31)> * 4: <2nd half for 64-bit> * 8: ldw 0(%sp), %r31 * 12: be 0x100(%sr2, %r0) * 16: ldi __NR_restart_syscall, %r20 */ #ifndef __LP64__ put_user(regs->gr[31], &usp[0]); put_user(0x0fc0109f, &usp[2]); #else put_user(regs->gr[31] >> 32, &usp[0]); put_user(regs->gr[31] & 0xffffffff, &usp[1]); put_user(0x0fc010df, &usp[2]); #endif put_user(0xe0008200, &usp[3]); put_user(0x34140000, &usp[4]); /* Stack is 64-byte aligned, and we only need * to flush 1 cache line. * Flushing one cacheline is cheap. * "sync" on bigger (> 4 way) boxes is not. */ asm("fdc %%r0(%%sr3, %0)\n" "sync\n" "fic %%r0(%%sr3, %0)\n" "sync\n" : : "r"(regs->gr[30])); regs->gr[31] = regs->gr[30] + 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; } else if (regs->gr[28] == -ERESTARTNOHAND || regs->gr[28] == -ERESTARTSYS || regs->gr[28] == -ERESTARTNOINTR) { /* Hooray for delayed branching. We don't have to restore %r20 (the system call number) because it gets loaded in the delay slot of the branch external instruction. */ regs->gr[31] -= 8; /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; } } if (in_syscall) insert_restart_trampoline(regs); DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", regs->gr[28]); Loading