[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4ACECE47.3080004@jp.fujitsu.com>
Date: Fri, 09 Oct 2009 14:46:47 +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 4/4] mce-inject: support injecting multiple error to a CPU
There is only one register set in structure mce_fake_banks, so
we cannot inject more than one event to a CPU. For example, we
cannot emulate situation that bank 1 of CPU X has a error while
bank 3 of same CPU X has an another error.
This patch make mce_fake_banks to have a list of register set,
and allow us to test more various error combination.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@...fujitsu.com>
---
arch/x86/include/asm/mce.h | 6 +++++
arch/x86/kernel/cpu/mcheck/mce-inject.c | 32 +++++++++++++++++++++++++++---
arch/x86/kernel/cpu/mcheck/mce.c | 22 ++++++++++++++------
3 files changed, 49 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 0668044..8776ab1 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -244,6 +244,12 @@ struct mce_fake_banks {
__u8 inject_flags; /* software inject flags */
+ struct list_head list;
+};
+
+struct mce_fake_bank {
+ struct list_head list;
+ __u8 loaded;
__u8 bank;
__u64 status;
__u64 misc;
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 6275318..943fc93 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -29,15 +29,30 @@
static void inject_mce(struct mce *m)
{
struct mce_fake_banks *banks = &per_cpu(mce_fake_banks, m->extcpu);
+ struct mce_fake_bank *b, *temp;
banks->mcgstatus = m->mcgstatus;
banks->ip = m->ip;
banks->cs = m->cs;
banks->inject_flags = m->inject_flags;
- banks->bank = m->bank;
- banks->status = m->status;
- banks->addr = m->addr;
- banks->misc = m->misc;
+
+ list_for_each_entry(temp, &banks->list, list) {
+ if (temp->bank == m->bank)
+ b = temp;
+ }
+ if (!b) {
+ b = kzalloc(sizeof(struct mce_fake_bank), GFP_KERNEL);
+ if (!b)
+ return; /* -ENOMEM */
+ INIT_LIST_HEAD(&b->list);
+ b->bank = m->bank;
+ list_add(&b->list, &banks->list);
+ }
+
+ b->status = m->status;
+ b->addr = m->addr;
+ b->misc = m->misc;
+ b->loaded = 1;
mb();
banks->loaded = 1;
@@ -45,6 +60,15 @@ static void inject_mce(struct mce *m)
static void clean_injected(struct mce_fake_banks *banks)
{
+ struct mce_fake_bank *b;
+
+ list_for_each_entry(b, &banks->list, list) {
+ /*
+ * Might be in NMI context, so avoid doing kfree here.
+ * Allocated fake bank will be reused in next injections.
+ */
+ b->loaded = 0;
+ }
banks->loaded = 0;
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index edd2a82..327c72d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -303,19 +303,26 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
static u64 *mce_get_fake_reg(u32 msr)
{
- unsigned bank = __get_cpu_var(mce_fake_banks).bank;
+ struct mce_fake_bank *b;
if (msr == rip_msr)
return &__get_cpu_var(mce_fake_banks).ip;
- if (msr == MSR_IA32_MCx_STATUS(bank))
- return &__get_cpu_var(mce_fake_banks).status;
- if (msr == MSR_IA32_MCx_ADDR(bank))
- return &__get_cpu_var(mce_fake_banks).addr;
- if (msr == MSR_IA32_MCx_MISC(bank))
- return &__get_cpu_var(mce_fake_banks).misc;
if (msr == MSR_IA32_MCG_STATUS)
return &__get_cpu_var(mce_fake_banks).mcgstatus;
+ list_for_each_entry(b, &__get_cpu_var(mce_fake_banks).list, list) {
+ unsigned bank = b->bank;
+
+ if (!b->loaded)
+ continue;
+ if (msr == MSR_IA32_MCx_STATUS(bank))
+ return &b->status;
+ if (msr == MSR_IA32_MCx_ADDR(bank))
+ return &b->addr;
+ if (msr == MSR_IA32_MCx_MISC(bank))
+ return &b->misc;
+ }
+
return NULL;
}
@@ -1456,6 +1463,7 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
mce_cpu_features(c);
mce_init_timer();
INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
+ INIT_LIST_HEAD(&__get_cpu_var(mce_fake_banks).list);
}
/*
--
1.6.2.2
--
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