diff mbox

[RFC:,04/13] powerpc/476: add machine check handler for 47x core

Message ID 20100301191323.20987.13284.sendpatchset@norville.austin.ibm.com (mailing list archive)
State Superseded
Delegated to: Josh Boyer
Headers show

Commit Message

Dave Kleikamp March 1, 2010, 12:13 p.m. UTC
powerpc/476: add machine check handler for 47x core

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

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>
---

 arch/powerpc/include/asm/cputable.h  |    1 +
 arch/powerpc/include/asm/reg_booke.h |    2 +-
 arch/powerpc/kernel/cputable.c       |    1 +
 arch/powerpc/kernel/traps.c          |   38 ++++++++++++++++++++++++++++++++++
 4 files changed, 41 insertions(+), 1 deletions(-)

Comments

Olof Johansson March 1, 2010, 9:08 p.m. UTC | #1
On Mon, Mar 01, 2010 at 05:13:23AM -0700, Dave Kleikamp wrote:
> powerpc/476: add machine check handler for 47x core
> 
> From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
> 
> The 47x core's MCSR varies from 44x, so it needs it's own machine check
> handler.


> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -376,6 +376,44 @@ int machine_check_440A(struct pt_regs *regs)
>  	}
>  	return 0;
>  }
> +
> +int machine_check_47x(struct pt_regs *regs)
> +{
> +	unsigned long reason = get_mc_reason(regs);
> +
> +	printk("Machine check in kernel mode.\n");

It's quite possible that the other machine check handlers don't have
printk KERN_-levels on them but it would be a good idea to use them here.

> +	if (reason & ESR_IMCP){
> +		printk("Instruction Synchronous Machine Check exception\n");
> +		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
> +	}
> +	else {

} else {

Or, rather, add an early return above and you can just remove one level of indentation below.


> +		u32 mcsr = mfspr(SPRN_MCSR);
> +		if (mcsr & MCSR_IB)
> +			printk("Instruction Read PLB Error\n");
> +		if (mcsr & MCSR_DRB)
> +			printk("Data Read PLB Error\n");
> +		if (mcsr & MCSR_DWB)
> +			printk("Data Write PLB Error\n");
> +		if (mcsr & MCSR_TLBP)
> +			printk("TLB Parity Error\n");
> +		if (mcsr & MCSR_ICP){
> +			flush_instruction_cache();
> +			printk("I-Cache Parity Error\n");
> +		}
> +		if (mcsr & MCSR_DCSP)
> +			printk("D-Cache Search Parity Error\n");
> +		if (mcsr & PPC47x_MCSR_GPR)
> +			printk("GPR Parity Error\n");
> +		if (mcsr & PPC47x_MCSR_FPR)
> +			printk("FPR Parity Error\n");
> +		if (mcsr & PPC47x_MCSR_IMP)
> +			printk("Machine Check exception is imprecise\n");
> +
> +		/* Clear MCSR */
> +		mtspr(SPRN_MCSR, mcsr);
> +	}
> +	return 0;
> +}
Dave Kleikamp March 1, 2010, 11:22 p.m. UTC | #2
On Mon, 2010-03-01 at 15:08 -0600, Olof Johansson wrote:
> On Mon, Mar 01, 2010 at 05:13:23AM -0700, Dave Kleikamp wrote:
> > powerpc/476: add machine check handler for 47x core
> > 
> > From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
> > 
> > The 47x core's MCSR varies from 44x, so it needs it's own machine check
> > handler.
> 
> 
> > --- a/arch/powerpc/kernel/traps.c
> > +++ b/arch/powerpc/kernel/traps.c
> > @@ -376,6 +376,44 @@ int machine_check_440A(struct pt_regs *regs)
> >  	}
> >  	return 0;
> >  }
> > +
> > +int machine_check_47x(struct pt_regs *regs)
> > +{
> > +	unsigned long reason = get_mc_reason(regs);
> > +
> > +	printk("Machine check in kernel mode.\n");
> 
> It's quite possible that the other machine check handlers don't have
> printk KERN_-levels on them but it would be a good idea to use them here.

Right.  As it's new code, it should be as correct as possible.

> > +	if (reason & ESR_IMCP){
> > +		printk("Instruction Synchronous Machine Check exception\n");
> > +		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
> > +	}
> > +	else {
> 
> } else {
> 
> Or, rather, add an early return above and you can just remove one level of indentation below.

agreed.

Thanks,
Shaggy
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 75b774e..9fff628 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);
 extern int machine_check_440A(struct pt_regs *regs);
 extern int machine_check_e500(struct pt_regs *regs);
 extern int machine_check_e200(struct pt_regs *regs);
+extern int machine_check_47x(struct pt_regs *regs);
 
 /* NOTE WELL: Update identify_cpu() if fields are added or removed! */
 struct cpu_spec {
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index ee61a9d..a9245b9 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -194,7 +194,7 @@ 
 #ifdef CONFIG_PPC_47x
 #define PPC47x_MCSR_GPR	0x01000000 /* GPR parity error */
 #define PPC47x_MCSR_FPR	0x00800000 /* FPR parity error */
-#define PPC47x_MCSR_IPR	0x00400000 /* Imprecise Machine Check Exception */
+#define PPC47x_MCSR_IMP	0x00400000 /* Imprecise Machine Check Exception */
 #endif
 
 #ifdef CONFIG_E500
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 338ac47..7b2a67c 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1712,6 +1712,7 @@  static struct cpu_spec __initdata cpu_specs[] = {
 			MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 128,
+		.machine_check		= machine_check_47x,
 		.platform		= "ppc470",
 	},
 	{	/* default match */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d069ff8..66617b6 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -376,6 +376,44 @@  int machine_check_440A(struct pt_regs *regs)
 	}
 	return 0;
 }
+
+int machine_check_47x(struct pt_regs *regs)
+{
+	unsigned long reason = get_mc_reason(regs);
+
+	printk("Machine check in kernel mode.\n");
+	if (reason & ESR_IMCP){
+		printk("Instruction Synchronous Machine Check exception\n");
+		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+	}
+	else {
+		u32 mcsr = mfspr(SPRN_MCSR);
+		if (mcsr & MCSR_IB)
+			printk("Instruction Read PLB Error\n");
+		if (mcsr & MCSR_DRB)
+			printk("Data Read PLB Error\n");
+		if (mcsr & MCSR_DWB)
+			printk("Data Write PLB Error\n");
+		if (mcsr & MCSR_TLBP)
+			printk("TLB Parity Error\n");
+		if (mcsr & MCSR_ICP){
+			flush_instruction_cache();
+			printk("I-Cache Parity Error\n");
+		}
+		if (mcsr & MCSR_DCSP)
+			printk("D-Cache Search Parity Error\n");
+		if (mcsr & PPC47x_MCSR_GPR)
+			printk("GPR Parity Error\n");
+		if (mcsr & PPC47x_MCSR_FPR)
+			printk("FPR Parity Error\n");
+		if (mcsr & PPC47x_MCSR_IMP)
+			printk("Machine Check exception is imprecise\n");
+
+		/* Clear MCSR */
+		mtspr(SPRN_MCSR, mcsr);
+	}
+	return 0;
+}
 #elif defined(CONFIG_E500)
 int machine_check_e500(struct pt_regs *regs)
 {