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

+17 -13
+17 -13
arch/powerpc/kernel/irq.c
··· 180 181 void replay_soft_interrupts(void) 182 { 183 - /* 184 - * We use local_paca rather than get_paca() to avoid all 185 - * the debug_smp_processor_id() business in this low level 186 - * function 187 - */ 188 - unsigned char happened = local_paca->irq_happened; 189 struct pt_regs regs; 190 191 ppc_save_regs(&regs); 192 regs.softe = IRQS_ENABLED; ··· 214 * This is a higher priority interrupt than the others, so 215 * replay it first. 216 */ 217 - if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_HMI)) { 218 local_paca->irq_happened &= ~PACA_IRQ_HMI; 219 regs.trap = 0xe60; 220 handle_hmi_exception(&regs); ··· 222 hard_irq_disable(); 223 } 224 225 - if (happened & PACA_IRQ_DEC) { 226 local_paca->irq_happened &= ~PACA_IRQ_DEC; 227 regs.trap = 0x900; 228 timer_interrupt(&regs); ··· 230 hard_irq_disable(); 231 } 232 233 - if (happened & PACA_IRQ_EE) { 234 local_paca->irq_happened &= ~PACA_IRQ_EE; 235 regs.trap = 0x500; 236 do_IRQ(&regs); ··· 238 hard_irq_disable(); 239 } 240 241 - if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (happened & PACA_IRQ_DBELL)) { 242 local_paca->irq_happened &= ~PACA_IRQ_DBELL; 243 if (IS_ENABLED(CONFIG_PPC_BOOK3E)) 244 regs.trap = 0x280; ··· 250 } 251 252 /* Book3E does not support soft-masking PMI interrupts */ 253 - if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_PMI)) { 254 local_paca->irq_happened &= ~PACA_IRQ_PMI; 255 regs.trap = 0xf00; 256 performance_monitor_exception(&regs); ··· 258 hard_irq_disable(); 259 } 260 261 - happened = local_paca->irq_happened; 262 - if (happened & ~PACA_IRQ_HARD_DIS) { 263 /* 264 * We are responding to the next interrupt, so interrupt-off 265 * latencies should be reset here.
··· 180 181 void replay_soft_interrupts(void) 182 { 183 struct pt_regs regs; 184 + 185 + /* 186 + * Be careful here, calling these interrupt handlers can cause 187 + * softirqs to be raised, which they may run when calling irq_exit, 188 + * which will cause local_irq_enable() to be run, which can then 189 + * recurse into this function. Don't keep any state across 190 + * interrupt handler calls which may change underneath us. 191 + * 192 + * We use local_paca rather than get_paca() to avoid all the 193 + * debug_smp_processor_id() business in this low level function. 194 + */ 195 196 ppc_save_regs(&regs); 197 regs.softe = IRQS_ENABLED; ··· 209 * This is a higher priority interrupt than the others, so 210 * replay it first. 211 */ 212 + if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_HMI)) { 213 local_paca->irq_happened &= ~PACA_IRQ_HMI; 214 regs.trap = 0xe60; 215 handle_hmi_exception(&regs); ··· 217 hard_irq_disable(); 218 } 219 220 + if (local_paca->irq_happened & PACA_IRQ_DEC) { 221 local_paca->irq_happened &= ~PACA_IRQ_DEC; 222 regs.trap = 0x900; 223 timer_interrupt(&regs); ··· 225 hard_irq_disable(); 226 } 227 228 + if (local_paca->irq_happened & PACA_IRQ_EE) { 229 local_paca->irq_happened &= ~PACA_IRQ_EE; 230 regs.trap = 0x500; 231 do_IRQ(&regs); ··· 233 hard_irq_disable(); 234 } 235 236 + if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (local_paca->irq_happened & PACA_IRQ_DBELL)) { 237 local_paca->irq_happened &= ~PACA_IRQ_DBELL; 238 if (IS_ENABLED(CONFIG_PPC_BOOK3E)) 239 regs.trap = 0x280; ··· 245 } 246 247 /* Book3E does not support soft-masking PMI interrupts */ 248 + if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_PMI)) { 249 local_paca->irq_happened &= ~PACA_IRQ_PMI; 250 regs.trap = 0xf00; 251 performance_monitor_exception(&regs); ··· 253 hard_irq_disable(); 254 } 255 256 + if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) { 257 /* 258 * We are responding to the next interrupt, so interrupt-off 259 * latencies should be reset here.