root/arch/powerpc/kernel/mce_power.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. addr_to_pfn
  2. flush_and_reload_slb
  3. flush_erat
  4. mce_flush
  5. mce_find_instr_ea_and_phys
  6. mce_handle_ierror
  7. mce_handle_derror
  8. mce_handle_ue_error
  9. mce_handle_error
  10. __machine_check_early_realmode_p7
  11. __machine_check_early_realmode_p8
  12. __machine_check_early_realmode_p9

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

/* [<][>][^][v][top][bottom][index][help] */