diff options
author | Andre Detsch <adetsch@br.ibm.com> | 2007-07-20 15:39:27 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@klappe.arndb.de> | 2007-07-20 15:41:43 -0400 |
commit | 8d2655e621bfc3c3f925016f881a36739d479f69 (patch) | |
tree | 773d3f13c31850a719832bca93fd0d27ce1a9d8b | |
parent | dbdf04c40161f81d74e27f04e201acb3a5dfad69 (diff) |
[CELL] saving spus information for kexec crash
This patch adds support for investigating spus information after a
kernel crash event, through kdump vmcore file.
Implementation is based on xmon code, but the new functionality was
kept independent from xmon.
Signed-off-by: Lucio Jose Herculano Correia <luciojhc@br.ibm.com>
Signed-off-by: Andre Detsch <adetsch@br.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-rw-r--r-- | arch/powerpc/kernel/crash.c | 67 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 2 | ||||
-rw-r--r-- | include/asm-powerpc/spu.h | 8 |
3 files changed, 76 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index d3f2080d2eee..37658ea417fa 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -219,6 +219,72 @@ void crash_kexec_secondary(struct pt_regs *regs) | |||
219 | cpus_in_sr = CPU_MASK_NONE; | 219 | cpus_in_sr = CPU_MASK_NONE; |
220 | } | 220 | } |
221 | #endif | 221 | #endif |
222 | #ifdef CONFIG_SPU_BASE | ||
223 | |||
224 | #include <asm/spu.h> | ||
225 | #include <asm/spu_priv1.h> | ||
226 | |||
227 | struct crash_spu_info { | ||
228 | struct spu *spu; | ||
229 | u32 saved_spu_runcntl_RW; | ||
230 | u32 saved_spu_status_R; | ||
231 | u32 saved_spu_npc_RW; | ||
232 | u64 saved_mfc_sr1_RW; | ||
233 | u64 saved_mfc_dar; | ||
234 | u64 saved_mfc_dsisr; | ||
235 | }; | ||
236 | |||
237 | #define CRASH_NUM_SPUS 16 /* Enough for current hardware */ | ||
238 | static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS]; | ||
239 | |||
240 | static void crash_kexec_stop_spus(void) | ||
241 | { | ||
242 | struct spu *spu; | ||
243 | int i; | ||
244 | u64 tmp; | ||
245 | |||
246 | for (i = 0; i < CRASH_NUM_SPUS; i++) { | ||
247 | if (!crash_spu_info[i].spu) | ||
248 | continue; | ||
249 | |||
250 | spu = crash_spu_info[i].spu; | ||
251 | |||
252 | crash_spu_info[i].saved_spu_runcntl_RW = | ||
253 | in_be32(&spu->problem->spu_runcntl_RW); | ||
254 | crash_spu_info[i].saved_spu_status_R = | ||
255 | in_be32(&spu->problem->spu_status_R); | ||
256 | crash_spu_info[i].saved_spu_npc_RW = | ||
257 | in_be32(&spu->problem->spu_npc_RW); | ||
258 | |||
259 | crash_spu_info[i].saved_mfc_dar = spu_mfc_dar_get(spu); | ||
260 | crash_spu_info[i].saved_mfc_dsisr = spu_mfc_dsisr_get(spu); | ||
261 | tmp = spu_mfc_sr1_get(spu); | ||
262 | crash_spu_info[i].saved_mfc_sr1_RW = tmp; | ||
263 | |||
264 | tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
265 | spu_mfc_sr1_set(spu, tmp); | ||
266 | |||
267 | __delay(200); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | void crash_register_spus(struct list_head *list) | ||
272 | { | ||
273 | struct spu *spu; | ||
274 | |||
275 | list_for_each_entry(spu, list, full_list) { | ||
276 | if (WARN_ON(spu->number >= CRASH_NUM_SPUS)) | ||
277 | continue; | ||
278 | |||
279 | crash_spu_info[spu->number].spu = spu; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | #else | ||
284 | static inline void crash_kexec_stop_spus(void) | ||
285 | { | ||
286 | } | ||
287 | #endif /* CONFIG_SPU_BASE */ | ||
222 | 288 | ||
223 | void default_machine_crash_shutdown(struct pt_regs *regs) | 289 | void default_machine_crash_shutdown(struct pt_regs *regs) |
224 | { | 290 | { |
@@ -254,6 +320,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
254 | crash_save_cpu(regs, crashing_cpu); | 320 | crash_save_cpu(regs, crashing_cpu); |
255 | crash_kexec_prepare_cpus(crashing_cpu); | 321 | crash_kexec_prepare_cpus(crashing_cpu); |
256 | cpu_set(crashing_cpu, cpus_in_crash); | 322 | cpu_set(crashing_cpu, cpus_in_crash); |
323 | crash_kexec_stop_spus(); | ||
257 | if (ppc_md.kexec_cpu_down) | 324 | if (ppc_md.kexec_cpu_down) |
258 | ppc_md.kexec_cpu_down(1, 0); | 325 | ppc_md.kexec_cpu_down(1, 0); |
259 | } | 326 | } |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 96a8f609690c..c563066e640d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -676,7 +676,7 @@ static int __init init_spu_base(void) | |||
676 | } | 676 | } |
677 | 677 | ||
678 | xmon_register_spus(&spu_full_list); | 678 | xmon_register_spus(&spu_full_list); |
679 | 679 | crash_register_spus(&spu_full_list); | |
680 | spu_add_sysdev_attr(&attr_stat); | 680 | spu_add_sysdev_attr(&attr_stat); |
681 | 681 | ||
682 | return 0; | 682 | return 0; |
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index eedc828cef2d..42d88a6d2dfd 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h | |||
@@ -188,6 +188,14 @@ int spu_irq_class_0_bottom(struct spu *spu); | |||
188 | int spu_irq_class_1_bottom(struct spu *spu); | 188 | int spu_irq_class_1_bottom(struct spu *spu); |
189 | void spu_irq_setaffinity(struct spu *spu, int cpu); | 189 | void spu_irq_setaffinity(struct spu *spu, int cpu); |
190 | 190 | ||
191 | #ifdef CONFIG_KEXEC | ||
192 | void crash_register_spus(struct list_head *list); | ||
193 | #else | ||
194 | static inline void crash_register_spus(struct list_head *list) | ||
195 | { | ||
196 | } | ||
197 | #endif | ||
198 | |||
191 | extern void spu_invalidate_slbs(struct spu *spu); | 199 | extern void spu_invalidate_slbs(struct spu *spu); |
192 | extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm); | 200 | extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm); |
193 | 201 | ||