RAS changes for v4.7
Subsystems (3)
Linus,
Please pull the latest ras-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git ras-core-for-linus
# HEAD: 754a92305980b1fecffe033dd3fdc49c37f8e4b0 x86/RAS: Add SMCA support to AMD Error Injector
Main changes in this cycle were:
- AMD MCE/RAS handling updates (Yazen Ghannam, Aravind Gopalakrishnan)
- Cleanups (Borislav Petkov)
- logging fix (Tony Luck)
Thanks,
Ingo
------------------>
Aravind Gopalakrishnan (3):
x86/mce: Log MCEs after a warm rest on AMD, Fam17h and later x86/mce: Grade uncorrected errors for SMCA-enabled systems x86/mce: Carve out writes to MCx_STATUS and MCx_CTL
Borislav Petkov (2):
x86/RAS: Rename AMD MCE injector config item x86/mce/AMD: Save an indentation level in prepare_threshold_block()
Davidlohr Bueso (1):
x86/mce: Remove explicit smp_rmb() when starting CPUs sync
Tony Luck (1):
x86/mce: Look in genpool instead of mcelog for pending error records
Yazen Ghannam (9):
x86/mce: Define vendor-specific MSR accessors
x86/mce: Detect and use SMCA-specific msr_ops
x86/mce: Detect local MCEs properly
x86/mce/AMD: Log Deferred Errors using SMCA MCA_DE{STAT,ADDR} registers x86/mce/AMD: Disable LogDeferredInMcaStat for SMCA systems x86/cpu: Add detection of AMD RAS Capabilities
x86/mce: Update AMD mcheck init to use cpu_has() facilities EDAC, mce_amd: Detect SMCA using X86_FEATURE_SMCA
x86/RAS: Add SMCA support to AMD Error Injector
arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/cpufeatures.h | 7 +- arch/x86/include/asm/mce.h | 19 ++++ arch/x86/kernel/cpu/common.c | 10 +- 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 | 160 +++++++++++++++++++++--------- arch/x86/kernel/cpu/mcheck/mce_amd.c | 94 ++++++++++++------ arch/x86/ras/Kconfig | 2 +- arch/x86/ras/Makefile | 2 +- arch/x86/ras/mce_amd_inj.c | 31 ++++-- drivers/edac/mce_amd.c | 9 +- 13 files changed, 331 insertions(+), 95 deletions(-)
arch/x86/include/asm/cpufeature.h +1 -0
@@ -27,6 +27,7 @@ enum cpuid_leafsCPUID_6_EAX ,CPUID_8000_000A_EDX ,CPUID_7_ECX , + CPUID_8000_0007_EBX, };#ifdef CONFIG_X86_FEATURE_NAMES
arch/x86/include/asm/cpufeatures.h +6 -1
@@ -12,7 +12,7 @@/* * Defines x86 CPU feature bits */ -#define NCAPINTS 17/* N 32-bit words worth of info */ +#define NCAPINTS 18/* N 32-bit words worth of info */ #define NBUGINTS 1/* N 32-bit bug flags */ /*
@@ -280,6 +280,11 @@#define X86_FEATURE_PKU (16*32+ 3)/* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (16*32+ 4)/* OS Protection Keys Enable */ +/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ +#define X86_FEATURE_OVERFLOW_RECOV (17*32+0)/* MCA overflow recovery support */ +#define X86_FEATURE_SUCCOR (17*32+1)/* Uncorrectable error containment and recovery */ +#define X86_FEATURE_SMCA (17*32+3)/* Scalable MCA */ +/* * BUG word(s) */
arch/x86/include/asm/mce.h +19 -0
@@ -104,13 +104,23 @@#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_DESTAT 0xc0002008 +#define MSR_AMD64_SMCA_MC0_DEADDR 0xc0002009#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)) +#define MSR_AMD64_SMCA_MCx_DESTAT (x) (MSR_AMD64_SMCA_MC0_DESTAT + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_DEADDR (x) (MSR_AMD64_SMCA_MC0_DEADDR + 0x10*(x))#define MSR_AMD64_SMCA_MCx_MISCy (x, y) ((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x)))/*
@@ -168,9 +178,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/common.c +7 -3
@@ -717,6 +717,13 @@ void get_cpu_cap(struct cpuinfo_x86 *c) } } +if (c->extended_cpuid_level >=0x80000007 ) { +cpuid (0x80000007 , &eax, &ebx, &ecx, &edx); + + c->x86_capability[CPUID_8000_0007_EBX ] = ebx; + c->x86_power = edx; + } +if (c->extended_cpuid_level >=0x80000008 ) {cpuid (0x80000008 , &eax, &ebx, &ecx, &edx);
@@ -729,9 +736,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_phys_bits =36 ;#endif -if (c->extended_cpuid_level >=0x80000007 ) - c->x86_power =cpuid_edx (0x80000007 ); -if (c->extended_cpuid_level >=0x8000000a ) c->x86_capability[CPUID_8000_000A_EDX ] =cpuid_edx (0x8000000a );
arch/x86/kernel/cpu/mcheck/mce-genpool.c +46 -0
52 lines not on this page · raw message
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-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 ;
arch/x86/kernel/cpu/mcheck/mce.c +113 -47
336 lines not on this page · raw message
arch/x86/kernel/cpu/mcheck/mce_amd.c +64 -30
161 lines not on this page · raw message
arch/x86/ras/Kconfig +1 -1
@@ -1,4 +1,4 @@ -config AMD_MCE_INJ +config MCE_AMD_INJ tristate "Simple MCE injection interface for AMD processors" depends on RAS && EDAC_DECODE_MCE && DEBUG_FS && AMD_NB default n
arch/x86/ras/Makefile +1 -1
@@ -1,2 +1,2 @@ -obj-$(CONFIG_AMD_MCE_INJ) += mce_amd_inj.o +obj-$(CONFIG_MCE_AMD_INJ) += mce_amd_inj.o
arch/x86/ras/mce_amd_inj.c +25 -6
@@ -290,14 +290,33 @@ static void do_inject(void)wrmsr_on_cpu (cpu,MSR_IA32_MCG_STATUS , (u32 )mcg_status, (u32)(mcg_status >>32 )); -wrmsr_on_cpu (cpu,MSR_IA32_MCx_STATUS (b), - (u32 )i_mce.status, (u32)(i_mce.status >>32 )); +if (boot_cpu_has (X86_FEATURE_SMCA )) { +if (inj_type ==DFR_INT_INJ ) { +wrmsr_on_cpu (cpu,MSR_AMD64_SMCA_MCx_DESTAT (b), + (u32 )i_mce.status, (u32)(i_mce.status >>32 )); + +wrmsr_on_cpu (cpu,MSR_AMD64_SMCA_MCx_DEADDR (b), + (u32 )i_mce.addr, (u32)(i_mce.addr >>32 )); + }else { +wrmsr_on_cpu (cpu,MSR_AMD64_SMCA_MCx_STATUS (b), + (u32 )i_mce.status, (u32)(i_mce.status >>32 )); + +wrmsr_on_cpu (cpu,MSR_AMD64_SMCA_MCx_ADDR (b), + (u32 )i_mce.addr, (u32)(i_mce.addr >>32 )); + } + +wrmsr_on_cpu (cpu,MSR_AMD64_SMCA_MCx_MISC (b), + (u32 )i_mce.misc, (u32)(i_mce.misc >>32 )); + }else { +wrmsr_on_cpu (cpu,MSR_IA32_MCx_STATUS (b), + (u32 )i_mce.status, (u32)(i_mce.status >>32 )); -wrmsr_on_cpu (cpu,MSR_IA32_MCx_ADDR (b), - (u32 )i_mce.addr, (u32)(i_mce.addr >>32 )); +wrmsr_on_cpu (cpu,MSR_IA32_MCx_ADDR (b), + (u32 )i_mce.addr, (u32)(i_mce.addr >>32 )); -wrmsr_on_cpu (cpu,MSR_IA32_MCx_MISC (b), - (u32 )i_mce.misc, (u32)(i_mce.misc >>32 )); +wrmsr_on_cpu (cpu,MSR_IA32_MCx_MISC (b), + (u32 )i_mce.misc, (u32)(i_mce.misc >>32 )); + }toggle_hw_mce_inject (cpu, false);
drivers/edac/mce_amd.c +3 -6
@@ -1052,7 +1052,6 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)struct mce *m = (struct mce *)data;struct cpuinfo_x86 *c = &cpu_data (m->extcpu);int ecc; -u32 ebx =cpuid_ebx (0x80000007 );if (amd_filter_mce (m))return NOTIFY_STOP ;
@@ -1075,7 +1074,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) ((m->status &MCI_STATUS_DEFERRED ) ?"Deferred" :"-" ), ((m->status & MCI_STATUS_POISON) ? "Poison" : "-")); -if (!!(ebx &BIT (3 ))) { +if (boot_cpu_has (X86_FEATURE_SMCA )) {u32 low, high;u32 addr =MSR_AMD64_SMCA_MCx_CONFIG (m->bank);
@@ -1094,7 +1093,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)if (m->status &MCI_STATUS_ADDRV )pr_emerg (HW_ERR "MC%d Error Address: 0x%016llx\n" , m->bank, m->addr); -if (!!(ebx &BIT (3 ))) { +if (boot_cpu_has (X86_FEATURE_SMCA )) {decode_smca_errors (m); goto err_code; }
@@ -1149,7 +1148,6 @@ static struct notifier_block amd_mce_dec_nb = {static int __init mce_amd_init (void ) {struct cpuinfo_x86 *c = &boot_cpu_data; -u32 ebx;if (c->x86_vendor !=X86_VENDOR_AMD )return -ENODEV ;
@@ -1205,9 +1203,8 @@ static int __init mce_amd_init(void)break ;case 0x17 : - ebx =cpuid_ebx (0x80000007 ); xec_mask =0x3f ; -if (!(ebx &BIT (3 ))) { +if (!boot_cpu_has (X86_FEATURE_SMCA )) {printk (KERN_WARNING "Decoding supported only on Scalable MCA processors.\n" ); goto err_out; }