Add MCE broadcast checkiing.
Some platform will broadcast MCE to all logical processor, while some platform
will not. Distinguish these platforms will be helpful for unified MCA handler.
the "mce_fb" is a option to emulate the broadcast MCA in non-broadcast
platform. This is mainly for MCA software trigger.
Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>
diff -r afbebac312e8 xen/arch/x86/cpu/mcheck/mce.c
--- a/xen/arch/x86/cpu/mcheck/mce.c Wed Jan 27 20:52:41 2010 +0800
+++ b/xen/arch/x86/cpu/mcheck/mce.c Wed Jan 27 22:58:15 2010 +0800
@@ -25,10 +25,12 @@
int mce_disabled;
invbool_param("mce", mce_disabled);
-
+static int mce_force_broadcast;
+boolean_param("mce_fb", mce_force_broadcast);
int is_mc_panic;
unsigned int nr_mce_banks;
+int mce_broadcast = 0;
static uint64_t g_mcg_cap;
/* Real value in physical CTL MSR */
@@ -588,6 +590,21 @@ int mce_available(struct cpuinfo_x86 *c)
return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
}
+static int mce_is_broadcast(struct cpuinfo_x86 *c)
+{
+ if (mce_force_broadcast)
+ return 1;
+
+ /* According to Intel SDM Dec, 2009, 15.10.4.1, For processors with
+ * DisplayFamily_DisplayModel encoding of 06H_EH and above,
+ * a MCA signal is broadcast to all logical processors in the system
+ */
+ if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6 &&
+ c->x86_model >= 0xe)
+ return 1;
+ return 0;
+}
+
/*
* Check if bank 0 is usable for MCE. It isn't for AMD K7,
* and Intel P6 family before model 0x1a.
@@ -608,12 +625,23 @@ int mce_firstbank(struct cpuinfo_x86 *c)
/* This has to be run for each processor */
void mcheck_init(struct cpuinfo_x86 *c)
{
- int inited = 0, i;
+ int inited = 0, i, broadcast;
+ static int broadcast_check;
if (mce_disabled == 1) {
- printk(XENLOG_INFO "MCE support disabled by bootparam\n");
+ dprintk(XENLOG_INFO, "MCE support disabled by bootparam\n");
return;
}
+
+ broadcast = mce_is_broadcast(c);
+ if (broadcast_check && (broadcast != mce_broadcast) )
+ dprintk(XENLOG_INFO,
+ "CPUs have mixed broadcast support"
+ "may cause undetermined result!!!\n");
+
+ broadcast_check = 1;
+ if (broadcast)
+ mce_broadcast = broadcast;
for (i = 0; i < MAX_NR_BANKS; i++)
set_bit(i,mca_allbanks);
@@ -1542,14 +1570,17 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
if (target >= NR_CPUS)
return x86_mcerr("do_mca #MC: bad target", -EINVAL);
-
+
if (!cpu_isset(target, cpu_online_map))
return x86_mcerr("do_mca #MC: target offline", -EINVAL);
add_taint(TAINT_ERROR_INJECT);
- on_selected_cpus(cpumask_of(target), x86_mc_mceinject,
- mc_mceinject, 1);
+ if ( mce_broadcast )
+ on_each_cpu(x86_mc_mceinject, mc_mceinject, 0);
+ else
+ on_selected_cpus(cpumask_of(target), x86_mc_mceinject,
+ mc_mceinject, 1);
break;
default:
diff -r afbebac312e8 xen/arch/x86/cpu/mcheck/mce.h
--- a/xen/arch/x86/cpu/mcheck/mce.h Wed Jan 27 20:52:41 2010 +0800
+++ b/xen/arch/x86/cpu/mcheck/mce.h Wed Jan 27 20:52:46 2010 +0800
@@ -121,6 +121,7 @@ extern int cmci_support;
extern int cmci_support;
extern int ser_support;
extern int is_mc_panic;
+extern int mce_broadcast;
extern void mcheck_mca_clearbanks(cpu_banks_t);
extern mctelem_cookie_t mcheck_mca_logout(enum mca_source, cpu_banks_t,
diff -r afbebac312e8 xen/arch/x86/cpu/mcheck/mce_intel.c
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c Wed Jan 27 20:52:41 2010 +0800
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Wed Jan 27 20:52:46 2010 +0800
@@ -612,6 +612,8 @@ static void mce_barrier_enter(struct mce
{
int gen;
+ if (!mce_broadcast)
+ return;
atomic_inc(&bar->ingen);
gen = atomic_read(&bar->outgen);
mb();
@@ -627,6 +629,8 @@ static void mce_barrier_exit(struct mce_
{
int gen;
+ if (!mce_broadcast)
+ return;
atomic_inc(&bar->outgen);
gen = atomic_read(&bar->ingen);
mb();
broadcast.patch
Description: broadcast.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|