Skip to contentSkip to conversation

Reworking machine check handling and Fix 440/440A

PATCH In review Benjamin Herrenschmidt 2 participants 5 messages Dec 21, 2007 – Dec 24, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/21 Reworking machine check handling and Fix 440/440A

This adds a cputable function pointer for the CPU-side machine check handling. The semantic is still the same as the old one, the one in ppc_md. overrides the one in cputable, though ultimately we'll want to change that so the CPU gets first.

This removes CONFIG_440A which was a problem for multiplatform kernels and instead fixes up the IVOR at runtime from a setup_cpu function. The "A" version of the machine check also tweaks the regs->trap value to differenciate the 2 versions at the C level.

---

 arch/powerpc/kernel/cpu_setup_44x.S |    9 +++
 arch/powerpc/kernel/cputable.c      |  105 ++++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/head_44x.S      |   14 +++-
 arch/powerpc/kernel/head_booke.h    |    2 
 arch/powerpc/kernel/traps.c         |   62 ++++++++++++++++-----
 arch/powerpc/platforms/44x/Kconfig  |    5 -
 arch/ppc/kernel/traps.c             |   98 ++++++++++++++++++++++-----------
 include/asm-powerpc/cputable.h      |   13 ++++
 include/asm-powerpc/ptrace.h        |    3 -
 include/asm-powerpc/reg_booke.h     |    3 -
 include/asm-ppc/reg_booke.h         |    2 
 11 files changed, 258 insertions(+), 58 deletions(-)
arch/powerpc/kernel/cpu_setup_44x.S +9 -0
@@ -23,11 +23,20 @@ _GLOBAL(__setup_cpu_440epx)
 	mflr	r4
 	bl	__init_fpu_44x
 	bl	__plb_disable_wrp
+	bl	__fixup_440A_mcheck
 	mtlr	r4
 	blr
 _GLOBAL(__setup_cpu_440grx)
 	b	__plb_disable_wrp
+_GLOBAL(__setup_cpu_440gx)
+_GLOBAL(__setup_cpu_440spe)
+	b	__fixup_440A_mcheck
 
+ /* Temporary fixup for arch/ppc until we kill the whole thing */
+#ifndef CONFIG_PPC_MERGE
+_GLOBAL(__fixup_440A_mcheck)
+	blr
+#endif
 
 /* enable APU between CPU and FPU */
 _GLOBAL(__init_fpu_44x)
arch/powerpc/kernel/cputable.c +105 -0

694 lines not on this page · raw message

arch/powerpc/kernel/head_44x.S +10 -4
Index: linux-merge/arch/powerpc/kernel/head_44x.S
===================================================================
@@ -289,11 +289,8 @@ interrupt_base:
 	CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
 
 	/* Machine Check Interrupt */
-#ifdef CONFIG_440A
-	MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#else
 	CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#endif
+	MCHECK_EXCEPTION(0x0210, MachineCheckA, machine_check_exception)
 
 	/* Data Storage Interrupt */
 	START_EXCEPTION(DataStorage)
@@ -674,6 +671,15 @@ finish_tlb_load:
  */
 
 /*
+ * Adjust the machine check IVOR on 440A cores
+ */
+_GLOBAL(__fixup_440A_mcheck)
+	li	r3,MachineCheckA@l
+	mtspr	SPRN_IVOR1,r3
+	sync
+	blr
+
+/*
  * extern void giveup_altivec(struct task_struct *prev)
  *
  * The 44x core does not have an AltiVec unit.
arch/powerpc/kernel/traps.c +49 -13

117 lines not on this page · raw message

arch/powerpc/platforms/44x/Kconfig +0 -5
Index: linux-merge/arch/powerpc/platforms/44x/Kconfig
===================================================================
@@ -62,11 +62,6 @@ config 440GX
 config 440SP
 	bool
 
-config 440A
-	bool
-	depends on 440GX || 440EPX
-	default y
-
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
 	bool
arch/powerpc/kernel/head_booke.h +1 -1
Index: linux-merge/arch/powerpc/kernel/head_booke.h
===================================================================
@@ -166,7 +166,7 @@ label:
 	mfspr	r5,SPRN_ESR;					\
 	stw	r5,_ESR(r11);					\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+	EXC_XFER_TEMPLATE(hdlr, n+4, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
 			  NOCOPY, mcheck_transfer_to_handler,   \
 			  ret_from_mcheck_exc)
 
include/asm-powerpc/ptrace.h +2 -1
Index: linux-merge/include/asm-powerpc/ptrace.h
===================================================================
@@ -106,7 +106,8 @@ extern int ptrace_put_reg(struct task_st
  */
 #define FULL_REGS(regs)		(((regs)->trap & 1) == 0)
 #ifndef __powerpc64__
-#define IS_CRITICAL_EXC(regs)	(((regs)->trap & 2) == 0)
+#define IS_CRITICAL_EXC(regs)	(((regs)->trap & 2) != 0)
+#define IS_MCHECK_EXC(regs)	(((regs)->trap & 4) != 0)
 #endif /* ! __powerpc64__ */
 #define TRAP(regs)		((regs)->trap & ~0xF)
 #ifdef __powerpc64__
include/asm-powerpc/reg_booke.h +1 -2
Index: linux-merge/include/asm-powerpc/reg_booke.h
===================================================================
@@ -218,7 +218,6 @@
 #define	CCR1_TCS	0x00000080 /* Timer Clock Select */
 
 /* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
 #define MCSR_MCS	0x80000000 /* Machine Check Summary */
 #define MCSR_IB		0x40000000 /* Instruction PLB Error */
 #define MCSR_DRB	0x20000000 /* Data Read PLB Error */
@@ -228,7 +227,7 @@
 #define MCSR_DCSP	0x02000000 /* D-Cache Search Parity Error */
 #define MCSR_DCFP	0x01000000 /* D-Cache Flush Parity Error */
 #define MCSR_IMPE	0x00800000 /* Imprecise Machine Check Exception */
-#endif
+
 #ifdef CONFIG_E500
 #define MCSR_MCP 	0x80000000UL /* Machine Check Input Pin */
 #define MCSR_ICPERR 	0x40000000UL /* I-Cache Parity Error */
include/asm-powerpc/cputable.h +13 -0
Index: linux-merge/include/asm-powerpc/cputable.h
===================================================================
@@ -57,6 +57,14 @@ enum powerpc_pmc_type {
 	PPC_PMC_PA6T = 2,
 };
 
+struct pt_regs;
+
+extern int machine_check_generic(struct pt_regs *regs);
+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);
+
 /* NOTE WELL: Update identify_cpu() if fields are added or removed! */
 struct cpu_spec {
 	/* CPU is matched via (PVR & pvr_mask) == pvr_value */
@@ -97,6 +105,11 @@ struct cpu_spec {
 
 	/* Name of processor class, for the ELF AT_PLATFORM entry */
 	char		*platform;
+
+	/* Processor specific machine check handling. Return negative
+	 * if the error is fatal, 1 if it was fully recovered and 0 to
+	 * pass up (not CPU originated) */
+	int		(*machine_check)(struct pt_regs *regs);
 };
 
 extern struct cpu_spec		*cur_cpu_spec;
arch/ppc/kernel/traps.c +67 -31

147 lines not on this page · raw message

include/asm-ppc/reg_booke.h +1 -1
Index: linux-merge/include/asm-ppc/reg_booke.h
===================================================================
@@ -207,7 +207,7 @@
 #define	CCR1_TCS	0x00000080 /* Timer Clock Select */
 
 /* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
+#ifdef CONFIG_44x
 #define MCSR_MCS	0x80000000 /* Machine Check Summary */
 #define MCSR_IB		0x40000000 /* Instruction PLB Error */
 #define MCSR_DRB	0x20000000 /* Data Read PLB Error */
#1 lore raw

include/asm-ppc/reg_booke.h line 210

Quoted 10 lines · On Fri, 21 Dec 2007 15:39:21 +1100 Benjamin Herrenschmidt…

Index: linux-merge/include/asm-ppc/reg_booke.h
===================================================================

include/asm-ppc/reg_booke.h +1 -1
@@ -207,7 +207,7 @@
 #define	CCR1_TCS	0x00000080 /* Timer Clock Select */
 
 /* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
+#ifdef CONFIG_44x

Should be #ifdef CONFIG_4xx as I pointed out last time. I'll fix it when I commit.

josh

#2 lore raw
Quoted 11 lines · Josh Boyer
Quoted 7 lines · On Fri, 21 Dec 2007 15:39:21 +1100 Benjamin Herrenschmidt…

Index: linux-merge/include/asm-ppc/reg_booke.h
===================================================================

include/asm-ppc/reg_booke.h +0 -0
@@ -207,7 +207,7 @@
 #define	CCR1_TCS	0x00000080 /* Timer Clock Select */
 
Quoted 6 lines

include/asm-ppc/reg_booke.h line 210

Quoted 3 lines
include/asm-ppc/reg_booke.h +1 -1
 /* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
+#ifdef CONFIG_44x

Should be #ifdef CONFIG_4xx as I pointed out last time. I'll fix it when I commit.

Ah weird, I though I fixed it... I must have fixed powerpc and not ppc.

Ben.

#3 lore raw
In reply to Benjamin Herrenschmidt
Quoted 4 lines · On Fri, 21 Dec 2007 15:39:21 +1100 Benjamin Herrenschmidt…

Index: linux-merge/arch/powerpc/kernel/traps.c
===================================================================

arch/powerpc/kernel/traps.c +0 -0

[snip]

arch/powerpc/kernel/traps.c static int generic_machine_check_excepti · line 388

Quoted 5 lines
arch/powerpc/kernel/traps.c +4 -1
-#elif defined (CONFIG_E500)
+	return 0;
+}
+#elif defined(CONFIG_E500)
+int machine_check_e500(struct pt_regs *regs)

This...

Quoted 7 lines
arch/powerpc/kernel/traps.c +3 -0
+{
+	unsigned long reason = get_mc_reason(regs);
+
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from MCSR=%lx): ", reason);

arch/powerpc/kernel/traps.c static int generic_machine_check_excepti · line 423

Quoted 9 lines
arch/powerpc/kernel/traps.c +5 -1
@@ -403,7 +416,14 @@ static int generic_machine_check_excepti
 		printk("Bus - Instruction Parity Error\n");
 	if (reason & MCSR_BUS_RPERR)
 		printk("Bus - Read Parity Error\n");
-#elif defined (CONFIG_E200)
+
+	return 0;
+}
+#elif defined(CONFIG_E200)
+int machine_check_e200(struct pt_regs *regs)

... and this cause build failures for most of the mpc8xxx defconfigs. The reason is that e200 and e500 are both lumped under CONFIG_FSL_BOOKE in cputable.c, but you have them segregated more here. I've added a fix that just does CONFIG_FSL_BOOKE here to match cputable.c.

josh

#4 lore raw
Quoted 24 lines · On Sun, 23 Dec 2007 19:32:10 -0600 Josh Boyer <[email protected]>…
Quoted 4 lines · On Fri, 21 Dec 2007 15:39:21 +1100 Benjamin Herrenschmidt…

Index: linux-merge/arch/powerpc/kernel/traps.c
===================================================================

arch/powerpc/kernel/traps.c +0 -0

[snip]

arch/powerpc/kernel/traps.c static int generic_machine_check_excepti · line 388

Quoted 5 lines
arch/powerpc/kernel/traps.c +4 -1
-#elif defined (CONFIG_E500)
+	return 0;
+}
+#elif defined(CONFIG_E500)
+int machine_check_e500(struct pt_regs *regs)

This...

Quoted 6 lines
arch/powerpc/kernel/traps.c +3 -0
+{
+	unsigned long reason = get_mc_reason(regs);
+
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from MCSR=%lx): ", reason);
Quoted 15 lines

arch/powerpc/kernel/traps.c static int generic_machine_check_excepti · line 423

Quoted 10 lines
arch/powerpc/kernel/traps.c +5 -1
@@ -403,7 +416,14 @@ static int generic_machine_check_excepti
 		printk("Bus - Instruction Parity Error\n");
 	if (reason & MCSR_BUS_RPERR)
 		printk("Bus - Read Parity Error\n");
-#elif defined (CONFIG_E200)
+
+	return 0;
+}
+#elif defined(CONFIG_E200)
+int machine_check_e200(struct pt_regs *regs)

... and this cause build failures for most of the mpc8xxx defconfigs. The reason is that e200 and e500 are both lumped under CONFIG_FSL_BOOKE in cputable.c, but you have them segregated more here. I've added a fix that just does CONFIG_FSL_BOOKE here to match cputable.c.

Actually, reverse that. There are other places where e200 and e500 are separated by ifdefs, so I made cputable.c match the rest.

josh