aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/signal32.c18
-rw-r--r--arch/sparc/kernel/signal_32.c20
-rw-r--r--arch/sparc/kernel/signal_64.c32
3 files changed, 43 insertions, 27 deletions
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 2caa556db86d..2e86fd1ddc7b 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -822,21 +822,23 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
822 * want to handle. Thus you cannot kill init even with a SIGKILL even by 822 * want to handle. Thus you cannot kill init even with a SIGKILL even by
823 * mistake. 823 * mistake.
824 */ 824 */
825void do_signal32(sigset_t *oldset, struct pt_regs * regs, 825void do_signal32(sigset_t *oldset, struct pt_regs * regs)
826 int restart_syscall, unsigned long orig_i0)
827{ 826{
828 struct k_sigaction ka; 827 struct k_sigaction ka;
828 unsigned long orig_i0;
829 int restart_syscall;
829 siginfo_t info; 830 siginfo_t info;
830 int signr; 831 int signr;
831 832
832 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 833 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
833 834
834 /* If the debugger messes with the program counter, it clears 835 restart_syscall = 0;
835 * the "in syscall" bit, directing us to not perform a syscall 836 orig_i0 = 0;
836 * restart. 837 if (pt_regs_is_syscall(regs) &&
837 */ 838 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
838 if (restart_syscall && !pt_regs_is_syscall(regs)) 839 restart_syscall = 1;
839 restart_syscall = 0; 840 orig_i0 = regs->u_regs[UREG_G2];
841 }
840 842
841 if (signr > 0) { 843 if (signr > 0) {
842 if (restart_syscall) 844 if (restart_syscall)
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 8ce247ac04cc..7dfaff64cd6b 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -519,10 +519,16 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
519 siginfo_t info; 519 siginfo_t info;
520 int signr; 520 int signr;
521 521
522 /* It's a lot of work and synchronization to add a new ptrace
523 * register for GDB to save and restore in order to get
524 * orig_i0 correct for syscall restarts when debugging.
525 *
526 * However, we luckily can use the fact that several registers
527 * are volatile across system calls. One such register is
528 * %g2, so use that as a place to save away orig_i0.
529 */
522 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) 530 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
523 restart_syscall = 1; 531 regs->u_regs[UREG_G2] = orig_i0;
524 else
525 restart_syscall = 0;
526 532
527 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 533 if (test_thread_flag(TIF_RESTORE_SIGMASK))
528 oldset = &current->saved_sigmask; 534 oldset = &current->saved_sigmask;
@@ -535,8 +541,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
535 * the software "in syscall" bit, directing us to not perform 541 * the software "in syscall" bit, directing us to not perform
536 * a syscall restart. 542 * a syscall restart.
537 */ 543 */
538 if (restart_syscall && !pt_regs_is_syscall(regs)) 544 restart_syscall = 0;
539 restart_syscall = 0; 545 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
546 restart_syscall = 1;
547 orig_i0 = regs->u_regs[UREG_G2];
548 }
549
540 550
541 if (signr > 0) { 551 if (signr > 0) {
542 if (restart_syscall) 552 if (restart_syscall)
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index a2b81598d905..1ddf0dedb929 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -529,11 +529,17 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
529 siginfo_t info; 529 siginfo_t info;
530 int signr; 530 int signr;
531 531
532 /* It's a lot of work and synchronization to add a new ptrace
533 * register for GDB to save and restore in order to get
534 * orig_i0 correct for syscall restarts when debugging.
535 *
536 * However, we luckily can use the fact that several registers
537 * are volatile across system calls. One such register is
538 * %g2, so use that as a place to save away orig_i0.
539 */
532 if (pt_regs_is_syscall(regs) && 540 if (pt_regs_is_syscall(regs) &&
533 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { 541 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
534 restart_syscall = 1; 542 regs->u_regs[UREG_G2] = orig_i0;
535 } else
536 restart_syscall = 0;
537 543
538 if (current_thread_info()->status & TS_RESTORE_SIGMASK) 544 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
539 oldset = &current->saved_sigmask; 545 oldset = &current->saved_sigmask;
@@ -542,22 +548,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
542 548
543#ifdef CONFIG_COMPAT 549#ifdef CONFIG_COMPAT
544 if (test_thread_flag(TIF_32BIT)) { 550 if (test_thread_flag(TIF_32BIT)) {
545 extern void do_signal32(sigset_t *, struct pt_regs *, 551 extern void do_signal32(sigset_t *, struct pt_regs *);
546 int restart_syscall, 552 do_signal32(oldset, regs);
547 unsigned long orig_i0);
548 do_signal32(oldset, regs, restart_syscall, orig_i0);
549 return; 553 return;
550 } 554 }
551#endif 555#endif
552 556
553 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 557 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
554 558
555 /* If the debugger messes with the program counter, it clears 559 restart_syscall = 0;
556 * the software "in syscall" bit, directing us to not perform 560 if (pt_regs_is_syscall(regs) &&
557 * a syscall restart. 561 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
558 */ 562 restart_syscall = 1;
559 if (restart_syscall && !pt_regs_is_syscall(regs)) 563 orig_i0 = regs->u_regs[UREG_G2];
560 restart_syscall = 0; 564 }
561 565
562 if (signr > 0) { 566 if (signr > 0) {
563 if (restart_syscall) 567 if (restart_syscall)