Permalink
Browse files

Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/gi…

…t/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 74fca9d to the compat signal handling as well
  arch/tile: fix up some issues in calling do_work_pending()
  • Loading branch information...
2 parents 8011652 + a134d22 commit 39d6411b7df566715138c8c9f7fa00227f4ae75b @torvalds torvalds committed May 16, 2012
@@ -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
@@ -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.
@@ -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,15 +1375,17 @@ 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.
* The normal non-arch flow redundantly clears TIF_SINGLESTEP, but we
* 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
{
@@ -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
@@ -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);

0 comments on commit 39d6411

Please sign in to comment.