All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: <linuxppc-dev@ozlabs.org>
Subject: [RFC/PATCH 5/9] powerpc: Fix 440/440A machine check handling
Date: Mon, 19 Nov 2007 19:25:04 +1100	[thread overview]
Message-ID: <20071119082552.21ADEDDE29@ozlabs.org> (raw)
In-Reply-To: <1195460700.350036.781662541765.qpush@grosgo>

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.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/cpu_setup_44x.S |    4 +-
 arch/powerpc/kernel/cputable.c      |    5 +++
 arch/powerpc/kernel/head_44x.S      |   14 ++++++--
 arch/powerpc/kernel/head_booke.h    |    2 -
 arch/powerpc/kernel/traps.c         |   58 +++++++++++++++++++++++++++++-------
 arch/powerpc/platforms/44x/Kconfig  |    5 ---
 include/asm-powerpc/ptrace.h        |    3 +
 include/asm-powerpc/reg_booke.h     |    3 -
 8 files changed, 70 insertions(+), 24 deletions(-)

Index: linux-work/arch/powerpc/kernel/cpu_setup_44x.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/cpu_setup_44x.S	2007-11-19 16:38:11.000000000 +1100
+++ linux-work/arch/powerpc/kernel/cpu_setup_44x.S	2007-11-19 16:58:25.000000000 +1100
@@ -23,11 +23,13 @@ _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)
+	b	__fixup_440A_mcheck
 
 /* enable APU between CPU and FPU */
 _GLOBAL(__init_fpu_44x)
Index: linux-work/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/cputable.c	2007-11-19 16:36:53.000000000 +1100
+++ linux-work/arch/powerpc/kernel/cputable.c	2007-11-19 16:37:31.000000000 +1100
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
 #ifdef CONFIG_PPC32
 extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
@@ -1193,6 +1194,7 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_440gx,
 		.platform		= "ppc440",
 	},
 	{ /* 440GX Rev. B */
@@ -1203,6 +1205,7 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_440gx,
 		.platform		= "ppc440",
 	},
 	{ /* 440GX Rev. C */
@@ -1213,6 +1216,7 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_440gx,
 		.platform		= "ppc440",
 	},
 	{ /* 440GX Rev. F */
@@ -1223,6 +1227,7 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_440gx,
 		.platform		= "ppc440",
 	},
 	{ /* 440SP Rev. A */
Index: linux-work/arch/powerpc/kernel/head_44x.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_44x.S	2007-11-19 16:41:48.000000000 +1100
+++ linux-work/arch/powerpc/kernel/head_44x.S	2007-11-19 16:58:53.000000000 +1100
@@ -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.
Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c	2007-11-19 16:44:07.000000000 +1100
+++ linux-work/arch/powerpc/kernel/traps.c	2007-11-19 17:19:44.000000000 +1100
@@ -334,18 +334,25 @@ static inline int check_io_access(struct
 #define clear_single_step(regs)	((regs)->msr &= ~MSR_SE)
 #endif
 
-static int generic_machine_check_exception(struct pt_regs *regs)
+#if defined(CONFIG_4xx)
+static int decode_machine_check_4xx(struct pt_regs *regs)
 {
 	unsigned long reason = get_mc_reason(regs);
 
-#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
 	if (reason & ESR_IMCP) {
 		printk("Instruction");
 		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
 	} else
 		printk("Data");
 	printk(" machine check in kernel mode.\n");
-#elif defined(CONFIG_440A)
+
+	return 0;
+}
+
+static int decode_machine_check_4xxA(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");
@@ -375,7 +382,13 @@ static int generic_machine_check_excepti
 		/* Clear MCSR */
 		mtspr(SPRN_MCSR, mcsr);
 	}
-#elif defined (CONFIG_E500)
+	return 0;
+}
+#elif defined(CONFIG_E500)
+static int decode_machine_check_e500(struct pt_regs *regs)
+{
+	unsigned long reason = get_mc_reason(regs);
+
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from MCSR=%lx): ", reason);
 
@@ -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)
+static int decode_machine_check_e200(struct pt_regs *regs)
+{
+	unsigned long reason = get_mc_reason(regs);
+
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from MCSR=%lx): ", reason);
 
@@ -421,7 +441,14 @@ static int generic_machine_check_excepti
 		printk("Bus - Read Bus Error on data load\n");
 	if (reason & MCSR_BUS_WRERR)
 		printk("Bus - Write Bus Error on buffered store or cache line push\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
+
+	return 0;
+}
+#else
+static int decode_machine_check_generic(struct pt_regs *regs)
+{
+	unsigned long reason = get_mc_reason(regs);
+
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", reason);
 	switch (reason & 0x601F0000) {
@@ -451,10 +478,9 @@ static int generic_machine_check_excepti
 	default:
 		printk("Unknown values in msr\n");
 	}
-#endif /* CONFIG_4xx */
-
 	return 0;
 }
+#endif /* everything else */
 
 void machine_check_exception(struct pt_regs *regs)
 {
@@ -463,8 +489,20 @@ void machine_check_exception(struct pt_r
 	/* See if any machine dependent calls */
 	if (ppc_md.machine_check_exception)
 		recover = ppc_md.machine_check_exception(regs);
-	else
-		recover = generic_machine_check_exception(regs);
+	else {
+#ifdef CONFIG_4xx
+		if (IS_MCHECK_EXC(regs))
+			recover = decode_machine_check_4xxA(regs);
+		else
+			recover = decode_machine_check_4xx(regs);
+#elif defined (CONFIG_E500)
+		recover = decode_machine_check_e500(regs);
+#elif defined (CONFIG_E200)
+		recover = decode_machine_check_e200(regs);
+#else
+		recover = decode_machine_check_generic(regs);
+#endif
+	}
 
 	if (recover)
 		return;
Index: linux-work/arch/powerpc/platforms/44x/Kconfig
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/Kconfig	2007-11-19 17:10:21.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/Kconfig	2007-11-19 17:10:25.000000000 +1100
@@ -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
Index: linux-work/arch/powerpc/kernel/head_booke.h
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_booke.h	2007-11-19 17:16:25.000000000 +1100
+++ linux-work/arch/powerpc/kernel/head_booke.h	2007-11-19 17:16:29.000000000 +1100
@@ -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)
 
Index: linux-work/include/asm-powerpc/ptrace.h
===================================================================
--- linux-work.orig/include/asm-powerpc/ptrace.h	2007-11-19 17:14:07.000000000 +1100
+++ linux-work/include/asm-powerpc/ptrace.h	2007-11-19 17:17:14.000000000 +1100
@@ -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__
Index: linux-work/include/asm-powerpc/reg_booke.h
===================================================================
--- linux-work.orig/include/asm-powerpc/reg_booke.h	2007-11-19 17:20:54.000000000 +1100
+++ linux-work/include/asm-powerpc/reg_booke.h	2007-11-19 17:20:59.000000000 +1100
@@ -207,7 +207,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 */
@@ -217,7 +216,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 */

  parent reply	other threads:[~2007-11-19  8:25 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-19  8:25 [RFC/PATCH 0/9] powerpc: 4xx PCI work in progress Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 1/9] powerpc: Make isa_mem_base common to 32 and 64 bits Benjamin Herrenschmidt
2007-11-19 10:32   ` Christoph Hellwig
2007-11-19 19:49     ` Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 2/9] powerpc: Merge pci_process_bridge_OF_ranges() Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 3/9] powerpc: Fix declaration of pcibios_free_controller Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 4/9] powerpc: Fix powerpc 32 bits resource fixup for 64 bits resources Benjamin Herrenschmidt
2007-11-19  8:25 ` Benjamin Herrenschmidt [this message]
2007-11-19  8:25 ` [RFC/PATCH 6/9] powerpc: Add xmon function to dump 44x TLB Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 7/9] powerpc: Fix kmalloc alignmenent on non-coherent DMA Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 8/9] powerpc 4xx PCI support Benjamin Herrenschmidt
2007-11-19  8:25 ` [RFC/PATCH 9/9] powerpc: PCI support for 4xx Ebony board Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071119082552.21ADEDDE29@ozlabs.org \
    --to=benh@kernel.crashing.org \
    --cc=linuxppc-dev@ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.