]> xenbits.xensource.com Git - xen.git/commitdiff
x86 mce: Change the method to get the extended MCA information.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 7 Jun 2010 14:46:48 +0000 (15:46 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 7 Jun 2010 14:46:48 +0000 (15:46 +0100)
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 <yunhong.jiang@inte.com>
xen/arch/x86/cpu/mcheck/amd_f10.c
xen/arch/x86/cpu/mcheck/mce.c
xen/arch/x86/cpu/mcheck/mce.h
xen/arch/x86/cpu/mcheck/mce_intel.c

index 18e6c071e5db91928e2fb80dd8961f2bae6a69bd..420bc41c6e140fa7b054d259add732f32edfdb77 100644 (file)
 #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 */
index b5222795ebc607b225c0dcae79eebfc1595f811f..b08299892587a0c94f86a9e21c775d1bffeb0ca7 100644 (file)
@@ -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)
index c4301140b6cc1c970a72daa9407121388e30072b..4c557356120e14284fd3ae0738ea2830f539f472 100644 (file)
@@ -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);
 
index 21c756c366fc95db020a58c5909cf45b74c81365..fbd4f41c58a5f5b48876e0a77401b57cbb680fdf 100644 (file)
@@ -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);