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

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.org


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 9abf2313
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <linux/compiler.h>	/* For unreachable() */
#include <linux/cpu.h>		/* For cpu_down() */
#include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/irq.h>

/*
 * kexec_image_info - Print received image details
@@ -154,6 +156,37 @@ void crash_smp_send_stop(void)
	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
 *
@@ -169,6 +202,8 @@ machine_crash_shutdown(struct pt_regs *regs)
	crash_smp_send_stop();

	crash_save_cpu(regs, smp_processor_id());
	machine_kexec_mask_interrupts();

	pr_info("Starting crashdump kernel...\n");
}