Unverified Commit e53d2818 authored by Nick Kossifidis's avatar Nick Kossifidis Committed by Palmer Dabbelt
Browse files

RISC-V: Add kdump support



This patch adds support for kdump, the kernel will reserve a
region for the crash kernel and jump there on panic. In order
for userspace tools (kexec-tools) to prepare the crash kernel
kexec image, we also need to expose some information on
/proc/iomem for the memory regions used by the kernel and for
the region reserved for crash kernel. Note that on userspace
the device tree is used to determine the system's memory
layout so the "System RAM" on /proc/iomem is ignored.

I tested this on riscv64 qemu and works as expected, you may
test it by triggering a crash through /proc/sysrq_trigger:

echo c > /proc/sysrq_trigger

Signed-off-by: default avatarNick Kossifidis <mick@ics.forth.gr>
Signed-off-by: default avatarPalmer Dabbelt <palmerdabbelt@google.com>
parent ffe0e526
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -81,4 +81,10 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
	int uses_interp);
#endif /* CONFIG_MMU */

#define ELF_CORE_COPY_REGS(dest, regs)			\
do {							\
	*(struct user_regs_struct *)&(dest) =		\
		*(struct user_regs_struct *)regs;	\
} while (0);

#endif /* _ASM_RISCV_ELF_H */
+13 −6
Original line number Diff line number Diff line
@@ -23,11 +23,16 @@

#define KEXEC_ARCH KEXEC_ARCH_RISCV

extern void riscv_crash_save_regs(struct pt_regs *newregs);

static inline void
crash_setup_regs(struct pt_regs *newregs,
		 struct pt_regs *oldregs)
{
	/* Dummy implementation for now */
	if (oldregs)
		memcpy(newregs, oldregs, sizeof(struct pt_regs));
	else
		riscv_crash_save_regs(newregs);
}


@@ -40,10 +45,12 @@ struct kimage_arch {
const extern unsigned char riscv_kexec_relocate[];
const extern unsigned int riscv_kexec_relocate_size;

typedef void (*riscv_kexec_do_relocate)(unsigned long first_ind_entry,
typedef void (*riscv_kexec_method)(unsigned long first_ind_entry,
				   unsigned long jump_addr,
				   unsigned long fdt_addr,
				   unsigned long hartid,
				   unsigned long va_pa_off);

extern riscv_kexec_method riscv_kexec_norelocate;

#endif
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ obj-$(CONFIG_SMP) += cpu_ops_sbi.o
endif
obj-$(CONFIG_HOTPLUG_CPU)	+= cpu-hotplug.o
obj-$(CONFIG_KGDB)		+= kgdb.o
obj-$(CONFIG_KEXEC)		+= kexec_relocate.o machine_kexec.o
obj-$(CONFIG_KEXEC)		+= kexec_relocate.o crash_save_regs.o machine_kexec.o

obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o

+56 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020 FORTH-ICS/CARV
 *  Nick Kossifidis <mick@ics.forth.gr>
 */

#include <asm/asm.h>    	/* For RISCV_* and REG_* macros */
#include <asm/csr.h>		/* For CSR_* macros */
#include <asm/asm-offsets.h>	/* For offsets on pt_regs */
#include <linux/linkage.h>	/* For SYM_* macros */

.section ".text"
SYM_CODE_START(riscv_crash_save_regs)
	REG_S ra,  PT_RA(a0)	/* x1 */
	REG_S sp,  PT_SP(a0)	/* x2 */
	REG_S gp,  PT_GP(a0)	/* x3 */
	REG_S tp,  PT_TP(a0)	/* x4 */
	REG_S t0,  PT_T0(a0)	/* x5 */
	REG_S t1,  PT_T1(a0)	/* x6 */
	REG_S t2,  PT_T2(a0)	/* x7 */
	REG_S s0,  PT_S0(a0)	/* x8/fp */
	REG_S s1,  PT_S1(a0)	/* x9 */
	REG_S a0,  PT_A0(a0)	/* x10 */
	REG_S a1,  PT_A1(a0)	/* x11 */
	REG_S a2,  PT_A2(a0)	/* x12 */
	REG_S a3,  PT_A3(a0)	/* x13 */
	REG_S a4,  PT_A4(a0)	/* x14 */
	REG_S a5,  PT_A5(a0)	/* x15 */
	REG_S a6,  PT_A6(a0)	/* x16 */
	REG_S a7,  PT_A7(a0)	/* x17 */
	REG_S s2,  PT_S2(a0)	/* x18 */
	REG_S s3,  PT_S3(a0)	/* x19 */
	REG_S s4,  PT_S4(a0)	/* x20 */
	REG_S s5,  PT_S5(a0)	/* x21 */
	REG_S s6,  PT_S6(a0)	/* x22 */
	REG_S s7,  PT_S7(a0)	/* x23 */
	REG_S s8,  PT_S8(a0)	/* x24 */
	REG_S s9,  PT_S9(a0)	/* x25 */
	REG_S s10, PT_S10(a0)	/* x26 */
	REG_S s11, PT_S11(a0)	/* x27 */
	REG_S t3,  PT_T3(a0)	/* x28 */
	REG_S t4,  PT_T4(a0)	/* x29 */
	REG_S t5,  PT_T5(a0)	/* x30 */
	REG_S t6,  PT_T6(a0)	/* x31 */

	csrr t1, CSR_STATUS
	csrr t2, CSR_EPC
	csrr t3, CSR_TVAL
	csrr t4, CSR_CAUSE

	REG_S t1, PT_STATUS(a0)
	REG_S t2, PT_EPC(a0)
	REG_S t3, PT_BADADDR(a0)
	REG_S t4, PT_CAUSE(a0)
	ret
SYM_CODE_END(riscv_crash_save_regs)
+67 −1
Original line number Diff line number Diff line
@@ -151,6 +151,72 @@ SYM_CODE_START(riscv_kexec_relocate)
SYM_CODE_END(riscv_kexec_relocate)
riscv_kexec_relocate_end:


/* Used for jumping to crashkernel */
.section ".text"
SYM_CODE_START(riscv_kexec_norelocate)
	/*
	 * s0: (const) Phys address to jump to
	 * s1: (const) Phys address of the FDT image
	 * s2: (const) The hartid of the current hart
	 * s3: (const) va_pa_offset, used when switching MMU off
	 */
	mv	s0, a1
	mv	s1, a2
	mv	s2, a3
	mv	s3, a4

	/* Disable / cleanup interrupts */
	csrw	CSR_SIE, zero
	csrw	CSR_SIP, zero

	/* Switch to physical addressing */
	la	s4, 1f
	sub	s4, s4, s3
	csrw	CSR_STVEC, s4
	csrw	CSR_SATP, zero

.align 2
1:
	/* Pass the arguments to the next kernel  / Cleanup*/
	mv	a0, s2
	mv	a1, s1
	mv	a2, s0

	/* Cleanup */
	mv	a3, zero
	mv	a4, zero
	mv	a5, zero
	mv	a6, zero
	mv	a7, zero

	mv	s0, zero
	mv	s1, zero
	mv	s2, zero
	mv	s3, zero
	mv	s4, zero
	mv	s5, zero
	mv	s6, zero
	mv	s7, zero
	mv	s8, zero
	mv	s9, zero
	mv	s10, zero
	mv	s11, zero

	mv	t0, zero
	mv	t1, zero
	mv	t2, zero
	mv	t3, zero
	mv	t4, zero
	mv	t5, zero
	mv	t6, zero
	csrw	CSR_SEPC, zero
	csrw	CSR_SCAUSE, zero
	csrw	CSR_SSCRATCH, zero

	jalr	zero, a2, 0
SYM_CODE_END(riscv_kexec_norelocate)

.section ".rodata"
SYM_DATA(riscv_kexec_relocate_size,
	.long riscv_kexec_relocate_end - riscv_kexec_relocate)
Loading