[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4AC05D48.1000007@jp.fujitsu.com>
Date: Mon, 28 Sep 2009 15:52:56 +0900
From: Hidetoshi Seto <seto.hidetoshi@...fujitsu.com>
To: Huang Ying <ying.huang@...el.com>
CC: Ingo Molnar <mingo@...e.hu>, "H. Peter Anvin" <hpa@...or.com>,
Andi Kleen <ak@...ux.intel.com>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: [PATCH 3/5] mce-inject: make injected mce valid only during faked
handler call
In the current implementation, injected MCE is valid from the point
the MCE is injected to the point the MCE is processed by the faked
handler call.
This has an undesired side-effect: it is possible for it to be
consumed by real machine_check_poll. This may confuse a real system
error and may confuse the mce test suite.
To fix this, this patch changes mce_rdmsrl/wemsrl() to refer injected
data only when injectm.valid states 3rd state "2", which indicates that
the injected MCE entry is valid and ready for the handler.
The injectm.valid becomes "2" only during faked MCE handler call
and protected by IRQ disabling. This make it impossible for real
machine_check_poll to consume it.
Reported-by: Huang Ying <ying.huang@...el.com>
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@...fujitsu.com>
---
arch/x86/include/asm/mce.h | 2 +-
arch/x86/kernel/cpu/mcheck/mce-inject.c | 17 +++++++++++++++--
arch/x86/kernel/cpu/mcheck/mce.c | 4 ++--
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 995dfd2..fd9c3ca 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -63,7 +63,7 @@ struct mce {
__u8 cs; /* code segment */
__u8 bank; /* machine check bank */
__u8 cpu; /* cpu number; obsolete; use extcpu now */
- __u8 valid; /* entry is valid */
+ __u8 valid; /* 1: entry is valid, 2: valid as fake (injectm) */
__u32 extcpu; /* linux cpu number that detected the error */
__u32 socketid; /* CPU socket ID */
__u32 apicid; /* CPU initial apic ID */
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 5bac818..702f712 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -50,10 +50,12 @@ static void raise_poll(struct mce *m)
mce_banks_t b;
memset(&b, 0xff, sizeof(mce_banks_t));
+
local_irq_save(flags);
+ m->valid = 2;
machine_check_poll(0, &b);
- local_irq_restore(flags);
m->valid = 0;
+ local_irq_restore(flags);
}
static void raise_exception(struct mce *m, struct pt_regs *pregs)
@@ -67,11 +69,13 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs)
regs.cs = m->cs;
pregs = ®s;
}
+
/* in mcheck exeception handler, irq will be disabled */
local_irq_save(flags);
+ m->valid = 2;
do_machine_check(pregs, 0);
- local_irq_restore(flags);
m->valid = 0;
+ local_irq_restore(flags);
}
static cpumask_t mce_inject_cpumask;
@@ -82,13 +86,19 @@ static int mce_raise_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int cpu = smp_processor_id();
struct mce *m = &__get_cpu_var(injectm);
+
if (val != DIE_NMI_IPI || !cpu_isset(cpu, mce_inject_cpumask))
return NOTIFY_DONE;
cpu_clear(cpu, mce_inject_cpumask);
+
+ if (!m->valid)
+ return NOTIFY_STOP;
+
if (m->inject_flags & MCE_INJ_EXCEPTION)
raise_exception(m, args->regs);
else if (m->status)
raise_poll(m);
+
return NOTIFY_STOP;
}
@@ -105,6 +115,9 @@ static int raise_local(void)
int ret = 0;
int cpu = m->extcpu;
+ if (!m->valid)
+ return 0;
+
if (m->inject_flags & MCE_INJ_EXCEPTION) {
printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu);
switch (context) {
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ac4f478..aeab37a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -306,7 +306,7 @@ static u64 mce_rdmsrl(u32 msr)
{
u64 v;
- if (__get_cpu_var(injectm).valid) {
+ if (__get_cpu_var(injectm).valid > 1) {
int offset = msr_to_offset(msr);
if (offset < 0)
@@ -329,7 +329,7 @@ static u64 mce_rdmsrl(u32 msr)
static void mce_wrmsrl(u32 msr, u64 v)
{
- if (__get_cpu_var(injectm).valid) {
+ if (__get_cpu_var(injectm).valid > 1) {
int offset = msr_to_offset(msr);
if (offset >= 0)
--
1.6.4.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists