aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/signal.c')
-rw-r--r--arch/sparc/kernel/signal.c64
1 files changed, 28 insertions, 36 deletions
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 368157926d24..3fd1df9f9ba7 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -145,6 +145,9 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) 145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
146 | (regs->psr & (PSR_ICC | PSR_EF)); 146 | (regs->psr & (PSR_ICC | PSR_EF));
147 147
148 /* Prevent syscall restart. */
149 pt_regs_clear_syscall(regs);
150
148 err |= __get_user(fpu_save, &sf->fpu_save); 151 err |= __get_user(fpu_save, &sf->fpu_save);
149 152
150 if (fpu_save) 153 if (fpu_save)
@@ -199,6 +202,9 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
199 202
200 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); 203 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);
201 204
205 /* Prevent syscall restart. */
206 pt_regs_clear_syscall(regs);
207
202 err |= __get_user(fpu_save, &sf->fpu_save); 208 err |= __get_user(fpu_save, &sf->fpu_save);
203 209
204 if (fpu_save) 210 if (fpu_save)
@@ -507,26 +513,36 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
507 * want to handle. Thus you cannot kill init even with a SIGKILL even by 513 * want to handle. Thus you cannot kill init even with a SIGKILL even by
508 * mistake. 514 * mistake.
509 */ 515 */
510asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) 516asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
511{ 517{
512 siginfo_t info;
513 struct sparc_deliver_cookie cookie;
514 struct k_sigaction ka; 518 struct k_sigaction ka;
515 int signr; 519 int restart_syscall;
516 sigset_t *oldset; 520 sigset_t *oldset;
521 siginfo_t info;
522 int signr;
517 523
518 cookie.restart_syscall = restart_syscall; 524 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
519 cookie.orig_i0 = orig_i0; 525 restart_syscall = 1;
526 else
527 restart_syscall = 0;
520 528
521 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 529 if (test_thread_flag(TIF_RESTORE_SIGMASK))
522 oldset = &current->saved_sigmask; 530 oldset = &current->saved_sigmask;
523 else 531 else
524 oldset = &current->blocked; 532 oldset = &current->blocked;
525 533
526 signr = get_signal_to_deliver(&info, &ka, regs, &cookie); 534 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
535
536 /* If the debugger messes with the program counter, it clears
537 * the software "in syscall" bit, directing us to not perform
538 * a syscall restart.
539 */
540 if (restart_syscall && !pt_regs_is_syscall(regs))
541 restart_syscall = 0;
542
527 if (signr > 0) { 543 if (signr > 0) {
528 if (cookie.restart_syscall) 544 if (restart_syscall)
529 syscall_restart(cookie.orig_i0, regs, &ka.sa); 545 syscall_restart(orig_i0, regs, &ka.sa);
530 handle_signal(signr, &ka, &info, oldset, regs); 546 handle_signal(signr, &ka, &info, oldset, regs);
531 547
532 /* a signal was successfully delivered; the saved 548 /* a signal was successfully delivered; the saved
@@ -538,16 +554,16 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
538 clear_thread_flag(TIF_RESTORE_SIGMASK); 554 clear_thread_flag(TIF_RESTORE_SIGMASK);
539 return; 555 return;
540 } 556 }
541 if (cookie.restart_syscall && 557 if (restart_syscall &&
542 (regs->u_regs[UREG_I0] == ERESTARTNOHAND || 558 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
543 regs->u_regs[UREG_I0] == ERESTARTSYS || 559 regs->u_regs[UREG_I0] == ERESTARTSYS ||
544 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { 560 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
545 /* replay the system call when we are done */ 561 /* replay the system call when we are done */
546 regs->u_regs[UREG_I0] = cookie.orig_i0; 562 regs->u_regs[UREG_I0] = orig_i0;
547 regs->pc -= 4; 563 regs->pc -= 4;
548 regs->npc -= 4; 564 regs->npc -= 4;
549 } 565 }
550 if (cookie.restart_syscall && 566 if (restart_syscall &&
551 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 567 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
552 regs->u_regs[UREG_G1] = __NR_restart_syscall; 568 regs->u_regs[UREG_G1] = __NR_restart_syscall;
553 regs->pc -= 4; 569 regs->pc -= 4;
@@ -599,27 +615,3 @@ do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
599out: 615out:
600 return ret; 616 return ret;
601} 617}
602
603void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
604{
605 struct sparc_deliver_cookie *cp = cookie;
606
607 if (cp->restart_syscall &&
608 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
609 regs->u_regs[UREG_I0] == ERESTARTSYS ||
610 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
611 /* replay the system call when we are done */
612 regs->u_regs[UREG_I0] = cp->orig_i0;
613 regs->pc -= 4;
614 regs->npc -= 4;
615 cp->restart_syscall = 0;
616 }
617
618 if (cp->restart_syscall &&
619 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
620 regs->u_regs[UREG_G1] = __NR_restart_syscall;
621 regs->pc -= 4;
622 regs->npc -= 4;
623 cp->restart_syscall = 0;
624 }
625}