Skip to content

Commit

Permalink
powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
Mahesh Salgaonkar authored and Benjamin Herrenschmidt committed Dec 5, 2013
1 parent e22a227 commit ae744f3
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
3 changes: 3 additions & 0 deletions arch/powerpc/include/asm/mce.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,7 @@
P7_DSISR_MC_SLB_MULTIHIT | \
P7_DSISR_MC_SLB_MULTIHIT_PARITY)

#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \
P8_DSISR_MC_ERAT_MULTIHIT_SEC)

#endif /* __ASM_PPC64_MCE_H__ */
4 changes: 4 additions & 0 deletions arch/powerpc/kernel/cputable.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ extern void __restore_cpu_a2(void);
extern void __flush_tlb_power7(unsigned long inval_selector);
extern void __flush_tlb_power8(unsigned long inval_selector);
extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
#endif /* CONFIG_PPC64 */
#if defined(CONFIG_E500)
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
Expand Down Expand Up @@ -462,6 +463,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Power7 */
Expand Down Expand Up @@ -521,6 +523,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Power8 */
Expand All @@ -540,6 +543,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.machine_check_early = __machine_check_early_realmode_p8,
.platform = "power8",
},
{ /* Cell Broadband Engine */
Expand Down
34 changes: 34 additions & 0 deletions arch/powerpc/kernel/mce_power.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,37 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
/* TODO: Decode machine check reason. */
return handled;
}

static long mce_handle_ierror_p8(uint64_t srr1)
{
long handled = 0;

handled = mce_handle_common_ierror(srr1);

if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
flush_and_reload_slb();
handled = 1;
}
return handled;
}

static long mce_handle_derror_p8(uint64_t dsisr)
{
return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
}

long __machine_check_early_realmode_p8(struct pt_regs *regs)
{
uint64_t srr1;
long handled = 1;

srr1 = regs->msr;

if (P7_SRR1_MC_LOADSTORE(srr1))
handled = mce_handle_derror_p8(regs->dsisr);
else
handled = mce_handle_ierror_p8(srr1);

/* TODO: Decode machine check reason. */
return handled;
}

0 comments on commit ae744f3

Please sign in to comment.