Commit b17d19a5 authored by Guo Ren's avatar Guo Ren Committed by Palmer Dabbelt

riscv: kexec: Fixup irq controller broken in kexec crash path

If a crash happens on cpu3 and all interrupts are binding on cpu0, the
bad irq routing will cause a crash kernel which can't receive any irq.
Because crash kernel won't clean up all harts' PLIC enable bits in
enable registers. This patch is similar to 9141a003 ("ARM: 7316/1:
kexec: EOI active and mask all interrupts in kexec crash path") and
78fd584c ("arm64: kdump: implement machine_crash_shutdown()"), and
PowerPC also has the same mechanism.

Fixes: fba8a867 ("RISC-V: Add kexec support")
Signed-off-by: default avatarGuo Ren <guoren@linux.alibaba.com>
Signed-off-by: default avatarGuo Ren <guoren@kernel.org>
Reviewed-by: default avatarXianting Tian <xianting.tian@linux.alibaba.com>
Cc: Nick Kossifidis <mick@ics.forth.gr>
Cc: Palmer Dabbelt <palmer@rivosinc.com>
Link: https://lore.kernel.org/r/20221020141603.2856206-2-guoren@kernel.orgSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 9abf2313
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/compiler.h> /* For unreachable() */ #include <linux/compiler.h> /* For unreachable() */
#include <linux/cpu.h> /* For cpu_down() */ #include <linux/cpu.h> /* For cpu_down() */
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
/* /*
* kexec_image_info - Print received image details * kexec_image_info - Print received image details
...@@ -154,6 +156,37 @@ void crash_smp_send_stop(void) ...@@ -154,6 +156,37 @@ void crash_smp_send_stop(void)
cpus_stopped = 1; cpus_stopped = 1;
} }
static void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
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)
chip->irq_eoi(&desc->irq_data);
if (chip->irq_mask)
chip->irq_mask(&desc->irq_data);
if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
chip->irq_disable(&desc->irq_data);
}
}
/* /*
* machine_crash_shutdown - Prepare to kexec after a kernel crash * machine_crash_shutdown - Prepare to kexec after a kernel crash
* *
...@@ -169,6 +202,8 @@ machine_crash_shutdown(struct pt_regs *regs) ...@@ -169,6 +202,8 @@ machine_crash_shutdown(struct pt_regs *regs)
crash_smp_send_stop(); crash_smp_send_stop();
crash_save_cpu(regs, smp_processor_id()); crash_save_cpu(regs, smp_processor_id());
machine_kexec_mask_interrupts();
pr_info("Starting crashdump kernel...\n"); pr_info("Starting crashdump kernel...\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment