diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-10-11 12:14:58 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-12-13 10:46:47 -0500 |
commit | 7aa1c8f47e7e792d11f898cbdddaf6fa21ff08cc (patch) | |
tree | e34986c087ab7a9f91c8303eda7f13736e315905 /arch/mips/kernel/machine_kexec.c | |
parent | 98cdee0eae861e8d25c147a72c5f309e883f4ed8 (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.c | 33 |
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; | |||
19 | extern unsigned long kexec_start_address; | 19 | extern unsigned long kexec_start_address; |
20 | extern unsigned long kexec_indirection_page; | 20 | extern unsigned long kexec_indirection_page; |
21 | 21 | ||
22 | int (*_machine_kexec_prepare)(struct kimage *) = NULL; | ||
23 | void (*_machine_kexec_shutdown)(void) = NULL; | ||
24 | void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; | ||
25 | #ifdef CONFIG_SMP | ||
26 | void (*relocated_kexec_smp_wait) (void *); | ||
27 | atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); | ||
28 | #endif | ||
29 | |||
22 | int | 30 | int |
23 | machine_kexec_prepare(struct kimage *kimage) | 31 | machine_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) | |||
33 | void | 43 | void |
34 | machine_shutdown(void) | 44 | machine_shutdown(void) |
35 | { | 45 | { |
46 | if (_machine_kexec_shutdown) | ||
47 | _machine_kexec_shutdown(); | ||
36 | } | 48 | } |
37 | 49 | ||
38 | void | 50 | void |
39 | machine_crash_shutdown(struct pt_regs *regs) | 51 | machine_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 | ||
43 | typedef void (*noretfun_t)(void) __attribute__((noreturn)); | 59 | typedef void (*noretfun_t)(void) __noreturn; |
44 | 60 | ||
45 | void | 61 | void |
46 | machine_kexec(struct kimage *image) | 62 | machine_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 | } |