aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/machine_kexec.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-10-11 12:14:58 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-12-13 10:46:47 -0500
commit7aa1c8f47e7e792d11f898cbdddaf6fa21ff08cc (patch)
treee34986c087ab7a9f91c8303eda7f13736e315905 /arch/mips/kernel/machine_kexec.c
parent98cdee0eae861e8d25c147a72c5f309e883f4ed8 (diff)
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: Maxim 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: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/machine_kexec.c')
-rw-r--r--arch/mips/kernel/machine_kexec.c33
1 files changed, 29 insertions, 4 deletions
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}