Message ID | 20231208111015.173237-1-songshuaishuai@tinylab.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [-fixes] riscv: kexec: Avoid deadlock in kexec crash path | expand |
Hi Song Shuai, On Fri, 8 Dec 2023, Song Shuai wrote: > If the kexec crash code is called in the interrupt context, the > machine_kexec_mask_interrupts() function will trigger a deadlock while > trying to acquire the irqdesc spinlock and then deacitive irqchip. > > To avoid the deadlock, this patch directly EOI the irq regardless of > the active status of irqchip. Taking a quick look at the other architectures, looks like no one else is doing this. Is this addressing a RISC-V-only problem? > diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c > index f6c7135b00d7..d7ddf4d2b243 100644 > --- a/arch/riscv/kernel/machine_kexec.c > +++ b/arch/riscv/kernel/machine_kexec.c > @@ -149,20 +149,12 @@ static void machine_kexec_mask_interrupts(void) > > for_each_irq_desc(i, desc) { > struct irq_chip *chip; > - int ret; > > chip = irq_desc_get_chip(desc); > if (!chip) > continue; > > - /* > - * First try to remove the active state. If this > - * fails, try to EOI the interrupt. > - */ > - ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false); > - > - if (ret && irqd_irq_inprogress(&desc->irq_data) && > - chip->irq_eoi) > + if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data)) > chip->irq_eoi(&desc->irq_data); - Paul
diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c index f6c7135b00d7..d7ddf4d2b243 100644 --- a/arch/riscv/kernel/machine_kexec.c +++ b/arch/riscv/kernel/machine_kexec.c @@ -149,20 +149,12 @@ static void machine_kexec_mask_interrupts(void) for_each_irq_desc(i, desc) { struct irq_chip *chip; - int ret; chip = irq_desc_get_chip(desc); if (!chip) continue; - /* - * First try to remove the active state. If this - * fails, try to EOI the interrupt. - */ - ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false); - - if (ret && irqd_irq_inprogress(&desc->irq_data) && - chip->irq_eoi) + if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data)) chip->irq_eoi(&desc->irq_data); if (chip->irq_mask)
If the kexec crash code is called in the interrupt context, the machine_kexec_mask_interrupts() function will trigger a deadlock while trying to acquire the irqdesc spinlock and then deacitive irqchip. To avoid the deadlock, this patch directly EOI the irq regardless of the active status of irqchip. Fixes: b17d19a5314a ("riscv: kexec: Fixup irq controller broken in kexec crash path") Signed-off-by: Song Shuai <songshuaishuai@tinylab.org> --- Note that: 1. this deadlock can reproduced via echo EXCEPTION to lkdtm INT_HW_IRQ_EN point 2. RISC-V HLIC and PLIC irqchips don't have the irq_set_irqchip_state handler and I don't know is it ok to deactive irqchip without the spinlock in this code context, so I simply removed that snippet as arm and powerpc do. I would like to listen to your advice. --- arch/riscv/kernel/machine_kexec.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)