diff options
author | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2010-03-04 22:43:18 -0500 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2010-05-05 09:27:22 -0400 |
commit | fc5e709731429bc2db27897630e7c0089f297680 (patch) | |
tree | 95d3f7a7a43b549b3347318245e752f699fd8223 | |
parent | e7f75ad01d590243904c2d95ab47e6b2e9ef6dad (diff) |
powerpc/476: add machine check handler for 47x core
The 47x core's MCSR varies from 44x, so it needs it's own machine check
handler.
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
-rw-r--r-- | arch/powerpc/include/asm/cputable.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 40 |
3 files changed, 42 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 97ab5089df67..e3cba4e1eb34 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -72,6 +72,7 @@ extern int machine_check_4xx(struct pt_regs *regs); | |||
72 | extern int machine_check_440A(struct pt_regs *regs); | 72 | extern int machine_check_440A(struct pt_regs *regs); |
73 | extern int machine_check_e500(struct pt_regs *regs); | 73 | extern int machine_check_e500(struct pt_regs *regs); |
74 | extern int machine_check_e200(struct pt_regs *regs); | 74 | extern int machine_check_e200(struct pt_regs *regs); |
75 | extern int machine_check_47x(struct pt_regs *regs); | ||
75 | 76 | ||
76 | /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ | 77 | /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ |
77 | struct cpu_spec { | 78 | struct cpu_spec { |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index a1d845839727..ad6baf834a76 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -1712,6 +1712,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1712 | MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL, | 1712 | MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL, |
1713 | .icache_bsize = 32, | 1713 | .icache_bsize = 32, |
1714 | .dcache_bsize = 128, | 1714 | .dcache_bsize = 128, |
1715 | .machine_check = machine_check_47x, | ||
1715 | .platform = "ppc470", | 1716 | .platform = "ppc470", |
1716 | }, | 1717 | }, |
1717 | { /* default match */ | 1718 | { /* default match */ |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 29d128eb6c43..ca7ce85ebc2e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -380,6 +380,46 @@ int machine_check_440A(struct pt_regs *regs) | |||
380 | } | 380 | } |
381 | return 0; | 381 | return 0; |
382 | } | 382 | } |
383 | |||
384 | int machine_check_47x(struct pt_regs *regs) | ||
385 | { | ||
386 | unsigned long reason = get_mc_reason(regs); | ||
387 | u32 mcsr; | ||
388 | |||
389 | printk(KERN_ERR "Machine check in kernel mode.\n"); | ||
390 | if (reason & ESR_IMCP) { | ||
391 | printk(KERN_ERR | ||
392 | "Instruction Synchronous Machine Check exception\n"); | ||
393 | mtspr(SPRN_ESR, reason & ~ESR_IMCP); | ||
394 | return 0; | ||
395 | } | ||
396 | mcsr = mfspr(SPRN_MCSR); | ||
397 | if (mcsr & MCSR_IB) | ||
398 | printk(KERN_ERR "Instruction Read PLB Error\n"); | ||
399 | if (mcsr & MCSR_DRB) | ||
400 | printk(KERN_ERR "Data Read PLB Error\n"); | ||
401 | if (mcsr & MCSR_DWB) | ||
402 | printk(KERN_ERR "Data Write PLB Error\n"); | ||
403 | if (mcsr & MCSR_TLBP) | ||
404 | printk(KERN_ERR "TLB Parity Error\n"); | ||
405 | if (mcsr & MCSR_ICP) { | ||
406 | flush_instruction_cache(); | ||
407 | printk(KERN_ERR "I-Cache Parity Error\n"); | ||
408 | } | ||
409 | if (mcsr & MCSR_DCSP) | ||
410 | printk(KERN_ERR "D-Cache Search Parity Error\n"); | ||
411 | if (mcsr & PPC47x_MCSR_GPR) | ||
412 | printk(KERN_ERR "GPR Parity Error\n"); | ||
413 | if (mcsr & PPC47x_MCSR_FPR) | ||
414 | printk(KERN_ERR "FPR Parity Error\n"); | ||
415 | if (mcsr & PPC47x_MCSR_IPR) | ||
416 | printk(KERN_ERR "Machine Check exception is imprecise\n"); | ||
417 | |||
418 | /* Clear MCSR */ | ||
419 | mtspr(SPRN_MCSR, mcsr); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
383 | #elif defined(CONFIG_E500) | 423 | #elif defined(CONFIG_E500) |
384 | int machine_check_e500(struct pt_regs *regs) | 424 | int machine_check_e500(struct pt_regs *regs) |
385 | { | 425 | { |