Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Machine check exception handling CPU-side for power7 and power8
0004  *
0005  * Copyright 2013 IBM Corporation
0006  * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
0007  */
0008 
0009 #undef DEBUG
0010 #define pr_fmt(fmt) "mce_power: " fmt
0011 
0012 #include <linux/types.h>
0013 #include <linux/ptrace.h>
0014 #include <linux/extable.h>
0015 #include <linux/pgtable.h>
0016 #include <asm/mmu.h>
0017 #include <asm/mce.h>
0018 #include <asm/machdep.h>
0019 #include <asm/pte-walk.h>
0020 #include <asm/sstep.h>
0021 #include <asm/exception-64s.h>
0022 #include <asm/extable.h>
0023 #include <asm/inst.h>
0024 
0025 /*
0026  * Convert an address related to an mm to a PFN. NOTE: we are in real
0027  * mode, we could potentially race with page table updates.
0028  */
0029 unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
0030 {
0031     pte_t *ptep, pte;
0032     unsigned int shift;
0033     unsigned long pfn, flags;
0034     struct mm_struct *mm;
0035 
0036     if (user_mode(regs))
0037         mm = current->mm;
0038     else
0039         mm = &init_mm;
0040 
0041     local_irq_save(flags);
0042     ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift);
0043     if (!ptep) {
0044         pfn = ULONG_MAX;
0045         goto out;
0046     }
0047     pte = READ_ONCE(*ptep);
0048 
0049     if (!pte_present(pte) || pte_special(pte)) {
0050         pfn = ULONG_MAX;
0051         goto out;
0052     }
0053 
0054     if (shift <= PAGE_SHIFT)
0055         pfn = pte_pfn(pte);
0056     else {
0057         unsigned long rpnmask = (1ul << shift) - PAGE_SIZE;
0058         pfn = pte_pfn(__pte(pte_val(pte) | (addr & rpnmask)));
0059     }
0060 out:
0061     local_irq_restore(flags);
0062     return pfn;
0063 }
0064 
0065 static bool mce_in_guest(void)
0066 {
0067 #ifdef CONFIG_KVM_BOOK3S_HANDLER
0068     /*
0069      * If machine check is hit when in guest context or low level KVM
0070      * code, avoid looking up any translations or making any attempts
0071      * to recover, just record the event and pass to KVM.
0072      */
0073     if (get_paca()->kvm_hstate.in_guest)
0074         return true;
0075 #endif
0076     return false;
0077 }
0078 
0079 /* flush SLBs and reload */
0080 #ifdef CONFIG_PPC_64S_HASH_MMU
0081 void flush_and_reload_slb(void)
0082 {
0083     if (early_radix_enabled())
0084         return;
0085 
0086     /* Invalidate all SLBs */
0087     slb_flush_all_realmode();
0088 
0089     /*
0090      * This probably shouldn't happen, but it may be possible it's
0091      * called in early boot before SLB shadows are allocated.
0092      */
0093     if (!get_slb_shadow())
0094         return;
0095 
0096     slb_restore_bolted_realmode();
0097 }
0098 #endif
0099 
0100 void flush_erat(void)
0101 {
0102 #ifdef CONFIG_PPC_64S_HASH_MMU
0103     if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
0104         flush_and_reload_slb();
0105         return;
0106     }
0107 #endif
0108     asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory");
0109 }
0110 
0111 #define MCE_FLUSH_SLB 1
0112 #define MCE_FLUSH_TLB 2
0113 #define MCE_FLUSH_ERAT 3
0114 
0115 static int mce_flush(int what)
0116 {
0117 #ifdef CONFIG_PPC_64S_HASH_MMU
0118     if (what == MCE_FLUSH_SLB) {
0119         flush_and_reload_slb();
0120         return 1;
0121     }
0122 #endif
0123     if (what == MCE_FLUSH_ERAT) {
0124         flush_erat();
0125         return 1;
0126     }
0127     if (what == MCE_FLUSH_TLB) {
0128         tlbiel_all();
0129         return 1;
0130     }
0131 
0132     return 0;
0133 }
0134 
0135 #define SRR1_MC_LOADSTORE(srr1) ((srr1) & PPC_BIT(42))
0136 
0137 struct mce_ierror_table {
0138     unsigned long srr1_mask;
0139     unsigned long srr1_value;
0140     bool nip_valid; /* nip is a valid indicator of faulting address */
0141     unsigned int error_type;
0142     unsigned int error_subtype;
0143     unsigned int error_class;
0144     unsigned int initiator;
0145     unsigned int severity;
0146     bool sync_error;
0147 };
0148 
0149 static const struct mce_ierror_table mce_p7_ierror_table[] = {
0150 { 0x00000000001c0000, 0x0000000000040000, true,
0151   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0152   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0153 { 0x00000000001c0000, 0x0000000000080000, true,
0154   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0155   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0156 { 0x00000000001c0000, 0x00000000000c0000, true,
0157   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0158   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0159 { 0x00000000001c0000, 0x0000000000100000, true,
0160   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */
0161   MCE_ECLASS_SOFT_INDETERMINATE,
0162   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0163 { 0x00000000001c0000, 0x0000000000140000, true,
0164   MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0165   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0166 { 0x00000000001c0000, 0x0000000000180000, true,
0167   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE,
0168   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0169 { 0x00000000001c0000, 0x00000000001c0000, true,
0170   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0171   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0172 { 0, 0, 0, 0, 0, 0, 0 } };
0173 
0174 static const struct mce_ierror_table mce_p8_ierror_table[] = {
0175 { 0x00000000081c0000, 0x0000000000040000, true,
0176   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0177   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0178 { 0x00000000081c0000, 0x0000000000080000, true,
0179   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0180   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0181 { 0x00000000081c0000, 0x00000000000c0000, true,
0182   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0183   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0184 { 0x00000000081c0000, 0x0000000000100000, true,
0185   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0186   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0187 { 0x00000000081c0000, 0x0000000000140000, true,
0188   MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0189   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0190 { 0x00000000081c0000, 0x0000000000180000, true,
0191   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH,
0192   MCE_ECLASS_HARDWARE,
0193   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0194 { 0x00000000081c0000, 0x00000000001c0000, true,
0195   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0196   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0197 { 0x00000000081c0000, 0x0000000008000000, true,
0198   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE,
0199   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0200 { 0x00000000081c0000, 0x0000000008040000, true,
0201   MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT,
0202   MCE_ECLASS_HARDWARE,
0203   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0204 { 0, 0, 0, 0, 0, 0, 0 } };
0205 
0206 static const struct mce_ierror_table mce_p9_ierror_table[] = {
0207 { 0x00000000081c0000, 0x0000000000040000, true,
0208   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0209   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0210 { 0x00000000081c0000, 0x0000000000080000, true,
0211   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0212   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0213 { 0x00000000081c0000, 0x00000000000c0000, true,
0214   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0215   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0216 { 0x00000000081c0000, 0x0000000000100000, true,
0217   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0218   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0219 { 0x00000000081c0000, 0x0000000000140000, true,
0220   MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0221   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0222 { 0x00000000081c0000, 0x0000000000180000, true,
0223   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE,
0224   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0225 { 0x00000000081c0000, 0x00000000001c0000, true,
0226   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_IFETCH_FOREIGN, MCE_ECLASS_SOFTWARE,
0227   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0228 { 0x00000000081c0000, 0x0000000008000000, true,
0229   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE,
0230   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0231 { 0x00000000081c0000, 0x0000000008040000, true,
0232   MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT,
0233   MCE_ECLASS_HARDWARE,
0234   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0235 { 0x00000000081c0000, 0x00000000080c0000, true,
0236   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_IFETCH, MCE_ECLASS_SOFTWARE,
0237   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0238 { 0x00000000081c0000, 0x0000000008100000, true,
0239   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_SOFTWARE,
0240   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0241 { 0x00000000081c0000, 0x0000000008140000, false,
0242   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_STORE, MCE_ECLASS_HARDWARE,
0243   MCE_INITIATOR_CPU,  MCE_SEV_FATAL, false }, /* ASYNC is fatal */
0244 { 0x00000000081c0000, 0x0000000008180000, false,
0245   MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_STORE_TIMEOUT,
0246   MCE_INITIATOR_CPU,  MCE_SEV_FATAL, false }, /* ASYNC is fatal */
0247 { 0x00000000081c0000, 0x00000000081c0000, true, MCE_ECLASS_HARDWARE,
0248   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN,
0249   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0250 { 0, 0, 0, 0, 0, 0, 0 } };
0251 
0252 static const struct mce_ierror_table mce_p10_ierror_table[] = {
0253 { 0x00000000081c0000, 0x0000000000040000, true,
0254   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE,
0255   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0256 { 0x00000000081c0000, 0x0000000000080000, true,
0257   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0258   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0259 { 0x00000000081c0000, 0x00000000000c0000, true,
0260   MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0261   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0262 { 0x00000000081c0000, 0x0000000000100000, true,
0263   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0264   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0265 { 0x00000000081c0000, 0x0000000000140000, true,
0266   MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0267   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0268 { 0x00000000081c0000, 0x0000000000180000, true,
0269   MCE_ERROR_TYPE_UE,  MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE,
0270   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0271 { 0x00000000081c0000, 0x00000000001c0000, true,
0272   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_IFETCH_FOREIGN, MCE_ECLASS_SOFTWARE,
0273   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0274 { 0x00000000081c0000, 0x0000000008080000, true,
0275   MCE_ERROR_TYPE_USER,MCE_USER_ERROR_SCV, MCE_ECLASS_SOFTWARE,
0276   MCE_INITIATOR_CPU,  MCE_SEV_WARNING, true },
0277 { 0x00000000081c0000, 0x00000000080c0000, true,
0278   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_IFETCH, MCE_ECLASS_SOFTWARE,
0279   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0280 { 0x00000000081c0000, 0x0000000008100000, true,
0281   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_SOFTWARE,
0282   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0283 { 0x00000000081c0000, 0x0000000008140000, false,
0284   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_STORE, MCE_ECLASS_HARDWARE,
0285   MCE_INITIATOR_CPU,  MCE_SEV_FATAL, false }, /* ASYNC is fatal */
0286 { 0x00000000081c0000, 0x00000000081c0000, true, MCE_ECLASS_HARDWARE,
0287   MCE_ERROR_TYPE_RA,  MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN,
0288   MCE_INITIATOR_CPU,  MCE_SEV_SEVERE, true },
0289 { 0, 0, 0, 0, 0, 0, 0 } };
0290 
0291 struct mce_derror_table {
0292     unsigned long dsisr_value;
0293     bool dar_valid; /* dar is a valid indicator of faulting address */
0294     unsigned int error_type;
0295     unsigned int error_subtype;
0296     unsigned int error_class;
0297     unsigned int initiator;
0298     unsigned int severity;
0299     bool sync_error;
0300 };
0301 
0302 static const struct mce_derror_table mce_p7_derror_table[] = {
0303 { 0x00008000, false,
0304   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE,
0305   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0306 { 0x00004000, true,
0307   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0308   MCE_ECLASS_HARDWARE,
0309   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0310 { 0x00000800, true,
0311   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0312   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0313 { 0x00000400, true,
0314   MCE_ERROR_TYPE_TLB,  MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0315   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0316 { 0x00000080, true,
0317   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0318   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0319 { 0x00000100, true,
0320   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0321   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0322 { 0x00000040, true,
0323   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_INDETERMINATE, /* BOTH */
0324   MCE_ECLASS_HARD_INDETERMINATE,
0325   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0326 { 0, false, 0, 0, 0, 0, 0 } };
0327 
0328 static const struct mce_derror_table mce_p8_derror_table[] = {
0329 { 0x00008000, false,
0330   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE,
0331   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0332 { 0x00004000, true,
0333   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0334   MCE_ECLASS_HARDWARE,
0335   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0336 { 0x00002000, true,
0337   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE,
0338   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0339 { 0x00001000, true,
0340   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT,
0341   MCE_ECLASS_HARDWARE,
0342   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0343 { 0x00000800, true,
0344   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0345   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0346 { 0x00000400, true,
0347   MCE_ERROR_TYPE_TLB,  MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0348   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0349 { 0x00000200, true,
0350   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, /* SECONDARY ERAT */
0351   MCE_ECLASS_SOFT_INDETERMINATE,
0352   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0353 { 0x00000080, true,
0354   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_MULTIHIT,  /* Before PARITY */
0355   MCE_ECLASS_SOFT_INDETERMINATE,
0356   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0357 { 0x00000100, true,
0358   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0359   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0360 { 0, false, 0, 0, 0, 0, 0 } };
0361 
0362 static const struct mce_derror_table mce_p9_derror_table[] = {
0363 { 0x00008000, false,
0364   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE,
0365   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0366 { 0x00004000, true,
0367   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0368   MCE_ECLASS_HARDWARE,
0369   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0370 { 0x00002000, true,
0371   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE,
0372   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0373 { 0x00001000, true,
0374   MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT,
0375   MCE_ECLASS_HARDWARE,
0376   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0377 { 0x00000800, true,
0378   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0379   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0380 { 0x00000400, true,
0381   MCE_ERROR_TYPE_TLB,  MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0382   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0383 { 0x00000200, false,
0384   MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE, MCE_ECLASS_SOFTWARE,
0385   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0386 { 0x00000080, true,
0387   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_MULTIHIT,  /* Before PARITY */
0388   MCE_ECLASS_SOFT_INDETERMINATE,
0389   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0390 { 0x00000100, true,
0391   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0392   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0393 { 0x00000040, true,
0394   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_LOAD, MCE_ECLASS_HARDWARE,
0395   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0396 { 0x00000020, false,
0397   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0398   MCE_ECLASS_HARDWARE,
0399   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0400 { 0x00000010, false,
0401   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN,
0402   MCE_ECLASS_HARDWARE,
0403   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0404 { 0x00000008, false,
0405   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_LOAD_STORE_FOREIGN, MCE_ECLASS_HARDWARE,
0406   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0407 { 0, false, 0, 0, 0, 0, 0 } };
0408 
0409 static const struct mce_derror_table mce_p10_derror_table[] = {
0410 { 0x00008000, false,
0411   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE,
0412   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0413 { 0x00004000, true,
0414   MCE_ERROR_TYPE_UE,   MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0415   MCE_ECLASS_HARDWARE,
0416   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0417 { 0x00000800, true,
0418   MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0419   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0420 { 0x00000400, true,
0421   MCE_ERROR_TYPE_TLB,  MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE,
0422   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0423 { 0x00000200, false,
0424   MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE, MCE_ECLASS_SOFTWARE,
0425   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0426 { 0x00000080, true,
0427   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_MULTIHIT,  /* Before PARITY */
0428   MCE_ECLASS_SOFT_INDETERMINATE,
0429   MCE_INITIATOR_CPU,   MCE_SEV_WARNING, true },
0430 { 0x00000100, true,
0431   MCE_ERROR_TYPE_SLB,  MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE,
0432   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0433 { 0x00000040, true,
0434   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_LOAD, MCE_ECLASS_HARDWARE,
0435   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0436 { 0x00000020, false,
0437   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
0438   MCE_ECLASS_HARDWARE,
0439   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0440 { 0x00000010, false,
0441   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN,
0442   MCE_ECLASS_HARDWARE,
0443   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0444 { 0x00000008, false,
0445   MCE_ERROR_TYPE_RA,   MCE_RA_ERROR_LOAD_STORE_FOREIGN, MCE_ECLASS_HARDWARE,
0446   MCE_INITIATOR_CPU,   MCE_SEV_SEVERE, true },
0447 { 0, false, 0, 0, 0, 0, 0 } };
0448 
0449 static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
0450                     uint64_t *phys_addr)
0451 {
0452     /*
0453      * Carefully look at the NIP to determine
0454      * the instruction to analyse. Reading the NIP
0455      * in real-mode is tricky and can lead to recursive
0456      * faults
0457      */
0458     ppc_inst_t instr;
0459     unsigned long pfn, instr_addr;
0460     struct instruction_op op;
0461     struct pt_regs tmp = *regs;
0462 
0463     pfn = addr_to_pfn(regs, regs->nip);
0464     if (pfn != ULONG_MAX) {
0465         instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
0466         instr = ppc_inst_read((u32 *)instr_addr);
0467         if (!analyse_instr(&op, &tmp, instr)) {
0468             pfn = addr_to_pfn(regs, op.ea);
0469             *addr = op.ea;
0470             *phys_addr = (pfn << PAGE_SHIFT);
0471             return 0;
0472         }
0473         /*
0474          * analyse_instr() might fail if the instruction
0475          * is not a load/store, although this is unexpected
0476          * for load/store errors or if we got the NIP
0477          * wrong
0478          */
0479     }
0480     *addr = 0;
0481     return -1;
0482 }
0483 
0484 static int mce_handle_ierror(struct pt_regs *regs, unsigned long srr1,
0485         const struct mce_ierror_table table[],
0486         struct mce_error_info *mce_err, uint64_t *addr,
0487         uint64_t *phys_addr)
0488 {
0489     int handled = 0;
0490     int i;
0491 
0492     *addr = 0;
0493 
0494     for (i = 0; table[i].srr1_mask; i++) {
0495         if ((srr1 & table[i].srr1_mask) != table[i].srr1_value)
0496             continue;
0497 
0498         if (!mce_in_guest()) {
0499             /* attempt to correct the error */
0500             switch (table[i].error_type) {
0501             case MCE_ERROR_TYPE_SLB:
0502 #ifdef CONFIG_PPC_64S_HASH_MMU
0503                 if (local_paca->in_mce == 1)
0504                     slb_save_contents(local_paca->mce_faulty_slbs);
0505 #endif
0506                 handled = mce_flush(MCE_FLUSH_SLB);
0507                 break;
0508             case MCE_ERROR_TYPE_ERAT:
0509                 handled = mce_flush(MCE_FLUSH_ERAT);
0510                 break;
0511             case MCE_ERROR_TYPE_TLB:
0512                 handled = mce_flush(MCE_FLUSH_TLB);
0513                 break;
0514             }
0515         }
0516 
0517         /* now fill in mce_error_info */
0518         mce_err->error_type = table[i].error_type;
0519         mce_err->error_class = table[i].error_class;
0520         switch (table[i].error_type) {
0521         case MCE_ERROR_TYPE_UE:
0522             mce_err->u.ue_error_type = table[i].error_subtype;
0523             break;
0524         case MCE_ERROR_TYPE_SLB:
0525             mce_err->u.slb_error_type = table[i].error_subtype;
0526             break;
0527         case MCE_ERROR_TYPE_ERAT:
0528             mce_err->u.erat_error_type = table[i].error_subtype;
0529             break;
0530         case MCE_ERROR_TYPE_TLB:
0531             mce_err->u.tlb_error_type = table[i].error_subtype;
0532             break;
0533         case MCE_ERROR_TYPE_USER:
0534             mce_err->u.user_error_type = table[i].error_subtype;
0535             break;
0536         case MCE_ERROR_TYPE_RA:
0537             mce_err->u.ra_error_type = table[i].error_subtype;
0538             break;
0539         case MCE_ERROR_TYPE_LINK:
0540             mce_err->u.link_error_type = table[i].error_subtype;
0541             break;
0542         }
0543         mce_err->sync_error = table[i].sync_error;
0544         mce_err->severity = table[i].severity;
0545         mce_err->initiator = table[i].initiator;
0546         if (table[i].nip_valid && !mce_in_guest()) {
0547             *addr = regs->nip;
0548             if (mce_err->sync_error &&
0549                 table[i].error_type == MCE_ERROR_TYPE_UE) {
0550                 unsigned long pfn;
0551 
0552                 if (get_paca()->in_mce < MAX_MCE_DEPTH) {
0553                     pfn = addr_to_pfn(regs, regs->nip);
0554                     if (pfn != ULONG_MAX) {
0555                         *phys_addr =
0556                             (pfn << PAGE_SHIFT);
0557                     }
0558                 }
0559             }
0560         }
0561         return handled;
0562     }
0563 
0564     mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
0565     mce_err->error_class = MCE_ECLASS_UNKNOWN;
0566     mce_err->severity = MCE_SEV_SEVERE;
0567     mce_err->initiator = MCE_INITIATOR_CPU;
0568     mce_err->sync_error = true;
0569 
0570     return 0;
0571 }
0572 
0573 static int mce_handle_derror(struct pt_regs *regs,
0574         const struct mce_derror_table table[],
0575         struct mce_error_info *mce_err, uint64_t *addr,
0576         uint64_t *phys_addr)
0577 {
0578     uint64_t dsisr = regs->dsisr;
0579     int handled = 0;
0580     int found = 0;
0581     int i;
0582 
0583     *addr = 0;
0584 
0585     for (i = 0; table[i].dsisr_value; i++) {
0586         if (!(dsisr & table[i].dsisr_value))
0587             continue;
0588 
0589         if (!mce_in_guest()) {
0590             /* attempt to correct the error */
0591             switch (table[i].error_type) {
0592             case MCE_ERROR_TYPE_SLB:
0593 #ifdef CONFIG_PPC_64S_HASH_MMU
0594                 if (local_paca->in_mce == 1)
0595                     slb_save_contents(local_paca->mce_faulty_slbs);
0596 #endif
0597                 if (mce_flush(MCE_FLUSH_SLB))
0598                     handled = 1;
0599                 break;
0600             case MCE_ERROR_TYPE_ERAT:
0601                 if (mce_flush(MCE_FLUSH_ERAT))
0602                     handled = 1;
0603                 break;
0604             case MCE_ERROR_TYPE_TLB:
0605                 if (mce_flush(MCE_FLUSH_TLB))
0606                     handled = 1;
0607                 break;
0608             }
0609         }
0610 
0611         /*
0612          * Attempt to handle multiple conditions, but only return
0613          * one. Ensure uncorrectable errors are first in the table
0614          * to match.
0615          */
0616         if (found)
0617             continue;
0618 
0619         /* now fill in mce_error_info */
0620         mce_err->error_type = table[i].error_type;
0621         mce_err->error_class = table[i].error_class;
0622         switch (table[i].error_type) {
0623         case MCE_ERROR_TYPE_UE:
0624             mce_err->u.ue_error_type = table[i].error_subtype;
0625             break;
0626         case MCE_ERROR_TYPE_SLB:
0627             mce_err->u.slb_error_type = table[i].error_subtype;
0628             break;
0629         case MCE_ERROR_TYPE_ERAT:
0630             mce_err->u.erat_error_type = table[i].error_subtype;
0631             break;
0632         case MCE_ERROR_TYPE_TLB:
0633             mce_err->u.tlb_error_type = table[i].error_subtype;
0634             break;
0635         case MCE_ERROR_TYPE_USER:
0636             mce_err->u.user_error_type = table[i].error_subtype;
0637             break;
0638         case MCE_ERROR_TYPE_RA:
0639             mce_err->u.ra_error_type = table[i].error_subtype;
0640             break;
0641         case MCE_ERROR_TYPE_LINK:
0642             mce_err->u.link_error_type = table[i].error_subtype;
0643             break;
0644         }
0645         mce_err->sync_error = table[i].sync_error;
0646         mce_err->severity = table[i].severity;
0647         mce_err->initiator = table[i].initiator;
0648         if (table[i].dar_valid)
0649             *addr = regs->dar;
0650         else if (mce_err->sync_error && !mce_in_guest() &&
0651                 table[i].error_type == MCE_ERROR_TYPE_UE) {
0652             /*
0653              * We do a maximum of 4 nested MCE calls, see
0654              * kernel/exception-64s.h
0655              */
0656             if (get_paca()->in_mce < MAX_MCE_DEPTH)
0657                 mce_find_instr_ea_and_phys(regs, addr,
0658                                phys_addr);
0659         }
0660         found = 1;
0661     }
0662 
0663     if (found)
0664         return handled;
0665 
0666     mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
0667     mce_err->error_class = MCE_ECLASS_UNKNOWN;
0668     mce_err->severity = MCE_SEV_SEVERE;
0669     mce_err->initiator = MCE_INITIATOR_CPU;
0670     mce_err->sync_error = true;
0671 
0672     return 0;
0673 }
0674 
0675 static long mce_handle_ue_error(struct pt_regs *regs,
0676                 struct mce_error_info *mce_err)
0677 {
0678     if (mce_in_guest())
0679         return 0;
0680 
0681     mce_common_process_ue(regs, mce_err);
0682     if (mce_err->ignore_event)
0683         return 1;
0684 
0685     /*
0686      * On specific SCOM read via MMIO we may get a machine check
0687      * exception with SRR0 pointing inside opal. If that is the
0688      * case OPAL may have recovery address to re-read SCOM data in
0689      * different way and hence we can recover from this MC.
0690      */
0691 
0692     if (ppc_md.mce_check_early_recovery) {
0693         if (ppc_md.mce_check_early_recovery(regs))
0694             return 1;
0695     }
0696 
0697     return 0;
0698 }
0699 
0700 static long mce_handle_error(struct pt_regs *regs,
0701         unsigned long srr1,
0702         const struct mce_derror_table dtable[],
0703         const struct mce_ierror_table itable[])
0704 {
0705     struct mce_error_info mce_err = { 0 };
0706     uint64_t addr, phys_addr = ULONG_MAX;
0707     long handled;
0708 
0709     if (SRR1_MC_LOADSTORE(srr1))
0710         handled = mce_handle_derror(regs, dtable, &mce_err, &addr,
0711                 &phys_addr);
0712     else
0713         handled = mce_handle_ierror(regs, srr1, itable, &mce_err, &addr,
0714                 &phys_addr);
0715 
0716     if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE)
0717         handled = mce_handle_ue_error(regs, &mce_err);
0718 
0719     save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr);
0720 
0721     return handled;
0722 }
0723 
0724 long __machine_check_early_realmode_p7(struct pt_regs *regs)
0725 {
0726     /* P7 DD1 leaves top bits of DSISR undefined */
0727     regs->dsisr &= 0x0000ffff;
0728 
0729     return mce_handle_error(regs, regs->msr,
0730             mce_p7_derror_table, mce_p7_ierror_table);
0731 }
0732 
0733 long __machine_check_early_realmode_p8(struct pt_regs *regs)
0734 {
0735     return mce_handle_error(regs, regs->msr,
0736             mce_p8_derror_table, mce_p8_ierror_table);
0737 }
0738 
0739 long __machine_check_early_realmode_p9(struct pt_regs *regs)
0740 {
0741     unsigned long srr1 = regs->msr;
0742 
0743     /*
0744      * On POWER9 DD2.1 and below, it's possible to get a machine check
0745      * caused by a paste instruction where only DSISR bit 25 is set. This
0746      * will result in the MCE handler seeing an unknown event and the kernel
0747      * crashing. An MCE that occurs like this is spurious, so we don't need
0748      * to do anything in terms of servicing it. If there is something that
0749      * needs to be serviced, the CPU will raise the MCE again with the
0750      * correct DSISR so that it can be serviced properly. So detect this
0751      * case and mark it as handled.
0752      */
0753     if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000)
0754         return 1;
0755 
0756     /*
0757      * Async machine check due to bad real address from store or foreign
0758      * link time out comes with the load/store bit (PPC bit 42) set in
0759      * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're
0760      * directed to the ierror table so it will find the cause (which
0761      * describes it correctly as a store error).
0762      */
0763     if (SRR1_MC_LOADSTORE(srr1) &&
0764             ((srr1 & 0x081c0000) == 0x08140000 ||
0765              (srr1 & 0x081c0000) == 0x08180000)) {
0766         srr1 &= ~PPC_BIT(42);
0767     }
0768 
0769     return mce_handle_error(regs, srr1,
0770             mce_p9_derror_table, mce_p9_ierror_table);
0771 }
0772 
0773 long __machine_check_early_realmode_p10(struct pt_regs *regs)
0774 {
0775     unsigned long srr1 = regs->msr;
0776 
0777     /*
0778      * Async machine check due to bad real address from store comes with
0779      * the load/store bit (PPC bit 42) set in SRR1, but the cause comes in
0780      * SRR1 not DSISR. Clear bit 42 so we're directed to the ierror table
0781      * so it will find the cause (which describes it correctly as a store
0782      * error).
0783      */
0784     if (SRR1_MC_LOADSTORE(srr1) &&
0785             (srr1 & 0x081c0000) == 0x08140000) {
0786         srr1 &= ~PPC_BIT(42);
0787     }
0788 
0789     return mce_handle_error(regs, srr1,
0790             mce_p10_derror_table, mce_p10_ierror_table);
0791 }