162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <linux/printk.h> 762306a36Sopenharmony_ci#include <linux/ptrace.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <asm/reg.h> 1062306a36Sopenharmony_ci#include <asm/cacheflush.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciint machine_check_440A(struct pt_regs *regs) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci unsigned long reason = regs->esr; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci printk("Machine check in kernel mode.\n"); 1762306a36Sopenharmony_ci if (reason & ESR_IMCP){ 1862306a36Sopenharmony_ci printk("Instruction Synchronous Machine Check exception\n"); 1962306a36Sopenharmony_ci mtspr(SPRN_ESR, reason & ~ESR_IMCP); 2062306a36Sopenharmony_ci } 2162306a36Sopenharmony_ci else { 2262306a36Sopenharmony_ci u32 mcsr = mfspr(SPRN_MCSR); 2362306a36Sopenharmony_ci if (mcsr & MCSR_IB) 2462306a36Sopenharmony_ci printk("Instruction Read PLB Error\n"); 2562306a36Sopenharmony_ci if (mcsr & MCSR_DRB) 2662306a36Sopenharmony_ci printk("Data Read PLB Error\n"); 2762306a36Sopenharmony_ci if (mcsr & MCSR_DWB) 2862306a36Sopenharmony_ci printk("Data Write PLB Error\n"); 2962306a36Sopenharmony_ci if (mcsr & MCSR_TLBP) 3062306a36Sopenharmony_ci printk("TLB Parity Error\n"); 3162306a36Sopenharmony_ci if (mcsr & MCSR_ICP){ 3262306a36Sopenharmony_ci flush_instruction_cache(); 3362306a36Sopenharmony_ci printk("I-Cache Parity Error\n"); 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci if (mcsr & MCSR_DCSP) 3662306a36Sopenharmony_ci printk("D-Cache Search Parity Error\n"); 3762306a36Sopenharmony_ci if (mcsr & MCSR_DCFP) 3862306a36Sopenharmony_ci printk("D-Cache Flush Parity Error\n"); 3962306a36Sopenharmony_ci if (mcsr & MCSR_IMPE) 4062306a36Sopenharmony_ci printk("Machine Check exception is imprecise\n"); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /* Clear MCSR */ 4362306a36Sopenharmony_ci mtspr(SPRN_MCSR, mcsr); 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci return 0; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#ifdef CONFIG_PPC_47x 4962306a36Sopenharmony_ciint machine_check_47x(struct pt_regs *regs) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci unsigned long reason = regs->esr; 5262306a36Sopenharmony_ci u32 mcsr; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci printk(KERN_ERR "Machine check in kernel mode.\n"); 5562306a36Sopenharmony_ci if (reason & ESR_IMCP) { 5662306a36Sopenharmony_ci printk(KERN_ERR "Instruction Synchronous Machine Check exception\n"); 5762306a36Sopenharmony_ci mtspr(SPRN_ESR, reason & ~ESR_IMCP); 5862306a36Sopenharmony_ci return 0; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci mcsr = mfspr(SPRN_MCSR); 6162306a36Sopenharmony_ci if (mcsr & MCSR_IB) 6262306a36Sopenharmony_ci printk(KERN_ERR "Instruction Read PLB Error\n"); 6362306a36Sopenharmony_ci if (mcsr & MCSR_DRB) 6462306a36Sopenharmony_ci printk(KERN_ERR "Data Read PLB Error\n"); 6562306a36Sopenharmony_ci if (mcsr & MCSR_DWB) 6662306a36Sopenharmony_ci printk(KERN_ERR "Data Write PLB Error\n"); 6762306a36Sopenharmony_ci if (mcsr & MCSR_TLBP) 6862306a36Sopenharmony_ci printk(KERN_ERR "TLB Parity Error\n"); 6962306a36Sopenharmony_ci if (mcsr & MCSR_ICP) { 7062306a36Sopenharmony_ci flush_instruction_cache(); 7162306a36Sopenharmony_ci printk(KERN_ERR "I-Cache Parity Error\n"); 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci if (mcsr & MCSR_DCSP) 7462306a36Sopenharmony_ci printk(KERN_ERR "D-Cache Search Parity Error\n"); 7562306a36Sopenharmony_ci if (mcsr & PPC47x_MCSR_GPR) 7662306a36Sopenharmony_ci printk(KERN_ERR "GPR Parity Error\n"); 7762306a36Sopenharmony_ci if (mcsr & PPC47x_MCSR_FPR) 7862306a36Sopenharmony_ci printk(KERN_ERR "FPR Parity Error\n"); 7962306a36Sopenharmony_ci if (mcsr & PPC47x_MCSR_IPR) 8062306a36Sopenharmony_ci printk(KERN_ERR "Machine Check exception is imprecise\n"); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* Clear MCSR */ 8362306a36Sopenharmony_ci mtspr(SPRN_MCSR, mcsr); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci#endif /* CONFIG_PPC_47x */ 88