root/arch/powerpc/platforms/44x/machine_check.c
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 */

#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/ptrace.h>

#include <asm/reg.h>
#include <asm/cacheflush.h>

int machine_check_4xx(struct pt_regs *regs)
{
        unsigned long reason = regs->esr;

        if (reason & ESR_IMCP) {
                printk("Instruction");
                mtspr(SPRN_ESR, reason & ~ESR_IMCP);
        } else
                printk("Data");

        printk(" machine check in kernel mode.\n");

        return 0;
}

int machine_check_440A(struct pt_regs *regs)
{
        unsigned long reason = regs->esr;

        printk("Machine check in kernel mode.\n");
        if (reason & ESR_IMCP){
                printk("Instruction Synchronous Machine Check exception\n");
                mtspr(SPRN_ESR, reason & ~ESR_IMCP);
        }
        else {
                u32 mcsr = mfspr(SPRN_MCSR);
                if (mcsr & MCSR_IB)
                        printk("Instruction Read PLB Error\n");
                if (mcsr & MCSR_DRB)
                        printk("Data Read PLB Error\n");
                if (mcsr & MCSR_DWB)
                        printk("Data Write PLB Error\n");
                if (mcsr & MCSR_TLBP)
                        printk("TLB Parity Error\n");
                if (mcsr & MCSR_ICP){
                        flush_instruction_cache();
                        printk("I-Cache Parity Error\n");
                }
                if (mcsr & MCSR_DCSP)
                        printk("D-Cache Search Parity Error\n");
                if (mcsr & MCSR_DCFP)
                        printk("D-Cache Flush Parity Error\n");
                if (mcsr & MCSR_IMPE)
                        printk("Machine Check exception is imprecise\n");

                /* Clear MCSR */
                mtspr(SPRN_MCSR, mcsr);
        }
        return 0;
}

#ifdef CONFIG_PPC_47x
int machine_check_47x(struct pt_regs *regs)
{
        unsigned long reason = regs->esr;
        u32 mcsr;

        printk(KERN_ERR "Machine check in kernel mode.\n");
        if (reason & ESR_IMCP) {
                printk(KERN_ERR "Instruction Synchronous Machine Check exception\n");
                mtspr(SPRN_ESR, reason & ~ESR_IMCP);
                return 0;
        }
        mcsr = mfspr(SPRN_MCSR);
        if (mcsr & MCSR_IB)
                printk(KERN_ERR "Instruction Read PLB Error\n");
        if (mcsr & MCSR_DRB)
                printk(KERN_ERR "Data Read PLB Error\n");
        if (mcsr & MCSR_DWB)
                printk(KERN_ERR "Data Write PLB Error\n");
        if (mcsr & MCSR_TLBP)
                printk(KERN_ERR "TLB Parity Error\n");
        if (mcsr & MCSR_ICP) {
                flush_instruction_cache();
                printk(KERN_ERR "I-Cache Parity Error\n");
        }
        if (mcsr & MCSR_DCSP)
                printk(KERN_ERR "D-Cache Search Parity Error\n");
        if (mcsr & PPC47x_MCSR_GPR)
                printk(KERN_ERR "GPR Parity Error\n");
        if (mcsr & PPC47x_MCSR_FPR)
                printk(KERN_ERR "FPR Parity Error\n");
        if (mcsr & PPC47x_MCSR_IPR)
                printk(KERN_ERR "Machine Check exception is imprecise\n");

        /* Clear MCSR */
        mtspr(SPRN_MCSR, mcsr);

        return 0;
}
#endif /* CONFIG_PPC_47x */