aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2013-10-30 10:35:26 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-12-05 00:04:40 -0500
commitae744f3432d3872c51298d922728e13c24ccc068 (patch)
tree32a734e20e7cec4abf8142fc4f1ca294607162ee
parente22a22740c1ac23aaa10835f026b3549ee3e4e75 (diff)
powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors on power8.
This patch handles the memory errors on power8. If we get a machine check exception due to SLB or TLB errors, then flush SLBs/TLBs and reload SLBs to recover. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/mce.h3
-rw-r--r--arch/powerpc/kernel/cputable.c4
-rw-r--r--arch/powerpc/kernel/mce_power.c34
3 files changed, 41 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
index 8157d4eaead6..e3ffa825b970 100644
--- a/arch/powerpc/include/asm/mce.h
+++ b/arch/powerpc/include/asm/mce.h
@@ -64,4 +64,7 @@
64 P7_DSISR_MC_SLB_MULTIHIT | \ 64 P7_DSISR_MC_SLB_MULTIHIT | \
65 P7_DSISR_MC_SLB_MULTIHIT_PARITY) 65 P7_DSISR_MC_SLB_MULTIHIT_PARITY)
66 66
67#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \
68 P8_DSISR_MC_ERAT_MULTIHIT_SEC)
69
67#endif /* __ASM_PPC64_MCE_H__ */ 70#endif /* __ASM_PPC64_MCE_H__ */
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index c54188bcdd9e..6c8dd5da4de5 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -74,6 +74,7 @@ extern void __restore_cpu_a2(void);
74extern void __flush_tlb_power7(unsigned long inval_selector); 74extern void __flush_tlb_power7(unsigned long inval_selector);
75extern void __flush_tlb_power8(unsigned long inval_selector); 75extern void __flush_tlb_power8(unsigned long inval_selector);
76extern long __machine_check_early_realmode_p7(struct pt_regs *regs); 76extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
77extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
77#endif /* CONFIG_PPC64 */ 78#endif /* CONFIG_PPC64 */
78#if defined(CONFIG_E500) 79#if defined(CONFIG_E500)
79extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); 80extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -462,6 +463,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
462 .cpu_setup = __setup_cpu_power8, 463 .cpu_setup = __setup_cpu_power8,
463 .cpu_restore = __restore_cpu_power8, 464 .cpu_restore = __restore_cpu_power8,
464 .flush_tlb = __flush_tlb_power8, 465 .flush_tlb = __flush_tlb_power8,
466 .machine_check_early = __machine_check_early_realmode_p8,
465 .platform = "power8", 467 .platform = "power8",
466 }, 468 },
467 { /* Power7 */ 469 { /* Power7 */
@@ -521,6 +523,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
521 .cpu_setup = __setup_cpu_power8, 523 .cpu_setup = __setup_cpu_power8,
522 .cpu_restore = __restore_cpu_power8, 524 .cpu_restore = __restore_cpu_power8,
523 .flush_tlb = __flush_tlb_power8, 525 .flush_tlb = __flush_tlb_power8,
526 .machine_check_early = __machine_check_early_realmode_p8,
524 .platform = "power8", 527 .platform = "power8",
525 }, 528 },
526 { /* Power8 */ 529 { /* Power8 */
@@ -540,6 +543,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
540 .cpu_setup = __setup_cpu_power8, 543 .cpu_setup = __setup_cpu_power8,
541 .cpu_restore = __restore_cpu_power8, 544 .cpu_restore = __restore_cpu_power8,
542 .flush_tlb = __flush_tlb_power8, 545 .flush_tlb = __flush_tlb_power8,
546 .machine_check_early = __machine_check_early_realmode_p8,
543 .platform = "power8", 547 .platform = "power8",
544 }, 548 },
545 { /* Cell Broadband Engine */ 549 { /* Cell Broadband Engine */
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 690547319b03..60a217f11275 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -148,3 +148,37 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
148 /* TODO: Decode machine check reason. */ 148 /* TODO: Decode machine check reason. */
149 return handled; 149 return handled;
150} 150}
151
152static long mce_handle_ierror_p8(uint64_t srr1)
153{
154 long handled = 0;
155
156 handled = mce_handle_common_ierror(srr1);
157
158 if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
159 flush_and_reload_slb();
160 handled = 1;
161 }
162 return handled;
163}
164
165static long mce_handle_derror_p8(uint64_t dsisr)
166{
167 return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
168}
169
170long __machine_check_early_realmode_p8(struct pt_regs *regs)
171{
172 uint64_t srr1;
173 long handled = 1;
174
175 srr1 = regs->msr;
176
177 if (P7_SRR1_MC_LOADSTORE(srr1))
178 handled = mce_handle_derror_p8(regs->dsisr);
179 else
180 handled = mce_handle_ierror_p8(srr1);
181
182 /* TODO: Decode machine check reason. */
183 return handled;
184}