From 9d13fd9fd320a7740c6446c048ff6a2990095966 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 7 Jun 2010 15:46:48 +0100 Subject: [PATCH] x86 mce: Change the method to get the extended MCA information. Several changes to get the extended MCA information: a) Use the x86_mcinfo_reserve in mcinfo_extended to reserve buffer from mc_info, instead of using the stack b) For intel's extended MSR, we don't need write them one by one as the MSR are continous c) We don't need enum mca_extinfo, since we can consider the extended MSR as either per bank, or global. Currently we add a hook in global data collection, and didn't call register intel_get_extended_msrs as callback. Later that hook can be replaced by cleaner way Signed-off-by: Jiang, Yunhong --- xen/arch/x86/cpu/mcheck/amd_f10.c | 48 +++++++++++++---------- xen/arch/x86/cpu/mcheck/mce.c | 15 +++++-- xen/arch/x86/cpu/mcheck/mce.h | 8 +--- xen/arch/x86/cpu/mcheck/mce_intel.c | 61 +++++++++++++---------------- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/xen/arch/x86/cpu/mcheck/amd_f10.c b/xen/arch/x86/cpu/mcheck/amd_f10.c index 18e6c071e5..420bc41c6e 100644 --- a/xen/arch/x86/cpu/mcheck/amd_f10.c +++ b/xen/arch/x86/cpu/mcheck/amd_f10.c @@ -49,37 +49,43 @@ #include "x86_mca.h" -static enum mca_extinfo +static struct mcinfo_extended * amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status) { - struct mcinfo_extended mc_ext; + struct mcinfo_extended *mc_ext; /* Family 0x10 introduced additional MSR that belong to the * northbridge bank (4). */ if (mi == NULL || bank != 4) - return MCA_EXTINFO_IGNORED; + return NULL; if (!(status & MCi_STATUS_VAL)) - return MCA_EXTINFO_IGNORED; + return NULL; if (!(status & MCi_STATUS_MISCV)) - return MCA_EXTINFO_IGNORED; - - memset(&mc_ext, 0, sizeof(mc_ext)); - mc_ext.common.type = MC_TYPE_EXTENDED; - mc_ext.common.size = sizeof(mc_ext); - mc_ext.mc_msrs = 3; - - mc_ext.mc_msr[0].reg = MSR_F10_MC4_MISC1; - mc_ext.mc_msr[1].reg = MSR_F10_MC4_MISC2; - mc_ext.mc_msr[2].reg = MSR_F10_MC4_MISC3; - - mca_rdmsrl(MSR_F10_MC4_MISC1, mc_ext.mc_msr[0].value); - mca_rdmsrl(MSR_F10_MC4_MISC2, mc_ext.mc_msr[1].value); - mca_rdmsrl(MSR_F10_MC4_MISC3, mc_ext.mc_msr[2].value); - - x86_mcinfo_add(mi, &mc_ext); - return MCA_EXTINFO_LOCAL; + return NULL; + + mc_ext = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_extended)); + if (!mc_ext) + { + mi->flags |= MCINFO_FLAGS_UNCOMPLETE; + return NULL; + } + + memset(mc_ext, 0, sizeof(mc_ext)); + mc_ext->common.type = MC_TYPE_EXTENDED; + mc_ext->common.size = sizeof(mc_ext); + mc_ext->mc_msrs = 3; + + mc_ext->mc_msr[0].reg = MSR_F10_MC4_MISC1; + mc_ext->mc_msr[1].reg = MSR_F10_MC4_MISC2; + mc_ext->mc_msr[2].reg = MSR_F10_MC4_MISC3; + + mca_rdmsrl(MSR_F10_MC4_MISC1, mc_ext->mc_msr[0].value); + mca_rdmsrl(MSR_F10_MC4_MISC2, mc_ext->mc_msr[1].value); + mca_rdmsrl(MSR_F10_MC4_MISC3, mc_ext->mc_msr[2].value); + + return mc_ext; } /* AMD Family10 machine check */ diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c index b5222795eb..b082998925 100644 --- a/xen/arch/x86/cpu/mcheck/mce.c +++ b/xen/arch/x86/cpu/mcheck/mce.c @@ -229,7 +229,6 @@ mctelem_cookie_t mcheck_mca_logout(enum mca_source who, cpu_banks_t bankmask, mctelem_class_t which = MC_URGENT; /* XXXgcc */ int errcnt = 0; int i; - enum mca_extinfo cbret = MCA_EXTINFO_IGNORED; mca_rdmsrl(MSR_IA32_MCG_STATUS, gstatus); switch (who) { @@ -291,6 +290,15 @@ mctelem_cookie_t mcheck_mca_logout(enum mca_source who, cpu_banks_t bankmask, /* mc_info should at least hold up the global information */ ASSERT(mig); mca_init_global(mc_flags, mig); + /* A hook here to get global extended msrs */ + { + struct mcinfo_extended *intel_get_extended_msrs( + struct mcinfo_global *mig, struct mc_info *mi); + + if (boot_cpu_data.x86_vendor == + X86_VENDOR_INTEL) + intel_get_extended_msrs(mig, mci); + } } } @@ -309,9 +317,8 @@ mctelem_cookie_t mcheck_mca_logout(enum mca_source who, cpu_banks_t bankmask, mib = mca_init_bank(who, mci, i); - if (mc_callback_bank_extended && cbret != MCA_EXTINFO_GLOBAL) { - cbret = mc_callback_bank_extended(mci, i, status); - } + if (mc_callback_bank_extended) + mc_callback_bank_extended(mci, i, status); /* By default, need_clear = 1 */ if (who != MCA_MCE_SCAN && need_clear) diff --git a/xen/arch/x86/cpu/mcheck/mce.h b/xen/arch/x86/cpu/mcheck/mce.h index c4301140b6..4c55735612 100644 --- a/xen/arch/x86/cpu/mcheck/mce.h +++ b/xen/arch/x86/cpu/mcheck/mce.h @@ -110,12 +110,6 @@ enum mca_source { MCA_MCE_SCAN }; -enum mca_extinfo { - MCA_EXTINFO_LOCAL, - MCA_EXTINFO_GLOBAL, - MCA_EXTINFO_IGNORED -}; - struct mca_summary { uint32_t errcnt; /* number of banks with valid errors */ int ripv; /* meaningful on #MC */ @@ -157,7 +151,7 @@ extern mctelem_cookie_t mcheck_mca_logout(enum mca_source, cpu_banks_t, typedef int (*mce_need_clearbank_t)(enum mca_source who, u64 status); extern void mce_need_clearbank_register(mce_need_clearbank_t); -typedef enum mca_extinfo (*x86_mce_callback_t) +typedef struct mcinfo_extended *(*x86_mce_callback_t) (struct mc_info *, uint16_t, uint64_t); extern void x86_mce_callback_register(x86_mce_callback_t); diff --git a/xen/arch/x86/cpu/mcheck/mce_intel.c b/xen/arch/x86/cpu/mcheck/mce_intel.c index 21c756c366..fbd4f41c58 100644 --- a/xen/arch/x86/cpu/mcheck/mce_intel.c +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c @@ -155,53 +155,49 @@ static inline void intel_get_extended_msr(struct mcinfo_extended *ext, u32 msr) if ( ext->mc_msrs < ARRAY_SIZE(ext->mc_msr) && msr < MSR_IA32_MCG_EAX + nr_intel_ext_msrs ) { ext->mc_msr[ext->mc_msrs].reg = msr; - mca_rdmsrl(msr, ext->mc_msr[ext->mc_msrs].value); + rdmsrl(msr, ext->mc_msr[ext->mc_msrs].value); ++ext->mc_msrs; } } -static enum mca_extinfo -intel_get_extended_msrs(struct mc_info *mci, uint16_t bank, uint64_t status) + +struct mcinfo_extended * +intel_get_extended_msrs(struct mcinfo_global *mig, struct mc_info *mi) { - struct mcinfo_extended mc_ext; + struct mcinfo_extended *mc_ext; + int i; + + /* + * According to spec, processor _support_ 64 bit will always + * have MSR beyond IA32_MCG_MISC + */ + if (!mi|| !mig || nr_intel_ext_msrs == 0 || + !(mig->mc_gstatus & MCG_STATUS_EIPV)) + return NULL; - if (mci == NULL || nr_intel_ext_msrs == 0 || !(status & MCG_STATUS_EIPV)) - return MCA_EXTINFO_IGNORED; + mc_ext = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_extended)); + if (!mc_ext) + { + mi->flags |= MCINFO_FLAGS_UNCOMPLETE; + return NULL; + } /* this function will called when CAP(9).MCG_EXT_P = 1 */ memset(&mc_ext, 0, sizeof(struct mcinfo_extended)); - mc_ext.common.type = MC_TYPE_EXTENDED; - mc_ext.common.size = sizeof(mc_ext); - - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EAX); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EBX); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_ECX); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EDX); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_ESI); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EDI); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EBP); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_ESP); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EFLAGS); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_EIP); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_MISC); + mc_ext->common.type = MC_TYPE_EXTENDED; + mc_ext->common.size = sizeof(struct mcinfo_extended); + + for (i = MSR_IA32_MCG_EAX; i <= MSR_IA32_MCG_MISC; i++) + intel_get_extended_msr(mc_ext, i); #ifdef __x86_64__ - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R8); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R9); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R10); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R11); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R12); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R13); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R14); - intel_get_extended_msr(&mc_ext, MSR_IA32_MCG_R15); + for (i = MSR_IA32_MCG_R8; i <= MSR_IA32_MCG_R15; i++) + intel_get_extended_msr(mc_ext, i); #endif - x86_mcinfo_add(mci, &mc_ext); - - return MCA_EXTINFO_GLOBAL; + return mc_ext; } - static void intel_UCR_handler(struct mcinfo_bank *bank, struct mcinfo_global *global, struct mcinfo_extended *extension, @@ -960,7 +956,6 @@ enum mcheck_type intel_mcheck_init(struct cpuinfo_x86 *c) /* machine check is available */ x86_mce_vector_register(intel_machine_check); - x86_mce_callback_register(intel_get_extended_msrs); mce_recoverable_register(intel_recoverable_scan); mce_need_clearbank_register(intel_need_clearbank_scan); -- 2.39.5