1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Machine check exception handling CPU-side for power7 and power8 4 * 5 * Copyright 2013 IBM Corporation 6 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> 7 */ 8 9 #undef DEBUG 10 #define pr_fmt(fmt) "mce_power: " fmt 11 12 #include <linux/types.h> 13 #include <linux/ptrace.h> 14 #include <linux/extable.h> 15 #include <asm/mmu.h> 16 #include <asm/mce.h> 17 #include <asm/machdep.h> 18 #include <asm/pgtable.h> 19 #include <asm/pte-walk.h> 20 #include <asm/sstep.h> 21 #include <asm/exception-64s.h> 22 #include <asm/extable.h> 23 24 /* 25 * Convert an address related to an mm to a PFN. NOTE: we are in real 26 * mode, we could potentially race with page table updates. 27 */ 28 unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) 29 { 30 pte_t *ptep; 31 unsigned int shift; 32 unsigned long flags; 33 struct mm_struct *mm; 34 35 if (user_mode(regs)) 36 mm = current->mm; 37 else 38 mm = &init_mm; 39 40 local_irq_save(flags); 41 ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift); 42 local_irq_restore(flags); 43 44 if (!ptep || pte_special(*ptep)) 45 return ULONG_MAX; 46 47 if (shift > PAGE_SHIFT) { 48 unsigned long rpnmask = (1ul << shift) - PAGE_SIZE; 49 50 return pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask))); 51 } 52 53 return pte_pfn(*ptep); 54 } 55 56 /* flush SLBs and reload */ 57 #ifdef CONFIG_PPC_BOOK3S_64 58 void flush_and_reload_slb(void) 59 { 60 /* Invalidate all SLBs */ 61 slb_flush_all_realmode(); 62 63 #ifdef CONFIG_KVM_BOOK3S_HANDLER 64 /* 65 * If machine check is hit when in guest or in transition, we will 66 * only flush the SLBs and continue. 67 */ 68 if (get_paca()->kvm_hstate.in_guest) 69 return; 70 #endif 71 if (early_radix_enabled()) 72 return; 73 74 /* 75 * This probably shouldn't happen, but it may be possible it's 76 * called in early boot before SLB shadows are allocated. 77 */ 78 if (!get_slb_shadow()) 79 return; 80 81 slb_restore_bolted_realmode(); 82 } 83 #endif 84 85 static void flush_erat(void) 86 { 87 #ifdef CONFIG_PPC_BOOK3S_64 88 if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { 89 flush_and_reload_slb(); 90 return; 91 } 92 #endif 93 asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); 94 } 95 96 #define MCE_FLUSH_SLB 1 97 #define MCE_FLUSH_TLB 2 98 #define MCE_FLUSH_ERAT 3 99 100 static int mce_flush(int what) 101 { 102 #ifdef CONFIG_PPC_BOOK3S_64 103 if (what == MCE_FLUSH_SLB) { 104 flush_and_reload_slb(); 105 return 1; 106 } 107 #endif 108 if (what == MCE_FLUSH_ERAT) { 109 flush_erat(); 110 return 1; 111 } 112 if (what == MCE_FLUSH_TLB) { 113 tlbiel_all(); 114 return 1; 115 } 116 117 return 0; 118 } 119 120 #define SRR1_MC_LOADSTORE(srr1) ((srr1) & PPC_BIT(42)) 121 122 struct mce_ierror_table { 123 unsigned long srr1_mask; 124 unsigned long srr1_value; 125 bool nip_valid; /* nip is a valid indicator of faulting address */ 126 unsigned int error_type; 127 unsigned int error_subtype; 128 unsigned int error_class; 129 unsigned int initiator; 130 unsigned int severity; 131 bool sync_error; 132 }; 133 134 static const struct mce_ierror_table mce_p7_ierror_table[] = { 135 { 0x00000000001c0000, 0x0000000000040000, true, 136 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 137 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 138 { 0x00000000001c0000, 0x0000000000080000, true, 139 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 140 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 141 { 0x00000000001c0000, 0x00000000000c0000, true, 142 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 143 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 144 { 0x00000000001c0000, 0x0000000000100000, true, 145 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */ 146 MCE_ECLASS_SOFT_INDETERMINATE, 147 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 148 { 0x00000000001c0000, 0x0000000000140000, true, 149 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 150 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 151 { 0x00000000001c0000, 0x0000000000180000, true, 152 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE, 153 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 154 { 0x00000000001c0000, 0x00000000001c0000, true, 155 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 156 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 157 { 0, 0, 0, 0, 0, 0, 0 } }; 158 159 static const struct mce_ierror_table mce_p8_ierror_table[] = { 160 { 0x00000000081c0000, 0x0000000000040000, true, 161 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 162 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 163 { 0x00000000081c0000, 0x0000000000080000, true, 164 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 165 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 166 { 0x00000000081c0000, 0x00000000000c0000, true, 167 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 168 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 169 { 0x00000000081c0000, 0x0000000000100000, true, 170 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 171 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 172 { 0x00000000081c0000, 0x0000000000140000, true, 173 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 174 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 175 { 0x00000000081c0000, 0x0000000000180000, true, 176 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, 177 MCE_ECLASS_HARDWARE, 178 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 179 { 0x00000000081c0000, 0x00000000001c0000, true, 180 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 181 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 182 { 0x00000000081c0000, 0x0000000008000000, true, 183 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE, 184 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 185 { 0x00000000081c0000, 0x0000000008040000, true, 186 MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT, 187 MCE_ECLASS_HARDWARE, 188 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 189 { 0, 0, 0, 0, 0, 0, 0 } }; 190 191 static const struct mce_ierror_table mce_p9_ierror_table[] = { 192 { 0x00000000081c0000, 0x0000000000040000, true, 193 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH, MCE_ECLASS_HARDWARE, 194 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 195 { 0x00000000081c0000, 0x0000000000080000, true, 196 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 197 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 198 { 0x00000000081c0000, 0x00000000000c0000, true, 199 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 200 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 201 { 0x00000000081c0000, 0x0000000000100000, true, 202 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 203 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 204 { 0x00000000081c0000, 0x0000000000140000, true, 205 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 206 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 207 { 0x00000000081c0000, 0x0000000000180000, true, 208 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_HARDWARE, 209 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 210 { 0x00000000081c0000, 0x00000000001c0000, true, 211 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH_FOREIGN, MCE_ECLASS_SOFTWARE, 212 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 213 { 0x00000000081c0000, 0x0000000008000000, true, 214 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_IFETCH_TIMEOUT, MCE_ECLASS_HARDWARE, 215 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 216 { 0x00000000081c0000, 0x0000000008040000, true, 217 MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT, 218 MCE_ECLASS_HARDWARE, 219 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 220 { 0x00000000081c0000, 0x00000000080c0000, true, 221 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH, MCE_ECLASS_SOFTWARE, 222 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 223 { 0x00000000081c0000, 0x0000000008100000, true, 224 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH, MCE_ECLASS_SOFTWARE, 225 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 226 { 0x00000000081c0000, 0x0000000008140000, false, 227 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_STORE, MCE_ECLASS_HARDWARE, 228 MCE_INITIATOR_CPU, MCE_SEV_FATAL, false }, /* ASYNC is fatal */ 229 { 0x00000000081c0000, 0x0000000008180000, false, 230 MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_STORE_TIMEOUT, 231 MCE_INITIATOR_CPU, MCE_SEV_FATAL, false }, /* ASYNC is fatal */ 232 { 0x00000000081c0000, 0x00000000081c0000, true, MCE_ECLASS_HARDWARE, 233 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN, 234 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 235 { 0, 0, 0, 0, 0, 0, 0 } }; 236 237 struct mce_derror_table { 238 unsigned long dsisr_value; 239 bool dar_valid; /* dar is a valid indicator of faulting address */ 240 unsigned int error_type; 241 unsigned int error_subtype; 242 unsigned int error_class; 243 unsigned int initiator; 244 unsigned int severity; 245 bool sync_error; 246 }; 247 248 static const struct mce_derror_table mce_p7_derror_table[] = { 249 { 0x00008000, false, 250 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 251 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 252 { 0x00004000, true, 253 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 254 MCE_ECLASS_HARDWARE, 255 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 256 { 0x00000800, true, 257 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 258 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 259 { 0x00000400, true, 260 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 261 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 262 { 0x00000080, true, 263 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 264 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 265 { 0x00000100, true, 266 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 267 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 268 { 0x00000040, true, 269 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */ 270 MCE_ECLASS_HARD_INDETERMINATE, 271 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 272 { 0, false, 0, 0, 0, 0, 0 } }; 273 274 static const struct mce_derror_table mce_p8_derror_table[] = { 275 { 0x00008000, false, 276 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 277 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 278 { 0x00004000, true, 279 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 280 MCE_ECLASS_HARDWARE, 281 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 282 { 0x00002000, true, 283 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE, 284 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 285 { 0x00001000, true, 286 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT, 287 MCE_ECLASS_HARDWARE, 288 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 289 { 0x00000800, true, 290 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 291 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 292 { 0x00000400, true, 293 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 294 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 295 { 0x00000200, true, 296 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, /* SECONDARY ERAT */ 297 MCE_ECLASS_SOFT_INDETERMINATE, 298 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 299 { 0x00000080, true, 300 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, /* Before PARITY */ 301 MCE_ECLASS_SOFT_INDETERMINATE, 302 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 303 { 0x00000100, true, 304 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 305 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 306 { 0, false, 0, 0, 0, 0, 0 } }; 307 308 static const struct mce_derror_table mce_p9_derror_table[] = { 309 { 0x00008000, false, 310 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE, MCE_ECLASS_HARDWARE, 311 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 312 { 0x00004000, true, 313 MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 314 MCE_ECLASS_HARDWARE, 315 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 316 { 0x00002000, true, 317 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT, MCE_ECLASS_HARDWARE, 318 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 319 { 0x00001000, true, 320 MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT, 321 MCE_ECLASS_HARDWARE, 322 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 323 { 0x00000800, true, 324 MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 325 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 326 { 0x00000400, true, 327 MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT, MCE_ECLASS_SOFT_INDETERMINATE, 328 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 329 { 0x00000200, false, 330 MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE, MCE_ECLASS_SOFTWARE, 331 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 332 { 0x00000080, true, 333 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT, /* Before PARITY */ 334 MCE_ECLASS_SOFT_INDETERMINATE, 335 MCE_INITIATOR_CPU, MCE_SEV_WARNING, true }, 336 { 0x00000100, true, 337 MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY, MCE_ECLASS_HARD_INDETERMINATE, 338 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 339 { 0x00000040, true, 340 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD, MCE_ECLASS_HARDWARE, 341 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 342 { 0x00000020, false, 343 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE, 344 MCE_ECLASS_HARDWARE, 345 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 346 { 0x00000010, false, 347 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN, 348 MCE_ECLASS_HARDWARE, 349 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 350 { 0x00000008, false, 351 MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD_STORE_FOREIGN, MCE_ECLASS_HARDWARE, 352 MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true }, 353 { 0, false, 0, 0, 0, 0, 0 } }; 354 355 static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr, 356 uint64_t *phys_addr) 357 { 358 /* 359 * Carefully look at the NIP to determine 360 * the instruction to analyse. Reading the NIP 361 * in real-mode is tricky and can lead to recursive 362 * faults 363 */ 364 int instr; 365 unsigned long pfn, instr_addr; 366 struct instruction_op op; 367 struct pt_regs tmp = *regs; 368 369 pfn = addr_to_pfn(regs, regs->nip); 370 if (pfn != ULONG_MAX) { 371 instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK); 372 instr = *(unsigned int *)(instr_addr); 373 if (!analyse_instr(&op, &tmp, instr)) { 374 pfn = addr_to_pfn(regs, op.ea); 375 *addr = op.ea; 376 *phys_addr = (pfn << PAGE_SHIFT); 377 return 0; 378 } 379 /* 380 * analyse_instr() might fail if the instruction 381 * is not a load/store, although this is unexpected 382 * for load/store errors or if we got the NIP 383 * wrong 384 */ 385 } 386 *addr = 0; 387 return -1; 388 } 389 390 static int mce_handle_ierror(struct pt_regs *regs, 391 const struct mce_ierror_table table[], 392 struct mce_error_info *mce_err, uint64_t *addr, 393 uint64_t *phys_addr) 394 { 395 uint64_t srr1 = regs->msr; 396 int handled = 0; 397 int i; 398 399 *addr = 0; 400 401 for (i = 0; table[i].srr1_mask; i++) { 402 if ((srr1 & table[i].srr1_mask) != table[i].srr1_value) 403 continue; 404 405 /* attempt to correct the error */ 406 switch (table[i].error_type) { 407 case MCE_ERROR_TYPE_SLB: 408 if (local_paca->in_mce == 1) 409 slb_save_contents(local_paca->mce_faulty_slbs); 410 handled = mce_flush(MCE_FLUSH_SLB); 411 break; 412 case MCE_ERROR_TYPE_ERAT: 413 handled = mce_flush(MCE_FLUSH_ERAT); 414 break; 415 case MCE_ERROR_TYPE_TLB: 416 handled = mce_flush(MCE_FLUSH_TLB); 417 break; 418 } 419 420 /* now fill in mce_error_info */ 421 mce_err->error_type = table[i].error_type; 422 mce_err->error_class = table[i].error_class; 423 switch (table[i].error_type) { 424 case MCE_ERROR_TYPE_UE: 425 mce_err->u.ue_error_type = table[i].error_subtype; 426 break; 427 case MCE_ERROR_TYPE_SLB: 428 mce_err->u.slb_error_type = table[i].error_subtype; 429 break; 430 case MCE_ERROR_TYPE_ERAT: 431 mce_err->u.erat_error_type = table[i].error_subtype; 432 break; 433 case MCE_ERROR_TYPE_TLB: 434 mce_err->u.tlb_error_type = table[i].error_subtype; 435 break; 436 case MCE_ERROR_TYPE_USER: 437 mce_err->u.user_error_type = table[i].error_subtype; 438 break; 439 case MCE_ERROR_TYPE_RA: 440 mce_err->u.ra_error_type = table[i].error_subtype; 441 break; 442 case MCE_ERROR_TYPE_LINK: 443 mce_err->u.link_error_type = table[i].error_subtype; 444 break; 445 } 446 mce_err->sync_error = table[i].sync_error; 447 mce_err->severity = table[i].severity; 448 mce_err->initiator = table[i].initiator; 449 if (table[i].nip_valid) { 450 *addr = regs->nip; 451 if (mce_err->sync_error && 452 table[i].error_type == MCE_ERROR_TYPE_UE) { 453 unsigned long pfn; 454 455 if (get_paca()->in_mce < MAX_MCE_DEPTH) { 456 pfn = addr_to_pfn(regs, regs->nip); 457 if (pfn != ULONG_MAX) { 458 *phys_addr = 459 (pfn << PAGE_SHIFT); 460 } 461 } 462 } 463 } 464 return handled; 465 } 466 467 mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 468 mce_err->error_class = MCE_ECLASS_UNKNOWN; 469 mce_err->severity = MCE_SEV_SEVERE; 470 mce_err->initiator = MCE_INITIATOR_CPU; 471 mce_err->sync_error = true; 472 473 return 0; 474 } 475 476 static int mce_handle_derror(struct pt_regs *regs, 477 const struct mce_derror_table table[], 478 struct mce_error_info *mce_err, uint64_t *addr, 479 uint64_t *phys_addr) 480 { 481 uint64_t dsisr = regs->dsisr; 482 int handled = 0; 483 int found = 0; 484 int i; 485 486 *addr = 0; 487 488 for (i = 0; table[i].dsisr_value; i++) { 489 if (!(dsisr & table[i].dsisr_value)) 490 continue; 491 492 /* attempt to correct the error */ 493 switch (table[i].error_type) { 494 case MCE_ERROR_TYPE_SLB: 495 if (local_paca->in_mce == 1) 496 slb_save_contents(local_paca->mce_faulty_slbs); 497 if (mce_flush(MCE_FLUSH_SLB)) 498 handled = 1; 499 break; 500 case MCE_ERROR_TYPE_ERAT: 501 if (mce_flush(MCE_FLUSH_ERAT)) 502 handled = 1; 503 break; 504 case MCE_ERROR_TYPE_TLB: 505 if (mce_flush(MCE_FLUSH_TLB)) 506 handled = 1; 507 break; 508 } 509 510 /* 511 * Attempt to handle multiple conditions, but only return 512 * one. Ensure uncorrectable errors are first in the table 513 * to match. 514 */ 515 if (found) 516 continue; 517 518 /* now fill in mce_error_info */ 519 mce_err->error_type = table[i].error_type; 520 mce_err->error_class = table[i].error_class; 521 switch (table[i].error_type) { 522 case MCE_ERROR_TYPE_UE: 523 mce_err->u.ue_error_type = table[i].error_subtype; 524 break; 525 case MCE_ERROR_TYPE_SLB: 526 mce_err->u.slb_error_type = table[i].error_subtype; 527 break; 528 case MCE_ERROR_TYPE_ERAT: 529 mce_err->u.erat_error_type = table[i].error_subtype; 530 break; 531 case MCE_ERROR_TYPE_TLB: 532 mce_err->u.tlb_error_type = table[i].error_subtype; 533 break; 534 case MCE_ERROR_TYPE_USER: 535 mce_err->u.user_error_type = table[i].error_subtype; 536 break; 537 case MCE_ERROR_TYPE_RA: 538 mce_err->u.ra_error_type = table[i].error_subtype; 539 break; 540 case MCE_ERROR_TYPE_LINK: 541 mce_err->u.link_error_type = table[i].error_subtype; 542 break; 543 } 544 mce_err->sync_error = table[i].sync_error; 545 mce_err->severity = table[i].severity; 546 mce_err->initiator = table[i].initiator; 547 if (table[i].dar_valid) 548 *addr = regs->dar; 549 else if (mce_err->sync_error && 550 table[i].error_type == MCE_ERROR_TYPE_UE) { 551 /* 552 * We do a maximum of 4 nested MCE calls, see 553 * kernel/exception-64s.h 554 */ 555 if (get_paca()->in_mce < MAX_MCE_DEPTH) 556 mce_find_instr_ea_and_phys(regs, addr, 557 phys_addr); 558 } 559 found = 1; 560 } 561 562 if (found) 563 return handled; 564 565 mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 566 mce_err->error_class = MCE_ECLASS_UNKNOWN; 567 mce_err->severity = MCE_SEV_SEVERE; 568 mce_err->initiator = MCE_INITIATOR_CPU; 569 mce_err->sync_error = true; 570 571 return 0; 572 } 573 574 static long mce_handle_ue_error(struct pt_regs *regs, 575 struct mce_error_info *mce_err) 576 { 577 long handled = 0; 578 const struct exception_table_entry *entry; 579 580 entry = search_kernel_exception_table(regs->nip); 581 if (entry) { 582 mce_err->ignore_event = true; 583 regs->nip = extable_fixup(entry); 584 return 1; 585 } 586 587 /* 588 * On specific SCOM read via MMIO we may get a machine check 589 * exception with SRR0 pointing inside opal. If that is the 590 * case OPAL may have recovery address to re-read SCOM data in 591 * different way and hence we can recover from this MC. 592 */ 593 594 if (ppc_md.mce_check_early_recovery) { 595 if (ppc_md.mce_check_early_recovery(regs)) 596 handled = 1; 597 } 598 return handled; 599 } 600 601 static long mce_handle_error(struct pt_regs *regs, 602 const struct mce_derror_table dtable[], 603 const struct mce_ierror_table itable[]) 604 { 605 struct mce_error_info mce_err = { 0 }; 606 uint64_t addr, phys_addr = ULONG_MAX; 607 uint64_t srr1 = regs->msr; 608 long handled; 609 610 if (SRR1_MC_LOADSTORE(srr1)) 611 handled = mce_handle_derror(regs, dtable, &mce_err, &addr, 612 &phys_addr); 613 else 614 handled = mce_handle_ierror(regs, itable, &mce_err, &addr, 615 &phys_addr); 616 617 if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) 618 handled = mce_handle_ue_error(regs, &mce_err); 619 620 save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr); 621 622 return handled; 623 } 624 625 long __machine_check_early_realmode_p7(struct pt_regs *regs) 626 { 627 /* P7 DD1 leaves top bits of DSISR undefined */ 628 regs->dsisr &= 0x0000ffff; 629 630 return mce_handle_error(regs, mce_p7_derror_table, mce_p7_ierror_table); 631 } 632 633 long __machine_check_early_realmode_p8(struct pt_regs *regs) 634 { 635 return mce_handle_error(regs, mce_p8_derror_table, mce_p8_ierror_table); 636 } 637 638 long __machine_check_early_realmode_p9(struct pt_regs *regs) 639 { 640 /* 641 * On POWER9 DD2.1 and below, it's possible to get a machine check 642 * caused by a paste instruction where only DSISR bit 25 is set. This 643 * will result in the MCE handler seeing an unknown event and the kernel 644 * crashing. An MCE that occurs like this is spurious, so we don't need 645 * to do anything in terms of servicing it. If there is something that 646 * needs to be serviced, the CPU will raise the MCE again with the 647 * correct DSISR so that it can be serviced properly. So detect this 648 * case and mark it as handled. 649 */ 650 if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000) 651 return 1; 652 653 return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table); 654 } 655