Commit b333a99e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-5.11-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fix from Michael Ellerman:
 "One fix for a bug in our soft interrupt masking, which could lead to
  interrupt replaying recursing, causing spurious interrupts.

  Thanks to Nicholas Piggin"

* tag 'powerpc-5.11-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/64s: prevent recursive replay_soft_interrupts causing superfluous interrupt
parents 1188866d 4025c784
......@@ -180,13 +180,18 @@ void notrace restore_interrupts(void)
void replay_soft_interrupts(void)
{
struct pt_regs regs;
/*
* We use local_paca rather than get_paca() to avoid all
* the debug_smp_processor_id() business in this low level
* function
* Be careful here, calling these interrupt handlers can cause
* softirqs to be raised, which they may run when calling irq_exit,
* which will cause local_irq_enable() to be run, which can then
* recurse into this function. Don't keep any state across
* interrupt handler calls which may change underneath us.
*
* We use local_paca rather than get_paca() to avoid all the
* debug_smp_processor_id() business in this low level function.
*/
unsigned char happened = local_paca->irq_happened;
struct pt_regs regs;
ppc_save_regs(&regs);
regs.softe = IRQS_ENABLED;
......@@ -209,7 +214,7 @@ void replay_soft_interrupts(void)
* This is a higher priority interrupt than the others, so
* replay it first.
*/
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_HMI)) {
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_HMI)) {
local_paca->irq_happened &= ~PACA_IRQ_HMI;
regs.trap = 0xe60;
handle_hmi_exception(&regs);
......@@ -217,7 +222,7 @@ void replay_soft_interrupts(void)
hard_irq_disable();
}
if (happened & PACA_IRQ_DEC) {
if (local_paca->irq_happened & PACA_IRQ_DEC) {
local_paca->irq_happened &= ~PACA_IRQ_DEC;
regs.trap = 0x900;
timer_interrupt(&regs);
......@@ -225,7 +230,7 @@ void replay_soft_interrupts(void)
hard_irq_disable();
}
if (happened & PACA_IRQ_EE) {
if (local_paca->irq_happened & PACA_IRQ_EE) {
local_paca->irq_happened &= ~PACA_IRQ_EE;
regs.trap = 0x500;
do_IRQ(&regs);
......@@ -233,7 +238,7 @@ void replay_soft_interrupts(void)
hard_irq_disable();
}
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (happened & PACA_IRQ_DBELL)) {
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (local_paca->irq_happened & PACA_IRQ_DBELL)) {
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
if (IS_ENABLED(CONFIG_PPC_BOOK3E))
regs.trap = 0x280;
......@@ -245,7 +250,7 @@ void replay_soft_interrupts(void)
}
/* Book3E does not support soft-masking PMI interrupts */
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_PMI)) {
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_PMI)) {
local_paca->irq_happened &= ~PACA_IRQ_PMI;
regs.trap = 0xf00;
performance_monitor_exception(&regs);
......@@ -253,8 +258,7 @@ void replay_soft_interrupts(void)
hard_irq_disable();
}
happened = local_paca->irq_happened;
if (happened & ~PACA_IRQ_HARD_DIS) {
if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) {
/*
* We are responding to the next interrupt, so interrupt-off
* latencies should be reset here.
......
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