One fix for a bug in our soft interrupt masking, which could lead to interrupt
 replaying recursing, causing spurious interrupts.
 
 Thanks to:
   Nicholas Piggin.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmAWjOITHG1wZUBlbGxl
 cm1hbi5pZC5hdQAKCRBR6+o8yOGlgPxED/9yFcXGg/Xr/pEYTcwz8+CBvvunfw2s
 Bm/S1g7uMrAYHUFViKZ4PtzHwzVyEiJPf72stIaYTGmfSwqEnyN71sV3Ij19yXoK
 ywxbBx18G4cfaCJFuoL2AFTNYC1ZAC2B+1Yk4KboyxGsG9sNspk8uysCxD4dInEt
 qIWVHjqV7e/RUgdqJv5vM/PqMGDqkriB2vjn+UBs9Cv6P27n/MmcIqJRCPwKNQ3t
 v2kQ4fALPJRfGL4tQku/RUTa/0dPjCt0wYpbly4257yWzLjwc4xqVqNVgQfO2bj8
 4wA68mIP5KpJ+5b5Qe9Jy5i/GqopN05akfqKuP5ILA6+NuVetZIWvVi9fzo39/x8
 rJY+37XtfoRMFeAbidd6sMpNjPsJRyv5bDeHRI0iZJj99+OK4AHkcngQyDb7bXag
 91jfDHRPhyzDazw/eKPeQkK+DNSF2u7EFRXbvO3d8FzH/EeV558m/w/ld94DUO3c
 M0nzCRSzijXkas+mPX6gRX3zK/4hrL+EHGqpGhPRTeCIaFRctapYlaQCdx/6npbH
 Q+5dHAKK+2Rj8KbjDGkt7ue8T+a9CUgdcjZYtO+4yZ8PKckuj2CFp9tKRR5veemS
 jFEArK3QA/8Gz57HCaks9fz6Ki7szUF1YurIO/5oRK7CWz6lOtRxT4AO1pHYNcLO
 NiiJfFjq5r4X/A==
 =hC+4
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2021-01-31 11:37:43 -08:00
Родитель 1188866d9c 4025c784c5
Коммит b333a99e14
1 изменённых файлов: 17 добавлений и 13 удалений

Просмотреть файл

@ -180,14 +180,19 @@ void notrace restore_interrupts(void)
void replay_soft_interrupts(void) void replay_soft_interrupts(void)
{ {
/*
* 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; struct pt_regs regs;
/*
* 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.
*/
ppc_save_regs(&regs); ppc_save_regs(&regs);
regs.softe = IRQS_ENABLED; regs.softe = IRQS_ENABLED;
@ -209,7 +214,7 @@ again:
* This is a higher priority interrupt than the others, so * This is a higher priority interrupt than the others, so
* replay it first. * 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; local_paca->irq_happened &= ~PACA_IRQ_HMI;
regs.trap = 0xe60; regs.trap = 0xe60;
handle_hmi_exception(&regs); handle_hmi_exception(&regs);
@ -217,7 +222,7 @@ again:
hard_irq_disable(); hard_irq_disable();
} }
if (happened & PACA_IRQ_DEC) { if (local_paca->irq_happened & PACA_IRQ_DEC) {
local_paca->irq_happened &= ~PACA_IRQ_DEC; local_paca->irq_happened &= ~PACA_IRQ_DEC;
regs.trap = 0x900; regs.trap = 0x900;
timer_interrupt(&regs); timer_interrupt(&regs);
@ -225,7 +230,7 @@ again:
hard_irq_disable(); hard_irq_disable();
} }
if (happened & PACA_IRQ_EE) { if (local_paca->irq_happened & PACA_IRQ_EE) {
local_paca->irq_happened &= ~PACA_IRQ_EE; local_paca->irq_happened &= ~PACA_IRQ_EE;
regs.trap = 0x500; regs.trap = 0x500;
do_IRQ(&regs); do_IRQ(&regs);
@ -233,7 +238,7 @@ again:
hard_irq_disable(); 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; local_paca->irq_happened &= ~PACA_IRQ_DBELL;
if (IS_ENABLED(CONFIG_PPC_BOOK3E)) if (IS_ENABLED(CONFIG_PPC_BOOK3E))
regs.trap = 0x280; regs.trap = 0x280;
@ -245,7 +250,7 @@ again:
} }
/* Book3E does not support soft-masking PMI interrupts */ /* 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; local_paca->irq_happened &= ~PACA_IRQ_PMI;
regs.trap = 0xf00; regs.trap = 0xf00;
performance_monitor_exception(&regs); performance_monitor_exception(&regs);
@ -253,8 +258,7 @@ again:
hard_irq_disable(); hard_irq_disable();
} }
happened = local_paca->irq_happened; if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) {
if (happened & ~PACA_IRQ_HARD_DIS) {
/* /*
* We are responding to the next interrupt, so interrupt-off * We are responding to the next interrupt, so interrupt-off
* latencies should be reset here. * latencies should be reset here.