Skip to content

Commit ae744f3

Browse files
maheshsalozbenh
authored andcommitted
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>
1 parent e22a227 commit ae744f3

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

arch/powerpc/include/asm/mce.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,7 @@
6464
P7_DSISR_MC_SLB_MULTIHIT | \
6565
P7_DSISR_MC_SLB_MULTIHIT_PARITY)
6666

67+
#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \
68+
P8_DSISR_MC_ERAT_MULTIHIT_SEC)
69+
6770
#endif /* __ASM_PPC64_MCE_H__ */

arch/powerpc/kernel/cputable.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ extern void __restore_cpu_a2(void);
7474
extern void __flush_tlb_power7(unsigned long inval_selector);
7575
extern void __flush_tlb_power8(unsigned long inval_selector);
7676
extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
77+
extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
7778
#endif /* CONFIG_PPC64 */
7879
#if defined(CONFIG_E500)
7980
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -462,6 +463,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
462463
.cpu_setup = __setup_cpu_power8,
463464
.cpu_restore = __restore_cpu_power8,
464465
.flush_tlb = __flush_tlb_power8,
466+
.machine_check_early = __machine_check_early_realmode_p8,
465467
.platform = "power8",
466468
},
467469
{ /* Power7 */
@@ -521,6 +523,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
521523
.cpu_setup = __setup_cpu_power8,
522524
.cpu_restore = __restore_cpu_power8,
523525
.flush_tlb = __flush_tlb_power8,
526+
.machine_check_early = __machine_check_early_realmode_p8,
524527
.platform = "power8",
525528
},
526529
{ /* Power8 */
@@ -540,6 +543,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
540543
.cpu_setup = __setup_cpu_power8,
541544
.cpu_restore = __restore_cpu_power8,
542545
.flush_tlb = __flush_tlb_power8,
546+
.machine_check_early = __machine_check_early_realmode_p8,
543547
.platform = "power8",
544548
},
545549
{ /* Cell Broadband Engine */

arch/powerpc/kernel/mce_power.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,37 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
148148
/* TODO: Decode machine check reason. */
149149
return handled;
150150
}
151+
152+
static 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+
165+
static long mce_handle_derror_p8(uint64_t dsisr)
166+
{
167+
return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
168+
}
169+
170+
long __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+
}

0 commit comments

Comments
 (0)