Skip to contentSkip to conversation

PPC32 Machine Check Handling

RFC PATCH In review Adrian Cox 3 participants 4 messages Aug 27, 2004 – Nov 4, 2004 PowerPC

lore
Share & tools
lore

Adrian Cox

author
#0 lore raw

RFC PATCH 1/1 PPC32 Machine Check Handling

The attached patch rearranges PPC32 machine check handling in order to test for internal CPU failures before signalling user processes. This makes the behaviour match that of i386.

The patch currently only changes behaviour for 6xx processors. It does not enable any extra causes of machine check, but it will turn internal CPU faults into kernel panics rather than signals.

The PowerMac and Qspan specific code is moved into platform files. There don't seem to be any boards in the tree that actually use Qspan PCI. I'd like to hear test reports for PowerMac machines that take machine checks on I/O faults.

Paul, Tom: This isn't the finished version, but is there any chance of something like this going mainstream? The current behaviour makes it very hard to separate chip failures and cooling problems from application bugs.

- Adrian Cox
Humboldt Solutions Ltd.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/08/27 10:55:15+01:00 [email protected]
# First stage of restructuring machine check.
#

# arch/ppc/kernel/mcheck_6xx.c
#   2004/08/27 10:55:06+01:00 [email protected] +113 -0
#
# arch/ppc/kernel/mcheck_6xx.c
#   2004/08/27 10:55:06+01:00 [email protected] +0 -0
#   BitKeeper file /home/adrian/kernels/sa107-2.6/sa107-merge/arch/ppc/kernel/mcheck_6xx.c
#
# arch/ppc/kernel/mcheck.h
#   2004/08/27 10:55:05+01:00 [email protected] +17 -0
#
# include/asm-ppc/system.h
#   2004/08/27 10:55:05+01:00 [email protected] +1 -0
#   Add generic handler for a fatal machine check.
#
# include/asm-ppc/machdep.h
#   2004/08/27 10:55:05+01:00 [email protected] +1 -0
#   Add machine check handler.
#
# include/asm-ppc/cputable.h
#   2004/08/27 10:55:05+01:00 [email protected] +6 -0
#   Add machine check handler.
#
# arch/ppc/syslib/qspan_pci.c
#   2004/08/27 10:55:05+01:00 [email protected] +10 -0
#   Handle machine checks from PCI accesss.
#
# arch/ppc/platforms/pmac_setup.c
#   2004/08/27 10:55:05+01:00 [email protected] +49 -0
#   Pmac specific machine check handler to cope with failed I/O accesses.
#
# arch/ppc/kernel/traps.c
#   2004/08/27 10:55:05+01:00 [email protected] +21 -87
#   Move to new machine check handling. Qspan and PowerMac code moved
#   to platform files.
#
# arch/ppc/kernel/mcheck.h
#   2004/08/27 10:55:05+01:00 [email protected] +0 -0
#   BitKeeper file /home/adrian/kernels/sa107-2.6/sa107-merge/arch/ppc/kernel/mcheck.h
#
# arch/ppc/kernel/cputable.c
#   2004/08/27 10:55:05+01:00 [email protected] +31 -30
#   Add 6xx specific machine check handlers
#
# arch/ppc/kernel/Makefile
#   2004/08/27 10:55:05+01:00 [email protected] +1 -1
#   Add 6xx CPU specific machine check handlers
#
diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	Fri Aug 27 10:57:57 2004
+++ b/arch/ppc/kernel/Makefile	Fri Aug 27 10:57:57 2004
@@ -15,7 +15,7 @@
 					process.o signal.o ptrace.o align.o \
 					semaphore.o syscalls.o setup.o \
 					cputable.o ppc_htab.o
-obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o mcheck_6xx.o
 obj-$(CONFIG_POWER4)		+= cpu_setup_power4.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	Fri Aug 27 10:57:57 2004
+++ b/arch/ppc/kernel/cputable.c	Fri Aug 27 10:57:57 2004
@@ -15,6 +15,7 @@
 #include <linux/threads.h>
 #include <linux/init.h>
 #include <asm/cputable.h>
+#include "mcheck.h"

struct cpu_spec* cur_cpu_spec[NR_CPUS];

@@ -80,7 +81,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC,

     	32, 32,
-	__setup_cpu_603
+	__setup_cpu_603, mcheck_603
     },
     {	/* 603e */
     	0xffff0000, 0x00060000, "603e",

@@ -89,7 +90,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
- __setup_cpu_603
+ __setup_cpu_603, mcheck_603

     },
     {	/* 603ev */
     	0xffff0000, 0x00070000, "603ev",

@@ -98,7 +99,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
- __setup_cpu_603
+ __setup_cpu_603, mcheck_603

     },
     {	/* 604 */
     	0xffff0000, 0x00040000, "604",

@@ -107,7 +108,7 @@
CPU_FTR_HPTE_TABLE,
COMMON_PPC,
32, 32,
- __setup_cpu_604
+ __setup_cpu_604, mcheck_604

     },
     {	/* 604e */
     	0xfffff000, 0x00090000, "604e",

@@ -116,7 +117,7 @@
CPU_FTR_HPTE_TABLE,
COMMON_PPC,
32, 32,
- __setup_cpu_604
+ __setup_cpu_604, mcheck_604

     },
     {	/* 604r */
     	0xffff0000, 0x00090000, "604r",

@@ -125,7 +126,7 @@
CPU_FTR_HPTE_TABLE,
COMMON_PPC,
32, 32,
- __setup_cpu_604
+ __setup_cpu_604, mcheck_604

     },
     {	/* 604ev */
     	0xffff0000, 0x000a0000, "604ev",

@@ -134,7 +135,7 @@
CPU_FTR_HPTE_TABLE,
COMMON_PPC,
32, 32,
- __setup_cpu_604
+ __setup_cpu_604, mcheck_604

     },
     {	/* 740/750 (0x4202, don't support TAU ?) */
     	0xffffffff, 0x00084202, "740/750",

@@ -143,7 +144,7 @@
CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750
+ __setup_cpu_750, mcheck_750

     },
     {	/* 745/755 */
     	0xfffff000, 0x00083000, "745/755",

@@ -152,7 +153,7 @@
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750
+ __setup_cpu_750, mcheck_750

     },
     {	/* 750CX (80100 and 8010x?) */
     	0xfffffff0, 0x00080100, "750CX",

@@ -161,7 +162,7 @@
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750cx
+ __setup_cpu_750cx, mcheck_750

     },
     {	/* 750CX (82201 and 82202) */
     	0xfffffff0, 0x00082200, "750CX",

@@ -170,7 +171,7 @@
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750cx
+ __setup_cpu_750cx, mcheck_750

     },
     {	/* 750CXe (82214) */
     	0xfffffff0, 0x00082210, "750CXe",

@@ -179,7 +180,7 @@
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750cx
+ __setup_cpu_750cx, mcheck_750

     },
     {	/* 750FX rev 1.x */
     	0xffffff00, 0x70000100, "750FX",

@@ -189,7 +190,7 @@
CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
COMMON_PPC,
32, 32,
- __setup_cpu_750
+ __setup_cpu_750, mcheck_750

     },
     {	/* 750FX rev 2.0 must disable HID0[DPM] */
     	0xffffffff, 0x70000200, "750FX",

@@ -199,7 +200,7 @@
CPU_FTR_NO_DPM,
COMMON_PPC,
32, 32,
- __setup_cpu_750
+ __setup_cpu_750, mcheck_750

     },
     {	/* 750FX (All revs except 2.0) */
     	0xffff0000, 0x70000000, "750FX",

@@ -209,7 +210,7 @@
CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, COMMON_PPC,
32, 32,
- __setup_cpu_750fx
+ __setup_cpu_750fx, mcheck_750

     },
     {	/* 750GX */
     	0xffff0000, 0x70020000, "750GX",

@@ -218,7 +219,7 @@
CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, COMMON_PPC,
32, 32,
- __setup_cpu_750fx
+ __setup_cpu_750fx, mcheck_750

     },
     {	/* 740/750 (L2CR bit need fixup for 740) */
     	0xffff0000, 0x00080000, "740/750",

@@ -227,7 +228,7 @@
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, COMMON_PPC,
32, 32,
- __setup_cpu_750
+ __setup_cpu_750, mcheck_750

     },
     {	/* 7400 rev 1.1 ? (no TAU) */
     	0xffffffff, 0x000c1101, "7400 (1.1)",

@@ -237,7 +238,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_7400
+ __setup_cpu_7400, mcheck_7400

     },
     {	/* 7400 */
     	0xffff0000, 0x000c0000, "7400",

@@ -247,7 +248,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_7400
+ __setup_cpu_7400, mcheck_7400

     },
     {	/* 7410 */
     	0xffff0000, 0x800c0000, "7410",

@@ -257,7 +258,7 @@
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_7410
+ __setup_cpu_7410, mcheck_7400

     },
     {	/* 7450 2.0 - no doze/nap */
     	0xffffffff, 0x80000200, "7450",

@@ -267,7 +268,7 @@
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NEED_COHERENT, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7450 2.1 */
     	0xffffffff, 0x80000201, "7450",

@@ -278,7 +279,7 @@
CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, 32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7450 2.3 and newer */
     	0xffff0000, 0x80000000, "7450",

@@ -289,7 +290,7 @@
CPU_FTR_NEED_COHERENT,
COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7455 rev 1.x */
     	0xffffff00, 0x80010100, "7455",

@@ -300,7 +301,7 @@
CPU_FTR_NEED_COHERENT,
COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7455 rev 2.0 */
     	0xffffffff, 0x80010200, "7455",

@@ -311,7 +312,7 @@
CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7455 others */
     	0xffff0000, 0x80010000, "7455",

@@ -322,7 +323,7 @@
CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, 32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7447/7457 Rev 1.0 */
     	0xffffffff, 0x80020100, "7447/7457",

@@ -355,7 +356,7 @@
CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, 32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 7447A */
     	0xffff0000, 0x80030000, "7447A",

@@ -366,7 +367,7 @@
CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, 32, 32,
- __setup_cpu_745x
+ __setup_cpu_745x, mcheck_7450

     },
     {	/* 82xx (8240, 8245, 8260 are all 603e cores) */

0x7fff0000, 0x00810000, "82xx",
@@ -374,7 +375,7 @@
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, COMMON_PPC,
32, 32,
- __setup_cpu_603
+ __setup_cpu_603, mcheck_603
},
{ /* All G2_LE (603e core, plus some) have the same pvr */
0x7fff0000, 0x00820000, "G2_LE",
@@ -382,7 +383,7 @@
CPU_FTR_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, COMMON_PPC,
32, 32,
- __setup_cpu_603
+ __setup_cpu_603, mcheck_603

     },
     {	/* default match, we assume split I/D cache & TB (non-601)... */
     	0x00000000, 0x00000000, "(generic PPC)",
arch/ppc/kernel/mcheck.h new file +17 -0
diff -Nru a/arch/ppc/kernel/mcheck.h b/arch/ppc/kernel/mcheck.h
@@ -0,0 +1,17 @@
+/*
+ *  arch/ppc/kernel/mcheck.h
+ *
+ *  Copyright (C) 2004 Humboldt Solutions Ltd.
+ *  Author Adrian Cox <[email protected]>
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+int mcheck_603(struct pt_regs *regs);
+int mcheck_604(struct pt_regs *regs);
+int mcheck_750(struct pt_regs *regs);
+int mcheck_7400(struct pt_regs *regs);
+int mcheck_7450(struct pt_regs *regs);
+
arch/ppc/kernel/mcheck_6xx.c new file +113 -0

113 lines not on this page · raw message

arch/ppc/kernel/traps.c +21 -87

150 lines not on this page · raw message

arch/ppc/platforms/pmac_setup.c +49 -0

61 lines not on this page · raw message

arch/ppc/syslib/qspan_pci.c +10 -0
diff -Nru a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
@@ -369,11 +369,21 @@
    /* Lots to do here, all board and configuration specific. */
 }
 
+static int qspan_mcheck(struct pt_regs *regs)
+{
+	if (! user_mode(regs)) {
+		bad_page_fault(regs, regs->dar, SIGBUS);
+		return 0;
+	}
+	return 1;
+}
+
 void __init
 m8xx_setup_pci_ptrs(void))
 {
 	set_config_access_method(qspan);
 
 	ppc_md.pcibios_fixup = m8xx_pcibios_fixup;
+	ppc_md.mcheck = qspan_mcheck;
 }
 
include/asm-ppc/cputable.h +6 -0
diff -Nru a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h
@@ -30,8 +30,10 @@
  * via the mkdefs mecanism.
  */
 struct cpu_spec;
+struct pt_regs;
 
 typedef	void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+typedef int (*cpu_mcheck_t)(struct pt_regs *regs);
 
 struct cpu_spec {
 	/* CPU is matched via (PVR & pvr_mask) == pvr_value */
@@ -50,6 +52,10 @@
 	 * BHT, SPD, etc... from head.S before branching to identify_machine
 	 */
 	cpu_setup_t	cpu_setup;
+	/* this is called when a machine check occurs. It returns 0 if it has handled the machine
+	* check, and a non-zero cause value if not. This may be interpreted by platform specific
+	 * handlers. */
+	cpu_mcheck_t	cpu_mcheck;
 };
 
 extern struct cpu_spec		cpu_specs[];
include/asm-ppc/machdep.h +1 -0
diff -Nru a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
@@ -63,6 +63,7 @@
 	void		(*nvram_write_val)(int addr, unsigned char val);
 	void		(*nvram_sync)(void);
 
+	int		(*mcheck)(struct pt_regs *);
 	/*
 	 * optional PCI "hooks"
 	 */
include/asm-ppc/system.h +1 -0
diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h
@@ -86,6 +86,7 @@
 extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
 extern void bad_page_fault(struct pt_regs *, unsigned long, int);
 extern void die(const char *, struct pt_regs *, long);
+NORET_TYPE void fatal_machine_check(const char *, struct pt_regs *);
 
 struct device_node;
 extern void note_scsi_host(struct device_node *, void *);
#1 lore raw
Quoted 13 lines · Adrian Cox

The attached patch rearranges PPC32 machine check handling in order to test for internal CPU failures before signalling user processes. This makes the behaviour match that of i386.

The patch currently only changes behaviour for 6xx processors. It does not enable any extra causes of machine check, but it will turn internal CPU faults into kernel panics rather than signals.

The PowerMac and Qspan specific code is moved into platform files. There don't seem to be any boards in the tree that actually use Qspan PCI. I'd like to hear test reports for PowerMac machines that take machine checks on I/O faults.

Quoted 4 lines

Paul, Tom: This isn't the finished version, but is there any chance of something like this going mainstream? The current behaviour makes it very hard to separate chip failures and cooling problems from application bugs.

This seems like a fine idea to me.

--
Tom Rini
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

#2 lore raw
Quoted 3 lines · Tom Rini
Quoted 3 lines

The PowerMac and Qspan specific code is moved into platform files. There
don't seem to be any boards in the tree that actually use Qspan PCI.

The MBX-860, RPC Classic (with PCI enabled) are two well known boards that use the Qspan. I don't know many people that use those boards, I'm just listing them for documentation purposes :-) There are also some custom boards that use it, but I suspect it won't affect them.

Thanks.

	-- Dan

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

#3 lore raw
In reply to Tom Rini
Quoted 14 lines · Tom Rini
Quoted 13 lines · Adrian Cox

The attached patch rearranges PPC32 machine check handling in order to test for internal CPU failures before signalling user processes. This makes the behaviour match that of i386.

The patch currently only changes behaviour for 6xx processors. It does not enable any extra causes of machine check, but it will turn internal CPU faults into kernel panics rather than signals.

The PowerMac and Qspan specific code is moved into platform files. There don't seem to be any boards in the tree that actually use Qspan PCI. I'd like to hear test reports for PowerMac machines that take machine checks on I/O faults.

Quoted 6 lines
Quoted 4 lines

Paul, Tom: This isn't the finished version, but is there any chance of something like this going mainstream? The current behaviour makes it very hard to separate chip failures and cooling problems from application bugs.

This seems like a fine idea to me.

This get cleaned up anymore, etc? Thanks.

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/