cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mce_power.c (26476B)


      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}