diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/ptrace.c | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/rtrap.S | 11 | ||||
-rw-r--r-- | arch/sparc/kernel/signal.c | 64 |
4 files changed, 40 insertions, 41 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 57d1bbdd0bd2..4bcfe54f878d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -1306,6 +1306,8 @@ ret_from_fork: | |||
1306 | .align 4 | 1306 | .align 4 |
1307 | .globl linux_sparc_syscall | 1307 | .globl linux_sparc_syscall |
1308 | linux_sparc_syscall: | 1308 | linux_sparc_syscall: |
1309 | sethi %hi(PSR_SYSCALL), %l4 | ||
1310 | or %l0, %l4, %l0 | ||
1309 | /* Direct access to user regs, must faster. */ | 1311 | /* Direct access to user regs, must faster. */ |
1310 | cmp %g1, NR_SYSCALLS | 1312 | cmp %g1, NR_SYSCALLS |
1311 | bgeu linux_sparc_ni_syscall | 1313 | bgeu linux_sparc_ni_syscall |
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 60dfc65549db..81f3b929743f 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c | |||
@@ -170,8 +170,8 @@ static int genregs32_set(struct task_struct *target, | |||
170 | switch (pos) { | 170 | switch (pos) { |
171 | case 32: /* PSR */ | 171 | case 32: /* PSR */ |
172 | psr = regs->psr; | 172 | psr = regs->psr; |
173 | psr &= ~PSR_ICC; | 173 | psr &= ~(PSR_ICC | PSR_SYSCALL); |
174 | psr |= (reg & PSR_ICC); | 174 | psr |= (reg & (PSR_ICC | PSR_SYSCALL)); |
175 | regs->psr = psr; | 175 | regs->psr = psr; |
176 | break; | 176 | break; |
177 | case 33: /* PC */ | 177 | case 33: /* PC */ |
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index 77ca6fd81253..b27b5b56f77a 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S | |||
@@ -50,8 +50,9 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1 | |||
50 | ret_trap_entry: | 50 | ret_trap_entry: |
51 | ret_trap_lockless_ipi: | 51 | ret_trap_lockless_ipi: |
52 | andcc %t_psr, PSR_PS, %g0 | 52 | andcc %t_psr, PSR_PS, %g0 |
53 | sethi %hi(PSR_SYSCALL), %g1 | ||
53 | be 1f | 54 | be 1f |
54 | nop | 55 | andn %t_psr, %g1, %t_psr |
55 | 56 | ||
56 | wr %t_psr, 0x0, %psr | 57 | wr %t_psr, 0x0, %psr |
57 | b ret_trap_kernel | 58 | b ret_trap_kernel |
@@ -73,7 +74,6 @@ signal_p: | |||
73 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr | 74 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr |
74 | 75 | ||
75 | mov %l5, %o1 | 76 | mov %l5, %o1 |
76 | mov %l6, %o2 | ||
77 | call do_signal | 77 | call do_signal |
78 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr | 78 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr |
79 | 79 | ||
@@ -81,6 +81,8 @@ signal_p: | |||
81 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr | 81 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr |
82 | clr %l6 | 82 | clr %l6 |
83 | ret_trap_continue: | 83 | ret_trap_continue: |
84 | sethi %hi(PSR_SYSCALL), %g1 | ||
85 | andn %t_psr, %g1, %t_psr | ||
84 | wr %t_psr, 0x0, %psr | 86 | wr %t_psr, 0x0, %psr |
85 | WRITE_PAUSE | 87 | WRITE_PAUSE |
86 | 88 | ||
@@ -137,8 +139,9 @@ ret_trap_userwins_ok: | |||
137 | LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) | 139 | LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) |
138 | or %t_pc, %t_npc, %g2 | 140 | or %t_pc, %t_npc, %g2 |
139 | andcc %g2, 0x3, %g0 | 141 | andcc %g2, 0x3, %g0 |
142 | sethi %hi(PSR_SYCALL), %g2 | ||
140 | be 1f | 143 | be 1f |
141 | nop | 144 | andn %t_psr, %g2, %t_psr |
142 | 145 | ||
143 | b ret_trap_unaligned_pc | 146 | b ret_trap_unaligned_pc |
144 | add %sp, STACKFRAME_SZ, %o0 | 147 | add %sp, STACKFRAME_SZ, %o0 |
@@ -201,6 +204,8 @@ rtrap_patch5: and %g1, 0xff, %g1 | |||
201 | 1: | 204 | 1: |
202 | LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) | 205 | LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) |
203 | 2: | 206 | 2: |
207 | sethi %hi(PSR_SYSCALL), %twin_tmp1 | ||
208 | andn %t_psr, %twin_tmp1, %t_psr | ||
204 | wr %t_psr, 0x0, %psr | 209 | wr %t_psr, 0x0, %psr |
205 | WRITE_PAUSE | 210 | WRITE_PAUSE |
206 | 211 | ||
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 | */ |
510 | asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) | 516 | asmlinkage 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 = ¤t->saved_sigmask; | 530 | oldset = ¤t->saved_sigmask; |
523 | else | 531 | else |
524 | oldset = ¤t->blocked; | 532 | oldset = ¤t->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, | |||
599 | out: | 615 | out: |
600 | return ret; | 616 | return ret; |
601 | } | 617 | } |
602 | |||
603 | void 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 | } | ||