aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-11-14 23:32:16 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-14 23:43:07 -0500
commit1d299bc7732c34d85bd43ac1a8745f5a2fed2078 (patch)
tree6a39fe975dd6c18ab0e5efda38ac0a5c04c62863 /arch/sparc/kernel
parent9ff03b392fa34f6d549fbb56bf05d8a0483aa818 (diff)
sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls.
Although we provide a proper way for a debugger to control whether syscall restart occurs, we run into problems because orig_i0 is not saved and restored properly. Luckily we can solve this problem without having to make debuggers aware of the issue. Across system calls, several registers are considered volatile and can be safely clobbered. Therefore we use the pt_regs save area of one of those registers, %g2, as a place to save and restore orig_i0. Debuggers transparently will do the right thing because they save and restore this register already. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-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)