@@ -180,13 +180,18 @@ void notrace restore_interrupts(void)
180180
181181void replay_soft_interrupts (void )
182182{
183+ struct pt_regs regs ;
184+
183185 /*
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
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.
187194 */
188- unsigned char happened = local_paca -> irq_happened ;
189- struct pt_regs regs ;
190195
191196 ppc_save_regs (& regs );
192197 regs .softe = IRQS_ENABLED ;
@@ -209,31 +214,31 @@ void replay_soft_interrupts(void)
209214 * This is a higher priority interrupt than the others, so
210215 * replay it first.
211216 */
212- if (IS_ENABLED (CONFIG_PPC_BOOK3S ) && (happened & PACA_IRQ_HMI )) {
217+ if (IS_ENABLED (CONFIG_PPC_BOOK3S ) && (local_paca -> irq_happened & PACA_IRQ_HMI )) {
213218 local_paca -> irq_happened &= ~PACA_IRQ_HMI ;
214219 regs .trap = 0xe60 ;
215220 handle_hmi_exception (& regs );
216221 if (!(local_paca -> irq_happened & PACA_IRQ_HARD_DIS ))
217222 hard_irq_disable ();
218223 }
219224
220- if (happened & PACA_IRQ_DEC ) {
225+ if (local_paca -> irq_happened & PACA_IRQ_DEC ) {
221226 local_paca -> irq_happened &= ~PACA_IRQ_DEC ;
222227 regs .trap = 0x900 ;
223228 timer_interrupt (& regs );
224229 if (!(local_paca -> irq_happened & PACA_IRQ_HARD_DIS ))
225230 hard_irq_disable ();
226231 }
227232
228- if (happened & PACA_IRQ_EE ) {
233+ if (local_paca -> irq_happened & PACA_IRQ_EE ) {
229234 local_paca -> irq_happened &= ~PACA_IRQ_EE ;
230235 regs .trap = 0x500 ;
231236 do_IRQ (& regs );
232237 if (!(local_paca -> irq_happened & PACA_IRQ_HARD_DIS ))
233238 hard_irq_disable ();
234239 }
235240
236- if (IS_ENABLED (CONFIG_PPC_DOORBELL ) && (happened & PACA_IRQ_DBELL )) {
241+ if (IS_ENABLED (CONFIG_PPC_DOORBELL ) && (local_paca -> irq_happened & PACA_IRQ_DBELL )) {
237242 local_paca -> irq_happened &= ~PACA_IRQ_DBELL ;
238243 if (IS_ENABLED (CONFIG_PPC_BOOK3E ))
239244 regs .trap = 0x280 ;
@@ -245,16 +250,15 @@ void replay_soft_interrupts(void)
245250 }
246251
247252 /* Book3E does not support soft-masking PMI interrupts */
248- if (IS_ENABLED (CONFIG_PPC_BOOK3S ) && (happened & PACA_IRQ_PMI )) {
253+ if (IS_ENABLED (CONFIG_PPC_BOOK3S ) && (local_paca -> irq_happened & PACA_IRQ_PMI )) {
249254 local_paca -> irq_happened &= ~PACA_IRQ_PMI ;
250255 regs .trap = 0xf00 ;
251256 performance_monitor_exception (& regs );
252257 if (!(local_paca -> irq_happened & PACA_IRQ_HARD_DIS ))
253258 hard_irq_disable ();
254259 }
255260
256- happened = local_paca -> irq_happened ;
257- if (happened & ~PACA_IRQ_HARD_DIS ) {
261+ if (local_paca -> irq_happened & ~PACA_IRQ_HARD_DIS ) {
258262 /*
259263 * We are responding to the next interrupt, so interrupt-off
260264 * latencies should be reset here.
0 commit comments