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