powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule

Based on an original patch by Valentine Barshak <vbarshak@ru.mvista.com>

Use preempt_schedule_irq to prevent infinite irq-entry and
eventual stack overflow problems with fast-paced IRQ sources.

This kind of problems has been observed on the PASemi Electra IDE
controller. We have to make sure we are soft-disabled before calling
preempt_schedule_irq and hard disable interrupts after that
to avoid unrecoverable exceptions.

This patch also moves the "clrrdi r9,r1,THREAD_SHIFT" out of
the #ifdef CONFIG_PPC_BOOK3E scope, since r9 is clobbered
and has to be restored in both cases.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 01deab98
...@@ -658,42 +658,43 @@ do_work: ...@@ -658,42 +658,43 @@ do_work:
cmpdi r0,0 cmpdi r0,0
crandc eq,cr1*4+eq,eq crandc eq,cr1*4+eq,eq
bne restore bne restore
/* here we are preempting the current task */
1: /* Here we are preempting the current task.
#ifdef CONFIG_TRACE_IRQFLAGS *
bl .trace_hardirqs_on * Ensure interrupts are soft-disabled. We also properly mark
/* Note: we just clobbered r10 which used to contain the previous * the PACA to reflect the fact that they are hard-disabled
* MSR before the hard-disabling done by the caller of do_work. * and trace the change
* We don't have that value anymore, but it doesn't matter as
* we will hard-enable unconditionally, we can just reload the
* current MSR into r10
*/ */
mfmsr r10 li r0,0
#endif /* CONFIG_TRACE_IRQFLAGS */
li r0,1
stb r0,PACASOFTIRQEN(r13) stb r0,PACASOFTIRQEN(r13)
stb r0,PACAHARDIRQEN(r13) stb r0,PACAHARDIRQEN(r13)
TRACE_DISABLE_INTS
/* Call the scheduler with soft IRQs off */
1: bl .preempt_schedule_irq
/* Hard-disable interrupts again (and update PACA) */
#ifdef CONFIG_PPC_BOOK3E #ifdef CONFIG_PPC_BOOK3E
wrteei 1
bl .preempt_schedule
wrteei 0 wrteei 0
#else #else
ori r10,r10,MSR_EE
mtmsrd r10,1 /* reenable interrupts */
bl .preempt_schedule
mfmsr r10 mfmsr r10
clrrdi r9,r1,THREAD_SHIFT rldicl r10,r10,48,1
rldicl r10,r10,48,1 /* disable interrupts again */
rotldi r10,r10,16 rotldi r10,r10,16
mtmsrd r10,1 mtmsrd r10,1
#endif /* CONFIG_PPC_BOOK3E */ #endif /* CONFIG_PPC_BOOK3E */
li r0,0
stb r0,PACAHARDIRQEN(r13)
/* Re-test flags and eventually loop */
clrrdi r9,r1,THREAD_SHIFT
ld r4,TI_FLAGS(r9) ld r4,TI_FLAGS(r9)
andi. r0,r4,_TIF_NEED_RESCHED andi. r0,r4,_TIF_NEED_RESCHED
bne 1b bne 1b
b restore b restore
user_work: user_work:
#endif #endif /* CONFIG_PREEMPT */
/* Enable interrupts */ /* Enable interrupts */
#ifdef CONFIG_PPC_BOOK3E #ifdef CONFIG_PPC_BOOK3E
wrteei 1 wrteei 1
......
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