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