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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
@@ -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
|
||||||
|
Reference in New Issue
Block a user