Mailing List Archive

[xen-unstable] x86 mce: Change the method to get the extended MCA information.
# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1275922008 -3600
# Node ID b704a2e22fd672136817e3ad8b0e5aa6f146bc93
# Parent b9d824ff0bbc9fe12c947ee994b9a8d1a3dbeb65
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 <yunhong.jiang@inte.com>
---
xen/arch/x86/cpu/mcheck/amd_f10.c | 42 ++++++++++++----------
xen/arch/x86/cpu/mcheck/mce.c | 15 +++++---
xen/arch/x86/cpu/mcheck/mce.h | 8 ----
xen/arch/x86/cpu/mcheck/mce_intel.c | 67 ++++++++++++++++--------------------
4 files changed, 67 insertions(+), 65 deletions(-)

diff -r b9d824ff0bbc -r b704a2e22fd6 xen/arch/x86/cpu/mcheck/amd_f10.c
--- a/xen/arch/x86/cpu/mcheck/amd_f10.c Mon Jun 07 15:45:56 2010 +0100
+++ b/xen/arch/x86/cpu/mcheck/amd_f10.c Mon Jun 07 15:46:48 2010 +0100
@@ -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;
+ 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 = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_extended));
+ if (!mc_ext)
+ {
+ mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
+ return NULL;
+ }

- 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;
+ 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;

- 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;
+ 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 -r b9d824ff0bbc -r b704a2e22fd6 xen/arch/x86/cpu/mcheck/mce.c
--- a/xen/arch/x86/cpu/mcheck/mce.c Mon Jun 07 15:45:56 2010 +0100
+++ b/xen/arch/x86/cpu/mcheck/mce.c Mon Jun 07 15:46:48 2010 +0100
@@ -229,7 +229,6 @@ mctelem_cookie_t mcheck_mca_logout(enum
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
/* 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

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 -r b9d824ff0bbc -r b704a2e22fd6 xen/arch/x86/cpu/mcheck/mce.h
--- a/xen/arch/x86/cpu/mcheck/mce.h Mon Jun 07 15:45:56 2010 +0100
+++ b/xen/arch/x86/cpu/mcheck/mce.h Mon Jun 07 15:46:48 2010 +0100
@@ -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 @@ typedef int (*mce_need_clearbank_t)(enum
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 -r b9d824ff0bbc -r b704a2e22fd6 xen/arch/x86/cpu/mcheck/mce_intel.c
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c Mon Jun 07 15:45:56 2010 +0100
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Mon Jun 07 15:46:48 2010 +0100
@@ -155,52 +155,48 @@ static inline void intel_get_extended_ms
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 mc_ext;
-
- if (mci == NULL || nr_intel_ext_msrs == 0 || !(status & MCG_STATUS_EIPV))
- return MCA_EXTINFO_IGNORED;
+
+struct mcinfo_extended *
+intel_get_extended_msrs(struct mcinfo_global *mig, struct mc_info *mi)
+{
+ 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;
+
+ 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,
@@ -960,7 +956,6 @@ enum mcheck_type intel_mcheck_init(struc

/* 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);


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog