mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
powerpc/83xx: handle machine check caused by watchdog timer
[ Upstream commit 0deae39cec ]
When the watchdog timer is set in interrupt mode, it causes a
machine check when it times out. The purpose of this mode is to
ease debugging, not to crash the kernel and reboot the machine.
This patch implements a special handling for that, in order to not
crash the kernel if the watchdog times out while in interrupt or
within the idle task.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
[scottwood: added missing #include]
Signed-off-by: Scott Wood <oss@buserror.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e914a7747a
commit
f2f645667e
@@ -44,6 +44,7 @@ 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);
|
||||
int machine_check_8xx(struct pt_regs *regs);
|
||||
int machine_check_83xx(struct pt_regs *regs);
|
||||
|
||||
extern void cpu_down_flush_e500v2(void);
|
||||
extern void cpu_down_flush_e500mc(void);
|
||||
|
||||
@@ -663,6 +663,8 @@
|
||||
#define SRR1_PROGTRAP 0x00020000 /* Trap */
|
||||
#define SRR1_PROGADDR 0x00010000 /* SRR0 contains subsequent addr */
|
||||
|
||||
#define SRR1_MCE_MCP 0x00080000 /* Machine check signal caused interrupt */
|
||||
|
||||
#define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */
|
||||
#define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */
|
||||
#define HSRR1_DENORM 0x00100000 /* Denorm exception */
|
||||
|
||||
@@ -1162,6 +1162,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#ifdef CONFIG_PPC_83xx
|
||||
{ /* e300c1 (a 603e core, plus some) on 83xx */
|
||||
.pvr_mask = 0x7fff0000,
|
||||
.pvr_value = 0x00830000,
|
||||
@@ -1172,7 +1173,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.machine_check = machine_check_83xx,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* e300c2 (an e300c1 core, plus some, minus FPU) on 83xx */
|
||||
@@ -1186,7 +1187,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.machine_check = machine_check_83xx,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* e300c3 (e300c1, plus one IU, half cache size) on 83xx */
|
||||
@@ -1200,7 +1201,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.machine_check = machine_check_83xx,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e300",
|
||||
.oprofile_type = PPC_OPROFILE_FSL_EMB,
|
||||
@@ -1217,12 +1218,13 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.machine_check = machine_check_83xx,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e300",
|
||||
.oprofile_type = PPC_OPROFILE_FSL_EMB,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#endif
|
||||
{ /* default match, we assume split I/D cache & TB (non-601)... */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/debug.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/ipic.h>
|
||||
@@ -150,3 +151,19 @@ void __init mpc83xx_setup_arch(void)
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
}
|
||||
|
||||
int machine_check_83xx(struct pt_regs *regs)
|
||||
{
|
||||
u32 mask = 1 << (31 - IPIC_MCP_WDT);
|
||||
|
||||
if (!(regs->msr & SRR1_MCE_MCP) || !(ipic_get_mcp_status() & mask))
|
||||
return machine_check_generic(regs);
|
||||
ipic_clear_mcp_status(mask);
|
||||
|
||||
if (debugger_fault_handler(regs))
|
||||
return 1;
|
||||
|
||||
die("Watchdog NMI Reset", regs, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user