diff options
| -rw-r--r-- | arch/tile/include/asm/signal.h | 2 | ||||
| -rw-r--r-- | arch/tile/kernel/compat_signal.c | 6 | ||||
| -rw-r--r-- | arch/tile/kernel/intvec_32.S | 24 | ||||
| -rw-r--r-- | arch/tile/kernel/signal.c | 10 |
4 files changed, 29 insertions, 13 deletions
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index c1ee1d61d44..81d92a45cd4 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
| 27 | struct pt_regs; | 27 | struct pt_regs; |
| 28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); | 28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); |
| 29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); | 29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); |
| 30 | void do_signal(struct pt_regs *regs); | 30 | void do_signal(struct pt_regs *regs); |
| 31 | #endif | 31 | #endif |
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 543d6a33aa2..dbb0dfc7bec 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
| @@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
| 290 | return ret; | 290 | return ret; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | /* The assembly shim for this function arranges to ignore the return value. */ | ||
| 293 | long compat_sys_rt_sigreturn(struct pt_regs *regs) | 294 | long compat_sys_rt_sigreturn(struct pt_regs *regs) |
| 294 | { | 295 | { |
| 295 | struct compat_rt_sigframe __user *frame = | 296 | struct compat_rt_sigframe __user *frame = |
| 296 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); | 297 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); |
| 297 | sigset_t set; | 298 | sigset_t set; |
| 298 | long r0; | ||
| 299 | 299 | ||
| 300 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 300 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 301 | goto badframe; | 301 | goto badframe; |
| @@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) | |||
| 308 | recalc_sigpending(); | 308 | recalc_sigpending(); |
| 309 | spin_unlock_irq(¤t->sighand->siglock); | 309 | spin_unlock_irq(¤t->sighand->siglock); |
| 310 | 310 | ||
| 311 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 311 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
| 312 | goto badframe; | 312 | goto badframe; |
| 313 | 313 | ||
| 314 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) | 314 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) |
| 315 | goto badframe; | 315 | goto badframe; |
| 316 | 316 | ||
| 317 | return r0; | 317 | return 0; |
| 318 | 318 | ||
| 319 | badframe: | 319 | badframe: |
| 320 | force_sig(SIGSEGV, current); | 320 | force_sig(SIGSEGV, current); |
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index f5821626247..5eed4a02bf6 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
| @@ -1342,8 +1342,8 @@ handle_syscall: | |||
| 1342 | lw r20, r20 | 1342 | lw r20, r20 |
| 1343 | 1343 | ||
| 1344 | /* Jump to syscall handler. */ | 1344 | /* Jump to syscall handler. */ |
| 1345 | jalr r20; .Lhandle_syscall_link: | 1345 | jalr r20 |
| 1346 | FEEDBACK_REENTER(handle_syscall) | 1346 | .Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ |
| 1347 | 1347 | ||
| 1348 | /* | 1348 | /* |
| 1349 | * Write our r0 onto the stack so it gets restored instead | 1349 | * Write our r0 onto the stack so it gets restored instead |
| @@ -1352,6 +1352,9 @@ handle_syscall: | |||
| 1352 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) | 1352 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) |
| 1353 | sw r29, r0 | 1353 | sw r29, r0 |
| 1354 | 1354 | ||
| 1355 | .Lsyscall_sigreturn_skip: | ||
| 1356 | FEEDBACK_REENTER(handle_syscall) | ||
| 1357 | |||
| 1355 | /* Do syscall trace again, if requested. */ | 1358 | /* Do syscall trace again, if requested. */ |
| 1356 | lw r30, r31 | 1359 | lw r30, r31 |
| 1357 | andi r30, r30, _TIF_SYSCALL_TRACE | 1360 | andi r30, r30, _TIF_SYSCALL_TRACE |
| @@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr) | |||
| 1536 | }; \ | 1539 | }; \ |
| 1537 | STD_ENDPROC(_##x) | 1540 | STD_ENDPROC(_##x) |
| 1538 | 1541 | ||
| 1542 | /* | ||
| 1543 | * Special-case sigreturn to not write r0 to the stack on return. | ||
| 1544 | * This is technically more efficient, but it also avoids difficulties | ||
| 1545 | * in the 64-bit OS when handling 32-bit compat code, since we must not | ||
| 1546 | * sign-extend r0 for the sigreturn return-value case. | ||
| 1547 | */ | ||
| 1548 | #define PTREGS_SYSCALL_SIGRETURN(x, reg) \ | ||
| 1549 | STD_ENTRY(_##x); \ | ||
| 1550 | addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ | ||
| 1551 | { \ | ||
| 1552 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
| 1553 | j x \ | ||
| 1554 | }; \ | ||
| 1555 | STD_ENDPROC(_##x) | ||
| 1556 | |||
| 1539 | PTREGS_SYSCALL(sys_execve, r3) | 1557 | PTREGS_SYSCALL(sys_execve, r3) |
| 1540 | PTREGS_SYSCALL(sys_sigaltstack, r2) | 1558 | PTREGS_SYSCALL(sys_sigaltstack, r2) |
| 1541 | PTREGS_SYSCALL(sys_rt_sigreturn, r0) | 1559 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
| 1542 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) | 1560 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) |
| 1543 | 1561 | ||
| 1544 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1562 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 757407e3669..1260321155f 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
| @@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, | |||
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | int restore_sigcontext(struct pt_regs *regs, | 54 | int restore_sigcontext(struct pt_regs *regs, |
| 55 | struct sigcontext __user *sc, long *pr0) | 55 | struct sigcontext __user *sc) |
| 56 | { | 56 | { |
| 57 | int err = 0; | 57 | int err = 0; |
| 58 | int i; | 58 | int i; |
| @@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs, | |||
| 75 | 75 | ||
| 76 | regs->faultnum = INT_SWINT_1_SIGRETURN; | 76 | regs->faultnum = INT_SWINT_1_SIGRETURN; |
| 77 | 77 | ||
| 78 | err |= __get_user(*pr0, &sc->gregs[0]); | ||
| 79 | return err; | 78 | return err; |
| 80 | } | 79 | } |
| 81 | 80 | ||
| 82 | /* sigreturn() returns long since it restores r0 in the interrupted code. */ | 81 | /* The assembly shim for this function arranges to ignore the return value. */ |
| 83 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | 82 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) |
| 84 | { | 83 | { |
| 85 | struct rt_sigframe __user *frame = | 84 | struct rt_sigframe __user *frame = |
| 86 | (struct rt_sigframe __user *)(regs->sp); | 85 | (struct rt_sigframe __user *)(regs->sp); |
| 87 | sigset_t set; | 86 | sigset_t set; |
| 88 | long r0; | ||
| 89 | 87 | ||
| 90 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 88 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 91 | goto badframe; | 89 | goto badframe; |
| @@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | |||
| 98 | recalc_sigpending(); | 96 | recalc_sigpending(); |
| 99 | spin_unlock_irq(¤t->sighand->siglock); | 97 | spin_unlock_irq(¤t->sighand->siglock); |
| 100 | 98 | ||
| 101 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 99 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
| 102 | goto badframe; | 100 | goto badframe; |
| 103 | 101 | ||
| 104 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) | 102 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) |
| 105 | goto badframe; | 103 | goto badframe; |
| 106 | 104 | ||
| 107 | return r0; | 105 | return 0; |
| 108 | 106 | ||
| 109 | badframe: | 107 | badframe: |
| 110 | force_sig(SIGSEGV, current); | 108 | force_sig(SIGSEGV, current); |
