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