aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/Kconfig23
-rw-r--r--arch/mips/include/asm/kexec.h27
-rw-r--r--arch/mips/include/asm/smp.h6
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/crash.c71
-rw-r--r--arch/mips/kernel/crash_dump.c77
-rw-r--r--arch/mips/kernel/machine_kexec.c33
-rw-r--r--arch/mips/kernel/relocate_kernel.S88
-rw-r--r--arch/mips/kernel/setup.c56
-rw-r--r--arch/mips/kernel/smp.c17
-rw-r--r--arch/mips/kernel/traps.c4
11 files changed, 396 insertions, 9 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 462f9c4fe2e5..c97fc030fdac 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2379,6 +2379,29 @@ config KEXEC
2379 support. As of this writing the exact hardware interface is 2379 support. As of this writing the exact hardware interface is
2380 strongly in flux, so no good recommendation can be made. 2380 strongly in flux, so no good recommendation can be made.
2381 2381
2382config CRASH_DUMP
2383 bool "Kernel crash dumps"
2384 help
2385 Generate crash dump after being started by kexec.
2386 This should be normally only set in special crash dump kernels
2387 which are loaded in the main kernel with kexec-tools into
2388 a specially reserved region and then later executed after
2389 a crash by kdump/kexec. The crash dump kernel must be compiled
2390 to a memory address not used by the main kernel or firmware using
2391 PHYSICAL_START.
2392
2393config PHYSICAL_START
2394 hex "Physical address where the kernel is loaded"
2395 default "0xffffffff84000000" if 64BIT
2396 default "0x84000000" if 32BIT
2397 depends on CRASH_DUMP
2398 help
2399 This gives the CKSEG0 or KSEG0 address where the kernel is loaded.
2400 If you plan to use kernel for capturing the crash dump change
2401 this value to start of the reserved region (the "X" value as
2402 specified in the "crashkernel=YM@XM" command line boot parameter
2403 passed to the panic-ed kernel).
2404
2382config SECCOMP 2405config SECCOMP
2383 bool "Enable seccomp to safely compute untrusted bytecode" 2406 bool "Enable seccomp to safely compute untrusted bytecode"
2384 depends on PROC_FS 2407 depends on PROC_FS
diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 4314892aaebb..ee25ebbf2a28 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -9,22 +9,43 @@
9#ifndef _MIPS_KEXEC 9#ifndef _MIPS_KEXEC
10# define _MIPS_KEXEC 10# define _MIPS_KEXEC
11 11
12#include <asm/stacktrace.h>
13
12/* Maximum physical address we can use pages from */ 14/* Maximum physical address we can use pages from */
13#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000) 15#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
14/* Maximum address we can reach in physical address mode */ 16/* Maximum address we can reach in physical address mode */
15#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000) 17#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
16 /* Maximum address we can use for the control code buffer */ 18 /* Maximum address we can use for the control code buffer */
17#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000) 19#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
18 20/* Reserve 3*4096 bytes for board-specific info */
19#define KEXEC_CONTROL_PAGE_SIZE 4096 21#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
20 22
21/* The native architecture */ 23/* The native architecture */
22#define KEXEC_ARCH KEXEC_ARCH_MIPS 24#define KEXEC_ARCH KEXEC_ARCH_MIPS
25#define MAX_NOTE_BYTES 1024
23 26
24static inline void crash_setup_regs(struct pt_regs *newregs, 27static inline void crash_setup_regs(struct pt_regs *newregs,
25 struct pt_regs *oldregs) 28 struct pt_regs *oldregs)
26{ 29{
27 /* Dummy implementation for now */ 30 if (oldregs)
31 memcpy(newregs, oldregs, sizeof(*newregs));
32 else
33 prepare_frametrace(newregs);
28} 34}
29 35
36#ifdef CONFIG_KEXEC
37struct kimage;
38extern unsigned long kexec_args[4];
39extern int (*_machine_kexec_prepare)(struct kimage *);
40extern void (*_machine_kexec_shutdown)(void);
41extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
42extern void default_machine_crash_shutdown(struct pt_regs *regs);
43#ifdef CONFIG_SMP
44extern const unsigned char kexec_smp_wait[];
45extern unsigned long secondary_kexec_args[4];
46extern void (*relocated_kexec_smp_wait) (void *);
47extern atomic_t kexec_ready_to_reboot;
48#endif
49#endif
50
30#endif /* !_MIPS_KEXEC */ 51#endif /* !_MIPS_KEXEC */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index d4fb4d852a6d..f33b5fd6972b 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -40,6 +40,8 @@ extern int __cpu_logical_map[NR_CPUS];
40#define SMP_CALL_FUNCTION 0x2 40#define SMP_CALL_FUNCTION 0x2
41/* Octeon - Tell another core to flush its icache */ 41/* Octeon - Tell another core to flush its icache */
42#define SMP_ICACHE_FLUSH 0x4 42#define SMP_ICACHE_FLUSH 0x4
43/* Used by kexec crashdump to save all cpu's state */
44#define SMP_DUMP 0x8
43 45
44extern volatile cpumask_t cpu_callin_map; 46extern volatile cpumask_t cpu_callin_map;
45 47
@@ -91,4 +93,8 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
91 mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); 93 mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
92} 94}
93 95
96#if defined(CONFIG_KEXEC)
97extern void (*dump_ipi_function_ptr)(void *);
98void dump_send_ipi(void (*dump_ipi_callback)(void *));
99#endif
94#endif /* __ASM_SMP_H */ 100#endif /* __ASM_SMP_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 8b28bc4e14ea..764597b5fb56 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -80,7 +80,8 @@ obj-$(CONFIG_I8253) += i8253.o
80 80
81obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o 81obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
82 82
83obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 83obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
84obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
84obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 85obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
85obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o 86obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
86obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o 87obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
new file mode 100644
index 000000000000..0f53c39324bb
--- /dev/null
+++ b/arch/mips/kernel/crash.c
@@ -0,0 +1,71 @@
1#include <linux/kernel.h>
2#include <linux/smp.h>
3#include <linux/reboot.h>
4#include <linux/kexec.h>
5#include <linux/bootmem.h>
6#include <linux/crash_dump.h>
7#include <linux/delay.h>
8#include <linux/init.h>
9#include <linux/irq.h>
10#include <linux/types.h>
11#include <linux/sched.h>
12
13/* This keeps a track of which one is crashing cpu. */
14static int crashing_cpu = -1;
15static cpumask_t cpus_in_crash = CPU_MASK_NONE;
16
17#ifdef CONFIG_SMP
18static void crash_shutdown_secondary(void *ignore)
19{
20 struct pt_regs *regs;
21 int cpu = smp_processor_id();
22
23 regs = task_pt_regs(current);
24
25 if (!cpu_online(cpu))
26 return;
27
28 local_irq_disable();
29 if (!cpu_isset(cpu, cpus_in_crash))
30 crash_save_cpu(regs, cpu);
31 cpu_set(cpu, cpus_in_crash);
32
33 while (!atomic_read(&kexec_ready_to_reboot))
34 cpu_relax();
35 relocated_kexec_smp_wait(NULL);
36 /* NOTREACHED */
37}
38
39static void crash_kexec_prepare_cpus(void)
40{
41 unsigned int msecs;
42
43 unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
44
45 dump_send_ipi(crash_shutdown_secondary);
46 smp_wmb();
47
48 /*
49 * The crash CPU sends an IPI and wait for other CPUs to
50 * respond. Delay of at least 10 seconds.
51 */
52 pr_emerg("Sending IPI to other cpus...\n");
53 msecs = 10000;
54 while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
55 cpu_relax();
56 mdelay(1);
57 }
58}
59
60#else /* !defined(CONFIG_SMP) */
61static void crash_kexec_prepare_cpus(void) {}
62#endif /* !defined(CONFIG_SMP) */
63
64void default_machine_crash_shutdown(struct pt_regs *regs)
65{
66 local_irq_disable();
67 crashing_cpu = smp_processor_id();
68 crash_save_cpu(regs, crashing_cpu);
69 crash_kexec_prepare_cpus();
70 cpu_set(crashing_cpu, cpus_in_crash);
71}
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c
new file mode 100644
index 000000000000..d9ec3898f9fa
--- /dev/null
+++ b/arch/mips/kernel/crash_dump.c
@@ -0,0 +1,77 @@
1#include <linux/highmem.h>
2#include <linux/bootmem.h>
3#include <linux/crash_dump.h>
4#include <asm/uaccess.h>
5
6unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
7
8static int __init parse_savemaxmem(char *p)
9{
10 if (p)
11 saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
12
13 return 1;
14}
15__setup("savemaxmem=", parse_savemaxmem);
16
17
18static void *kdump_buf_page;
19
20/**
21 * copy_oldmem_page - copy one page from "oldmem"
22 * @pfn: page frame number to be copied
23 * @buf: target memory address for the copy; this can be in kernel address
24 * space or user address space (see @userbuf)
25 * @csize: number of bytes to copy
26 * @offset: offset in bytes into the page (based on pfn) to begin the copy
27 * @userbuf: if set, @buf is in user address space, use copy_to_user(),
28 * otherwise @buf is in kernel address space, use memcpy().
29 *
30 * Copy a page from "oldmem". For this page, there is no pte mapped
31 * in the current kernel.
32 *
33 * Calling copy_to_user() in atomic context is not desirable. Hence first
34 * copying the data to a pre-allocated kernel page and then copying to user
35 * space in non-atomic context.
36 */
37ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
38 size_t csize, unsigned long offset, int userbuf)
39{
40 void *vaddr;
41
42 if (!csize)
43 return 0;
44
45 vaddr = kmap_atomic_pfn(pfn);
46
47 if (!userbuf) {
48 memcpy(buf, (vaddr + offset), csize);
49 kunmap_atomic(vaddr);
50 } else {
51 if (!kdump_buf_page) {
52 pr_warning("Kdump: Kdump buffer page not allocated\n");
53
54 return -EFAULT;
55 }
56 copy_page(kdump_buf_page, vaddr);
57 kunmap_atomic(vaddr);
58 if (copy_to_user(buf, (kdump_buf_page + offset), csize))
59 return -EFAULT;
60 }
61
62 return csize;
63}
64
65static int __init kdump_buf_page_init(void)
66{
67 int ret = 0;
68
69 kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
70 if (!kdump_buf_page) {
71 pr_warning("Kdump: Failed to allocate kdump buffer page\n");
72 ret = -ENOMEM;
73 }
74
75 return ret;
76}
77arch_initcall(kdump_buf_page_init);
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 85beb9b0b2d0..992e18474da5 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -5,7 +5,7 @@
5 * This source code is licensed under the GNU General Public License, 5 * This source code is licensed under the GNU General Public License,
6 * Version 2. See the file COPYING for more details. 6 * Version 2. See the file COPYING for more details.
7 */ 7 */
8 8#include <linux/compiler.h>
9#include <linux/kexec.h> 9#include <linux/kexec.h>
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/delay.h> 11#include <linux/delay.h>
@@ -19,9 +19,19 @@ extern const size_t relocate_new_kernel_size;
19extern unsigned long kexec_start_address; 19extern unsigned long kexec_start_address;
20extern unsigned long kexec_indirection_page; 20extern unsigned long kexec_indirection_page;
21 21
22int (*_machine_kexec_prepare)(struct kimage *) = NULL;
23void (*_machine_kexec_shutdown)(void) = NULL;
24void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
25#ifdef CONFIG_SMP
26void (*relocated_kexec_smp_wait) (void *);
27atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
28#endif
29
22int 30int
23machine_kexec_prepare(struct kimage *kimage) 31machine_kexec_prepare(struct kimage *kimage)
24{ 32{
33 if (_machine_kexec_prepare)
34 return _machine_kexec_prepare(kimage);
25 return 0; 35 return 0;
26} 36}
27 37
@@ -33,14 +43,20 @@ machine_kexec_cleanup(struct kimage *kimage)
33void 43void
34machine_shutdown(void) 44machine_shutdown(void)
35{ 45{
46 if (_machine_kexec_shutdown)
47 _machine_kexec_shutdown();
36} 48}
37 49
38void 50void
39machine_crash_shutdown(struct pt_regs *regs) 51machine_crash_shutdown(struct pt_regs *regs)
40{ 52{
53 if (_machine_crash_shutdown)
54 _machine_crash_shutdown(regs);
55 else
56 default_machine_crash_shutdown(regs);
41} 57}
42 58
43typedef void (*noretfun_t)(void) __attribute__((noreturn)); 59typedef void (*noretfun_t)(void) __noreturn;
44 60
45void 61void
46machine_kexec(struct kimage *image) 62machine_kexec(struct kimage *image)
@@ -52,7 +68,9 @@ machine_kexec(struct kimage *image)
52 reboot_code_buffer = 68 reboot_code_buffer =
53 (unsigned long)page_address(image->control_code_page); 69 (unsigned long)page_address(image->control_code_page);
54 70
55 kexec_start_address = image->start; 71 kexec_start_address =
72 (unsigned long) phys_to_virt(image->start);
73
56 kexec_indirection_page = 74 kexec_indirection_page =
57 (unsigned long) phys_to_virt(image->head & PAGE_MASK); 75 (unsigned long) phys_to_virt(image->head & PAGE_MASK);
58 76
@@ -63,7 +81,7 @@ machine_kexec(struct kimage *image)
63 * The generic kexec code builds a page list with physical 81 * The generic kexec code builds a page list with physical
64 * addresses. they are directly accessible through KSEG0 (or 82 * addresses. they are directly accessible through KSEG0 (or
65 * CKSEG0 or XPHYS if on 64bit system), hence the 83 * CKSEG0 or XPHYS if on 64bit system), hence the
66 * pys_to_virt() call. 84 * phys_to_virt() call.
67 */ 85 */
68 for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); 86 for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
69 ptr = (entry & IND_INDIRECTION) ? 87 ptr = (entry & IND_INDIRECTION) ?
@@ -81,5 +99,12 @@ machine_kexec(struct kimage *image)
81 printk("Will call new kernel at %08lx\n", image->start); 99 printk("Will call new kernel at %08lx\n", image->start);
82 printk("Bye ...\n"); 100 printk("Bye ...\n");
83 __flush_cache_all(); 101 __flush_cache_all();
102#ifdef CONFIG_SMP
103 /* All secondary cpus now may jump to kexec_wait cycle */
104 relocated_kexec_smp_wait = reboot_code_buffer +
105 (void *)(kexec_smp_wait - relocate_new_kernel);
106 smp_wmb();
107 atomic_set(&kexec_ready_to_reboot, 1);
108#endif
84 ((noretfun_t) reboot_code_buffer)(); 109 ((noretfun_t) reboot_code_buffer)();
85} 110}
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index 87481f916a61..0b108587f065 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -15,6 +15,11 @@
15#include <asm/addrspace.h> 15#include <asm/addrspace.h>
16 16
17LEAF(relocate_new_kernel) 17LEAF(relocate_new_kernel)
18 PTR_L a0, arg0
19 PTR_L a1, arg1
20 PTR_L a2, arg2
21 PTR_L a3, arg3
22
18 PTR_L s0, kexec_indirection_page 23 PTR_L s0, kexec_indirection_page
19 PTR_L s1, kexec_start_address 24 PTR_L s1, kexec_start_address
20 25
@@ -26,7 +31,6 @@ process_entry:
26 and s3, s2, 0x1 31 and s3, s2, 0x1
27 beq s3, zero, 1f 32 beq s3, zero, 1f
28 and s4, s2, ~0x1 /* store destination addr in s4 */ 33 and s4, s2, ~0x1 /* store destination addr in s4 */
29 move a0, s4
30 b process_entry 34 b process_entry
31 35
321: 361:
@@ -60,10 +64,92 @@ copy_word:
60 b process_entry 64 b process_entry
61 65
62done: 66done:
67#ifdef CONFIG_SMP
68 /* kexec_flag reset is signal to other CPUs what kernel
69 was moved to it's location. Note - we need relocated address
70 of kexec_flag. */
71
72 bal 1f
73 1: move t1,ra;
74 PTR_LA t2,1b
75 PTR_LA t0,kexec_flag
76 PTR_SUB t0,t0,t2;
77 PTR_ADD t0,t1,t0;
78 LONG_S zero,(t0)
79#endif
80
81 sync
63 /* jump to kexec_start_address */ 82 /* jump to kexec_start_address */
64 j s1 83 j s1
65 END(relocate_new_kernel) 84 END(relocate_new_kernel)
66 85
86#ifdef CONFIG_SMP
87/*
88 * Other CPUs should wait until code is relocated and
89 * then start at entry (?) point.
90 */
91LEAF(kexec_smp_wait)
92 PTR_L a0, s_arg0
93 PTR_L a1, s_arg1
94 PTR_L a2, s_arg2
95 PTR_L a3, s_arg3
96 PTR_L s1, kexec_start_address
97
98 /* Non-relocated address works for args and kexec_start_address ( old
99 * kernel is not overwritten). But we need relocated address of
100 * kexec_flag.
101 */
102
103 bal 1f
1041: move t1,ra;
105 PTR_LA t2,1b
106 PTR_LA t0,kexec_flag
107 PTR_SUB t0,t0,t2;
108 PTR_ADD t0,t1,t0;
109
1101: LONG_L s0, (t0)
111 bne s0, zero,1b
112
113 sync
114 j s1
115 END(kexec_smp_wait)
116#endif
117
118#ifdef __mips64
119 /* all PTR's must be aligned to 8 byte in 64-bit mode */
120 .align 3
121#endif
122
123/* All parameters to new kernel are passed in registers a0-a3.
124 * kexec_args[0..3] are uses to prepare register values.
125 */
126
127kexec_args:
128 EXPORT(kexec_args)
129arg0: PTR 0x0
130arg1: PTR 0x0
131arg2: PTR 0x0
132arg3: PTR 0x0
133 .size kexec_args,PTRSIZE*4
134
135#ifdef CONFIG_SMP
136/*
137 * Secondary CPUs may have different kernel parameters in
138 * their registers a0-a3. secondary_kexec_args[0..3] are used
139 * to prepare register values.
140 */
141secondary_kexec_args:
142 EXPORT(secondary_kexec_args)
143s_arg0: PTR 0x0
144s_arg1: PTR 0x0
145s_arg2: PTR 0x0
146s_arg3: PTR 0x0
147 .size secondary_kexec_args,PTRSIZE*4
148kexec_flag:
149 LONG 0x1
150
151#endif
152
67kexec_start_address: 153kexec_start_address:
68 EXPORT(kexec_start_address) 154 EXPORT(kexec_start_address)
69 PTR 0x0 155 PTR 0x0
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 290dc6a1d7a3..8c41187801ce 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -22,6 +22,7 @@
22#include <linux/console.h> 22#include <linux/console.h>
23#include <linux/pfn.h> 23#include <linux/pfn.h>
24#include <linux/debugfs.h> 24#include <linux/debugfs.h>
25#include <linux/kexec.h>
25 26
26#include <asm/addrspace.h> 27#include <asm/addrspace.h>
27#include <asm/bootinfo.h> 28#include <asm/bootinfo.h>
@@ -536,12 +537,64 @@ static void __init arch_mem_init(char **cmdline_p)
536 } 537 }
537 538
538 bootmem_init(); 539 bootmem_init();
540#ifdef CONFIG_KEXEC
541 if (crashk_res.start != crashk_res.end)
542 reserve_bootmem(crashk_res.start,
543 crashk_res.end - crashk_res.start + 1,
544 BOOTMEM_DEFAULT);
545#endif
539 device_tree_init(); 546 device_tree_init();
540 sparse_init(); 547 sparse_init();
541 plat_swiotlb_setup(); 548 plat_swiotlb_setup();
542 paging_init(); 549 paging_init();
543} 550}
544 551
552#ifdef CONFIG_KEXEC
553static inline unsigned long long get_total_mem(void)
554{
555 unsigned long long total;
556
557 total = max_pfn - min_low_pfn;
558 return total << PAGE_SHIFT;
559}
560
561static void __init mips_parse_crashkernel(void)
562{
563 unsigned long long total_mem;
564 unsigned long long crash_size, crash_base;
565 int ret;
566
567 total_mem = get_total_mem();
568 ret = parse_crashkernel(boot_command_line, total_mem,
569 &crash_size, &crash_base);
570 if (ret != 0 || crash_size <= 0)
571 return;
572
573 crashk_res.start = crash_base;
574 crashk_res.end = crash_base + crash_size - 1;
575}
576
577static void __init request_crashkernel(struct resource *res)
578{
579 int ret;
580
581 ret = request_resource(res, &crashk_res);
582 if (!ret)
583 pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n",
584 (unsigned long)((crashk_res.end -
585 crashk_res.start + 1) >> 20),
586 (unsigned long)(crashk_res.start >> 20));
587}
588#else /* !defined(CONFIG_KEXEC) */
589static void __init mips_parse_crashkernel(void)
590{
591}
592
593static void __init request_crashkernel(struct resource *res)
594{
595}
596#endif /* !defined(CONFIG_KEXEC) */
597
545static void __init resource_init(void) 598static void __init resource_init(void)
546{ 599{
547 int i; 600 int i;
@@ -557,6 +610,8 @@ static void __init resource_init(void)
557 /* 610 /*
558 * Request address space for all standard RAM. 611 * Request address space for all standard RAM.
559 */ 612 */
613 mips_parse_crashkernel();
614
560 for (i = 0; i < boot_mem_map.nr_map; i++) { 615 for (i = 0; i < boot_mem_map.nr_map; i++) {
561 struct resource *res; 616 struct resource *res;
562 unsigned long start, end; 617 unsigned long start, end;
@@ -593,6 +648,7 @@ static void __init resource_init(void)
593 */ 648 */
594 request_resource(res, &code_resource); 649 request_resource(res, &code_resource);
595 request_resource(res, &data_resource); 650 request_resource(res, &data_resource);
651 request_crashkernel(res);
596 } 652 }
597} 653}
598 654
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9005bf9fb859..2e6374a589ec 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -386,3 +386,20 @@ void flush_tlb_one(unsigned long vaddr)
386 386
387EXPORT_SYMBOL(flush_tlb_page); 387EXPORT_SYMBOL(flush_tlb_page);
388EXPORT_SYMBOL(flush_tlb_one); 388EXPORT_SYMBOL(flush_tlb_one);
389
390#if defined(CONFIG_KEXEC)
391void (*dump_ipi_function_ptr)(void *) = NULL;
392void dump_send_ipi(void (*dump_ipi_callback)(void *))
393{
394 int i;
395 int cpu = smp_processor_id();
396
397 dump_ipi_function_ptr = dump_ipi_callback;
398 smp_mb();
399 for_each_online_cpu(i)
400 if (i != cpu)
401 mp_ops->send_ipi_single(i, SMP_DUMP);
402
403}
404EXPORT_SYMBOL(dump_send_ipi);
405#endif
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9be3df1fa8a4..da0c29422cf2 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -13,6 +13,7 @@
13 */ 13 */
14#include <linux/bug.h> 14#include <linux/bug.h>
15#include <linux/compiler.h> 15#include <linux/compiler.h>
16#include <linux/kexec.h>
16#include <linux/init.h> 17#include <linux/init.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/module.h> 19#include <linux/module.h>
@@ -409,6 +410,9 @@ void __noreturn die(const char *str, struct pt_regs *regs)
409 panic("Fatal exception"); 410 panic("Fatal exception");
410 } 411 }
411 412
413 if (regs && kexec_should_crash(current))
414 crash_kexec(regs);
415
412 do_exit(sig); 416 do_exit(sig);
413} 417}
414 418