Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
arch/tile: handle rt_sigreturn() more cleanly
arch/tile: handle CLONE_SETTLS in copy_thread(), not user space

+37 -13
+1 -1
arch/tile/include/asm/signal.h
··· 25 26 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 27 struct pt_regs; 28 - int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); 29 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); 30 void do_signal(struct pt_regs *regs); 31 #endif
··· 25 26 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 27 struct pt_regs; 28 + int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); 29 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); 30 void do_signal(struct pt_regs *regs); 31 #endif
+3 -3
arch/tile/kernel/compat_signal.c
··· 290 return ret; 291 } 292 293 long compat_sys_rt_sigreturn(struct pt_regs *regs) 294 { 295 struct compat_rt_sigframe __user *frame = 296 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); 297 sigset_t set; 298 - long r0; 299 300 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 301 goto badframe; ··· 308 recalc_sigpending(); 309 spin_unlock_irq(&current->sighand->siglock); 310 311 - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) 312 goto badframe; 313 314 if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) 315 goto badframe; 316 317 - return r0; 318 319 badframe: 320 force_sig(SIGSEGV, current);
··· 290 return ret; 291 } 292 293 + /* The assembly shim for this function arranges to ignore the return value. */ 294 long compat_sys_rt_sigreturn(struct pt_regs *regs) 295 { 296 struct compat_rt_sigframe __user *frame = 297 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); 298 sigset_t set; 299 300 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 301 goto badframe; ··· 308 recalc_sigpending(); 309 spin_unlock_irq(&current->sighand->siglock); 310 311 + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 312 goto badframe; 313 314 if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) 315 goto badframe; 316 317 + return 0; 318 319 badframe: 320 force_sig(SIGSEGV, current);
+21 -3
arch/tile/kernel/intvec_32.S
··· 1342 lw r20, r20 1343 1344 /* Jump to syscall handler. */ 1345 - jalr r20; .Lhandle_syscall_link: 1346 - FEEDBACK_REENTER(handle_syscall) 1347 1348 /* 1349 * Write our r0 onto the stack so it gets restored instead ··· 1351 */ 1352 PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) 1353 sw r29, r0 1354 1355 /* Do syscall trace again, if requested. */ 1356 lw r30, r31 ··· 1539 }; \ 1540 STD_ENDPROC(_##x) 1541 1542 PTREGS_SYSCALL(sys_execve, r3) 1543 PTREGS_SYSCALL(sys_sigaltstack, r2) 1544 - PTREGS_SYSCALL(sys_rt_sigreturn, r0) 1545 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) 1546 1547 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
··· 1342 lw r20, r20 1343 1344 /* Jump to syscall handler. */ 1345 + jalr r20 1346 + .Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ 1347 1348 /* 1349 * Write our r0 onto the stack so it gets restored instead ··· 1351 */ 1352 PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) 1353 sw r29, r0 1354 + 1355 + .Lsyscall_sigreturn_skip: 1356 + FEEDBACK_REENTER(handle_syscall) 1357 1358 /* Do syscall trace again, if requested. */ 1359 lw r30, r31 ··· 1536 }; \ 1537 STD_ENDPROC(_##x) 1538 1539 + /* 1540 + * Special-case sigreturn to not write r0 to the stack on return. 1541 + * This is technically more efficient, but it also avoids difficulties 1542 + * in the 64-bit OS when handling 32-bit compat code, since we must not 1543 + * sign-extend r0 for the sigreturn return-value case. 1544 + */ 1545 + #define PTREGS_SYSCALL_SIGRETURN(x, reg) \ 1546 + STD_ENTRY(_##x); \ 1547 + addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ 1548 + { \ 1549 + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ 1550 + j x \ 1551 + }; \ 1552 + STD_ENDPROC(_##x) 1553 + 1554 PTREGS_SYSCALL(sys_execve, r3) 1555 PTREGS_SYSCALL(sys_sigaltstack, r2) 1556 + PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) 1557 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) 1558 1559 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+8
arch/tile/kernel/process.c
··· 212 childregs->sp = sp; /* override with new user stack pointer */ 213 214 /* 215 * Copy the callee-saved registers from the passed pt_regs struct 216 * into the context-switch callee-saved registers area. 217 * This way when we start the interrupt-return sequence, the ··· 546 return __switch_to(prev, next, next_current_ksp0(next)); 547 } 548 549 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, 550 void __user *, parent_tidptr, void __user *, child_tidptr, 551 struct pt_regs *, regs)
··· 212 childregs->sp = sp; /* override with new user stack pointer */ 213 214 /* 215 + * If CLONE_SETTLS is set, set "tp" in the new task to "r4", 216 + * which is passed in as arg #5 to sys_clone(). 217 + */ 218 + if (clone_flags & CLONE_SETTLS) 219 + childregs->tp = regs->regs[4]; 220 + 221 + /* 222 * Copy the callee-saved registers from the passed pt_regs struct 223 * into the context-switch callee-saved registers area. 224 * This way when we start the interrupt-return sequence, the ··· 539 return __switch_to(prev, next, next_current_ksp0(next)); 540 } 541 542 + /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ 543 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, 544 void __user *, parent_tidptr, void __user *, child_tidptr, 545 struct pt_regs *, regs)
+4 -6
arch/tile/kernel/signal.c
··· 52 */ 53 54 int restore_sigcontext(struct pt_regs *regs, 55 - struct sigcontext __user *sc, long *pr0) 56 { 57 int err = 0; 58 int i; ··· 75 76 regs->faultnum = INT_SWINT_1_SIGRETURN; 77 78 - err |= __get_user(*pr0, &sc->gregs[0]); 79 return err; 80 } 81 82 - /* sigreturn() returns long since it restores r0 in the interrupted code. */ 83 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) 84 { 85 struct rt_sigframe __user *frame = 86 (struct rt_sigframe __user *)(regs->sp); 87 sigset_t set; 88 - long r0; 89 90 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 91 goto badframe; ··· 96 recalc_sigpending(); 97 spin_unlock_irq(&current->sighand->siglock); 98 99 - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) 100 goto badframe; 101 102 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) 103 goto badframe; 104 105 - return r0; 106 107 badframe: 108 force_sig(SIGSEGV, current);
··· 52 */ 53 54 int restore_sigcontext(struct pt_regs *regs, 55 + struct sigcontext __user *sc) 56 { 57 int err = 0; 58 int i; ··· 75 76 regs->faultnum = INT_SWINT_1_SIGRETURN; 77 78 return err; 79 } 80 81 + /* The assembly shim for this function arranges to ignore the return value. */ 82 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) 83 { 84 struct rt_sigframe __user *frame = 85 (struct rt_sigframe __user *)(regs->sp); 86 sigset_t set; 87 88 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 89 goto badframe; ··· 98 recalc_sigpending(); 99 spin_unlock_irq(&current->sighand->siglock); 100 101 + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 102 goto badframe; 103 104 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) 105 goto badframe; 106 107 + return 0; 108 109 badframe: 110 force_sig(SIGSEGV, current);