154558Sbp// SPDX-License-Identifier: GPL-2.0-or-later 266479Sbp/* 354558Sbp * Machine check exception handling CPU-side for power7 and power8 454558Sbp * 554558Sbp * Copyright 2013 IBM Corporation 654558Sbp * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> 754558Sbp */ 854558Sbp 954558Sbp#undef DEBUG 1054558Sbp#define pr_fmt(fmt) "mce_power: " fmt 1154558Sbp 1254558Sbp#include <linux/types.h> 1354558Sbp#include <linux/ptrace.h> 1454558Sbp#include <linux/extable.h> 1554558Sbp#include <linux/pgtable.h> 1654558Sbp#include <asm/mmu.h> 1754558Sbp#include <asm/mce.h> 1854558Sbp#include <asm/machdep.h> 1954558Sbp#include <asm/pte-walk.h> 2054558Sbp#include <asm/sstep.h> 2154558Sbp#include <asm/exception-64s.h> 2254558Sbp#include <asm/extable.h> 2354558Sbp#include <asm/inst.h> 2454558Sbp 2554558Sbp/* 2654558Sbp * Convert an address related to an mm to a PFN. NOTE: we are in real 2754558Sbp * mode, we could potentially race with page table updates. 2854558Sbp */ 2954558Sbpunsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) 3054558Sbp{ 3156424Sbp pte_t *ptep, pte; 3254558Sbp unsigned int shift; 3354558Sbp unsigned long pfn, flags; 3454558Sbp struct mm_struct *mm; 3554558Sbp 3654558Sbp if (user_mode(regs)) 3754558Sbp mm = current->mm; 3854558Sbp else 3954558Sbp mm = &init_mm; 4054558Sbp 4154558Sbp local_irq_save(flags); 4254558Sbp ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift); 4354558Sbp if (!ptep) { 4454558Sbp pfn = ULONG_MAX; 4554558Sbp goto out; 4654558Sbp } 4754558Sbp pte = READ_ONCE(*ptep); 4854558Sbp 4954558Sbp if (!pte_present(pte) || pte_special(pte)) { 5054558Sbp pfn = ULONG_MAX; 5154558Sbp goto out; 5254558Sbp } 5354558Sbp 5454558Sbp if (shift <= PAGE_SHIFT) 5554558Sbp pfn = pte_pfn(pte); 5654558Sbp else { 5754558Sbp unsigned long rpnmask = (1ul << shift) - PAGE_SIZE; 5854558Sbp pfn = pte_pfn(__pte(pte_val(pte) | (addr & rpnmask))); 5954558Sbp } 6054558Sbpout: 6154558Sbp local_irq_restore(flags); 6254558Sbp return pfn; 6354558Sbp} 64143196Ssobomax 65143196Ssobomaxstatic bool mce_in_guest(void) 66143196Ssobomax{ 67143196Ssobomax#ifdef CONFIG_KVM_BOOK3S_HANDLER 68143196Ssobomax /* 69143196Ssobomax * If machine check is hit when in guest context or low level KVM 70143196Ssobomax * code, avoid looking up any translations or making any attempts 71143196Ssobomax * to recover, just record the event and pass to KVM. 72143196Ssobomax */ 7354558Sbp if (get_paca()->kvm_hstate.in_guest) 7454558Sbp return true; 7554558Sbp#endif 7654558Sbp return false; 7754558Sbp} 7854558Sbp 7954558Sbp/* flush SLBs and reload */ 8054558Sbp#ifdef CONFIG_PPC_64S_HASH_MMU 8187599Sobrienvoid flush_and_reload_slb(void) 8254558Sbp{ 8354558Sbp if (early_radix_enabled()) 8454558Sbp return; 8554558Sbp 8687599Sobrien /* Invalidate all SLBs */ 8754558Sbp slb_flush_all_realmode(); 8854558Sbp 89147256Sbrooks /* 90147256Sbrooks * This probably shouldn't happen, but it may be possible it's 91121816Sbrooks * called in early boot before SLB shadows are allocated. 9254558Sbp */ 9354558Sbp if (!get_slb_shadow()) 9454558Sbp return; 9560938Sjake 9654558Sbp slb_restore_bolted_realmode(); 9754558Sbp} 9854558Sbp#endif 9954558Sbp 10060938Sjakevoid flush_erat(void) 10154558Sbp{ 10254558Sbp#ifdef CONFIG_PPC_64S_HASH_MMU 10354558Sbp if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { 10459681Sbp flush_and_reload_slb(); 10566479Sbp return; 10654558Sbp } 10754558Sbp#endif 10854558Sbp asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); 10954558Sbp} 11054558Sbp 11154558Sbp#define MCE_FLUSH_SLB 1 11254558Sbp#define MCE_FLUSH_TLB 2 11354558Sbp#define MCE_FLUSH_ERAT 3 11454558Sbp 11554558Sbpstatic int mce_flush(int what) 11659681Sbp{ 11766479Sbp#ifdef CONFIG_PPC_64S_HASH_MMU 11854558Sbp if (what == MCE_FLUSH_SLB) { 11954558Sbp flush_and_reload_slb(); 12054558Sbp return 1; 12154558Sbp } 12254558Sbp#endif 12354558Sbp if (what == MCE_FLUSH_ERAT) { 12454558Sbp flush_erat(); 12554558Sbp return 1; 12654558Sbp } 12754558Sbp if (what == MCE_FLUSH_TLB) { 128147256Sbrooks tlbiel_all(); 12954558Sbp return 1; 13054558Sbp } 13154558Sbp 13254558Sbp return 0; 13354558Sbp} 13454558Sbp 13554558Sbp#define SRR1_MC_LOADSTORE(srr1) ((srr1) & PPC_BIT(42)) 13654558Sbp 13754558Sbpstruct mce_ierror_table { 138152315Sru unsigned long srr1_mask; 13954558Sbp unsigned long srr1_value; 14054558Sbp bool nip_valid; /* nip is a valid indicator of faulting address */ 14154558Sbp unsigned int error_type; 142148887Srwatson unsigned int error_subtype; 14354558Sbp unsigned int error_class; 144121816Sbrooks unsigned int initiator; 14554558Sbp unsigned int severity; 14654558Sbp bool sync_error; 14754558Sbp}; 14854558Sbp 14954558Sbpstatic const struct mce_ierror_table mce_p7_ierror_table[] = { 15054558Sbp{ 0x00000000001c0000, 0x0000000000040000, true, 15154558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 15254558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 15354558Sbp{ 0x00000000001c0000, 0x0000000000080000, true, 154147256Sbrooks MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 15554558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 15654558Sbp{ 0x00000000001c0000, 0x00000000000c0000, true, 15754558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 15854558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 159147256Sbrooks{ 0x00000000001c0000, 0x0000000000100000, true, 160147256Sbrooks MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */ 161147256Sbrooks MCE_ECLASS_SOFT_INDETERMINATE, 16254558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 16354558Sbp{ 0x00000000001c0000, 0x0000000000140000, true, 16454558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 16554558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 16654558Sbp{ 0x00000000001c0000, 0x0000000000180000, true, 16754558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE, 16854558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 16954558Sbp{ 0x00000000001c0000, 0x00000000001c0000, true, 17054558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 17154558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 17254558Sbp{ 0, 0, 0, 0, 0, 0, 0 } }; 17354558Sbp 174121816Sbrooksstatic const struct mce_ierror_table mce_p8_ierror_table[] = { 17554558Sbp{ 0x00000000081c0000, 0x0000000000040000, true, 17654558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 17754558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 178121816Sbrooks{ 0x00000000081c0000, 0x0000000000080000, true, 17954558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 18054558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 18154558Sbp{ 0x00000000081c0000, 0x00000000000c0000, true, 182106939Ssam MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 183106939Ssam MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 184106939Ssam{ 0x00000000081c0000, 0x0000000000100000, true, 18554558Sbp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 186121816Sbrooks MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 18754558Sbp{ 0x00000000081c0000, 0x0000000000140000, true, 18854558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 18954558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 19054558Sbp{ 0x00000000081c0000, 0x0000000000180000, true, 19154558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, 19254558Sbp MCE_ECLASS_HARDWARE, 193106939Ssam MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 19454558Sbp{ 0x00000000081c0000, 0x00000000001c0000, true, 19554558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 19654558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 19754558Sbp{ 0x00000000081c0000, 0x0000000008000000, true, 19854558Sbp MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE, 19954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 20054558Sbp{ 0x00000000081c0000, 0x0000000008040000, true, 20154558Sbp MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT, 20254558Sbp MCE_ECLASS_HARDWARE, 20354558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 20454558Sbp{ 0, 0, 0, 0, 0, 0, 0 } }; 20554558Sbp 20654558Sbpstatic const struct mce_ierror_table mce_p9_ierror_table[] = { 20754558Sbp{ 0x00000000081c0000, 0x0000000000040000, true, 20854558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 20954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 21054558Sbp{ 0x00000000081c0000, 0x0000000000080000, true, 211130549Smlaier MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 21254558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 213148887Srwatson{ 0x00000000081c0000, 0x00000000000c0000, true, 214147256Sbrooks MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 21554558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 21654558Sbp{ 0x00000000081c0000, 0x0000000000100000, true, 21754558Sbp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 21854558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 21954558Sbp{ 0x00000000081c0000, 0x0000000000140000, true, 22054558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 221106939Ssam MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 222130549Smlaier{ 0x00000000081c0000, 0x0000000000180000, true, 223130549Smlaier MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE, 22459681Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 22559681Sbp{ 0x00000000081c0000, 0x00000000001c0000, true, 22654558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH_FOREIGN, MCE_ECLASS_SOFTWARE, 22769152Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 22854558Sbp{ 0x00000000081c0000, 0x0000000008000000, true, 229148887Srwatson MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE, 23054558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 23154558Sbp{ 0x00000000081c0000, 0x0000000008040000, true, 23254558Sbp MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT, 23354558Sbp MCE_ECLASS_HARDWARE, 23454558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 23554558Sbp{ 0x00000000081c0000, 0x00000000080c0000, true, 23654558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH, MCE_ECLASS_SOFTWARE, 23754558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 238111888Sjlemon{ 0x00000000081c0000, 0x0000000008100000, true, 23954558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_SOFTWARE, 240111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 241111888Sjlemon{ 0x00000000081c0000, 0x0000000008140000, false, 24254558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_STORE, MCE_ECLASS_HARDWARE, 24354558Sbp MCE_INITIATOR_CPU, MCE_SEV_FATAL, false }, /* ASYNC is fatal */ 244111888Sjlemon{ 0x00000000081c0000, 0x0000000008180000, false, 245111888Sjlemon MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_STORE_TIMEOUT, 24654558Sbp MCE_INITIATOR_CPU, MCE_SEV_FATAL, false }, /* ASYNC is fatal */ 24754558Sbp{ 0x00000000081c0000, 0x00000000081c0000, true, MCE_ECLASS_HARDWARE, 24854558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN, 249111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 250122702Sandre{ 0, 0, 0, 0, 0, 0, 0 } }; 251111888Sjlemon 252111888Sjlemonstatic const struct mce_ierror_table mce_p10_ierror_table[] = { 25354558Sbp{ 0x00000000081c0000, 0x0000000000040000, true, 25454558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 255111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 256111888Sjlemon{ 0x00000000081c0000, 0x0000000000080000, true, 25754558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 25854558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 259111888Sjlemon{ 0x00000000081c0000, 0x00000000000c0000, true, 260111888Sjlemon MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 26154558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 262111888Sjlemon{ 0x00000000081c0000, 0x0000000000100000, true, 263111888Sjlemon MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 26454558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 26554558Sbp{ 0x00000000081c0000, 0x0000000000140000, true, 26654558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 26754558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 268111888Sjlemon{ 0x00000000081c0000, 0x0000000000180000, true, 26954558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE, 270111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 271111888Sjlemon{ 0x00000000081c0000, 0x00000000001c0000, true, 27254558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH_FOREIGN, MCE_ECLASS_SOFTWARE, 27354558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 274111888Sjlemon{ 0x00000000081c0000, 0x0000000008080000, true, 27554558Sbp MCE_ERROR_TYPE_USER,MCE_USER_ERROR_SCV, MCE_ECLASS_SOFTWARE, 276111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 27754558Sbp{ 0x00000000081c0000, 0x00000000080c0000, true, 27854558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH, MCE_ECLASS_SOFTWARE, 279111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 280111888Sjlemon{ 0x00000000081c0000, 0x0000000008100000, true, 28154558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_SOFTWARE, 282111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 283111888Sjlemon{ 0x00000000081c0000, 0x0000000008140000, false, 28454558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_STORE, MCE_ECLASS_HARDWARE, 28554558Sbp MCE_INITIATOR_CPU, MCE_SEV_FATAL, false }, /* ASYNC is fatal */ 28654558Sbp{ 0x00000000081c0000, 0x00000000081c0000, true, MCE_ECLASS_HARDWARE, 28754558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN, 288111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 28954558Sbp{ 0, 0, 0, 0, 0, 0, 0 } }; 290111888Sjlemon 291111888Sjlemonstruct mce_derror_table { 29254558Sbp unsigned long dsisr_value; 29354558Sbp bool dar_valid; /* dar is a valid indicator of faulting address */ 294111888Sjlemon unsigned int error_type; 29554558Sbp unsigned int error_subtype; 296111888Sjlemon unsigned int error_class; 29754558Sbp unsigned int initiator; 29854558Sbp unsigned int severity; 299111888Sjlemon bool sync_error; 300111888Sjlemon}; 30154558Sbp 302111888Sjlemonstatic const struct mce_derror_table mce_p7_derror_table[] = { 303111888Sjlemon{ 0x00008000, false, 30454558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 305111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 30654558Sbp{ 0x00004000, true, 30754558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 30854558Sbp MCE_ECLASS_HARDWARE, 30954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 31054558Sbp{ 0x00000800, true, 31154558Sbp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 31254558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 31371891Sbp{ 0x00000400, true, 31454558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 31554558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 31654558Sbp{ 0x00000080, true, 31754558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 318111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 31954558Sbp{ 0x00000100, true, 32054558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 321132778Skan MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 32254558Sbp{ 0x00000040, true, 32354558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */ 32454558Sbp MCE_ECLASS_HARD_INDETERMINATE, 32554558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 32654558Sbp{ 0, false, 0, 0, 0, 0, 0 } }; 32754558Sbp 32854558Sbpstatic const struct mce_derror_table mce_p8_derror_table[] = { 32954558Sbp{ 0x00008000, false, 33054558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 33154558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 33254558Sbp{ 0x00004000, true, 33354558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 33454558Sbp MCE_ECLASS_HARDWARE, 33554558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 33654558Sbp{ 0x00002000, true, 33754558Sbp MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE, 33854558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 33954558Sbp{ 0x00001000, true, 34054558Sbp MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT, 34154558Sbp MCE_ECLASS_HARDWARE, 34254558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 34354558Sbp{ 0x00000800, true, 34454558Sbp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 34554558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 34654558Sbp{ 0x00000400, true, 34759681Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 34854558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 34954558Sbp{ 0x00000200, true, 35054558Sbp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, /* SECONDARY ERAT */ 35154558Sbp MCE_ECLASS_SOFT_INDETERMINATE, 35254558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 35354558Sbp{ 0x00000080, true, 35454558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, /* Before PARITY */ 35554558Sbp MCE_ECLASS_SOFT_INDETERMINATE, 35654558Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 35754558Sbp{ 0x00000100, true, 35854558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 35954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 36054558Sbp{ 0, false, 0, 0, 0, 0, 0 } }; 36154558Sbp 36259681Sbpstatic const struct mce_derror_table mce_p9_derror_table[] = { 36354558Sbp{ 0x00008000, false, 364147256Sbrooks MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 36554558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 36659681Sbp{ 0x00004000, true, 36754558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 36854558Sbp MCE_ECLASS_HARDWARE, 36954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 370123922Ssam{ 0x00002000, true, 37154558Sbp MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE, 37254558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 37354558Sbp{ 0x00001000, true, 37454558Sbp MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT, 375111888Sjlemon MCE_ECLASS_HARDWARE, 376111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 37754558Sbp{ 0x00000800, true, 378111888Sjlemon MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 379111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 38054558Sbp{ 0x00000400, true, 38154558Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 382111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 383111888Sjlemon{ 0x00000200, false, 384111888Sjlemon MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE, MCE_ECLASS_SOFTWARE, 385111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 386111888Sjlemon{ 0x00000080, true, 38754558Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, /* Before PARITY */ 38854558Sbp MCE_ECLASS_SOFT_INDETERMINATE, 389111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 39054558Sbp{ 0x00000100, true, 391111888Sjlemon MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 392111888Sjlemon MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 39354558Sbp{ 0x00000040, true, 39454558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD, MCE_ECLASS_HARDWARE, 39554558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 39666479Sbp{ 0x00000020, false, 39766479Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 39854558Sbp MCE_ECLASS_HARDWARE, 399121816Sbrooks MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 40059681Sbp{ 0x00000010, false, 40154558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN, 40254558Sbp MCE_ECLASS_HARDWARE, 40354558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 40454558Sbp{ 0x00000008, false, 40559681Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD_STORE_FOREIGN, MCE_ECLASS_HARDWARE, 406121816Sbrooks MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 40754558Sbp{ 0, false, 0, 0, 0, 0, 0 } }; 40854558Sbp 40954558Sbpstatic const struct mce_derror_table mce_p10_derror_table[] = { 41054558Sbp{ 0x00008000, false, 41159681Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 41254558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 41354558Sbp{ 0x00004000, true, 41454558Sbp MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 41554558Sbp MCE_ECLASS_HARDWARE, 41654558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 41754558Sbp{ 0x00000800, true, 418111119Simp MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 41959681Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 42059681Sbp{ 0x00000400, true, 42159681Sbp MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 42259681Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 42359681Sbp{ 0x00000200, false, 42459681Sbp MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE, MCE_ECLASS_SOFTWARE, 42559681Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 42659681Sbp{ 0x00000080, true, 42759681Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, /* Before PARITY */ 42859681Sbp MCE_ECLASS_SOFT_INDETERMINATE, 42959681Sbp MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 43059681Sbp{ 0x00000100, true, 43159681Sbp MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 43259681Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 43354558Sbp{ 0x00000040, true, 43454558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD, MCE_ECLASS_HARDWARE, 43554558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 43654558Sbp{ 0x00000020, false, 43754558Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 43866479Sbp MCE_ECLASS_HARDWARE, 43954558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 44054558Sbp{ 0x00000010, false, 441111119Simp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN, 44259681Sbp MCE_ECLASS_HARDWARE, 44359681Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 44459681Sbp{ 0x00000008, false, 44559681Sbp MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD_STORE_FOREIGN, MCE_ECLASS_HARDWARE, 44654558Sbp MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 44754558Sbp{ 0, false, 0, 0, 0, 0, 0 } }; 44854558Sbp 44966479Sbpstatic int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr, 45054558Sbp uint64_t *phys_addr) 45154558Sbp{ 45259681Sbp /* 45354558Sbp * Carefully look at the NIP to determine 45459681Sbp * the instruction to analyse. Reading the NIP 45554558Sbp * in real-mode is tricky and can lead to recursive 45654558Sbp * faults 45754558Sbp */ 45854558Sbp ppc_inst_t instr; 45954558Sbp unsigned long pfn, instr_addr; 46054558Sbp struct instruction_op op; 46154558Sbp struct pt_regs tmp = *regs; 46254558Sbp 46354558Sbp pfn = addr_to_pfn(regs, regs->nip); 46454558Sbp if (pfn != ULONG_MAX) { 46554558Sbp instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK); 46654558Sbp instr = ppc_inst_read((u32 *)instr_addr); 46754558Sbp if (!analyse_instr(&op, &tmp, instr)) { 46854558Sbp pfn = addr_to_pfn(regs, op.ea); 46969781Sdwmalone *addr = op.ea; 470111119Simp *phys_addr = (pfn << PAGE_SHIFT); 47154558Sbp return 0; 47254558Sbp } 473147256Sbrooks /* 474121816Sbrooks * analyse_instr() might fail if the instruction 475147256Sbrooks * is not a load/store, although this is unexpected 476154318Srwatson * for load/store errors or if we got the NIP 477154318Srwatson * wrong 478147256Sbrooks */ 479154318Srwatson } 480121816Sbrooks *addr = 0; 481121816Sbrooks return -1; 482121816Sbrooks} 483121816Sbrooks 48454558Sbpstatic int mce_handle_ierror(struct pt_regs *regs, unsigned long srr1, 48554558Sbp const struct mce_ierror_table table[], 48654558Sbp struct mce_error_info *mce_err, uint64_t *addr, 48754558Sbp uint64_t *phys_addr) 48854558Sbp{ 48954558Sbp int handled = 0; 49054558Sbp int i; 49154558Sbp 49254558Sbp *addr = 0; 49354558Sbp 49454558Sbp for (i = 0; table[i].srr1_mask; i++) { 49554558Sbp if ((srr1 & table[i].srr1_mask) != table[i].srr1_value) 496154317Srwatson continue; 49754558Sbp 49854558Sbp if (!mce_in_guest()) { 499108172Shsu /* attempt to correct the error */ 50071999Sphk switch (table[i].error_type) { 50154558Sbp case MCE_ERROR_TYPE_SLB: 502121816Sbrooks#ifdef CONFIG_PPC_64S_HASH_MMU 50354558Sbp if (local_paca->in_mce == 1) 504111119Simp slb_save_contents(local_paca->mce_faulty_slbs); 50554558Sbp#endif 50654558Sbp handled = mce_flush(MCE_FLUSH_SLB); 50754558Sbp break; 50854558Sbp case MCE_ERROR_TYPE_ERAT: 50954558Sbp handled = mce_flush(MCE_FLUSH_ERAT); 51054558Sbp break; 51154558Sbp case MCE_ERROR_TYPE_TLB: 51254558Sbp handled = mce_flush(MCE_FLUSH_TLB); 51354558Sbp break; 51454558Sbp } 51554558Sbp } 51654558Sbp 51754558Sbp /* now fill in mce_error_info */ 51854558Sbp mce_err->error_type = table[i].error_type; 51954558Sbp mce_err->error_class = table[i].error_class; 52054558Sbp switch (table[i].error_type) { 52154558Sbp case MCE_ERROR_TYPE_UE: 52254558Sbp mce_err->u.ue_error_type = table[i].error_subtype; 52354558Sbp break; 52454558Sbp case MCE_ERROR_TYPE_SLB: 52554558Sbp mce_err->u.slb_error_type = table[i].error_subtype; 52654558Sbp break; 52754558Sbp case MCE_ERROR_TYPE_ERAT: 52854558Sbp mce_err->u.erat_error_type = table[i].error_subtype; 52954558Sbp break; 530108172Shsu case MCE_ERROR_TYPE_TLB: 53154558Sbp mce_err->u.tlb_error_type = table[i].error_subtype; 53254558Sbp break; 53354558Sbp case MCE_ERROR_TYPE_USER: 534154317Srwatson mce_err->u.user_error_type = table[i].error_subtype; 53554558Sbp break; 536147256Sbrooks case MCE_ERROR_TYPE_RA: 537147256Sbrooks mce_err->u.ra_error_type = table[i].error_subtype; 538147256Sbrooks break; 53954558Sbp case MCE_ERROR_TYPE_LINK: 540147256Sbrooks mce_err->u.link_error_type = table[i].error_subtype; 54154558Sbp break; 54254558Sbp } 54354558Sbp mce_err->sync_error = table[i].sync_error; 54454558Sbp mce_err->severity = table[i].severity; 54554558Sbp mce_err->initiator = table[i].initiator; 54654558Sbp if (table[i].nip_valid && !mce_in_guest()) { 54754558Sbp *addr = regs->nip; 54854558Sbp if (mce_err->sync_error && 54954558Sbp table[i].error_type == MCE_ERROR_TYPE_UE) { 55054558Sbp unsigned long pfn; 55154558Sbp 55254558Sbp if (get_paca()->in_mce < MAX_MCE_DEPTH) { 55354558Sbp pfn = addr_to_pfn(regs, regs->nip); 55454558Sbp if (pfn != ULONG_MAX) { 55554558Sbp *phys_addr = 55654558Sbp (pfn << PAGE_SHIFT); 55754558Sbp } 55854558Sbp } 55954558Sbp } 56054558Sbp } 56154558Sbp return handled; 56254558Sbp } 56354558Sbp 56454558Sbp mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 56554558Sbp mce_err->error_class = MCE_ECLASS_UNKNOWN; 56654558Sbp mce_err->severity = MCE_SEV_SEVERE; 56754558Sbp mce_err->initiator = MCE_INITIATOR_CPU; 56854558Sbp mce_err->sync_error = true; 56954558Sbp 57054558Sbp return 0; 57154558Sbp} 57254558Sbp 57354558Sbpstatic int mce_handle_derror(struct pt_regs *regs, 57454558Sbp const struct mce_derror_table table[], 57554558Sbp struct mce_error_info *mce_err, uint64_t *addr, 57654558Sbp uint64_t *phys_addr) 57754558Sbp{ 57854558Sbp uint64_t dsisr = regs->dsisr; 57954558Sbp int handled = 0; 58054558Sbp int found = 0; 58154558Sbp int i; 58254558Sbp 58354558Sbp *addr = 0; 58454558Sbp 58554558Sbp for (i = 0; table[i].dsisr_value; i++) { 58654558Sbp if (!(dsisr & table[i].dsisr_value)) 58754558Sbp continue; 588132199Sphk 58954558Sbp if (!mce_in_guest()) { 59054558Sbp /* attempt to correct the error */ 59154558Sbp switch (table[i].error_type) { 59254558Sbp case MCE_ERROR_TYPE_SLB: 59354558Sbp#ifdef CONFIG_PPC_64S_HASH_MMU 59454558Sbp if (local_paca->in_mce == 1) 59554558Sbp slb_save_contents(local_paca->mce_faulty_slbs); 59654558Sbp#endif 59754558Sbp if (mce_flush(MCE_FLUSH_SLB)) 598 handled = 1; 599 break; 600 case MCE_ERROR_TYPE_ERAT: 601 if (mce_flush(MCE_FLUSH_ERAT)) 602 handled = 1; 603 break; 604 case MCE_ERROR_TYPE_TLB: 605 if (mce_flush(MCE_FLUSH_TLB)) 606 handled = 1; 607 break; 608 } 609 } 610 611 /* 612 * Attempt to handle multiple conditions, but only return 613 * one. Ensure uncorrectable errors are first in the table 614 * to match. 615 */ 616 if (found) 617 continue; 618 619 /* now fill in mce_error_info */ 620 mce_err->error_type = table[i].error_type; 621 mce_err->error_class = table[i].error_class; 622 switch (table[i].error_type) { 623 case MCE_ERROR_TYPE_UE: 624 mce_err->u.ue_error_type = table[i].error_subtype; 625 break; 626 case MCE_ERROR_TYPE_SLB: 627 mce_err->u.slb_error_type = table[i].error_subtype; 628 break; 629 case MCE_ERROR_TYPE_ERAT: 630 mce_err->u.erat_error_type = table[i].error_subtype; 631 break; 632 case MCE_ERROR_TYPE_TLB: 633 mce_err->u.tlb_error_type = table[i].error_subtype; 634 break; 635 case MCE_ERROR_TYPE_USER: 636 mce_err->u.user_error_type = table[i].error_subtype; 637 break; 638 case MCE_ERROR_TYPE_RA: 639 mce_err->u.ra_error_type = table[i].error_subtype; 640 break; 641 case MCE_ERROR_TYPE_LINK: 642 mce_err->u.link_error_type = table[i].error_subtype; 643 break; 644 } 645 mce_err->sync_error = table[i].sync_error; 646 mce_err->severity = table[i].severity; 647 mce_err->initiator = table[i].initiator; 648 if (table[i].dar_valid) 649 *addr = regs->dar; 650 else if (mce_err->sync_error && !mce_in_guest() && 651 table[i].error_type == MCE_ERROR_TYPE_UE) { 652 /* 653 * We do a maximum of 4 nested MCE calls, see 654 * kernel/exception-64s.h 655 */ 656 if (get_paca()->in_mce < MAX_MCE_DEPTH) 657 mce_find_instr_ea_and_phys(regs, addr, 658 phys_addr); 659 } 660 found = 1; 661 } 662 663 if (found) 664 return handled; 665 666 mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 667 mce_err->error_class = MCE_ECLASS_UNKNOWN; 668 mce_err->severity = MCE_SEV_SEVERE; 669 mce_err->initiator = MCE_INITIATOR_CPU; 670 mce_err->sync_error = true; 671 672 return 0; 673} 674 675static long mce_handle_ue_error(struct pt_regs *regs, 676 struct mce_error_info *mce_err) 677{ 678 if (mce_in_guest()) 679 return 0; 680 681 mce_common_process_ue(regs, mce_err); 682 if (mce_err->ignore_event) 683 return 1; 684 685 /* 686 * On specific SCOM read via MMIO we may get a machine check 687 * exception with SRR0 pointing inside opal. If that is the 688 * case OPAL may have recovery address to re-read SCOM data in 689 * different way and hence we can recover from this MC. 690 */ 691 692 if (ppc_md.mce_check_early_recovery) { 693 if (ppc_md.mce_check_early_recovery(regs)) 694 return 1; 695 } 696 697 return 0; 698} 699 700static long mce_handle_error(struct pt_regs *regs, 701 unsigned long srr1, 702 const struct mce_derror_table dtable[], 703 const struct mce_ierror_table itable[]) 704{ 705 struct mce_error_info mce_err = { 0 }; 706 uint64_t addr, phys_addr = ULONG_MAX; 707 long handled; 708 709 if (SRR1_MC_LOADSTORE(srr1)) 710 handled = mce_handle_derror(regs, dtable, &mce_err, &addr, 711 &phys_addr); 712 else 713 handled = mce_handle_ierror(regs, srr1, itable, &mce_err, &addr, 714 &phys_addr); 715 716 if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) 717 handled = mce_handle_ue_error(regs, &mce_err); 718 719 save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr); 720 721 return handled; 722} 723 724long __machine_check_early_realmode_p7(struct pt_regs *regs) 725{ 726 /* P7 DD1 leaves top bits of DSISR undefined */ 727 regs->dsisr &= 0x0000ffff; 728 729 return mce_handle_error(regs, regs->msr, 730 mce_p7_derror_table, mce_p7_ierror_table); 731} 732 733long __machine_check_early_realmode_p8(struct pt_regs *regs) 734{ 735 return mce_handle_error(regs, regs->msr, 736 mce_p8_derror_table, mce_p8_ierror_table); 737} 738 739long __machine_check_early_realmode_p9(struct pt_regs *regs) 740{ 741 unsigned long srr1 = regs->msr; 742 743 /* 744 * On POWER9 DD2.1 and below, it's possible to get a machine check 745 * caused by a paste instruction where only DSISR bit 25 is set. This 746 * will result in the MCE handler seeing an unknown event and the kernel 747 * crashing. An MCE that occurs like this is spurious, so we don't need 748 * to do anything in terms of servicing it. If there is something that 749 * needs to be serviced, the CPU will raise the MCE again with the 750 * correct DSISR so that it can be serviced properly. So detect this 751 * case and mark it as handled. 752 */ 753 if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000) 754 return 1; 755 756 /* 757 * Async machine check due to bad real address from store or foreign 758 * link time out comes with the load/store bit (PPC bit 42) set in 759 * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're 760 * directed to the ierror table so it will find the cause (which 761 * describes it correctly as a store error). 762 */ 763 if (SRR1_MC_LOADSTORE(srr1) && 764 ((srr1 & 0x081c0000) == 0x08140000 || 765 (srr1 & 0x081c0000) == 0x08180000)) { 766 srr1 &= ~PPC_BIT(42); 767 } 768 769 return mce_handle_error(regs, srr1, 770 mce_p9_derror_table, mce_p9_ierror_table); 771} 772 773long __machine_check_early_realmode_p10(struct pt_regs *regs) 774{ 775 unsigned long srr1 = regs->msr; 776 777 /* 778 * Async machine check due to bad real address from store comes with 779 * the load/store bit (PPC bit 42) set in SRR1, but the cause comes in 780 * SRR1 not DSISR. Clear bit 42 so we're directed to the ierror table 781 * so it will find the cause (which describes it correctly as a store 782 * error). 783 */ 784 if (SRR1_MC_LOADSTORE(srr1) && 785 (srr1 & 0x081c0000) == 0x08140000) { 786 srr1 &= ~PPC_BIT(42); 787 } 788 789 return mce_handle_error(regs, srr1, 790 mce_p10_derror_table, mce_p10_ierror_table); 791} 792