diff options
author | Matthew McClintock <msm@freescale.com> | 2010-07-21 17:14:53 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2010-08-02 15:36:28 -0400 |
commit | f933a41e419a954ef90605224e02c3ded78f3372 (patch) | |
tree | 996641c36b9c8f01e5f0c84cde19221db4c7ba0f | |
parent | e8e5c2155b0035b6e04f29be67f6444bc914005b (diff) |
powerpc/85xx: kexec for SMP 85xx BookE systems
Adds support for kexec on 85xx machines for the BookE platform.
Including support for SMP machines
Based off work from Maxim Uvarov <muvarov@mvista.com>
Signed-off-by: Matthew McClintock <msm@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/Kconfig | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/smp.c | 63 |
2 files changed, 68 insertions, 5 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4fa42038104..0e3fd3a489d 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -352,7 +352,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE | |||
352 | 352 | ||
353 | config KEXEC | 353 | config KEXEC |
354 | bool "kexec system call (EXPERIMENTAL)" | 354 | bool "kexec system call (EXPERIMENTAL)" |
355 | depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL | 355 | depends on (PPC_BOOK3S || FSL_BOOKE) && EXPERIMENTAL |
356 | help | 356 | help |
357 | kexec is a system call that implements the ability to shutdown your | 357 | kexec is a system call that implements the ability to shutdown your |
358 | current kernel, and to start another kernel. It is like a reboot | 358 | current kernel, and to start another kernel. It is like a reboot |
@@ -369,8 +369,8 @@ config KEXEC | |||
369 | 369 | ||
370 | config CRASH_DUMP | 370 | config CRASH_DUMP |
371 | bool "Build a kdump crash kernel" | 371 | bool "Build a kdump crash kernel" |
372 | depends on PPC64 || 6xx | 372 | depends on PPC64 || 6xx || FSL_BOOKE |
373 | select RELOCATABLE if PPC64 | 373 | select RELOCATABLE if PPC64 || FSL_BOOKE |
374 | help | 374 | help |
375 | Build a kernel suitable for use as a kdump capture kernel. | 375 | Build a kernel suitable for use as a kdump capture kernel. |
376 | The same kernel binary can be used as production kernel and dump | 376 | The same kernel binary can be used as production kernel and dump |
@@ -898,7 +898,7 @@ config KERNEL_START_BOOL | |||
898 | config KERNEL_START | 898 | config KERNEL_START |
899 | hex "Virtual address of kernel base" if KERNEL_START_BOOL | 899 | hex "Virtual address of kernel base" if KERNEL_START_BOOL |
900 | default PAGE_OFFSET if PAGE_OFFSET_BOOL | 900 | default PAGE_OFFSET if PAGE_OFFSET_BOOL |
901 | default "0xc2000000" if CRASH_DUMP | 901 | default "0xc2000000" if CRASH_DUMP && !RELOCATABLE |
902 | default "0xc0000000" | 902 | default "0xc0000000" |
903 | 903 | ||
904 | config PHYSICAL_START_BOOL | 904 | config PHYSICAL_START_BOOL |
@@ -911,7 +911,7 @@ config PHYSICAL_START_BOOL | |||
911 | 911 | ||
912 | config PHYSICAL_START | 912 | config PHYSICAL_START |
913 | hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL | 913 | hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL |
914 | default "0x02000000" if PPC_STD_MMU && CRASH_DUMP | 914 | default "0x02000000" if PPC_STD_MMU && CRASH_DUMP && !RELOCATABLE |
915 | default "0x00000000" | 915 | default "0x00000000" |
916 | 916 | ||
917 | config PHYSICAL_ALIGN | 917 | config PHYSICAL_ALIGN |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 4c3cde911c7..a6b106557be 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/kexec.h> | ||
18 | 19 | ||
19 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
@@ -24,6 +25,7 @@ | |||
24 | #include <asm/dbell.h> | 25 | #include <asm/dbell.h> |
25 | 26 | ||
26 | #include <sysdev/fsl_soc.h> | 27 | #include <sysdev/fsl_soc.h> |
28 | #include <sysdev/mpic.h> | ||
27 | 29 | ||
28 | extern void __early_start(void); | 30 | extern void __early_start(void); |
29 | 31 | ||
@@ -105,8 +107,64 @@ smp_85xx_setup_cpu(int cpu_nr) | |||
105 | 107 | ||
106 | struct smp_ops_t smp_85xx_ops = { | 108 | struct smp_ops_t smp_85xx_ops = { |
107 | .kick_cpu = smp_85xx_kick_cpu, | 109 | .kick_cpu = smp_85xx_kick_cpu, |
110 | #ifdef CONFIG_KEXEC | ||
111 | .give_timebase = smp_generic_give_timebase, | ||
112 | .take_timebase = smp_generic_take_timebase, | ||
113 | #endif | ||
108 | }; | 114 | }; |
109 | 115 | ||
116 | #ifdef CONFIG_KEXEC | ||
117 | static int kexec_down_cpus = 0; | ||
118 | |||
119 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) | ||
120 | { | ||
121 | mpic_teardown_this_cpu(1); | ||
122 | |||
123 | /* When crashing, this gets called on all CPU's we only | ||
124 | * take down the non-boot cpus */ | ||
125 | if (smp_processor_id() != boot_cpuid) | ||
126 | { | ||
127 | local_irq_disable(); | ||
128 | kexec_down_cpus++; | ||
129 | |||
130 | while (1); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void mpc85xx_smp_kexec_down(void *arg) | ||
135 | { | ||
136 | if (ppc_md.kexec_cpu_down) | ||
137 | ppc_md.kexec_cpu_down(0,1); | ||
138 | } | ||
139 | |||
140 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | ||
141 | { | ||
142 | int timeout = 2000; | ||
143 | int i; | ||
144 | |||
145 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); | ||
146 | |||
147 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | ||
148 | |||
149 | while ( (kexec_down_cpus != (num_online_cpus() - 1)) && | ||
150 | ( timeout > 0 ) ) | ||
151 | { | ||
152 | timeout--; | ||
153 | } | ||
154 | |||
155 | if ( !timeout ) | ||
156 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); | ||
157 | |||
158 | for (i = 0; i < num_present_cpus(); i++) | ||
159 | { | ||
160 | if ( i == smp_processor_id() ) continue; | ||
161 | mpic_reset_core(i); | ||
162 | } | ||
163 | |||
164 | default_machine_kexec(image); | ||
165 | } | ||
166 | #endif /* CONFIG_KEXEC */ | ||
167 | |||
110 | void __init mpc85xx_smp_init(void) | 168 | void __init mpc85xx_smp_init(void) |
111 | { | 169 | { |
112 | struct device_node *np; | 170 | struct device_node *np; |
@@ -124,4 +182,9 @@ void __init mpc85xx_smp_init(void) | |||
124 | BUG_ON(!smp_85xx_ops.message_pass); | 182 | BUG_ON(!smp_85xx_ops.message_pass); |
125 | 183 | ||
126 | smp_ops = &smp_85xx_ops; | 184 | smp_ops = &smp_85xx_ops; |
185 | |||
186 | #ifdef CONFIG_KEXEC | ||
187 | ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down; | ||
188 | ppc_md.machine_kexec = mpc85xx_smp_machine_kexec; | ||
189 | #endif | ||
127 | } | 190 | } |