Commit 39d6411b authored by Linus Torvalds's avatar Linus Torvalds

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 74fca9da to the compat signal handling as well
  arch/tile: fix up some issues in calling do_work_pending()
parents 80116529 a134d228
...@@ -100,9 +100,14 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti, ...@@ -100,9 +100,14 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti,
#else /* __ASSEMBLY__ */ #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__ #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 #else
#define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31 #define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31
#endif #endif
......
...@@ -403,19 +403,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -403,19 +403,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Set up registers for signal handler. * Set up registers for signal handler.
* Registers that we don't modify keep the value they had from * Registers that we don't modify keep the value they had from
* user-space at the time we took the signal. * 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->pc = ptr_to_compat_reg(ka->sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame); regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer; regs->lr = restorer;
regs->regs[0] = (unsigned long) usig; regs->regs[0] = (unsigned long) usig;
regs->regs[1] = ptr_to_compat_reg(&frame->info);
if (ka->sa.sa_flags & SA_SIGINFO) { regs->regs[2] = ptr_to_compat_reg(&frame->uc);
/* Need extra arguments, so mark to restore caller-saves. */ 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. * Notify any tracer that was single-stepping it.
......
...@@ -838,6 +838,18 @@ STD_ENTRY(interrupt_return) ...@@ -838,6 +838,18 @@ STD_ENTRY(interrupt_return)
.Lresume_userspace: .Lresume_userspace:
FEEDBACK_REENTER(interrupt_return) 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 * Disable interrupts so as to make sure we don't
* miss an interrupt that sets any of the thread flags (like * miss an interrupt that sets any of the thread flags (like
...@@ -848,9 +860,6 @@ STD_ENTRY(interrupt_return) ...@@ -848,9 +860,6 @@ STD_ENTRY(interrupt_return)
IRQ_DISABLE(r20, r21) IRQ_DISABLE(r20, r21)
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ 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. */ /* Check to see if there is any work to do before returning to user. */
{ {
...@@ -866,16 +875,18 @@ STD_ENTRY(interrupt_return) ...@@ -866,16 +875,18 @@ STD_ENTRY(interrupt_return)
/* /*
* Make sure we have all the registers saved for signal * Make sure we have all the registers saved for signal
* handling or single-step. Call out to C code to figure out * handling, notify-resume, or single-step. Call out to C
* exactly what we need to do for each flag bit, then if * code to figure out exactly what we need to do for each flag bit,
* necessary, reload the flags and recheck. * then if necessary, reload the flags and recheck.
*/ */
push_extra_callee_saves r0
{ {
PTREGS_PTR(r0, PTREGS_OFFSET_BASE) 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 * In the NMI case we
...@@ -1180,10 +1191,12 @@ handle_syscall: ...@@ -1180,10 +1191,12 @@ handle_syscall:
add r20, r20, tp add r20, r20, tp
lw r21, r20 lw r21, r20
addi r21, r21, 1 addi r21, r21, 1
sw r20, r21 {
sw r20, r21
GET_THREAD_INFO(r31)
}
/* Trace syscalls, if requested. */ /* Trace syscalls, if requested. */
GET_THREAD_INFO(r31)
addi r31, r31, THREAD_INFO_FLAGS_OFFSET addi r31, r31, THREAD_INFO_FLAGS_OFFSET
lw r30, r31 lw r30, r31
andi r30, r30, _TIF_SYSCALL_TRACE andi r30, r30, _TIF_SYSCALL_TRACE
...@@ -1362,7 +1375,10 @@ handle_ill: ...@@ -1362,7 +1375,10 @@ handle_ill:
3: 3:
/* set PC and continue */ /* set PC and continue */
lw r26, r24 lw r26, r24
sw r28, r26 {
sw r28, r26
GET_THREAD_INFO(r0)
}
/* /*
* Clear TIF_SINGLESTEP to prevent recursion if we execute an ill. * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
...@@ -1370,7 +1386,6 @@ handle_ill: ...@@ -1370,7 +1386,6 @@ handle_ill:
* need to clear it here and can't really impose on all other arches. * need to clear it here and can't really impose on all other arches.
* So what's another write between friends? * So what's another write between friends?
*/ */
GET_THREAD_INFO(r0)
addi r1, r0, THREAD_INFO_FLAGS_OFFSET addi r1, r0, THREAD_INFO_FLAGS_OFFSET
{ {
......
...@@ -646,6 +646,20 @@ STD_ENTRY(interrupt_return) ...@@ -646,6 +646,20 @@ STD_ENTRY(interrupt_return)
.Lresume_userspace: .Lresume_userspace:
FEEDBACK_REENTER(interrupt_return) 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 * Disable interrupts so as to make sure we don't
* miss an interrupt that sets any of the thread flags (like * miss an interrupt that sets any of the thread flags (like
...@@ -656,9 +670,6 @@ STD_ENTRY(interrupt_return) ...@@ -656,9 +670,6 @@ STD_ENTRY(interrupt_return)
IRQ_DISABLE(r20, r21) IRQ_DISABLE(r20, r21)
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ 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. */ /* Check to see if there is any work to do before returning to user. */
{ {
...@@ -674,16 +685,18 @@ STD_ENTRY(interrupt_return) ...@@ -674,16 +685,18 @@ STD_ENTRY(interrupt_return)
/* /*
* Make sure we have all the registers saved for signal * 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 * exactly what we need to do for each flag bit, then if
* necessary, reload the flags and recheck. * necessary, reload the flags and recheck.
*/ */
push_extra_callee_saves r0
{ {
PTREGS_PTR(r0, PTREGS_OFFSET_BASE) 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 * In the NMI case we
...@@ -968,11 +981,16 @@ handle_syscall: ...@@ -968,11 +981,16 @@ handle_syscall:
shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET)
add r20, r20, tp add r20, r20, tp
ld4s r21, r20 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. */ /* Trace syscalls, if requested. */
GET_THREAD_INFO(r31)
addi r31, r31, THREAD_INFO_FLAGS_OFFSET addi r31, r31, THREAD_INFO_FLAGS_OFFSET
ld r30, r31 ld r30, r31
andi r30, r30, _TIF_SYSCALL_TRACE andi r30, r30, _TIF_SYSCALL_TRACE
......
...@@ -567,6 +567,10 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, ...@@ -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) 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) { if (thread_info_flags & _TIF_NEED_RESCHED) {
schedule(); schedule();
return 1; return 1;
...@@ -589,8 +593,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) ...@@ -589,8 +593,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
return 1; return 1;
} }
if (thread_info_flags & _TIF_SINGLESTEP) { 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; return 0;
} }
panic("work_pending: bad flags %#x\n", thread_info_flags); panic("work_pending: bad flags %#x\n", thread_info_flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment