diff options
-rw-r--r-- | xen/arch/x86/cpu/mcheck/amd_f10.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/cpu/mcheck/mce_amd_quirks.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/cpu/mcheck/mce_quirks.h | 5 | ||||
-rw-r--r-- | xen/include/asm-x86/msr-index.h | 4 |
4 files changed, 21 insertions, 2 deletions
diff --git a/xen/arch/x86/cpu/mcheck/amd_f10.c b/xen/arch/x86/cpu/mcheck/amd_f10.c index 18e6c071e5..1dab7d046f 100644 --- a/xen/arch/x86/cpu/mcheck/amd_f10.c +++ b/xen/arch/x86/cpu/mcheck/amd_f10.c @@ -46,6 +46,7 @@ #include <asm/msr.h> #include "mce.h" +#include "mce_quirks.h" #include "x86_mca.h" @@ -85,9 +86,14 @@ amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status) /* AMD Family10 machine check */ enum mcheck_type amd_f10_mcheck_init(struct cpuinfo_x86 *c) { + enum mcequirk_amd_flags quirkflag = mcequirk_lookup_amd_quirkdata(c); + if (amd_k8_mcheck_init(c) == mcheck_none) return mcheck_none; + if (quirkflag == MCEQUIRK_F10_GART) + mcequirk_amd_apply(quirkflag); + x86_mce_callback_register(amd_f10_handler); return mcheck_amd_famXX; diff --git a/xen/arch/x86/cpu/mcheck/mce_amd_quirks.c b/xen/arch/x86/cpu/mcheck/mce_amd_quirks.c index 2067c7cda6..7da525c10f 100644 --- a/xen/arch/x86/cpu/mcheck/mce_amd_quirks.c +++ b/xen/arch/x86/cpu/mcheck/mce_amd_quirks.c @@ -29,6 +29,8 @@ static const struct mce_quirkdata mce_amd_quirks[] = { MCEQUIRK_K7_BANK0 }, { 0xf /* cpu family */, ANY /* all models */, ANY /* all steppings */, MCEQUIRK_K8_GART }, + { 0x10 /* cpu family */, ANY /* all models */, ANY /* all steppings */, + MCEQUIRK_F10_GART }, }; enum mcequirk_amd_flags @@ -54,6 +56,8 @@ mcequirk_lookup_amd_quirkdata(struct cpuinfo_x86 *c) int mcequirk_amd_apply(enum mcequirk_amd_flags flags) { + u64 val; + switch (flags) { case MCEQUIRK_K7_BANK0: return 1; /* first bank */ @@ -67,6 +71,10 @@ int mcequirk_amd_apply(enum mcequirk_amd_flags flags) wrmsrl(MSR_IA32_MC4_CTL, ~(1ULL << 10)); wrmsrl(MSR_IA32_MC4_STATUS, 0ULL); break; + case MCEQUIRK_F10_GART: + if (rdmsr_safe(MSR_AMD64_MCx_MASK(4), val) == 0) + wrmsr_safe(MSR_AMD64_MCx_MASK(4), val | (1 << 10)); + break; } return 0; diff --git a/xen/arch/x86/cpu/mcheck/mce_quirks.h b/xen/arch/x86/cpu/mcheck/mce_quirks.h index 055ba3b504..a33bddfb73 100644 --- a/xen/arch/x86/cpu/mcheck/mce_quirks.h +++ b/xen/arch/x86/cpu/mcheck/mce_quirks.h @@ -33,8 +33,9 @@ struct mce_quirkdata { */ enum mcequirk_amd_flags { - MCEQUIRK_K7_BANK0 = 0x1, - MCEQUIRK_K8_GART = 0x2, + MCEQUIRK_K7_BANK0 = 1, + MCEQUIRK_K8_GART, + MCEQUIRK_F10_GART }; enum mcequirk_intel_flags { diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h index 03fe835085..3d54e2ca24 100644 --- a/xen/include/asm-x86/msr-index.h +++ b/xen/include/asm-x86/msr-index.h @@ -98,6 +98,8 @@ #define CMCI_EN (1UL<<30) #define CMCI_THRESHOLD_MASK 0x7FFF +#define MSR_AMD64_MC0_MASK 0xc0010044 + #define MSR_IA32_MC1_CTL 0x00000404 #define MSR_IA32_MC1_CTL2 0x00000281 #define MSR_IA32_MC1_STATUS 0x00000405 @@ -151,6 +153,8 @@ #define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) #define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + #define MSR_P6_PERFCTR0 0x000000c1 #define MSR_P6_PERFCTR1 0x000000c2 #define MSR_P6_EVNTSEL0 0x00000186 |