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 to9141a003a4
("ARM: 7316/1: kexec: EOI active and mask all interrupts in kexec crash path") and78fd584cde
("arm64: kdump: implement machine_crash_shutdown()"), and PowerPC also has the same mechanism. Fixes:fba8a8674f
("RISC-V: Add kexec support") Signed-off-by: Guo Ren <guoren@linux.alibaba.com> Signed-off-by: Guo Ren <guoren@kernel.org> Reviewed-by: Xianting 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.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
9abf2313ad
commit
b17d19a531
1 changed files with 35 additions and 0 deletions
|
@ -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)
|
||||||
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)
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue