tip/ras/core: Second pile
Borislav Petkov
maintainercover tip/ras/core: Second pile
From: Borislav Petkov <[email protected]>
Hi,
this is the second pile of RAS stuff for 4.7. It is mostly AMD F17h enablement and some more work from Tony to divert flow from mcelog and into our new genpool facility.
Please queue on tip/ras/core.
Thanks.
Aravind Gopalakrishnan (3):
x86/mce: Log MCEs after a warm rest on AMD, fam 0x17 and later x86/mce: Grade uncorrected errors for SMCA-enabled systems x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
Tony Luck (1):
x86/mce: Look in genpool instead of mcelog for pending error records
Yazen Ghannam (3):
x86/mce: Define vendor-specific MSR accessors
x86/mce: Detect and use SMCA-specific msr_ops
x86/mce: Detect local MCEs properly
arch/x86/include/asm/mce.h | 15 +++ arch/x86/kernel/cpu/mcheck/mce-genpool.c | 46 +++++++++ arch/x86/kernel/cpu/mcheck/mce-internal.h | 15 +++ arch/x86/kernel/cpu/mcheck/mce-severity.c | 30 ++++++ arch/x86/kernel/cpu/mcheck/mce.c | 150 ++++++++++++++++++++++-------- arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +- 6 files changed, 220 insertions(+), 46 deletions(-)
Signature · 1 line
2.7.3
Borislav Petkov
maintainerPATCH 1/7 x86/mce: Log MCEs after a warm rest on AMD, fam 0x17 and later
From: Aravind Gopalakrishnan <[email protected]>
For Fam17h, we want to report errors that persist across reboots. Error persistence is dependent on HW and no BIOS currently fiddles with values here. So allow reporting of errors upon boot until something goes wrong.
Logging is disabled on older families because BIOS didn't clear the MCA banks after a cold reset.
--- arch/x86/kernel/cpu/mcheck/mce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/mcheck/mce.c +1 -1
@@ -1495,7 +1495,7 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)*/ clear_bit (10 , (unsigned long *)&mce_banks[4 ].ctl); } -if (c->x86 <=17 && cfg->bootlog <0 ) { +if (c->x86 <17 && cfg->bootlog <0 ) {/* * Lots of broken BIOS around that don't clear them * by default and leave crap in there. Don't log:
Signature · 1 line
2.7.3
tip-bot for Aravind Gopalakrishnan
merge bot[tip:ras/core] x86/mce: Log MCEs after a warm rest on AMD, Fam17h and later
x86/mce: Log MCEs after a warm rest on AMD, Fam17h and later
Commit-ID: 10001d91aa0efc793952051f9070a569cc388ebc Gitweb: http://git.kernel.org/tip/10001d91aa0efc793952051f9070a569cc388ebc Author: Aravind Gopalakrishnan <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:51 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:15 +0200
x86/mce: Log MCEs after a warm rest on AMD, Fam17h and later
For Fam17h, we want to report errors that persist across reboots. Error persistence is dependent on HW and no BIOS currently fiddles with values here. So allow reporting of errors upon boot until something goes wrong.
Logging is disabled on older families because BIOS didn't clear the MCA banks after a cold reset.
--- arch/x86/kernel/cpu/mcheck/mce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/mcheck/mce.c +1 -1
@@ -1495,7 +1495,7 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)*/ clear_bit (10 , (unsigned long *)&mce_banks[4 ].ctl); } -if (c->x86 <=17 && cfg->bootlog <0 ) { +if (c->x86 <17 && cfg->bootlog <0 ) {/* * Lots of broken BIOS around that don't clear them * by default and leave crap in there. Don't log:
Borislav Petkov
maintainerPATCH 2/7 x86/mce: Grade uncorrected errors for SMCA-enabled systems
In reply to Borislav PetkovFrom: Aravind Gopalakrishnan <[email protected]>
For upcoming processors with Scalable MCA feature, we need to check the "succor" CPUID bit and the TCC bit in the MCx_STATUS register in order to grade an MCE's severity.
--- arch/x86/kernel/cpu/mcheck/mce-severity.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
arch/x86/kernel/cpu/mcheck/mce-severity.c +30 -0
@@ -204,6 +204,33 @@ static int error_context(struct mce *m)return IN_KERNEL ; } +static int mce_severity_amd_smca (struct mce *m,int err_ctx) +{ +u32 addr =MSR_AMD64_SMCA_MCx_CONFIG (m->bank); +u32 low, high; + +/* +* We need to look at the following bits: +* - "succor" bit (data poisoning support), and +* - TCC bit (Task Context Corrupt) +* in MCi_STATUS to determine error severity. +*/ +if (!mce_flags.succor) +return MCE_PANIC_SEVERITY ; + +if (rdmsr_safe (addr, &low, &high)) +return MCE_PANIC_SEVERITY ; + +/* TCC (Task context corrupt). If set and if IN_KERNEL, panic. */ +if ((low &MCI_CONFIG_MCAX ) && + (m->status &MCI_STATUS_TCC ) && + (err_ctx ==IN_KERNEL )) +return MCE_PANIC_SEVERITY ; + +/* ...otherwise invoke hwpoison handler. */ +return MCE_AR_SEVERITY ; +} +/* * See AMD Error Scope Hierarchy table in a newer BKDG. For example * 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
@@ -225,6 +252,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, char **msg, bool is_exc* to at least kill process to prolong system operation. */ if (mce_flags.overflow_recov) { +if (mce_flags.smca) +return mce_severity_amd_smca (m, ctx); +/* software can try to contain */ if (!(m->mcgstatus &MCG_STATUS_RIPV ) && (ctx ==IN_KERNEL ))return MCE_PANIC_SEVERITY ;
Signature · 1 line
2.7.3
tip-bot for Aravind Gopalakrishnan
merge bot[tip:ras/core] x86/mce: Grade uncorrected errors for SMCA-enabled systems
x86/mce: Grade uncorrected errors for SMCA-enabled systems
Commit-ID: 6bda529ec42e1cd4dde1c3d0a1a18000ffd3d419 Gitweb: http://git.kernel.org/tip/6bda529ec42e1cd4dde1c3d0a1a18000ffd3d419 Author: Aravind Gopalakrishnan <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:52 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:15 +0200
x86/mce: Grade uncorrected errors for SMCA-enabled systems
For upcoming processors with Scalable MCA feature, we need to check the "succor" CPUID bit and the TCC bit in the MCx_STATUS register in order to grade an MCE's severity.
--- arch/x86/kernel/cpu/mcheck/mce-severity.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
arch/x86/kernel/cpu/mcheck/mce-severity.c +30 -0
@@ -204,6 +204,33 @@ static int error_context(struct mce *m)return IN_KERNEL ; } +static int mce_severity_amd_smca (struct mce *m,int err_ctx) +{ +u32 addr =MSR_AMD64_SMCA_MCx_CONFIG (m->bank); +u32 low, high; + +/* +* We need to look at the following bits: +* - "succor" bit (data poisoning support), and +* - TCC bit (Task Context Corrupt) +* in MCi_STATUS to determine error severity. +*/ +if (!mce_flags.succor) +return MCE_PANIC_SEVERITY ; + +if (rdmsr_safe (addr, &low, &high)) +return MCE_PANIC_SEVERITY ; + +/* TCC (Task context corrupt). If set and if IN_KERNEL, panic. */ +if ((low &MCI_CONFIG_MCAX ) && + (m->status &MCI_STATUS_TCC ) && + (err_ctx ==IN_KERNEL )) +return MCE_PANIC_SEVERITY ; + +/* ...otherwise invoke hwpoison handler. */ +return MCE_AR_SEVERITY ; +} +/* * See AMD Error Scope Hierarchy table in a newer BKDG. For example * 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
@@ -225,6 +252,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, char **msg, bool is_exc* to at least kill process to prolong system operation. */ if (mce_flags.overflow_recov) { +if (mce_flags.smca) +return mce_severity_amd_smca (m, ctx); +/* software can try to contain */ if (!(m->mcgstatus &MCG_STATUS_RIPV ) && (ctx ==IN_KERNEL ))return MCE_PANIC_SEVERITY ;
Borislav Petkov
maintainerPATCH 3/7 x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
In reply to Borislav PetkovFrom: Aravind Gopalakrishnan <[email protected]>
We need to do this after __mcheck_cpu_init_vendor() as for ScalableMCA processors, there are going to be new MSR write handlers if the feature is detected using CPUID bit (which happens in __mcheck_cpu_init_vendor()).
No functional change is introduced here.
--- arch/x86/kernel/cpu/mcheck/mce.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/mcheck/mce.c +8 -1
@@ -1420,7 +1420,6 @@ static void __mcheck_cpu_init_generic(void)enum mcp_flags m_fl =0 ;mce_banks_t all_banks;u64 cap; -int i;if (!mca_cfg.bootlog) m_fl =MCP_DONTLOG ;
@@ -1436,6 +1435,11 @@ static void __mcheck_cpu_init_generic(void)rdmsrl (MSR_IA32_MCG_CAP , cap);if (cap &MCG_CTL_P )wrmsr (MSR_IA32_MCG_CTL ,0xffffffff ,0xffffffff ); +} + +static void __mcheck_cpu_init_clear_banks (void ) +{ +int i;for (i =0 ; i < mca_cfg.banks; i++) {struct mce_bank *b = &mce_banks[i];
@@ -1717,6 +1721,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (c); +__mcheck_cpu_init_clear_banks ();__mcheck_cpu_init_timer (); }
@@ -2121,6 +2126,7 @@ static void mce_syscore_resume(void) {__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (raw_cpu_ptr (&cpu_info)); +__mcheck_cpu_init_clear_banks (); }static struct syscore_ops mce_syscore_ops = {
@@ -2138,6 +2144,7 @@ static void mce_cpu_restart(void *data)if (!mce_available (raw_cpu_ptr (&cpu_info)))return ;__mcheck_cpu_init_generic (); +__mcheck_cpu_init_clear_banks ();__mcheck_cpu_init_timer (); }
Signature · 1 line
2.7.3
tip-bot for Aravind Gopalakrishnan
merge bot[tip:ras/core] x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
Commit-ID: bb91f8c0176b072aeb6b84cfd7e04084025121e0 Gitweb: http://git.kernel.org/tip/bb91f8c0176b072aeb6b84cfd7e04084025121e0 Author: Aravind Gopalakrishnan <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:53 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:16 +0200
x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
We need to do this after __mcheck_cpu_init_vendor() as for ScalableMCA processors, there are going to be new MSR write handlers if the feature is detected using CPUID bit (which happens in __mcheck_cpu_init_vendor()).
No functional change is introduced here.
--- arch/x86/kernel/cpu/mcheck/mce.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/mcheck/mce.c +8 -1
@@ -1420,7 +1420,6 @@ static void __mcheck_cpu_init_generic(void)enum mcp_flags m_fl =0 ;mce_banks_t all_banks;u64 cap; -int i;if (!mca_cfg.bootlog) m_fl =MCP_DONTLOG ;
@@ -1436,6 +1435,11 @@ static void __mcheck_cpu_init_generic(void)rdmsrl (MSR_IA32_MCG_CAP , cap);if (cap &MCG_CTL_P )wrmsr (MSR_IA32_MCG_CTL ,0xffffffff ,0xffffffff ); +} + +static void __mcheck_cpu_init_clear_banks (void ) +{ +int i;for (i =0 ; i < mca_cfg.banks; i++) {struct mce_bank *b = &mce_banks[i];
@@ -1717,6 +1721,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (c); +__mcheck_cpu_init_clear_banks ();__mcheck_cpu_init_timer (); }
@@ -2121,6 +2126,7 @@ static void mce_syscore_resume(void) {__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (raw_cpu_ptr (&cpu_info)); +__mcheck_cpu_init_clear_banks (); }static struct syscore_ops mce_syscore_ops = {
@@ -2138,6 +2144,7 @@ static void mce_cpu_restart(void *data)if (!mce_available (raw_cpu_ptr (&cpu_info)))return ;__mcheck_cpu_init_generic (); +__mcheck_cpu_init_clear_banks ();__mcheck_cpu_init_timer (); }
Borislav Petkov
maintainerPATCH 4/7 x86/mce: Define vendor-specific MSR accessors
In reply to Borislav PetkovFrom: Yazen Ghannam <[email protected]>
Scalable MCA processors have a whole new range of MSR addresses to obtain bank related info such as CTL, MISC, ADDR, STATUS. Therefore, we need a way to abstract the MSR addresses per vendor.
Carved out from a patch by Aravind Gopalakrishnan
<[email protected]>.
--- arch/x86/include/asm/mce.h | 15 +++++++++++++ arch/x86/kernel/cpu/mcheck/mce.c | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
arch/x86/include/asm/mce.h +15 -0
@@ -104,10 +104,16 @@#define MCE_LOG_SIGNATURE "MACHINECHECK"/* AMD Scalable MCA */ +#define MSR_AMD64_SMCA_MC0_CTL 0xc0002000 +#define MSR_AMD64_SMCA_MC0_STATUS 0xc0002001 +#define MSR_AMD64_SMCA_MC0_ADDR 0xc0002002#define MSR_AMD64_SMCA_MC0_MISC0 0xc0002003#define MSR_AMD64_SMCA_MC0_CONFIG 0xc0002004#define MSR_AMD64_SMCA_MC0_IPID 0xc0002005#define MSR_AMD64_SMCA_MC0_MISC1 0xc000200a +#define MSR_AMD64_SMCA_MCx_CTL (x) (MSR_AMD64_SMCA_MC0_CTL + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_STATUS (x) (MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_ADDR (x) (MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x))#define MSR_AMD64_SMCA_MCx_MISC (x) (MSR_AMD64_SMCA_MC0_MISC0 + 0x10*(x))#define MSR_AMD64_SMCA_MCx_CONFIG (x) (MSR_AMD64_SMCA_MC0_CONFIG + 0x10*(x))#define MSR_AMD64_SMCA_MCx_IPID (x) (MSR_AMD64_SMCA_MC0_IPID + 0x10*(x))
@@ -168,9 +174,18 @@ struct mce_vendor_flags { __reserved_0 :61 ; }; + +struct mca_msr_regs { +u32 (*ctl) (int bank); +u32 (*status) (int bank); +u32 (*addr) (int bank); +u32 (*misc) (int bank); +}; +extern struct mce_vendor_flags mce_flags;extern struct mca_config mca_cfg; +extern struct mca_msr_regs msr_ops;extern void mce_register_decode_chain (struct notifier_block *nb);extern void mce_unregister_decode_chain (struct notifier_block *nb);
arch/x86/kernel/cpu/mcheck/mce.c +47 -0
53 lines not on this page · raw message
Signature · 1 line
2.7.3
tip-bot for Yazen Ghannam
merge bot[tip:ras/core] x86/mce: Define vendor-specific MSR accessors
x86/mce: Define vendor-specific MSR accessors
Commit-ID: a9750a31efdee79bea4ad1db93cf98a5db6e07ac Gitweb: http://git.kernel.org/tip/a9750a31efdee79bea4ad1db93cf98a5db6e07ac Author: Yazen Ghannam <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:54 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:16 +0200
x86/mce: Define vendor-specific MSR accessors
Scalable MCA processors have a whole new range of MSR addresses to obtain bank related info such as CTL, MISC, ADDR, STATUS. Therefore, we need a way to abstract the MSR addresses per vendor.
Carved out from a patch by Aravind Gopalakrishnan <[email protected]>.
--- arch/x86/include/asm/mce.h | 15 +++++++++++++ arch/x86/kernel/cpu/mcheck/mce.c | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
arch/x86/include/asm/mce.h +15 -0
@@ -104,10 +104,16 @@#define MCE_LOG_SIGNATURE "MACHINECHECK"/* AMD Scalable MCA */ +#define MSR_AMD64_SMCA_MC0_CTL 0xc0002000 +#define MSR_AMD64_SMCA_MC0_STATUS 0xc0002001 +#define MSR_AMD64_SMCA_MC0_ADDR 0xc0002002#define MSR_AMD64_SMCA_MC0_MISC0 0xc0002003#define MSR_AMD64_SMCA_MC0_CONFIG 0xc0002004#define MSR_AMD64_SMCA_MC0_IPID 0xc0002005#define MSR_AMD64_SMCA_MC0_MISC1 0xc000200a +#define MSR_AMD64_SMCA_MCx_CTL (x) (MSR_AMD64_SMCA_MC0_CTL + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_STATUS (x) (MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_ADDR (x) (MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x))#define MSR_AMD64_SMCA_MCx_MISC (x) (MSR_AMD64_SMCA_MC0_MISC0 + 0x10*(x))#define MSR_AMD64_SMCA_MCx_CONFIG (x) (MSR_AMD64_SMCA_MC0_CONFIG + 0x10*(x))#define MSR_AMD64_SMCA_MCx_IPID (x) (MSR_AMD64_SMCA_MC0_IPID + 0x10*(x))
@@ -168,9 +174,18 @@ struct mce_vendor_flags { __reserved_0 :61 ; }; + +struct mca_msr_regs { +u32 (*ctl) (int bank); +u32 (*status) (int bank); +u32 (*addr) (int bank); +u32 (*misc) (int bank); +}; +extern struct mce_vendor_flags mce_flags;extern struct mca_config mca_cfg; +extern struct mca_msr_regs msr_ops;extern void mce_register_decode_chain (struct notifier_block *nb);extern void mce_unregister_decode_chain (struct notifier_block *nb);
arch/x86/kernel/cpu/mcheck/mce.c +47 -0
53 lines not on this page · raw message
Borislav Petkov
maintainerPATCH 5/7 x86/mce: Detect and use SMCA-specific msr_ops
In reply to Borislav PetkovFrom: Yazen Ghannam <[email protected]>
Replace all calls to MCx_IA32_{CTL,ADDR,MISC,STATUS} with the appropriate msr_ops.
Use SMCA-specific msr_ops when on an SMCA-enabled processor.
Carved out from a patch by Aravind Gopalakrishnan
<[email protected]>.
--- arch/x86/kernel/cpu/mcheck/mce.c | 38 +++++++++++++++++++++++------------- arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +++++----- 2 files changed, 29 insertions(+), 19 deletions(-)
arch/x86/kernel/cpu/mcheck/mce.c +24 -14
@@ -403,11 +403,11 @@ static int msr_to_offset(u32 msr)if (msr == mca_cfg.rip_msr)return offsetof(struct mce , ip); -if (msr ==MSR_IA32_MCx_STATUS (bank)) +if (msr == msr_ops.status (bank))return offsetof(struct mce , status); -if (msr ==MSR_IA32_MCx_ADDR (bank)) +if (msr == msr_ops.addr (bank))return offsetof(struct mce , addr); -if (msr ==MSR_IA32_MCx_MISC (bank)) +if (msr == msr_ops.misc (bank))return offsetof(struct mce , misc);if (msr ==MSR_IA32_MCG_STATUS )return offsetof(struct mce , mcgstatus);
@@ -570,9 +570,9 @@ static struct notifier_block mce_srao_nb = {static void mce_read_aux (struct mce *m,int i) {if (m->status &MCI_STATUS_MISCV ) - m->misc =mce_rdmsrl (MSR_IA32_MCx_MISC (i)); + m->misc =mce_rdmsrl (msr_ops.misc (i));if (m->status &MCI_STATUS_ADDRV ) { - m->addr =mce_rdmsrl (MSR_IA32_MCx_ADDR (i)); + m->addr =mce_rdmsrl (msr_ops.addr (i));/* * Mask the reported address by the reported granularity.
@@ -654,7 +654,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) m.tsc =0 ;barrier (); - m.status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m.status =mce_rdmsrl (msr_ops.status (i));if (!(m.status &MCI_STATUS_VAL ))continue ;
@@ -701,7 +701,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)/* * Clear state for this bank. */ -mce_wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +mce_wrmsrl (msr_ops.status (i),0 ); }/*
@@ -726,7 +726,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,char *tmp;for (i =0 ; i < mca_cfg.banks; i++) { - m->status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m->status =mce_rdmsrl (msr_ops.status (i));if (m->status &MCI_STATUS_VAL ) {__set_bit (i, validp);if (quirk_no_way_out)
@@ -1004,7 +1004,7 @@ static void mce_clear_state(unsigned long *toclear)for (i =0 ; i < mca_cfg.banks; i++) {if (test_bit (i, toclear)) -mce_wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +mce_wrmsrl (msr_ops.status (i),0 ); } }
@@ -1123,7 +1123,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) m.addr =0 ; m.bank = i; - m.status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m.status =mce_rdmsrl (msr_ops.status (i));if ((m.status &MCI_STATUS_VAL ) ==0 )continue ;
@@ -1493,8 +1493,8 @@ static void __mcheck_cpu_init_clear_banks(void)if (!b->init)continue ; -wrmsrl (MSR_IA32_MCx_CTL (i), b->ctl); -wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +wrmsrl (msr_ops.ctl (i), b->ctl); +wrmsrl (msr_ops.status (i),0 ); } }
@@ -1684,6 +1684,16 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) mce_flags.overflow_recov = !!(ebx &BIT (0 )); mce_flags.succor = !!(ebx &BIT (1 )); mce_flags.smca = !!(ebx &BIT (3 )); + +/* +* Install proper ops for Scalable MCA enabled processors +*/ +if (mce_flags.smca) { + msr_ops.ctl = smca_ctl_reg; + msr_ops.status = smca_status_reg; + msr_ops.addr = smca_addr_reg; + msr_ops.misc = smca_misc_reg; + }mce_amd_feature_init (c);break ;
@@ -2134,7 +2144,7 @@ static void mce_disable_error_reporting(void)struct mce_bank *b = &mce_banks[i];if (b->init) -wrmsrl (MSR_IA32_MCx_CTL (i),0 ); +wrmsrl (msr_ops.ctl (i),0 ); }return ; }
@@ -2467,7 +2477,7 @@ static void mce_reenable_cpu(void *h)struct mce_bank *b = &mce_banks[i];if (b->init) -wrmsrl (MSR_IA32_MCx_CTL (i), b->ctl); +wrmsrl (msr_ops.ctl (i), b->ctl); } }
arch/x86/kernel/cpu/mcheck/mce_amd.c +5 -5
@@ -333,7 +333,7 @@ static u32 get_block_address(u32 current_addr, u32 low, u32 high,/* Fall back to method we used for older processors: */ switch (block) {case 0 : - addr =MSR_IA32_MCx_MISC (bank); + addr = msr_ops.misc (bank);break ;case 1 : offset = ((low &MASK_BLKPTR_LO ) >>21 );
@@ -435,7 +435,7 @@ static void __log_error(unsigned int bank, bool threshold_err, u64 misc)struct mce m;u64 status; -rdmsrl (MSR_IA32_MCx_STATUS (bank), status); +rdmsrl (msr_ops.status (bank), status);if (!(status &MCI_STATUS_VAL ))return ;
@@ -448,10 +448,10 @@ static void __log_error(unsigned int bank, bool threshold_err, u64 misc) m.misc = misc;if (m.status &MCI_STATUS_ADDRV ) -rdmsrl (MSR_IA32_MCx_ADDR (bank), m.addr); +rdmsrl (msr_ops.addr (bank), m.addr);mce_log (&m); -wrmsrl (MSR_IA32_MCx_STATUS (bank),0 ); +wrmsrl (msr_ops.status (bank),0 ); }static inline void __smp_deferred_error_interrupt (void )
@@ -483,7 +483,7 @@ static void amd_deferred_error_interrupt(void)unsigned int bank;for (bank =0 ; bank < mca_cfg.banks; ++bank) { -rdmsrl (MSR_IA32_MCx_STATUS (bank), status); +rdmsrl (msr_ops.status (bank), status);if (!(status &MCI_STATUS_VAL ) || !(status &MCI_STATUS_DEFERRED ))
Signature · 1 line
2.7.3
tip-bot for Yazen Ghannam
merge bot[tip:ras/core] x86/mce: Detect and use SMCA-specific msr_ops
x86/mce: Detect and use SMCA-specific msr_ops
Commit-ID: d9d73fcc878469d209d7a7030726f20dd10841a7 Gitweb: http://git.kernel.org/tip/d9d73fcc878469d209d7a7030726f20dd10841a7 Author: Yazen Ghannam <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:55 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:16 +0200
x86/mce: Detect and use SMCA-specific msr_ops
Replace all calls to MCx_IA32_{CTL,ADDR,MISC,STATUS} with the appropriate msr_ops.
Use SMCA-specific msr_ops when on an SMCA-enabled processor.
Carved out from a patch by Aravind Gopalakrishnan <[email protected]>.
--- arch/x86/kernel/cpu/mcheck/mce.c | 38 +++++++++++++++++++++++------------- arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +++++----- 2 files changed, 29 insertions(+), 19 deletions(-)
arch/x86/kernel/cpu/mcheck/mce.c +24 -14
@@ -403,11 +403,11 @@ static int msr_to_offset(u32 msr)if (msr == mca_cfg.rip_msr)return offsetof(struct mce , ip); -if (msr ==MSR_IA32_MCx_STATUS (bank)) +if (msr == msr_ops.status (bank))return offsetof(struct mce , status); -if (msr ==MSR_IA32_MCx_ADDR (bank)) +if (msr == msr_ops.addr (bank))return offsetof(struct mce , addr); -if (msr ==MSR_IA32_MCx_MISC (bank)) +if (msr == msr_ops.misc (bank))return offsetof(struct mce , misc);if (msr ==MSR_IA32_MCG_STATUS )return offsetof(struct mce , mcgstatus);
@@ -570,9 +570,9 @@ static struct notifier_block mce_srao_nb = {static void mce_read_aux (struct mce *m,int i) {if (m->status &MCI_STATUS_MISCV ) - m->misc =mce_rdmsrl (MSR_IA32_MCx_MISC (i)); + m->misc =mce_rdmsrl (msr_ops.misc (i));if (m->status &MCI_STATUS_ADDRV ) { - m->addr =mce_rdmsrl (MSR_IA32_MCx_ADDR (i)); + m->addr =mce_rdmsrl (msr_ops.addr (i));/* * Mask the reported address by the reported granularity.
@@ -654,7 +654,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) m.tsc =0 ;barrier (); - m.status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m.status =mce_rdmsrl (msr_ops.status (i));if (!(m.status &MCI_STATUS_VAL ))continue ;
@@ -701,7 +701,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)/* * Clear state for this bank. */ -mce_wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +mce_wrmsrl (msr_ops.status (i),0 ); }/*
@@ -726,7 +726,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,char *tmp;for (i =0 ; i < mca_cfg.banks; i++) { - m->status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m->status =mce_rdmsrl (msr_ops.status (i));if (m->status &MCI_STATUS_VAL ) {__set_bit (i, validp);if (quirk_no_way_out)
@@ -1004,7 +1004,7 @@ static void mce_clear_state(unsigned long *toclear)for (i =0 ; i < mca_cfg.banks; i++) {if (test_bit (i, toclear)) -mce_wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +mce_wrmsrl (msr_ops.status (i),0 ); } }
@@ -1123,7 +1123,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) m.addr =0 ; m.bank = i; - m.status =mce_rdmsrl (MSR_IA32_MCx_STATUS (i)); + m.status =mce_rdmsrl (msr_ops.status (i));if ((m.status &MCI_STATUS_VAL ) ==0 )continue ;
@@ -1493,8 +1493,8 @@ static void __mcheck_cpu_init_clear_banks(void)if (!b->init)continue ; -wrmsrl (MSR_IA32_MCx_CTL (i), b->ctl); -wrmsrl (MSR_IA32_MCx_STATUS (i),0 ); +wrmsrl (msr_ops.ctl (i), b->ctl); +wrmsrl (msr_ops.status (i),0 ); } }
@@ -1684,6 +1684,16 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) mce_flags.overflow_recov = !!(ebx &BIT (0 )); mce_flags.succor = !!(ebx &BIT (1 )); mce_flags.smca = !!(ebx &BIT (3 )); + +/* +* Install proper ops for Scalable MCA enabled processors +*/ +if (mce_flags.smca) { + msr_ops.ctl = smca_ctl_reg; + msr_ops.status = smca_status_reg; + msr_ops.addr = smca_addr_reg; + msr_ops.misc = smca_misc_reg; + }mce_amd_feature_init (c);break ;
@@ -2134,7 +2144,7 @@ static void mce_disable_error_reporting(void)struct mce_bank *b = &mce_banks[i];if (b->init) -wrmsrl (MSR_IA32_MCx_CTL (i),0 ); +wrmsrl (msr_ops.ctl (i),0 ); }return ; }
@@ -2467,7 +2477,7 @@ static void mce_reenable_cpu(void *h)struct mce_bank *b = &mce_banks[i];if (b->init) -wrmsrl (MSR_IA32_MCx_CTL (i), b->ctl); +wrmsrl (msr_ops.ctl (i), b->ctl); } }
arch/x86/kernel/cpu/mcheck/mce_amd.c +5 -5
@@ -333,7 +333,7 @@ static u32 get_block_address(u32 current_addr, u32 low, u32 high,/* Fall back to method we used for older processors: */ switch (block) {case 0 : - addr =MSR_IA32_MCx_MISC (bank); + addr = msr_ops.misc (bank);break ;case 1 : offset = ((low &MASK_BLKPTR_LO ) >>21 );
@@ -435,7 +435,7 @@ static void __log_error(unsigned int bank, bool threshold_err, u64 misc)struct mce m;u64 status; -rdmsrl (MSR_IA32_MCx_STATUS (bank), status); +rdmsrl (msr_ops.status (bank), status);if (!(status &MCI_STATUS_VAL ))return ;
@@ -448,10 +448,10 @@ static void __log_error(unsigned int bank, bool threshold_err, u64 misc) m.misc = misc;if (m.status &MCI_STATUS_ADDRV ) -rdmsrl (MSR_IA32_MCx_ADDR (bank), m.addr); +rdmsrl (msr_ops.addr (bank), m.addr);mce_log (&m); -wrmsrl (MSR_IA32_MCx_STATUS (bank),0 ); +wrmsrl (msr_ops.status (bank),0 ); }static inline void __smp_deferred_error_interrupt (void )
@@ -483,7 +483,7 @@ static void amd_deferred_error_interrupt(void)unsigned int bank;for (bank =0 ; bank < mca_cfg.banks; ++bank) { -rdmsrl (MSR_IA32_MCx_STATUS (bank), status); +rdmsrl (msr_ops.status (bank), status);if (!(status &MCI_STATUS_VAL ) || !(status &MCI_STATUS_DEFERRED ))
Borislav Petkov
maintainerPATCH 6/7 x86/mce: Look in genpool instead of mcelog for pending error records
In reply to Borislav PetkovFrom: Tony Luck <[email protected]>
A couple of issues here:
1) MCE_LOG_LEN is only 32 - so we may have more pending records than will fit in the buffer on high core count CPUs.
2) During a panic we may have a lot of duplicate records because multiple logical CPUs may have seen and logged the same error because some banks are shared.
Switch to using the genpool to look for the pending records. Squeeze out duplicated records.
--- arch/x86/kernel/cpu/mcheck/mce-genpool.c | 46 +++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/mcheck/mce-internal.h | 15 ++++++++++ arch/x86/kernel/cpu/mcheck/mce.c | 21 ++++++-------- 3 files changed, 70 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/mcheck/mce-genpool.c +46 -0
@@ -26,6 +26,52 @@ static struct gen_pool *mce_evt_pool;static LLIST_HEAD (mce_event_llist);static char gen_pool_buf[MCE_POOLSZ ]; +/* +* Compare the record "t" with each of the records on list "l" to see if +* an equivalent one is present in the list. +*/ +static bool is_duplicate_mce_record (struct mce_evt_llist *t,struct mce_evt_llist *l) +{ +struct mce_evt_llist *node; +struct mce *m1, *m2; + + m1 = &t->mce; + +llist_for_each_entry (node, &l->llnode, llnode) { + m2 = &node->mce; + +if (!mce_cmp (m1, m2)) +return true; + } +return false; +} + +/* +* The system has panicked - we'd like to peruse the list of mce records +* that have been queued, but not seen by anyone yet. The list is in +* reverse time order, so we need to reverse it. While doing that we can +* also drop duplicate records (these were logged because some banks are +* shared between cores or by all threads on a socket). +*/ +struct llist_node *mce_gen_pool_prepare_records (void ) +{ +struct llist_node *head; +LLIST_HEAD (new_head); +struct mce_evt_llist *node, *t; + + head =llist_del_all (&mce_event_llist); +if (!head) +return NULL ; + +/* squeeze out duplicates while reversing order */ +llist_for_each_entry_safe (node, t, head, llnode) { +if (!is_duplicate_mce_record (node, t)) +llist_add (&node->llnode, &new_head); + } + +return new_head.first; +} +void mce_gen_pool_process (void ) {struct llist_node *head;
arch/x86/kernel/cpu/mcheck/mce-internal.h +15 -0
@@ -35,6 +35,7 @@ void mce_gen_pool_process(void);bool mce_gen_pool_empty (void );int mce_gen_pool_add (struct mce *mce);int mce_gen_pool_init (void ); +struct llist_node *mce_gen_pool_prepare_records (void );extern int (*mce_severity)(struct mce *a,int tolerant,char **msg,bool is_excp);struct dentry *mce_get_debugfs_dir (void );
@@ -81,3 +82,17 @@ static inline int apei_clear_mce(u64 record_id)#endif void mce_inject_log (struct mce *m); + +/* +* We consider records to be equivalent if bank+status+addr+misc all match. +* This is only used when the system is going down because of a fatal error +* to avoid cluttering the console log with essentially repeated information. +* In normal processing all errors seen are logged. +*/ +static inline bool mce_cmp (struct mce *m1,struct mce *m2) +{ +return m1->bank != m2->bank || + m1->status != m2->status || + m1->addr != m2->addr || + m1->misc != m2->misc; +}
arch/x86/kernel/cpu/mcheck/mce.c +9 -12
@@ -161,7 +161,6 @@ void mce_log(struct mce *mce)if (!mce_gen_pool_add (mce))irq_work_queue (&mce_irq_work); - mce->finished =0 ;wmb ();for (;;) { entry =mce_log_get_idx_check (mcelog.next);
@@ -194,7 +193,6 @@ void mce_log(struct mce *mce) mcelog.entry[entry].finished =1 ;wmb (); - mce->finished =1 ;set_bit (0 , &mce_need_notify); }
@@ -337,7 +335,9 @@ static void wait_for_panic(void)static void mce_panic (const char *msg,struct mce *final,char *exp) { -int i, apei_err =0 ; +int apei_err =0 ; +struct llist_node *pending; +struct mce_evt_llist *l;if (!fake_panic) {/*
@@ -354,11 +354,10 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)if (atomic_inc_return (&mce_fake_panicked) >1 )return ; } + pending =mce_gen_pool_prepare_records ();/* First print corrected ones that are still unlogged */ -for (i =0 ; i <MCE_LOG_LEN ; i++) { -struct mce *m = &mcelog.entry[i]; -if (!(m->status &MCI_STATUS_VAL )) -continue ; +llist_for_each_entry (l, pending, llnode) { +struct mce *m = &l->mce;if (!(m->status &MCI_STATUS_UC )) {print_mce (m);if (!apei_err)
@@ -366,13 +365,11 @@ static void mce_panic(const char *msg, struct mce *final, char *exp) } }/* Now print uncorrected but with the final one last */ -for (i =0 ; i <MCE_LOG_LEN ; i++) { -struct mce *m = &mcelog.entry[i]; -if (!(m->status &MCI_STATUS_VAL )) -continue ; +llist_for_each_entry (l, pending, llnode) { +struct mce *m = &l->mce;if (!(m->status &MCI_STATUS_UC ))continue ; -if (!final ||memcmp (m, final,sizeof (struct mce ))) { +if (!final ||mce_cmp (m, final)) {print_mce (m);if (!apei_err) apei_err =apei_write_mce (m);
Signature · 1 line
2.7.3
tip-bot for Tony Luck
merge bot[tip:ras/core] x86/mce: Look in genpool instead of mcelog for pending error records
x86/mce: Look in genpool instead of mcelog for pending error records
Commit-ID: 5541c93cdf0cc0bb7f6065b43509171838665ea1 Gitweb: http://git.kernel.org/tip/5541c93cdf0cc0bb7f6065b43509171838665ea1 Author: Tony Luck <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:56 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:16 +0200
x86/mce: Look in genpool instead of mcelog for pending error records
A couple of issues here:
1) MCE_LOG_LEN is only 32 - so we may have more pending records than will fit in the buffer on high core count CPUs.
2) During a panic we may have a lot of duplicate records because multiple logical CPUs may have seen and logged the same error because some banks are shared.
Switch to using the genpool to look for the pending records. Squeeze out duplicated records.
--- arch/x86/kernel/cpu/mcheck/mce-genpool.c | 46 +++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/mcheck/mce-internal.h | 15 ++++++++++ arch/x86/kernel/cpu/mcheck/mce.c | 21 ++++++-------- 3 files changed, 70 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/mcheck/mce-genpool.c +46 -0
@@ -26,6 +26,52 @@ static struct gen_pool *mce_evt_pool;static LLIST_HEAD (mce_event_llist);static char gen_pool_buf[MCE_POOLSZ ]; +/* +* Compare the record "t" with each of the records on list "l" to see if +* an equivalent one is present in the list. +*/ +static bool is_duplicate_mce_record (struct mce_evt_llist *t,struct mce_evt_llist *l) +{ +struct mce_evt_llist *node; +struct mce *m1, *m2; + + m1 = &t->mce; + +llist_for_each_entry (node, &l->llnode, llnode) { + m2 = &node->mce; + +if (!mce_cmp (m1, m2)) +return true; + } +return false; +} + +/* +* The system has panicked - we'd like to peruse the list of MCE records +* that have been queued, but not seen by anyone yet. The list is in +* reverse time order, so we need to reverse it. While doing that we can +* also drop duplicate records (these were logged because some banks are +* shared between cores or by all threads on a socket). +*/ +struct llist_node *mce_gen_pool_prepare_records (void ) +{ +struct llist_node *head; +LLIST_HEAD (new_head); +struct mce_evt_llist *node, *t; + + head =llist_del_all (&mce_event_llist); +if (!head) +return NULL ; + +/* squeeze out duplicates while reversing order */ +llist_for_each_entry_safe (node, t, head, llnode) { +if (!is_duplicate_mce_record (node, t)) +llist_add (&node->llnode, &new_head); + } + +return new_head.first; +} +void mce_gen_pool_process (void ) {struct llist_node *head;
arch/x86/kernel/cpu/mcheck/mce-internal.h +15 -0
@@ -35,6 +35,7 @@ void mce_gen_pool_process(void);bool mce_gen_pool_empty (void );int mce_gen_pool_add (struct mce *mce);int mce_gen_pool_init (void ); +struct llist_node *mce_gen_pool_prepare_records (void );extern int (*mce_severity)(struct mce *a,int tolerant,char **msg,bool is_excp);struct dentry *mce_get_debugfs_dir (void );
@@ -81,3 +82,17 @@ static inline int apei_clear_mce(u64 record_id)#endif void mce_inject_log (struct mce *m); + +/* +* We consider records to be equivalent if bank+status+addr+misc all match. +* This is only used when the system is going down because of a fatal error +* to avoid cluttering the console log with essentially repeated information. +* In normal processing all errors seen are logged. +*/ +static inline bool mce_cmp (struct mce *m1,struct mce *m2) +{ +return m1->bank != m2->bank || + m1->status != m2->status || + m1->addr != m2->addr || + m1->misc != m2->misc; +}
arch/x86/kernel/cpu/mcheck/mce.c +9 -12
@@ -161,7 +161,6 @@ void mce_log(struct mce *mce)if (!mce_gen_pool_add (mce))irq_work_queue (&mce_irq_work); - mce->finished =0 ;wmb ();for (;;) { entry =mce_log_get_idx_check (mcelog.next);
@@ -194,7 +193,6 @@ void mce_log(struct mce *mce) mcelog.entry[entry].finished =1 ;wmb (); - mce->finished =1 ;set_bit (0 , &mce_need_notify); }
@@ -337,7 +335,9 @@ static void wait_for_panic(void)static void mce_panic (const char *msg,struct mce *final,char *exp) { -int i, apei_err =0 ; +int apei_err =0 ; +struct llist_node *pending; +struct mce_evt_llist *l;if (!fake_panic) {/*
@@ -354,11 +354,10 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)if (atomic_inc_return (&mce_fake_panicked) >1 )return ; } + pending =mce_gen_pool_prepare_records ();/* First print corrected ones that are still unlogged */ -for (i =0 ; i <MCE_LOG_LEN ; i++) { -struct mce *m = &mcelog.entry[i]; -if (!(m->status &MCI_STATUS_VAL )) -continue ; +llist_for_each_entry (l, pending, llnode) { +struct mce *m = &l->mce;if (!(m->status &MCI_STATUS_UC )) {print_mce (m);if (!apei_err)
@@ -366,13 +365,11 @@ static void mce_panic(const char *msg, struct mce *final, char *exp) } }/* Now print uncorrected but with the final one last */ -for (i =0 ; i <MCE_LOG_LEN ; i++) { -struct mce *m = &mcelog.entry[i]; -if (!(m->status &MCI_STATUS_VAL )) -continue ; +llist_for_each_entry (l, pending, llnode) { +struct mce *m = &l->mce;if (!(m->status &MCI_STATUS_UC ))continue ; -if (!final ||memcmp (m, final,sizeof (struct mce ))) { +if (!final ||mce_cmp (m, final)) {print_mce (m);if (!apei_err) apei_err =apei_write_mce (m);
Borislav Petkov
maintainerPATCH 7/7 x86/mce: Detect local MCEs properly
In reply to Borislav PetkovFrom: Yazen Ghannam <[email protected]>
Check the MCG_STATUS_LMCES bit on Intel to verify that current MCE is local. It is always local on AMD.
--- arch/x86/kernel/cpu/mcheck/mce.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-)
arch/x86/kernel/cpu/mcheck/mce.c +20 -13
@@ -1038,11 +1038,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)int i;int worst =0 ;int severity; +/* * Establish sequential order between the CPUs entering the machine * check handler. */ -int order; +int order =-1 ;/* * If no_way_out gets set, there is no safe way to recover from this * MCE. If mca_cfg.tolerant is cranked up, we'll try anyway.
@@ -1056,7 +1057,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)DECLARE_BITMAP (toclear,MAX_NR_BANKS );DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );char *msg ="Unknown" ; -int lmce =0 ; + +/* +* MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES +* on Intel. +*/ +int lmce =1 ;/* If this CPU is offline, just bail out. */ if (cpu_is_offline (smp_processor_id ())) {
@@ -1095,19 +1101,20 @@ void do_machine_check(struct pt_regs *regs, long error_code) kill_it =1 ;/* -* Check if this MCE is signaled to only this logical processor +* Check if this MCE is signaled to only this logical processor, +* on Intel only. */ -if (m.mcgstatus &MCG_STATUS_LMCES ) - lmce =1 ; -else { -/* -* Go through all the banks in exclusion of the other CPUs. -* This way we don't report duplicated events on shared banks -* because the first one to see it will clear it. -* If this is a Local MCE, then no need to perform rendezvous. -*/ +if (m.cpuvendor ==X86_VENDOR_INTEL ) + lmce = m.mcgstatus &MCG_STATUS_LMCES ; + +/* +* Go through all banks in exclusion of the other CPUs. This way we +* don't report duplicated events on shared banks because the first one +* to see it will clear it. If this is a Local MCE, then no need to +* perform rendezvous. +*/ +if (!lmce) order =mce_start (&no_way_out); - }for (i =0 ; i < cfg->banks; i++) {__clear_bit (i, toclear);
Signature · 1 line
2.7.3
tip-bot for Yazen Ghannam
merge bot[tip:ras/core] x86/mce: Detect local MCEs properly
x86/mce: Detect local MCEs properly
Commit-ID: fead35c68926682c90c995f22b48f1c8d78865c1 Gitweb: http://git.kernel.org/tip/fead35c68926682c90c995f22b48f1c8d78865c1 Author: Yazen Ghannam <[email protected]> AuthorDate: Sat, 30 Apr 2016 14:33:57 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 3 May 2016 08:24:17 +0200
x86/mce: Detect local MCEs properly
Check the MCG_STATUS_LMCES bit on Intel to verify that current MCE is local. It is always local on AMD.
--- arch/x86/kernel/cpu/mcheck/mce.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-)
arch/x86/kernel/cpu/mcheck/mce.c +20 -13
@@ -1038,11 +1038,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)int i;int worst =0 ;int severity; +/* * Establish sequential order between the CPUs entering the machine * check handler. */ -int order; +int order =-1 ;/* * If no_way_out gets set, there is no safe way to recover from this * MCE. If mca_cfg.tolerant is cranked up, we'll try anyway.
@@ -1056,7 +1057,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)DECLARE_BITMAP (toclear,MAX_NR_BANKS );DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );char *msg ="Unknown" ; -int lmce =0 ; + +/* +* MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES +* on Intel. +*/ +int lmce =1 ;/* If this CPU is offline, just bail out. */ if (cpu_is_offline (smp_processor_id ())) {
@@ -1095,19 +1101,20 @@ void do_machine_check(struct pt_regs *regs, long error_code) kill_it =1 ;/* -* Check if this MCE is signaled to only this logical processor +* Check if this MCE is signaled to only this logical processor, +* on Intel only. */ -if (m.mcgstatus &MCG_STATUS_LMCES ) - lmce =1 ; -else { -/* -* Go through all the banks in exclusion of the other CPUs. -* This way we don't report duplicated events on shared banks -* because the first one to see it will clear it. -* If this is a Local MCE, then no need to perform rendezvous. -*/ +if (m.cpuvendor ==X86_VENDOR_INTEL ) + lmce = m.mcgstatus &MCG_STATUS_LMCES ; + +/* +* Go through all banks in exclusion of the other CPUs. This way we +* don't report duplicated events on shared banks because the first one +* to see it will clear it. If this is a Local MCE, then no need to +* perform rendezvous. +*/ +if (!lmce) order =mce_start (&no_way_out); - }for (i =0 ; i < cfg->banks; i++) {__clear_bit (i, toclear);