Skip to content

Commit b333a99

Browse files
committed
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
2 parents 1188866 + 4025c78 commit b333a99

1 file changed

Lines changed: 16 additions & 12 deletions

File tree

arch/powerpc/kernel/irq.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,18 @@ void notrace restore_interrupts(void)
180180

181181
void 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

Comments
 (0)