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