diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/signal32.c | 18 | ||||
-rw-r--r-- | arch/sparc/kernel/signal_32.c | 20 | ||||
-rw-r--r-- | arch/sparc/kernel/signal_64.c | 32 |
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 | */ |
825 | void do_signal32(sigset_t *oldset, struct pt_regs * regs, | 825 | void 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 = ¤t->saved_sigmask; | 534 | oldset = ¤t->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 = ¤t->saved_sigmask; | 545 | oldset = ¤t->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) |