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