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 handled = mce_flush(MCE_FLUSH_SLB); 409 break; 410 case MCE_ERROR_TYPE_ERAT: 411 handled = mce_flush(MCE_FLUSH_ERAT); 412 break; 413 case MCE_ERROR_TYPE_TLB: 414 handled = mce_flush(MCE_FLUSH_TLB); 415 break; 416 } 417 418 /* now fill in mce_error_info */ 419 mce_err->error_type = table[i].error_type; 420 mce_err->error_class = table[i].error_class; 421 switch (table[i].error_type) { 422 case MCE_ERROR_TYPE_UE: 423 mce_err->u.ue_error_type = table[i].error_subtype; 424 break; 425 case MCE_ERROR_TYPE_SLB: 426 mce_err->u.slb_error_type = table[i].error_subtype; 427 break; 428 case MCE_ERROR_TYPE_ERAT: 429 mce_err->u.erat_error_type = table[i].error_subtype; 430 break; 431 case MCE_ERROR_TYPE_TLB: 432 mce_err->u.tlb_error_type = table[i].error_subtype; 433 break; 434 case MCE_ERROR_TYPE_USER: 435 mce_err->u.user_error_type = table[i].error_subtype; 436 break; 437 case MCE_ERROR_TYPE_RA: 438 mce_err->u.ra_error_type = table[i].error_subtype; 439 break; 440 case MCE_ERROR_TYPE_LINK: 441 mce_err->u.link_error_type = table[i].error_subtype; 442 break; 443 } 444 mce_err->sync_error = table[i].sync_error; 445 mce_err->severity = table[i].severity; 446 mce_err->initiator = table[i].initiator; 447 if (table[i].nip_valid) { 448 *addr = regs->nip; 449 if (mce_err->sync_error && 450 table[i].error_type == MCE_ERROR_TYPE_UE) { 451 unsigned long pfn; 452 453 if (get_paca()->in_mce < MAX_MCE_DEPTH) { 454 pfn = addr_to_pfn(regs, regs->nip); 455 if (pfn != ULONG_MAX) { 456 *phys_addr = 457 (pfn << PAGE_SHIFT); 458 } 459 } 460 } 461 } 462 return handled; 463 } 464 465 mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 466 mce_err->error_class = MCE_ECLASS_UNKNOWN; 467 mce_err->severity = MCE_SEV_SEVERE; 468 mce_err->initiator = MCE_INITIATOR_CPU; 469 mce_err->sync_error = true; 470 471 return 0; 472 } 473 474 static int mce_handle_derror(struct pt_regs *regs, 475 const struct mce_derror_table table[], 476 struct mce_error_info *mce_err, uint64_t *addr, 477 uint64_t *phys_addr) 478 { 479 uint64_t dsisr = regs->dsisr; 480 int handled = 0; 481 int found = 0; 482 int i; 483 484 *addr = 0; 485 486 for (i = 0; table[i].dsisr_value; i++) { 487 if (!(dsisr & table[i].dsisr_value)) 488 continue; 489 490 /* attempt to correct the error */ 491 switch (table[i].error_type) { 492 case MCE_ERROR_TYPE_SLB: 493 if (mce_flush(MCE_FLUSH_SLB)) 494 handled = 1; 495 break; 496 case MCE_ERROR_TYPE_ERAT: 497 if (mce_flush(MCE_FLUSH_ERAT)) 498 handled = 1; 499 break; 500 case MCE_ERROR_TYPE_TLB: 501 if (mce_flush(MCE_FLUSH_TLB)) 502 handled = 1; 503 break; 504 } 505 506 /* 507 * Attempt to handle multiple conditions, but only return 508 * one. Ensure uncorrectable errors are first in the table 509 * to match. 510 */ 511 if (found) 512 continue; 513 514 /* now fill in mce_error_info */ 515 mce_err->error_type = table[i].error_type; 516 mce_err->error_class = table[i].error_class; 517 switch (table[i].error_type) { 518 case MCE_ERROR_TYPE_UE: 519 mce_err->u.ue_error_type = table[i].error_subtype; 520 break; 521 case MCE_ERROR_TYPE_SLB: 522 mce_err->u.slb_error_type = table[i].error_subtype; 523 break; 524 case MCE_ERROR_TYPE_ERAT: 525 mce_err->u.erat_error_type = table[i].error_subtype; 526 break; 527 case MCE_ERROR_TYPE_TLB: 528 mce_err->u.tlb_error_type = table[i].error_subtype; 529 break; 530 case MCE_ERROR_TYPE_USER: 531 mce_err->u.user_error_type = table[i].error_subtype; 532 break; 533 case MCE_ERROR_TYPE_RA: 534 mce_err->u.ra_error_type = table[i].error_subtype; 535 break; 536 case MCE_ERROR_TYPE_LINK: 537 mce_err->u.link_error_type = table[i].error_subtype; 538 break; 539 } 540 mce_err->sync_error = table[i].sync_error; 541 mce_err->severity = table[i].severity; 542 mce_err->initiator = table[i].initiator; 543 if (table[i].dar_valid) 544 *addr = regs->dar; 545 else if (mce_err->sync_error && 546 table[i].error_type == MCE_ERROR_TYPE_UE) { 547 /* 548 * We do a maximum of 4 nested MCE calls, see 549 * kernel/exception-64s.h 550 */ 551 if (get_paca()->in_mce < MAX_MCE_DEPTH) 552 mce_find_instr_ea_and_phys(regs, addr, 553 phys_addr); 554 } 555 found = 1; 556 } 557 558 if (found) 559 return handled; 560 561 mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN; 562 mce_err->error_class = MCE_ECLASS_UNKNOWN; 563 mce_err->severity = MCE_SEV_SEVERE; 564 mce_err->initiator = MCE_INITIATOR_CPU; 565 mce_err->sync_error = true; 566 567 return 0; 568 } 569 570 static long mce_handle_ue_error(struct pt_regs *regs, 571 struct mce_error_info *mce_err) 572 { 573 long handled = 0; 574 const struct exception_table_entry *entry; 575 576 entry = search_kernel_exception_table(regs->nip); 577 if (entry) { 578 mce_err->ignore_event = true; 579 regs->nip = extable_fixup(entry); 580 return 1; 581 } 582 583 /* 584 * On specific SCOM read via MMIO we may get a machine check 585 * exception with SRR0 pointing inside opal. If that is the 586 * case OPAL may have recovery address to re-read SCOM data in 587 * different way and hence we can recover from this MC. 588 */ 589 590 if (ppc_md.mce_check_early_recovery) { 591 if (ppc_md.mce_check_early_recovery(regs)) 592 handled = 1; 593 } 594 return handled; 595 } 596 597 static long mce_handle_error(struct pt_regs *regs, 598 const struct mce_derror_table dtable[], 599 const struct mce_ierror_table itable[]) 600 { 601 struct mce_error_info mce_err = { 0 }; 602 uint64_t addr, phys_addr = ULONG_MAX; 603 uint64_t srr1 = regs->msr; 604 long handled; 605 606 if (SRR1_MC_LOADSTORE(srr1)) 607 handled = mce_handle_derror(regs, dtable, &mce_err, &addr, 608 &phys_addr); 609 else 610 handled = mce_handle_ierror(regs, itable, &mce_err, &addr, 611 &phys_addr); 612 613 if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) 614 handled = mce_handle_ue_error(regs, &mce_err); 615 616 save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr); 617 618 return handled; 619 } 620 621 long __machine_check_early_realmode_p7(struct pt_regs *regs) 622 { 623 /* P7 DD1 leaves top bits of DSISR undefined */ 624 regs->dsisr &= 0x0000ffff; 625 626 return mce_handle_error(regs, mce_p7_derror_table, mce_p7_ierror_table); 627 } 628 629 long __machine_check_early_realmode_p8(struct pt_regs *regs) 630 { 631 return mce_handle_error(regs, mce_p8_derror_table, mce_p8_ierror_table); 632 } 633 634 long __machine_check_early_realmode_p9(struct pt_regs *regs) 635 { 636 /* 637 * On POWER9 DD2.1 and below, it's possible to get a machine check 638 * caused by a paste instruction where only DSISR bit 25 is set. This 639 * will result in the MCE handler seeing an unknown event and the kernel 640 * crashing. An MCE that occurs like this is spurious, so we don't need 641 * to do anything in terms of servicing it. If there is something that 642 * needs to be serviced, the CPU will raise the MCE again with the 643 * correct DSISR so that it can be serviced properly. So detect this 644 * case and mark it as handled. 645 */ 646 if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000) 647 return 1; 648 649 return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table); 650 } 651