lkml.org 
[lkml]   [2019]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.9 57/91] powerpc/83xx: handle machine check caused by watchdog timer
    Date
    From: Christophe Leroy <christophe.leroy@c-s.fr>

    [ Upstream commit 0deae39cec6dab3a66794f3e9e83ca4dc30080f1 ]

    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>
    ---
    arch/powerpc/include/asm/cputable.h | 1 +
    arch/powerpc/include/asm/reg.h | 2 ++
    arch/powerpc/kernel/cputable.c | 10 ++++++----
    arch/powerpc/platforms/83xx/misc.c | 17 +++++++++++++++++
    4 files changed, 26 insertions(+), 4 deletions(-)

    diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
    index 4e54282c29b44..cf51aea47510c 100644
    --- a/arch/powerpc/include/asm/cputable.h
    +++ b/arch/powerpc/include/asm/cputable.h
    @@ -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);
    diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
    index ceb168cd3b814..26aeeaad32678 100644
    --- a/arch/powerpc/include/asm/reg.h
    +++ b/arch/powerpc/include/asm/reg.h
    @@ -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 */
    diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
    index 6a82ef039c509..7471ed48f41fa 100644
    --- a/arch/powerpc/kernel/cputable.c
    +++ b/arch/powerpc/kernel/cputable.c
    @@ -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,
    diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c
    index d75c9816a5c92..2b6589fe812dd 100644
    --- a/arch/powerpc/platforms/83xx/misc.c
    +++ b/arch/powerpc/platforms/83xx/misc.c
    @@ -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;
    +}
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-11-22 07:05    [W:4.523 / U:0.212 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site