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>
This commit is contained in:
parent
e22a22740c
commit
ae744f3432
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue