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