Skip to content

Commit 0a59228

Browse files
committed
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
2 parents 2ba16c4 + 81711ce commit 0a59228

File tree

5 files changed

+37
-13
lines changed

5 files changed

+37
-13
lines changed

arch/tile/include/asm/signal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
2727
struct pt_regs;
28-
int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
28+
int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
2929
int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
3030
void do_signal(struct pt_regs *regs);
3131
#endif

arch/tile/kernel/compat_signal.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
290290
return ret;
291291
}
292292

293+
/* The assembly shim for this function arranges to ignore the return value. */
293294
long compat_sys_rt_sigreturn(struct pt_regs *regs)
294295
{
295296
struct compat_rt_sigframe __user *frame =
296297
(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
297298
sigset_t set;
298-
long r0;
299299

300300
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
301301
goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
308308
recalc_sigpending();
309309
spin_unlock_irq(&current->sighand->siglock);
310310

311-
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
311+
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
312312
goto badframe;
313313

314314
if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
315315
goto badframe;
316316

317-
return r0;
317+
return 0;
318318

319319
badframe:
320320
force_sig(SIGSEGV, current);

arch/tile/kernel/intvec_32.S

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,8 +1342,8 @@ handle_syscall:
13421342
lw r20, r20
13431343

13441344
/* 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 */
13471347

13481348
/*
13491349
* Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
13521352
PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
13531353
sw r29, r0
13541354

1355+
.Lsyscall_sigreturn_skip:
1356+
FEEDBACK_REENTER(handle_syscall)
1357+
13551358
/* Do syscall trace again, if requested. */
13561359
lw r30, r31
13571360
andi r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
15361539
}; \
15371540
STD_ENDPROC(_##x)
15381541

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+
15391557
PTREGS_SYSCALL(sys_execve, r3)
15401558
PTREGS_SYSCALL(sys_sigaltstack, r2)
1541-
PTREGS_SYSCALL(sys_rt_sigreturn, r0)
1559+
PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
15421560
PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
15431561

15441562
/* Save additional callee-saves to pt_regs, put address in r4 and jump. */

arch/tile/kernel/process.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
211211
childregs->regs[0] = 0; /* return value is zero */
212212
childregs->sp = sp; /* override with new user stack pointer */
213213

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+
214221
/*
215222
* Copy the callee-saved registers from the passed pt_regs struct
216223
* into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
539546
return __switch_to(prev, next, next_current_ksp0(next));
540547
}
541548

549+
/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
542550
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
543551
void __user *, parent_tidptr, void __user *, child_tidptr,
544552
struct pt_regs *, regs)

arch/tile/kernel/signal.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
5252
*/
5353

5454
int restore_sigcontext(struct pt_regs *regs,
55-
struct sigcontext __user *sc, long *pr0)
55+
struct sigcontext __user *sc)
5656
{
5757
int err = 0;
5858
int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
7575

7676
regs->faultnum = INT_SWINT_1_SIGRETURN;
7777

78-
err |= __get_user(*pr0, &sc->gregs[0]);
7978
return err;
8079
}
8180

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. */
8382
SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
8483
{
8584
struct rt_sigframe __user *frame =
8685
(struct rt_sigframe __user *)(regs->sp);
8786
sigset_t set;
88-
long r0;
8987

9088
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
9189
goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
9896
recalc_sigpending();
9997
spin_unlock_irq(&current->sighand->siglock);
10098

101-
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
99+
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
102100
goto badframe;
103101

104102
if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
105103
goto badframe;
106104

107-
return r0;
105+
return 0;
108106

109107
badframe:
110108
force_sig(SIGSEGV, current);

0 commit comments

Comments
 (0)