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