Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

Pull two Tile arch fixes from Chris Metcalf:
 "These are both bug-fixes, one to avoid some issues in how we invoke
  the "pending userspace work" flags on return to userspace, and the
  other to provide the same signal handler arguments for tilegx32 that
  we do for tilegx64."

* 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  arch/tile: apply commit 74fca9da0 to the compat signal handling as well
  arch/tile: fix up some issues in calling do_work_pending()
This commit is contained in:
Linus Torvalds 2012-05-16 14:21:41 -07:00
commit 39d6411b7d
5 changed files with 73 additions and 34 deletions

View file

@ -100,9 +100,14 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti,
#else /* __ASSEMBLY__ */
/* how to get the thread information struct from ASM */
/*
* How to get the thread information struct from assembly.
* Note that we use different macros since different architectures
* have different semantics in their "mm" instruction and we would
* like to guarantee that the macro expands to exactly one instruction.
*/
#ifdef __tilegx__
#define GET_THREAD_INFO(reg) move reg, sp; mm reg, zero, LOG2_THREAD_SIZE, 63
#define EXTRACT_THREAD_INFO(reg) mm reg, zero, LOG2_THREAD_SIZE, 63
#else
#define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31
#endif

View file

@ -403,19 +403,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Set up registers for signal handler.
* Registers that we don't modify keep the value they had from
* user-space at the time we took the signal.
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c).
*/
regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer;
regs->regs[0] = (unsigned long) usig;
if (ka->sa.sa_flags & SA_SIGINFO) {
/* Need extra arguments, so mark to restore caller-saves. */
regs->regs[1] = ptr_to_compat_reg(&frame->info);
regs->regs[2] = ptr_to_compat_reg(&frame->uc);
regs->flags |= PT_FLAGS_CALLER_SAVES;
}
regs->regs[1] = ptr_to_compat_reg(&frame->info);
regs->regs[2] = ptr_to_compat_reg(&frame->uc);
regs->flags |= PT_FLAGS_CALLER_SAVES;
/*
* Notify any tracer that was single-stepping it.

View file

@ -838,6 +838,18 @@ STD_ENTRY(interrupt_return)
.Lresume_userspace:
FEEDBACK_REENTER(interrupt_return)
/*
* Use r33 to hold whether we have already loaded the callee-saves
* into ptregs. We don't want to do it twice in this loop, since
* then we'd clobber whatever changes are made by ptrace, etc.
* Get base of stack in r32.
*/
{
GET_THREAD_INFO(r32)
movei r33, 0
}
.Lretry_work_pending:
/*
* Disable interrupts so as to make sure we don't
* miss an interrupt that sets any of the thread flags (like
@ -848,9 +860,6 @@ STD_ENTRY(interrupt_return)
IRQ_DISABLE(r20, r21)
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */
/* Get base of stack in r32; note r30/31 are used as arguments here. */
GET_THREAD_INFO(r32)
/* Check to see if there is any work to do before returning to user. */
{
@ -866,16 +875,18 @@ STD_ENTRY(interrupt_return)
/*
* Make sure we have all the registers saved for signal
* handling or single-step. Call out to C code to figure out
* exactly what we need to do for each flag bit, then if
* necessary, reload the flags and recheck.
* handling, notify-resume, or single-step. Call out to C
* code to figure out exactly what we need to do for each flag bit,
* then if necessary, reload the flags and recheck.
*/
push_extra_callee_saves r0
{
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
jal do_work_pending
bnz r33, 1f
}
bnz r0, .Lresume_userspace
push_extra_callee_saves r0
movei r33, 1
1: jal do_work_pending
bnz r0, .Lretry_work_pending
/*
* In the NMI case we
@ -1180,10 +1191,12 @@ handle_syscall:
add r20, r20, tp
lw r21, r20
addi r21, r21, 1
sw r20, r21
{
sw r20, r21
GET_THREAD_INFO(r31)
}
/* Trace syscalls, if requested. */
GET_THREAD_INFO(r31)
addi r31, r31, THREAD_INFO_FLAGS_OFFSET
lw r30, r31
andi r30, r30, _TIF_SYSCALL_TRACE
@ -1362,7 +1375,10 @@ handle_ill:
3:
/* set PC and continue */
lw r26, r24
sw r28, r26
{
sw r28, r26
GET_THREAD_INFO(r0)
}
/*
* Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
@ -1370,7 +1386,6 @@ handle_ill:
* need to clear it here and can't really impose on all other arches.
* So what's another write between friends?
*/
GET_THREAD_INFO(r0)
addi r1, r0, THREAD_INFO_FLAGS_OFFSET
{

View file

@ -646,6 +646,20 @@ STD_ENTRY(interrupt_return)
.Lresume_userspace:
FEEDBACK_REENTER(interrupt_return)
/*
* Use r33 to hold whether we have already loaded the callee-saves
* into ptregs. We don't want to do it twice in this loop, since
* then we'd clobber whatever changes are made by ptrace, etc.
*/
{
movei r33, 0
move r32, sp
}
/* Get base of stack in r32. */
EXTRACT_THREAD_INFO(r32)
.Lretry_work_pending:
/*
* Disable interrupts so as to make sure we don't
* miss an interrupt that sets any of the thread flags (like
@ -656,9 +670,6 @@ STD_ENTRY(interrupt_return)
IRQ_DISABLE(r20, r21)
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */
/* Get base of stack in r32; note r30/31 are used as arguments here. */
GET_THREAD_INFO(r32)
/* Check to see if there is any work to do before returning to user. */
{
@ -674,16 +685,18 @@ STD_ENTRY(interrupt_return)
/*
* Make sure we have all the registers saved for signal
* handling or single-step. Call out to C code to figure out
* handling or notify-resume. Call out to C code to figure out
* exactly what we need to do for each flag bit, then if
* necessary, reload the flags and recheck.
*/
push_extra_callee_saves r0
{
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
jal do_work_pending
bnez r33, 1f
}
bnez r0, .Lresume_userspace
push_extra_callee_saves r0
movei r33, 1
1: jal do_work_pending
bnez r0, .Lretry_work_pending
/*
* In the NMI case we
@ -968,11 +981,16 @@ handle_syscall:
shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET)
add r20, r20, tp
ld4s r21, r20
addi r21, r21, 1
st4 r20, r21
{
addi r21, r21, 1
move r31, sp
}
{
st4 r20, r21
EXTRACT_THREAD_INFO(r31)
}
/* Trace syscalls, if requested. */
GET_THREAD_INFO(r31)
addi r31, r31, THREAD_INFO_FLAGS_OFFSET
ld r30, r31
andi r30, r30, _TIF_SYSCALL_TRACE

View file

@ -567,6 +567,10 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
*/
int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
{
/* If we enter in kernel mode, do nothing and exit the caller loop. */
if (!user_mode(regs))
return 0;
if (thread_info_flags & _TIF_NEED_RESCHED) {
schedule();
return 1;
@ -589,8 +593,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
return 1;
}
if (thread_info_flags & _TIF_SINGLESTEP) {
if ((regs->ex1 & SPR_EX_CONTEXT_1_1__PL_MASK) == 0)
single_step_once(regs);
single_step_once(regs);
return 0;
}
panic("work_pending: bad flags %#x\n", thread_info_flags);