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_64S_HASH_MMU
  81void flush_and_reload_slb(void)
  82{
  83        if (early_radix_enabled())
  84                return;
  85
  86        /* Invalidate all SLBs */
  87        slb_flush_all_realmode();
  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_64S_HASH_MMU
 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_64S_HASH_MMU
 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        ppc_inst_t 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#ifdef CONFIG_PPC_64S_HASH_MMU
 503                                if (local_paca->in_mce == 1)
 504                                        slb_save_contents(local_paca->mce_faulty_slbs);
 505#endif
 506                                handled = mce_flush(MCE_FLUSH_SLB);
 507                                break;
 508                        case MCE_ERROR_TYPE_ERAT:
 509                                handled = mce_flush(MCE_FLUSH_ERAT);
 510                                break;
 511                        case MCE_ERROR_TYPE_TLB:
 512                                handled = mce_flush(MCE_FLUSH_TLB);
 513                                break;
 514                        }
 515                }
 516
 517                /* now fill in mce_error_info */
 518                mce_err->error_type = table[i].error_type;
 519                mce_err->error_class = table[i].error_class;
 520                switch (table[i].error_type) {
 521                case MCE_ERROR_TYPE_UE:
 522                        mce_err->u.ue_error_type = table[i].error_subtype;
 523                        break;
 524                case MCE_ERROR_TYPE_SLB:
 525                        mce_err->u.slb_error_type = table[i].error_subtype;
 526                        break;
 527                case MCE_ERROR_TYPE_ERAT:
 528                        mce_err->u.erat_error_type = table[i].error_subtype;
 529                        break;
 530                case MCE_ERROR_TYPE_TLB:
 531                        mce_err->u.tlb_error_type = table[i].error_subtype;
 532                        break;
 533                case MCE_ERROR_TYPE_USER:
 534                        mce_err->u.user_error_type = table[i].error_subtype;
 535                        break;
 536                case MCE_ERROR_TYPE_RA:
 537                        mce_err->u.ra_error_type = table[i].error_subtype;
 538                        break;
 539                case MCE_ERROR_TYPE_LINK:
 540                        mce_err->u.link_error_type = table[i].error_subtype;
 541                        break;
 542                }
 543                mce_err->sync_error = table[i].sync_error;
 544                mce_err->severity = table[i].severity;
 545                mce_err->initiator = table[i].initiator;
 546                if (table[i].nip_valid && !mce_in_guest()) {
 547                        *addr = regs->nip;
 548                        if (mce_err->sync_error &&
 549                                table[i].error_type == MCE_ERROR_TYPE_UE) {
 550                                unsigned long pfn;
 551
 552                                if (get_paca()->in_mce < MAX_MCE_DEPTH) {
 553                                        pfn = addr_to_pfn(regs, regs->nip);
 554                                        if (pfn != ULONG_MAX) {
 555                                                *phys_addr =
 556                                                        (pfn << PAGE_SHIFT);
 557                                        }
 558                                }
 559                        }
 560                }
 561                return handled;
 562        }
 563
 564        mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
 565        mce_err->error_class = MCE_ECLASS_UNKNOWN;
 566        mce_err->severity = MCE_SEV_SEVERE;
 567        mce_err->initiator = MCE_INITIATOR_CPU;
 568        mce_err->sync_error = true;
 569
 570        return 0;
 571}
 572
 573static int mce_handle_derror(struct pt_regs *regs,
 574                const struct mce_derror_table table[],
 575                struct mce_error_info *mce_err, uint64_t *addr,
 576                uint64_t *phys_addr)
 577{
 578        uint64_t dsisr = regs->dsisr;
 579        int handled = 0;
 580        int found = 0;
 581        int i;
 582
 583        *addr = 0;
 584
 585        for (i = 0; table[i].dsisr_value; i++) {
 586                if (!(dsisr & table[i].dsisr_value))
 587                        continue;
 588
 589                if (!mce_in_guest()) {
 590                        /* attempt to correct the error */
 591                        switch (table[i].error_type) {
 592                        case MCE_ERROR_TYPE_SLB:
 593#ifdef CONFIG_PPC_64S_HASH_MMU
 594                                if (local_paca->in_mce == 1)
 595                                        slb_save_contents(local_paca->mce_faulty_slbs);
 596#endif
 597                                if (mce_flush(MCE_FLUSH_SLB))
 598                                        handled = 1;
 599                                break;
 600                        case MCE_ERROR_TYPE_ERAT:
 601                                if (mce_flush(MCE_FLUSH_ERAT))
 602                                        handled = 1;
 603                                break;
 604                        case MCE_ERROR_TYPE_TLB:
 605                                if (mce_flush(MCE_FLUSH_TLB))
 606                                        handled = 1;
 607                                break;
 608                        }
 609                }
 610
 611                /*
 612                 * Attempt to handle multiple conditions, but only return
 613                 * one. Ensure uncorrectable errors are first in the table
 614                 * to match.
 615                 */
 616                if (found)
 617                        continue;
 618
 619                /* now fill in mce_error_info */
 620                mce_err->error_type = table[i].error_type;
 621                mce_err->error_class = table[i].error_class;
 622                switch (table[i].error_type) {
 623                case MCE_ERROR_TYPE_UE:
 624                        mce_err->u.ue_error_type = table[i].error_subtype;
 625                        break;
 626                case MCE_ERROR_TYPE_SLB:
 627                        mce_err->u.slb_error_type = table[i].error_subtype;
 628                        break;
 629                case MCE_ERROR_TYPE_ERAT:
 630                        mce_err->u.erat_error_type = table[i].error_subtype;
 631                        break;
 632                case MCE_ERROR_TYPE_TLB:
 633                        mce_err->u.tlb_error_type = table[i].error_subtype;
 634                        break;
 635                case MCE_ERROR_TYPE_USER:
 636                        mce_err->u.user_error_type = table[i].error_subtype;
 637                        break;
 638                case MCE_ERROR_TYPE_RA:
 639                        mce_err->u.ra_error_type = table[i].error_subtype;
 640                        break;
 641                case MCE_ERROR_TYPE_LINK:
 642                        mce_err->u.link_error_type = table[i].error_subtype;
 643                        break;
 644                }
 645                mce_err->sync_error = table[i].sync_error;
 646                mce_err->severity = table[i].severity;
 647                mce_err->initiator = table[i].initiator;
 648                if (table[i].dar_valid)
 649                        *addr = regs->dar;
 650                else if (mce_err->sync_error && !mce_in_guest() &&
 651                                table[i].error_type == MCE_ERROR_TYPE_UE) {
 652                        /*
 653                         * We do a maximum of 4 nested MCE calls, see
 654                         * kernel/exception-64s.h
 655                         */
 656                        if (get_paca()->in_mce < MAX_MCE_DEPTH)
 657                                mce_find_instr_ea_and_phys(regs, addr,
 658                                                           phys_addr);
 659                }
 660                found = 1;
 661        }
 662
 663        if (found)
 664                return handled;
 665
 666        mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
 667        mce_err->error_class = MCE_ECLASS_UNKNOWN;
 668        mce_err->severity = MCE_SEV_SEVERE;
 669        mce_err->initiator = MCE_INITIATOR_CPU;
 670        mce_err->sync_error = true;
 671
 672        return 0;
 673}
 674
 675static long mce_handle_ue_error(struct pt_regs *regs,
 676                                struct mce_error_info *mce_err)
 677{
 678        if (mce_in_guest())
 679                return 0;
 680
 681        mce_common_process_ue(regs, mce_err);
 682        if (mce_err->ignore_event)
 683                return 1;
 684
 685        /*
 686         * On specific SCOM read via MMIO we may get a machine check
 687         * exception with SRR0 pointing inside opal. If that is the
 688         * case OPAL may have recovery address to re-read SCOM data in
 689         * different way and hence we can recover from this MC.
 690         */
 691
 692        if (ppc_md.mce_check_early_recovery) {
 693                if (ppc_md.mce_check_early_recovery(regs))
 694                        return 1;
 695        }
 696
 697        return 0;
 698}
 699
 700static long mce_handle_error(struct pt_regs *regs,
 701                unsigned long srr1,
 702                const struct mce_derror_table dtable[],
 703                const struct mce_ierror_table itable[])
 704{
 705        struct mce_error_info mce_err = { 0 };
 706        uint64_t addr, phys_addr = ULONG_MAX;
 707        long handled;
 708
 709        if (SRR1_MC_LOADSTORE(srr1))
 710                handled = mce_handle_derror(regs, dtable, &mce_err, &addr,
 711                                &phys_addr);
 712        else
 713                handled = mce_handle_ierror(regs, srr1, itable, &mce_err, &addr,
 714                                &phys_addr);
 715
 716        if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE)
 717                handled = mce_handle_ue_error(regs, &mce_err);
 718
 719        save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr);
 720
 721        return handled;
 722}
 723
 724long __machine_check_early_realmode_p7(struct pt_regs *regs)
 725{
 726        /* P7 DD1 leaves top bits of DSISR undefined */
 727        regs->dsisr &= 0x0000ffff;
 728
 729        return mce_handle_error(regs, regs->msr,
 730                        mce_p7_derror_table, mce_p7_ierror_table);
 731}
 732
 733long __machine_check_early_realmode_p8(struct pt_regs *regs)
 734{
 735        return mce_handle_error(regs, regs->msr,
 736                        mce_p8_derror_table, mce_p8_ierror_table);
 737}
 738
 739long __machine_check_early_realmode_p9(struct pt_regs *regs)
 740{
 741        unsigned long srr1 = regs->msr;
 742
 743        /*
 744         * On POWER9 DD2.1 and below, it's possible to get a machine check
 745         * caused by a paste instruction where only DSISR bit 25 is set. This
 746         * will result in the MCE handler seeing an unknown event and the kernel
 747         * crashing. An MCE that occurs like this is spurious, so we don't need
 748         * to do anything in terms of servicing it. If there is something that
 749         * needs to be serviced, the CPU will raise the MCE again with the
 750         * correct DSISR so that it can be serviced properly. So detect this
 751         * case and mark it as handled.
 752         */
 753        if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000)
 754                return 1;
 755
 756        /*
 757         * Async machine check due to bad real address from store or foreign
 758         * link time out comes with the load/store bit (PPC bit 42) set in
 759         * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're
 760         * directed to the ierror table so it will find the cause (which
 761         * describes it correctly as a store error).
 762         */
 763        if (SRR1_MC_LOADSTORE(srr1) &&
 764                        ((srr1 & 0x081c0000) == 0x08140000 ||
 765                         (srr1 & 0x081c0000) == 0x08180000)) {
 766                srr1 &= ~PPC_BIT(42);
 767        }
 768
 769        return mce_handle_error(regs, srr1,
 770                        mce_p9_derror_table, mce_p9_ierror_table);
 771}
 772
 773long __machine_check_early_realmode_p10(struct pt_regs *regs)
 774{
 775        unsigned long srr1 = regs->msr;
 776
 777        /*
 778         * Async machine check due to bad real address from store comes with
 779         * the load/store bit (PPC bit 42) set in SRR1, but the cause comes in
 780         * SRR1 not DSISR. Clear bit 42 so we're directed to the ierror table
 781         * so it will find the cause (which describes it correctly as a store
 782         * error).
 783         */
 784        if (SRR1_MC_LOADSTORE(srr1) &&
 785                        (srr1 & 0x081c0000) == 0x08140000) {
 786                srr1 &= ~PPC_BIT(42);
 787        }
 788
 789        return mce_handle_error(regs, srr1,
 790                        mce_p10_derror_table, mce_p10_ierror_table);
 791}
 792