Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7aa1c8f4 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

MIPS: kdump: Add support



[ralf@linux-mips.org: Original patch by Maxim Uvarov <muvarov@gmail.com>
with plenty of further shining, polishing, debugging and testing by me.]

Signed-off-by: default avatarMaxim Uvarov <muvarov@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: kexec@lists.infradead.org
Cc: horms@verge.net.au
Patchwork: https://patchwork.linux-mips.org/patch/1025/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 98cdee0e
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -2379,6 +2379,29 @@ config KEXEC
	  support.  As of this writing the exact hardware interface is
	  strongly in flux, so no good recommendation can be made.

config CRASH_DUMP
	  bool "Kernel crash dumps"
	  help
	  Generate crash dump after being started by kexec.
	  This should be normally only set in special crash dump kernels
	  which are loaded in the main kernel with kexec-tools into
	  a specially reserved region and then later executed after
	  a crash by kdump/kexec. The crash dump kernel must be compiled
	  to a memory address not used by the main kernel or firmware using
	  PHYSICAL_START.

config PHYSICAL_START
	  hex "Physical address where the kernel is loaded"
	  default "0xffffffff84000000" if 64BIT
	  default "0x84000000" if 32BIT
	  depends on CRASH_DUMP
	  help
	  This gives the CKSEG0 or KSEG0 address where the kernel is loaded.
	  If you plan to use kernel for capturing the crash dump change
	  this value to start of the reserved region (the "X" value as
	  specified in the "crashkernel=YM@XM" command line boot parameter
	  passed to the panic-ed kernel).

config SECCOMP
	bool "Enable seccomp to safely compute untrusted bytecode"
	depends on PROC_FS
+24 −3
Original line number Diff line number Diff line
@@ -9,22 +9,43 @@
#ifndef _MIPS_KEXEC
# define _MIPS_KEXEC

#include <asm/stacktrace.h>

/* Maximum physical address we can use pages from */
#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
/* Maximum address we can reach in physical address mode */
#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
 /* Maximum address we can use for the control code buffer */
#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)

#define KEXEC_CONTROL_PAGE_SIZE 4096
/* Reserve 3*4096 bytes for board-specific info */
#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)

/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_MIPS
#define MAX_NOTE_BYTES 1024

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

#ifdef CONFIG_KEXEC
struct kimage;
extern unsigned long kexec_args[4];
extern int (*_machine_kexec_prepare)(struct kimage *);
extern void (*_machine_kexec_shutdown)(void);
extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
#ifdef CONFIG_SMP
extern const unsigned char kexec_smp_wait[];
extern unsigned long secondary_kexec_args[4];
extern void (*relocated_kexec_smp_wait) (void *);
extern atomic_t kexec_ready_to_reboot;
#endif
#endif

#endif /* !_MIPS_KEXEC */
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_CALL_FUNCTION	0x2
/* Octeon - Tell another core to flush its icache */
#define SMP_ICACHE_FLUSH	0x4
/* Used by kexec crashdump to save all cpu's state */
#define SMP_DUMP		0x8

extern volatile cpumask_t cpu_callin_map;

@@ -91,4 +93,8 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
	mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
}

#if defined(CONFIG_KEXEC)
extern void (*dump_ipi_function_ptr)(void *);
void dump_send_ipi(void (*dump_ipi_callback)(void *));
#endif
#endif /* __ASM_SMP_H */
+2 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ obj-$(CONFIG_I8253) += i8253.o

obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o

obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
+71 −0
Original line number Diff line number Diff line
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
#include <linux/bootmem.h>
#include <linux/crash_dump.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/sched.h>

/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;

#ifdef CONFIG_SMP
static void crash_shutdown_secondary(void *ignore)
{
	struct pt_regs *regs;
	int cpu = smp_processor_id();

	regs = task_pt_regs(current);

	if (!cpu_online(cpu))
		return;

	local_irq_disable();
	if (!cpu_isset(cpu, cpus_in_crash))
		crash_save_cpu(regs, cpu);
	cpu_set(cpu, cpus_in_crash);

	while (!atomic_read(&kexec_ready_to_reboot))
		cpu_relax();
	relocated_kexec_smp_wait(NULL);
	/* NOTREACHED */
}

static void crash_kexec_prepare_cpus(void)
{
	unsigned int msecs;

	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */

	dump_send_ipi(crash_shutdown_secondary);
	smp_wmb();

	/*
	 * The crash CPU sends an IPI and wait for other CPUs to
	 * respond. Delay of at least 10 seconds.
	 */
	pr_emerg("Sending IPI to other cpus...\n");
	msecs = 10000;
	while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
		cpu_relax();
		mdelay(1);
	}
}

#else /* !defined(CONFIG_SMP)  */
static void crash_kexec_prepare_cpus(void) {}
#endif /* !defined(CONFIG_SMP)  */

void default_machine_crash_shutdown(struct pt_regs *regs)
{
	local_irq_disable();
	crashing_cpu = smp_processor_id();
	crash_save_cpu(regs, crashing_cpu);
	crash_kexec_prepare_cpus();
	cpu_set(crashing_cpu, cpus_in_crash);
}
Loading