aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/signal_64.c')
-rw-r--r--arch/sparc/kernel/signal_64.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index a2b81598d905..f0836cd0e2f2 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -529,11 +529,27 @@ 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 * Although it should be the case that most of the global
537 * registers are volatile across a system call, glibc already
538 * depends upon that fact that we preserve them. So we can't
539 * just use any global register to save away the orig_i0 value.
540 *
541 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
542 * preserved across a system call trap by various pieces of
543 * code in glibc.
544 *
545 * %g7 is used as the "thread register". %g6 is not used in
546 * any fixed manner. %g6 is used as a scratch register and
547 * a compiler temporary, but it's value is never used across
548 * a system call. Therefore %g6 is usable for orig_i0 storage.
549 */
532 if (pt_regs_is_syscall(regs) && 550 if (pt_regs_is_syscall(regs) &&
533 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { 551 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
534 restart_syscall = 1; 552 regs->u_regs[UREG_G6] = orig_i0;
535 } else
536 restart_syscall = 0;
537 553
538 if (current_thread_info()->status & TS_RESTORE_SIGMASK) 554 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
539 oldset = &current->saved_sigmask; 555 oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
542 558
543#ifdef CONFIG_COMPAT 559#ifdef CONFIG_COMPAT
544 if (test_thread_flag(TIF_32BIT)) { 560 if (test_thread_flag(TIF_32BIT)) {
545 extern void do_signal32(sigset_t *, struct pt_regs *, 561 extern void do_signal32(sigset_t *, struct pt_regs *);
546 int restart_syscall, 562 do_signal32(oldset, regs);
547 unsigned long orig_i0);
548 do_signal32(oldset, regs, restart_syscall, orig_i0);
549 return; 563 return;
550 } 564 }
551#endif 565#endif
552 566
553 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 567 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
554 568
555 /* If the debugger messes with the program counter, it clears 569 restart_syscall = 0;
556 * the software "in syscall" bit, directing us to not perform 570 if (pt_regs_is_syscall(regs) &&
557 * a syscall restart. 571 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
558 */ 572 restart_syscall = 1;
559 if (restart_syscall && !pt_regs_is_syscall(regs)) 573 orig_i0 = regs->u_regs[UREG_G6];
560 restart_syscall = 0; 574 }
561 575
562 if (signr > 0) { 576 if (signr > 0) {
563 if (restart_syscall) 577 if (restart_syscall)