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 */
next prev 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.