* x86 Machine check 32bit merge series
@ 2009-05-26 23:17 Andi Kleen
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
0 siblings, 1 reply; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:17 UTC (permalink / raw)
To: linux-kernel, x86, hpa
Machine checks are CPU errors which can be handled by the OS.
Here's an updated x86 machine check 32bit<->64bit merge series. It allows
to use the much superior (ok I am biased...) 64bit machine check code
on 32bit systems too.
It also contains the basic machine check injector code because
that was needed for testing.
I had this in the original mce patchkit, but dropped it later, but maintainers
requested to redo it.
This was available for some time on my git tree on kernel.org, but
I'm reposting it now for final merge.
This is based on the mce3 branch in
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git
which is a version of x86/mce2 branch from tip that actually compiles/works and
is rebased on 2.6.30rc7.
This is all ready to merge.
Merging would be:
Pull in mce3
Apply this patch series on top of it
(or pull it from
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git mce3-32bitmerge
)
then apply the following mce improvements series or
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git mce3-improvements
-Andi
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean
2009-05-26 23:17 x86 Machine check 32bit merge series Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 02/17] x86: MCE: Implement the PPro bank 0 quirk in the 64bit machine check code Andi Kleen
` (15 more replies)
0 siblings, 16 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Replace unsigned long with u64s if they need to contain 64bit values.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 868c6a2..08ffe55 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -156,15 +156,15 @@ static void print_mce(struct mce *m)
"and contact your hardware vendor\n");
}
-static void mce_panic(char *msg, struct mce *backup, unsigned long start)
+static void mce_panic(char *msg, struct mce *backup, u64 start)
{
int i;
oops_begin();
for (i = 0; i < MCE_LOG_LEN; i++) {
- unsigned long tsc = mcelog.entry[i].tsc;
+ u64 tsc = mcelog.entry[i].tsc;
- if (time_before(tsc, start))
+ if ((s64)(tsc - start) < 0)
continue;
print_mce(&mcelog.entry[i]);
if (backup && mcelog.entry[i].tsc == backup->tsc)
@@ -971,13 +971,13 @@ void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
static ssize_t show_ ## name(struct sys_device *s, \
struct sysdev_attribute *attr, \
char *buf) { \
- return sprintf(buf, "%lx\n", (unsigned long)var); \
+ return sprintf(buf, "%Lx\n", (u64)var); \
} \
static ssize_t set_ ## name(struct sys_device *s, \
struct sysdev_attribute *attr, \
const char *buf, size_t siz) { \
char *end; \
- unsigned long new = simple_strtoul(buf, &end, 0); \
+ u64 new = simple_strtoull(buf, &end, 0); \
\
if (end == buf) \
return -EINVAL; \
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 02/17] x86: MCE: Implement the PPro bank 0 quirk in the 64bit machine check code
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 03/17] x86: MCE: Port K7 bank 0 quirk to 64bit mce code Andi Kleen
` (14 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Quoting the comment:
* SDM documents that on family 6 bank 0 should not be written
* because it aliases to another special BIOS controlled
* register.
* But it's not aliased anymore on model 0x1a+
* Don't ignore bank 0 completely because there could be a valid
* event later, merely don't write CTL0.
This is mostly a port on the 32bit code, except that 32bit
always didn't write it and didn't have the 0x1a heuristic. I checked
with the CPU designers that the quirk is not required starting with
this model.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 40 ++++++++++++++++++++++++++++++++-----
1 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 08ffe55..89c9d6b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -65,6 +65,8 @@ static atomic_t mce_events;
static char trigger[128];
static char *trigger_argv[2] = { trigger, NULL };
+static unsigned long dont_init_banks;
+
static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
/* MCA banks polled by the period polling timer for corrected events */
@@ -72,6 +74,11 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
[0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
};
+static inline int skip_bank_init(int i)
+{
+ return i < BITS_PER_LONG && test_bit(i, &dont_init_banks);
+}
+
/* Do initial initialization of a struct mce */
void mce_setup(struct mce *m)
{
@@ -617,6 +624,8 @@ static void mce_init(void *dummy)
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
for (i = 0; i < banks; i++) {
+ if (skip_bank_init(i))
+ continue;
wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
}
@@ -644,6 +653,19 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
}
}
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ /*
+ * SDM documents that on family 6 bank 0 should not be written
+ * because it aliases to another special BIOS controlled
+ * register.
+ * But it's not aliased anymore on model 0x1a+
+ * Don't ignore bank 0 completely because there could be a
+ * valid event later, merely don't write CTL0.
+ */
+
+ if (c->x86 == 6 && c->x86_model < 0x1A)
+ __set_bit(0, &dont_init_banks);
+ }
}
static void mce_cpu_features(struct cpuinfo_x86 *c)
@@ -912,8 +934,10 @@ static int mce_disable(void)
{
int i;
- for (i = 0; i < banks; i++)
- wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+ for (i = 0; i < banks; i++) {
+ if (!skip_bank_init(i))
+ wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+ }
return 0;
}
@@ -1124,8 +1148,10 @@ static void mce_disable_cpu(void *h)
return;
if (!(action & CPU_TASKS_FROZEN))
cmci_clear();
- for (i = 0; i < banks; i++)
- wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+ for (i = 0; i < banks; i++) {
+ if (!skip_bank_init(i))
+ wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+ }
}
static void mce_reenable_cpu(void *h)
@@ -1138,8 +1164,10 @@ static void mce_reenable_cpu(void *h)
if (!(action & CPU_TASKS_FROZEN))
cmci_reenable();
- for (i = 0; i < banks; i++)
- wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+ for (i = 0; i < banks; i++) {
+ if (!skip_bank_init(i))
+ wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+ }
}
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 03/17] x86: MCE: Port K7 bank 0 quirk to 64bit mce code
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
2009-05-26 23:18 ` [PATCH 02/17] x86: MCE: Implement the PPro bank 0 quirk in the 64bit machine check code Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 04/17] x86: MCE: Use a call vector to call the 64bit mce handler Andi Kleen
` (13 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Various K7 have broken bank 0s. Don't enable it by default
Port from the 32bit code.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 89c9d6b..26048b5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -651,6 +651,12 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
*/
mce_bootlog = 0;
}
+ /*
+ * Various K7s with broken bank 0 around. Always disable
+ * by default.
+ */
+ if (c->x86 == 6)
+ bank[0] = 0;
}
if (c->x86_vendor == X86_VENDOR_INTEL) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 04/17] x86: MCE: Use a call vector to call the 64bit mce handler
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
2009-05-26 23:18 ` [PATCH 02/17] x86: MCE: Implement the PPro bank 0 quirk in the 64bit machine check code Andi Kleen
2009-05-26 23:18 ` [PATCH 03/17] x86: MCE: Port K7 bank 0 quirk to 64bit mce code Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 05/17] x86: MCE: Rename 64bit mce_dont_init to mce_disabled Andi Kleen
` (12 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Allows to call different machine check handlers from the low
level machine check entry vector.
This is needed for later when it will be used for 32bit too.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 23 ++++++++++++-----------
arch/x86/kernel/cpu/mcheck/mce.h | 3 ++-
arch/x86/kernel/entry_64.S | 2 +-
3 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 26048b5..13ba422 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -39,6 +39,16 @@
#include "mce.h"
+/* Handle unconfigured int18 (should never happen) */
+static void unexpected_machine_check(struct pt_regs *regs, long error_code)
+{
+ printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
+ smp_processor_id());
+}
+
+/* Call the installed machine check handler for this CPU setup. */
+void (*machine_check_vector)(struct pt_regs *, long error_code) =
+ unexpected_machine_check;
#ifdef CONFIG_X86_64
#define MISC_MCELOG_MINOR 227
@@ -716,6 +726,8 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
}
mce_cpu_quirks(c);
+ machine_check_vector = do_machine_check;
+
mce_init(NULL);
mce_cpu_features(c);
mce_init_timer();
@@ -1290,17 +1302,6 @@ int mce_disabled;
int nr_mce_banks;
EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
-/* Handle unconfigured int18 (should never happen) */
-static void unexpected_machine_check(struct pt_regs *regs, long error_code)
-{
- printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
- smp_processor_id());
-}
-
-/* Call the installed machine check handler for this CPU setup. */
-void (*machine_check_vector)(struct pt_regs *, long error_code) =
- unexpected_machine_check;
-
/* This has to be run for each processor */
void mcheck_init(struct cpuinfo_x86 *c)
{
diff --git a/arch/x86/kernel/cpu/mcheck/mce.h b/arch/x86/kernel/cpu/mcheck/mce.h
index 6c763de..def7e34 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.h
+++ b/arch/x86/kernel/cpu/mcheck/mce.h
@@ -7,11 +7,12 @@ extern void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
extern void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
extern void winchip_mcheck_init(struct cpuinfo_x86 *c);
-#ifdef CONFIG_X86_32
/* Call the installed machine check handler for this CPU setup. */
extern void (*machine_check_vector)(struct pt_regs *, long error_code);
+#ifdef CONFIG_X86_32
+
extern int nr_mce_banks;
extern void intel_set_thermal_handler(void);
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 38946c6..63276c4 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1382,7 +1382,7 @@ paranoiderrorentry stack_segment do_stack_segment
errorentry general_protection do_general_protection
errorentry page_fault do_page_fault
#ifdef CONFIG_X86_MCE
-paranoidzeroentry machine_check do_machine_check
+paranoidzeroentry machine_check *machine_check_vector(%rip)
#endif
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 05/17] x86: MCE: Rename 64bit mce_dont_init to mce_disabled
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (2 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 04/17] x86: MCE: Use a call vector to call the 64bit mce handler Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 06/17] x86: MCE: Move mce_disabled option into common 64bit/64bit code Andi Kleen
` (11 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Give it the same name as on 32bit. This makes further merging easier.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/include/asm/mce.h | 4 ----
arch/x86/kernel/cpu/mcheck/mce.c | 15 +++++++--------
2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 84b405d..ca79ee8 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -86,11 +86,7 @@ struct mce_log {
#ifdef __KERNEL__
-#ifdef CONFIG_X86_32
extern int mce_disabled;
-#else /* CONFIG_X86_32 */
-#endif /* !CONFIG_X86_32 */
-
#include <asm/atomic.h>
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 13ba422..9bbdd11 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -49,14 +49,15 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code)
/* Call the installed machine check handler for this CPU setup. */
void (*machine_check_vector)(struct pt_regs *, long error_code) =
unexpected_machine_check;
+
+int mce_disabled;
+
#ifdef CONFIG_X86_64
#define MISC_MCELOG_MINOR 227
atomic_t mce_entry;
-static int mce_dont_init;
-
/*
* Tolerant levels:
* 0: always panic on uncorrected errors, log corrected errors
@@ -194,7 +195,7 @@ static void mce_panic(char *msg, struct mce *backup, u64 start)
int mce_available(struct cpuinfo_x86 *c)
{
- if (mce_dont_init)
+ if (mce_disabled)
return 0;
return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
}
@@ -721,7 +722,7 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
return;
if (mce_cap_init() < 0) {
- mce_dont_init = 1;
+ mce_disabled = 1;
return;
}
mce_cpu_quirks(c);
@@ -912,7 +913,7 @@ static struct miscdevice mce_log_device = {
*/
static int __init mcheck_disable(char *str)
{
- mce_dont_init = 1;
+ mce_disabled = 1;
return 1;
}
__setup("nomce", mcheck_disable);
@@ -926,7 +927,7 @@ __setup("nomce", mcheck_disable);
static int __init mcheck_enable(char *str)
{
if (!strcmp(str, "off"))
- mce_dont_init = 1;
+ mce_disabled = 1;
else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog"))
mce_bootlog = (str[0] == 'b');
else if (isdigit(str[0]))
@@ -1297,8 +1298,6 @@ device_initcall(mce_init_device);
#else /* CONFIG_X86_32: */
-int mce_disabled;
-
int nr_mce_banks;
EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 06/17] x86: MCE: Move mce_disabled option into common 64bit/64bit code
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (3 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 05/17] x86: MCE: Rename 64bit mce_dont_init to mce_disabled Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 07/17] x86: MCE: Remove machine check handler idle notify on 64bit Andi Kleen
` (10 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
It's the same function, so let's share it.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 29 +++++++++++------------------
1 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 9bbdd11..68c3329 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -909,16 +909,6 @@ static struct miscdevice mce_log_device = {
};
/*
- * Old style boot options parsing. Only for compatibility.
- */
-static int __init mcheck_disable(char *str)
-{
- mce_disabled = 1;
- return 1;
-}
-__setup("nomce", mcheck_disable);
-
-/*
* mce=off disables machine check
* mce=TOLERANCELEVEL (number, see above)
* mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
@@ -1346,19 +1336,22 @@ void __init restart_mce(void)
set_in_cr4(X86_CR4_MCE);
}
-static int __init mcheck_disable(char *str)
-{
- mce_disabled = 1;
- return 1;
-}
-
static int __init mcheck_enable(char *str)
{
mce_disabled = -1;
return 1;
}
-__setup("nomce", mcheck_disable);
__setup("mce", mcheck_enable);
-#endif /* CONFIG_X86_32 */
+#endif /* CONFIG_X86_OLD_MCE */
+
+/*
+ * Old style boot options parsing. Only for compatibility.
+ */
+static int __init mcheck_disable(char *str)
+{
+ mce_disabled = 1;
+ return 1;
+}
+__setup("nomce", mcheck_disable);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 07/17] x86: MCE: Remove machine check handler idle notify on 64bit
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (4 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 06/17] x86: MCE: Move mce_disabled option into common 64bit/64bit code Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 08/17] x86: MCE: Remove oops_begin() use in 64bit machine check Andi Kleen
` (9 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
i386 has no idle notifiers, but the 64bit machine check
code uses them to wake up mcelog from a fatal machine check
exception.
For corrected machine checks found by the poller or
threshold interrupts going through an idle notifier is not needed
because the wake_up can is just done directly and doesn't
need the idle notifier. It is only needed for logging
exceptions.
To be honest I never liked the idle notifier even though I signed
off on it. On closer investigation the code actually turned out
to be nearly. Right now machine check exceptions on x86 are always
unrecoverable (lead to panic due to PCC), which means we never execute
the idle notifier path.
The only exception is the somewhat weird tolerant==3 case, which
ignores PCC. I'll fix this in a future patch in a much cleaner way.
So remove the "mcelog wakeup through idle notifier" code
from 64bit.
This allows to compile the 64bit machine check handler on 32bit
which doesn't have idle notifiers.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 23 -----------------------
1 files changed, 0 insertions(+), 23 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 68c3329..60acee3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -555,29 +555,6 @@ int mce_notify_user(void)
return 0;
}
-/* see if the idle task needs to notify userspace: */
-static int
-mce_idle_callback(struct notifier_block *nfb, unsigned long action,
- void *unused)
-{
- /* IDLE_END should be safe - interrupts are back on */
- if (action == IDLE_END && test_thread_flag(TIF_MCE_NOTIFY))
- mce_notify_user();
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block mce_idle_notifier = {
- .notifier_call = mce_idle_callback,
-};
-
-static __init int periodic_mcheck_init(void)
-{
- idle_notifier_register(&mce_idle_notifier);
- return 0;
-}
-__initcall(periodic_mcheck_init);
-
/*
* Initialize Machine Checks for a CPU.
*/
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 08/17] x86: MCE: Remove oops_begin() use in 64bit machine check
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (5 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 07/17] x86: MCE: Remove machine check handler idle notify on 64bit Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 09/17] x86: MCE: Remove unused stop/restart_mce on 32bit Andi Kleen
` (8 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
First 32bit doesn't have oops_begin, so it's a barrier of using
this code on 32bit.
On closer examination it turns out oops_begin is not
a good idea in a machine check panic anyways. All oops_begin
does it so check for recursive/parallel oopses and implement the
"wait on oops" heuristic. But there's actually no good reason
to lock machine checks against oopses or prevent them
from recursion. Also "wait on oops" does not really make
sense for a machine check too.
Replace it with a manual bust_spinlocks/console_verbose.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 60acee3..b9463b3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -178,7 +178,8 @@ static void mce_panic(char *msg, struct mce *backup, u64 start)
{
int i;
- oops_begin();
+ bust_spinlocks(1);
+ console_verbose();
for (i = 0; i < MCE_LOG_LEN; i++) {
u64 tsc = mcelog.entry[i].tsc;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 09/17] x86: MCE: Remove unused stop/restart_mce on 32bit
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (6 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 08/17] x86: MCE: Remove oops_begin() use in 64bit machine check Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 10/17] x86: MCE: Use 64bit machine check code " Andi Kleen
` (7 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
The calls for those got removed some time ago, so just remove
the functions too.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 14 --------------
1 files changed, 0 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b9463b3..62b863a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1300,20 +1300,6 @@ void mcheck_init(struct cpuinfo_x86 *c)
printk(KERN_INFO "mce: CPU supports %d MCE banks\n", nr_mce_banks);
}
-static unsigned long old_cr4 __initdata;
-
-void __init stop_mce(void)
-{
- old_cr4 = read_cr4();
- clear_in_cr4(X86_CR4_MCE);
-}
-
-void __init restart_mce(void)
-{
- if (old_cr4 & X86_CR4_MCE)
- set_in_cr4(X86_CR4_MCE);
-}
-
static int __init mcheck_enable(char *str)
{
mce_disabled = -1;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 10/17] x86: MCE: Use 64bit machine check code on 32bit
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (7 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 09/17] x86: MCE: Remove unused stop/restart_mce on 32bit Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 11/17] x86: MCE: Deprecate old 32bit machine check code Andi Kleen
` (6 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
The 64bit machine check code is in many ways much better than
the 32bit machine check code: it is more specification compliant,
is cleaner, only has a single code base versus one per CPU,
has better infrastructure for recovery, has a cleaner way to communicate
with user space etc. etc.
Use the 64bit code for 32bit too.
This is the second attempt to do this. There was one a couple of years
ago to unify this code for 32bit and 64bit. Back then this ran into some
trouble with K7s and was reverted.
I believe this time the K7 problems (and some others) are addressed.
I went over the old handlers and was very careful to retain
all quirks.
But of course this needs a lot of testing on old systems. On newer
64bit capable systems I don't expect much problems because they have been
already tested with the 64bit kernel.
I made this a CONFIG for now that still allows to select the old
machine check code. This is mostly to make testing easier,
if someone runs into a problem we can ask them to try
with the CONFIG switched.
The new code is default y for more coverage.
Once there is confidence the 64bit code works well on older hardware
too the CONFIG_X86_OLD_MCE and the associated code can be easily
removed.
This causes a behaviour change for 32bit installations. They now
have to install the mcelog package to be able to log
corrected machine checks.
The 64bit machine check code only handles CPUs which support the
standard Intel machine check architecture described in the IA32 SDM.
The 32bit code has special support for some older CPUs which
have non standard machine check architectures, in particular
WinChip C3 and Intel P5. I made those a separate CONFIG option
and kept them for now. The WinChip variant could be probably
removed without too much pain, it doesn't really do anything
interesting. P5 is also disabled by default (like it
was before) because many motherboards have it miswired, but
according to Alan Cox a few embedded setups use that one.
Forward ported/heavily changed version of old patch, original patch
included review/fixes from Thomas Gleixner, Bert Wesarg.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/Kconfig | 33 +++++++++++++++++++++++++++++++--
arch/x86/include/asm/entry_arch.h | 2 +-
arch/x86/kernel/apic/apic.c | 4 ++--
arch/x86/kernel/apic/nmi.c | 2 +-
arch/x86/kernel/cpu/mcheck/Makefile | 3 ++-
arch/x86/kernel/cpu/mcheck/mce.c | 32 ++++++++++++++++++++++++++++----
arch/x86/kernel/cpu/mcheck/mce.h | 18 +++++++++++++++---
arch/x86/kernel/cpu/mcheck/p5.c | 5 +++++
arch/x86/kernel/irq.c | 4 ++--
arch/x86/kernel/irqinit_32.c | 2 +-
arch/x86/kernel/signal.c | 4 ++--
arch/x86/kernel/traps.c | 4 ++--
12 files changed, 92 insertions(+), 21 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a6efe0a..c1c5ccd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -789,6 +789,22 @@ config X86_MCE
to disable it. MCE support simply ignores non-MCE processors like
the 386 and 486, so nearly everyone can say Y here.
+config X86_OLD_MCE
+ depends on X86_32 && X86_MCE
+ bool "Use legacy machine check code (will go away)"
+ default n
+ select X86_ANCIENT_MCE
+ ---help---
+ Use the old i386 machine check code. This is merely intended for
+ testing in a transition period. Try this if you run into any machine
+ check related software problems, but report the problem to
+ linux-kernel. When in doubt say no.
+
+config X86_NEW_MCE
+ depends on X86_MCE
+ bool
+ default y if (!X86_OLD_MCE && X86_32) || X86_64
+
config X86_MCE_INTEL
def_bool y
prompt "Intel MCE features"
@@ -805,6 +821,15 @@ config X86_MCE_AMD
Additional support for AMD specific MCE features such as
the DRAM Error Threshold.
+config X86_ANCIENT_MCE
+ def_bool n
+ depends on X86_32
+ prompt "Support for old Pentium 5 / WinChip machine checks"
+ ---help---
+ Include support for machine check handling on old Pentium 5 or WinChip
+ systems. These typically need to be enabled explicitely on the command
+ line.
+
config X86_MCE_THRESHOLD
depends on X86_MCE_AMD || X86_MCE_INTEL
bool
@@ -812,7 +837,7 @@ config X86_MCE_THRESHOLD
config X86_MCE_NONFATAL
tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
- depends on X86_32 && X86_MCE
+ depends on X86_OLD_MCE
---help---
Enabling this feature starts a timer that triggers every 5 seconds which
will look at the machine check registers to see if anything happened.
@@ -825,11 +850,15 @@ config X86_MCE_NONFATAL
config X86_MCE_P4THERMAL
bool "check for P4 thermal throttling interrupt."
- depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP)
+ depends on X86_OLD_MCE && X86_MCE && (X86_UP_APIC || SMP)
---help---
Enabling this feature will cause a message to be printed when the P4
enters thermal throttling.
+config X86_THERMAL_VECTOR
+ def_bool y
+ depends on X86_MCE_P4THERMAL || X86_MCE_INTEL
+
config VM86
bool "Enable VM86 support" if EMBEDDED
default y
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index c2e6bed..486c9e9 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -52,7 +52,7 @@ BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR)
#endif
-#ifdef CONFIG_X86_MCE_P4THERMAL
+#ifdef CONFIG_X86_THERMAL_VECTOR
BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
#endif
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f287092..ad53228 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -843,7 +843,7 @@ void clear_local_APIC(void)
}
/* lets not touch this if we didn't frob it */
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
if (maxlvt >= 5) {
v = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
@@ -1962,7 +1962,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
if (maxlvt >= 5)
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
#endif
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index ce4fbfa..c476227 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -66,7 +66,7 @@ static inline unsigned int get_nmi_count(int cpu)
static inline int mce_in_progress(void)
{
-#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
+#if defined(CONFIG_X86_NEW_MCE)
return atomic_read(&mce_entry) > 0;
#endif
return 0;
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index 55f01b3..5f8b094 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -1,6 +1,7 @@
obj-y = mce.o therm_throt.o
-obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o
+obj-$(CONFIG_X86_OLD_MCE) += k7.o p4.o p6.o
+obj-$(CONFIG_X86_ANCIENT_MCE) += winchip.o p5.o
obj-$(CONFIG_X86_MCE_P4THERMAL) += mce_intel.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o mce_intel.o
obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 62b863a..a3c8bd0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -52,7 +52,7 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) =
int mce_disabled;
-#ifdef CONFIG_X86_64
+#ifdef CONFIG_X86_NEW_MCE
#define MISC_MCELOG_MINOR 227
@@ -663,6 +663,21 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
}
}
+static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
+{
+ if (c->x86 != 5)
+ return;
+ switch (c->x86_vendor) {
+ case X86_VENDOR_INTEL:
+ if (mce_p5_enabled())
+ intel_p5_mcheck_init(c);
+ break;
+ case X86_VENDOR_CENTAUR:
+ winchip_mcheck_init(c);
+ break;
+ }
+}
+
static void mce_cpu_features(struct cpuinfo_x86 *c)
{
switch (c->x86_vendor) {
@@ -696,6 +711,11 @@ static void mce_init_timer(void)
*/
void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
{
+ if (mce_disabled)
+ return;
+
+ mce_ancient_init(c);
+
if (!mce_available(c))
return;
@@ -894,6 +914,10 @@ static struct miscdevice mce_log_device = {
*/
static int __init mcheck_enable(char *str)
{
+ if (*str == 0)
+ enable_p5_mce();
+ if (*str == '=')
+ str++;
if (!strcmp(str, "off"))
mce_disabled = 1;
else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog"))
@@ -901,13 +925,13 @@ static int __init mcheck_enable(char *str)
else if (isdigit(str[0]))
get_option(&str, &tolerant);
else {
- printk(KERN_INFO "mce= argument %s ignored. Please use /sys\n",
+ printk(KERN_INFO "mce argument %s ignored. Please use /sys\n",
str);
return 0;
}
return 1;
}
-__setup("mce=", mcheck_enable);
+__setup("mce", mcheck_enable);
/*
* Sysfs support
@@ -1264,7 +1288,7 @@ static __init int mce_init_device(void)
device_initcall(mce_init_device);
-#else /* CONFIG_X86_32: */
+#else /* CONFIG_X86_OLD_MCE: */
int nr_mce_banks;
EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.h b/arch/x86/kernel/cpu/mcheck/mce.h
index def7e34..2326284 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.h
+++ b/arch/x86/kernel/cpu/mcheck/mce.h
@@ -1,17 +1,29 @@
#include <linux/init.h>
#include <asm/mce.h>
+#ifdef CONFIG_X86_OLD_MCE
extern void amd_mcheck_init(struct cpuinfo_x86 *c);
extern void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
-extern void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
extern void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
-extern void winchip_mcheck_init(struct cpuinfo_x86 *c);
+#endif
+#ifdef CONFIG_X86_ANCIENT_MCE
+extern void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
+extern void winchip_mcheck_init(struct cpuinfo_x86 *c);
+extern int mce_p5_enable;
+static inline int mce_p5_enabled(void) { return mce_p5_enable; }
+static inline void enable_p5_mce(void) { mce_p5_enable = 1; }
+#else
+static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline int mce_p5_enabled(void) { return 0; }
+static inline void enable_p5_mce(void) { }
+#endif
/* Call the installed machine check handler for this CPU setup. */
extern void (*machine_check_vector)(struct pt_regs *, long error_code);
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_OLD_MCE
extern int nr_mce_banks;
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
index 8812f54..015f481 100644
--- a/arch/x86/kernel/cpu/mcheck/p5.c
+++ b/arch/x86/kernel/cpu/mcheck/p5.c
@@ -14,6 +14,9 @@
#include "mce.h"
+/* By default disabled */
+int mce_p5_enable;
+
/* Machine check handler for Pentium class Intel CPUs: */
static void pentium_machine_check(struct pt_regs *regs, long error_code)
{
@@ -44,9 +47,11 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
if (!cpu_has(c, X86_FEATURE_MCE))
return;
+#ifdef CONFIG_X86_OLD_MCE
/* Default P5 to off as its often misconnected: */
if (mce_disabled != -1)
return;
+#endif
machine_check_vector = pentium_machine_check;
/* Make sure the vector pointer is visible before we enable MCEs: */
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index c3fe010..35eddc9 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -89,7 +89,7 @@ static int show_other_interrupts(struct seq_file *p, int prec)
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
seq_printf(p, " Thermal event interrupts\n");
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
seq_printf(p, "%*s: ", prec, "THR");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
@@ -176,7 +176,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
#endif
#ifdef CONFIG_X86_MCE
sum += irq_stats(cpu)->irq_thermal_count;
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
sum += irq_stats(cpu)->irq_threshold_count;
#endif
#endif
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index 368b0a8..98846e0 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -181,7 +181,7 @@ void __init native_init_IRQ(void)
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
#endif
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
/* thermal monitor LVT interrupt */
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 1442516..d0851e3 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -25,11 +25,11 @@
#include <asm/ucontext.h>
#include <asm/i387.h>
#include <asm/vdso.h>
+#include <asm/mce.h>
#ifdef CONFIG_X86_64
#include <asm/proto.h>
#include <asm/ia32_unistd.h>
-#include <asm/mce.h>
#endif /* CONFIG_X86_64 */
#include <asm/syscall.h>
@@ -857,7 +857,7 @@ static void do_signal(struct pt_regs *regs)
void
do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
{
-#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
+#ifdef CONFIG_X86_NEW_MCE
/* notify userspace of pending MCEs */
if (thread_info_flags & _TIF_MCE_NOTIFY)
mce_notify_user();
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index a1d2883..ad771f1 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -798,7 +798,8 @@ unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
return new_kesp;
}
-#else
+#endif
+
asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
{
}
@@ -806,7 +807,6 @@ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
{
}
-#endif
/*
* 'math_state_restore()' saves the current math information in the
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 11/17] x86: MCE: Deprecate old 32bit machine check code
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (8 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 10/17] x86: MCE: Use 64bit machine check code " Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 12/17] x86: MCE: Enable MCE_INTEL for 32bit new MCE Andi Kleen
` (5 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Schedule for removal in 2.6.32
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
Documentation/feature-removal-schedule.txt | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index de491a3..f5ba352 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -437,3 +437,13 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate
driver but this caused driver conflicts.
Who: Jean Delvare <khali@linux-fr.org>
Krzysztof Helt <krzysztof.h1@wp.pl>
+
+----------------------------
+
+What: CONFIG_X86_OLD_MCE
+When: 2.6.32
+Why: Remove the old legacy 32bit machine check code. This has been
+ superseded by the newer machine check code from the 64bit port,
+ but the old version has been kept around for easier testing. Note this
+ doesn't impact the old P5 and WinChip machine check handlers.
+Who: Andi Kleen <andi@firstfloor.org>
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 12/17] x86: MCE: Enable MCE_INTEL for 32bit new MCE
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (9 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 11/17] x86: MCE: Deprecate old 32bit machine check code Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 13/17] x86: MCE: Enable MCE_AMD for 32bit NEW_MCE Andi Kleen
` (4 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Enable the 64bit MCE_INTEL code (CMCI, thermal interrupts) for 32bit NEW_MCE.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/Kconfig | 2 +-
arch/x86/include/asm/entry_arch.h | 4 ++++
arch/x86/include/asm/hardirq.h | 2 +-
arch/x86/include/asm/irq_vectors.h | 5 +++--
arch/x86/kernel/cpu/mcheck/threshold.c | 2 +-
arch/x86/kernel/entry_64.S | 2 +-
arch/x86/kernel/irqinit_32.c | 4 ++++
arch/x86/kernel/traps.c | 2 +-
8 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c1c5ccd..e1c9f77 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -808,7 +808,7 @@ config X86_NEW_MCE
config X86_MCE_INTEL
def_bool y
prompt "Intel MCE features"
- depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ depends on X86_NEW_MCE && X86_LOCAL_APIC
---help---
Additional support for intel specific MCE features such as
the thermal monitor.
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 486c9e9..b2eb9c0 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -56,4 +56,8 @@ BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR)
BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
+BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR)
+#endif
+
#endif
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 37555e5..922ee7c 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -20,7 +20,7 @@ typedef struct {
#endif
#ifdef CONFIG_X86_MCE
unsigned int irq_thermal_count;
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
unsigned int irq_threshold_count;
# endif
#endif
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 3cbd79b..451e24d 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -87,10 +87,11 @@
#define CALL_FUNCTION_SINGLE_VECTOR 0xfb
#define THERMAL_APIC_VECTOR 0xfa
+#define THRESHOLD_APIC_VECTOR 0xf9
+
#ifdef CONFIG_X86_32
-/* 0xf8 - 0xf9 : free */
+/* 0xf9 : free */
#else
-# define THRESHOLD_APIC_VECTOR 0xf9
# define UV_BAU_MESSAGE 0xf8
#endif
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
index 23ee9e7..d746df2 100644
--- a/arch/x86/kernel/cpu/mcheck/threshold.c
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -17,7 +17,7 @@ static void default_threshold_interrupt(void)
void (*mce_threshold_vector)(void) = default_threshold_interrupt;
-asmlinkage void mce_threshold_interrupt(void)
+asmlinkage void smp_threshold_interrupt(void)
{
exit_idle();
irq_enter();
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 63276c4..a31a7f2 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1007,7 +1007,7 @@ apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
#endif
apicinterrupt THRESHOLD_APIC_VECTOR \
- threshold_interrupt mce_threshold_interrupt
+ threshold_interrupt smp_threshold_interrupt
apicinterrupt THERMAL_APIC_VECTOR \
thermal_interrupt smp_thermal_interrupt
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index 98846e0..2512ad9 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -186,6 +186,10 @@ void __init native_init_IRQ(void)
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
+ alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
+#endif
+
if (!acpi_ioapic)
setup_irq(2, &irq2);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index ad771f1..0d358c8 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -804,7 +804,7 @@ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
{
}
-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
{
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 13/17] x86: MCE: Enable MCE_AMD for 32bit NEW_MCE
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (10 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 12/17] x86: MCE: Enable MCE_INTEL for 32bit new MCE Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 14/17] x86: MCE: Document new 32bit mcelog requirement in Documentation/Changes Andi Kleen
` (3 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
That's very easy using the infrastructure enabled earlier for MCE_INTEL
Untested.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/Kconfig | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e1c9f77..a148e7a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -816,7 +816,7 @@ config X86_MCE_INTEL
config X86_MCE_AMD
def_bool y
prompt "AMD MCE features"
- depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ depends on X86_NEW_MCE && X86_LOCAL_APIC
---help---
Additional support for AMD specific MCE features such as
the DRAM Error Threshold.
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 14/17] x86: MCE: Document new 32bit mcelog requirement in Documentation/Changes
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (11 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 13/17] x86: MCE: Enable MCE_AMD for 32bit NEW_MCE Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 15/17] Export add_timer_on for modules Andi Kleen
` (2 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
Documentation/Changes | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/Documentation/Changes b/Documentation/Changes
index b95082b..d21b3b5 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -48,6 +48,7 @@ o procps 3.2.0 # ps --version
o oprofile 0.9 # oprofiled --version
o udev 081 # udevinfo -V
o grub 0.93 # grub --version
+o mcelog 0.6
Kernel compilation
==================
@@ -276,6 +277,16 @@ before running exportfs or mountd. It is recommended that all NFS
services be protected from the internet-at-large by a firewall where
that is possible.
+mcelog
+------
+
+In Linux 2.6.31+ the i386 kernel needs to run the mcelog utility
+as a regular cronjob similar to the x86-64 kernel to process and log
+machine check events when CONFIG_X86_NEW_MCE is enabled. Machine check
+events are errors reported by the CPU. Processing them is strongly encouraged.
+All x86-64 kernels since 2.6.4 require the mcelog utility to
+process machine checks.
+
Getting updated software
========================
@@ -365,6 +376,10 @@ FUSE
----
o <http://sourceforge.net/projects/fuse>
+mcelog
+------
+o <ftp://ftp.kernel.org/pub/linux/utils/cpu/mce/mcelog/>
+
Networking
**********
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 15/17] Export add_timer_on for modules
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (12 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 14/17] x86: MCE: Document new 32bit mcelog requirement in Documentation/Changes Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 16/17] x86: MCE: Add MSR read wrappers for easier error injection Andi Kleen
2009-05-26 23:18 ` [PATCH 17/17] x86: MCE: Add basic error injection infrastructure Andi Kleen
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Needed in followon patch.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
kernel/timer.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kernel/timer.c b/kernel/timer.c
index cffffad..e2c47b8 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -756,6 +756,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
wake_up_idle_cpu(cpu);
spin_unlock_irqrestore(&base->lock, flags);
}
+EXPORT_SYMBOL_GPL(add_timer_on);
/**
* del_timer - deactive a timer.
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 16/17] x86: MCE: Add MSR read wrappers for easier error injection
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (13 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 15/17] Export add_timer_on for modules Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
2009-05-26 23:18 ` [PATCH 17/17] x86: MCE: Add basic error injection infrastructure Andi Kleen
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
This will be used by future patches to allow machine check error injection.
Right now it's a nop, except for adding some wrappers around the MSR reads.
This is early in the sequence to avoid too many conflicts.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/cpu/mcheck/mce.c | 37 +++++++++++++++++++++++++------------
1 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index a3c8bd0..76962ff 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -194,6 +194,19 @@ static void mce_panic(char *msg, struct mce *backup, u64 start)
panic(msg);
}
+/* MSR access wrappers used for error injection */
+static u64 mce_rdmsrl(u32 msr)
+{
+ u64 v;
+ rdmsrl(msr, v);
+ return v;
+}
+
+static void mce_wrmsrl(u32 msr, u64 v)
+{
+ wrmsrl(msr, v);
+}
+
int mce_available(struct cpuinfo_x86 *c)
{
if (mce_disabled)
@@ -213,7 +226,7 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
if (rip_msr) {
/* Assume the RIP in the MSR is exact. Is this true? */
m->mcgstatus |= MCG_STATUS_EIPV;
- rdmsrl(rip_msr, m->ip);
+ m->ip = mce_rdmsrl(rip_msr);
m->cs = 0;
}
}
@@ -231,7 +244,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
mce_setup(&m);
- rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+ m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
for (i = 0; i < banks; i++) {
if (!bank[i] || !test_bit(i, *b))
continue;
@@ -242,7 +255,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
m.tsc = 0;
barrier();
- rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
+ m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
if (!(m.status & MCI_STATUS_VAL))
continue;
@@ -257,9 +270,9 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
continue;
if (m.status & MCI_STATUS_MISCV)
- rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
+ m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
if (m.status & MCI_STATUS_ADDRV)
- rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
+ m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
if (!(flags & MCP_TIMESTAMP))
m.tsc = 0;
@@ -275,7 +288,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
/*
* Clear state for this bank.
*/
- wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+ mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
}
/*
@@ -320,7 +333,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
mce_setup(&m);
- rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+ m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
/* if the restart IP is not valid, we're done for */
if (!(m.mcgstatus & MCG_STATUS_RIPV))
@@ -338,7 +351,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
m.addr = 0;
m.bank = i;
- rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
+ m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
if ((m.status & MCI_STATUS_VAL) == 0)
continue;
@@ -378,9 +391,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
}
if (m.status & MCI_STATUS_MISCV)
- rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
+ m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
if (m.status & MCI_STATUS_ADDRV)
- rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
+ m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
mce_get_rip(&m, regs);
mce_log(&m);
@@ -449,9 +462,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
/* the last thing we do is clear state */
for (i = 0; i < banks; i++) {
if (test_bit(i, toclear))
- wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+ mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
}
- wrmsrl(MSR_IA32_MCG_STATUS, 0);
+ mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
out2:
atomic_dec(&mce_entry);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 17/17] x86: MCE: Add basic error injection infrastructure
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
` (14 preceding siblings ...)
2009-05-26 23:18 ` [PATCH 16/17] x86: MCE: Add MSR read wrappers for easier error injection Andi Kleen
@ 2009-05-26 23:18 ` Andi Kleen
15 siblings, 0 replies; 18+ messages in thread
From: Andi Kleen @ 2009-05-26 23:18 UTC (permalink / raw)
To: linux-kernel, x86, hpa; +Cc: Andi Kleen
From: Andi Kleen <ak@linux.intel.com>
Allow user programs to write mce records into /dev/mcelog. When they do
that a fake machine check is triggered to test the machine check code.
This uses the MCE MSR wrappers added earlier.
The implementation is straight forward. There is a struct mce record
per CPU and the MCE MSR accesses get data from there if there is valid
data injected there. This allows to test the machine check code
relatively realistically because only the lowest layer of hardware
access is intercepted.
The test suite and injector are available at
git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git
git://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/Kconfig | 8 ++
arch/x86/include/asm/mce.h | 3 +
arch/x86/kernel/cpu/mcheck/Makefile | 1 +
arch/x86/kernel/cpu/mcheck/mce-inject.c | 126 +++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/mcheck/mce.c | 39 +++++++++-
5 files changed, 176 insertions(+), 1 deletions(-)
create mode 100644 arch/x86/kernel/cpu/mcheck/mce-inject.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a148e7a..e25b635 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -835,6 +835,14 @@ config X86_MCE_THRESHOLD
bool
default y
+config X86_MCE_INJECT
+ depends on X86_NEW_MCE
+ tristate "Machine check injector support"
+ ---help---
+ Provide support for injecting machine checks for testing purposes.
+ If you don't know what a machine check is and you don't do kernel
+ QA it is safe to say n.
+
config X86_MCE_NONFATAL
tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
depends on X86_OLD_MCE
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index ca79ee8..8ad67bf 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -141,6 +141,9 @@ extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
extern int mce_notify_user(void);
+DECLARE_PER_CPU(struct mce, injectm);
+extern struct file_operations mce_chrdev_ops;
+
#ifdef CONFIG_X86_MCE
extern void mcheck_init(struct cpuinfo_x86 *c);
#else
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index 5f8b094..60ee182 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o mce_intel.o
obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o
obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
+obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
new file mode 100644
index 0000000..58afac4
--- /dev/null
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -0,0 +1,126 @@
+/*
+ * Machine check injection support.
+ * Copyright 2008 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Authors:
+ * Andi Kleen
+ * Ying Huang
+ */
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <asm/uaccess.h>
+#include <asm/mce.h>
+
+/* Update fake mce registers on current CPU. */
+static void inject_mce(struct mce *m)
+{
+ struct mce *i = &per_cpu(injectm, m->cpu);
+
+ /* Make sure noone reads partially written injectm */
+ i->finished = 0;
+ mb();
+ m->finished = 0;
+ /* First set the fields after finished */
+ i->cpu = m->cpu;
+ mb();
+ /* Now write record in order, finished last (except above) */
+ memcpy(i, m, sizeof(struct mce));
+ /* Finally activate it */
+ mb();
+ i->finished = 1;
+}
+
+struct delayed_mce {
+ struct timer_list timer;
+ struct mce m;
+};
+
+/* Inject mce on current CPU */
+static void raise_mce(unsigned long data)
+{
+ struct delayed_mce *dm = (struct delayed_mce *)data;
+ struct mce *m = &dm->m;
+ int cpu = m->cpu;
+
+ inject_mce(m);
+ if (m->status & MCI_STATUS_UC) {
+ struct pt_regs regs;
+ memset(®s, 0, sizeof(struct pt_regs));
+ regs.ip = m->ip;
+ regs.cs = m->cs;
+ printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu);
+ do_machine_check(®s, 0);
+ printk(KERN_INFO "MCE exception done on CPU %d\n", cpu);
+ } else {
+ mce_banks_t b;
+ memset(&b, 0xff, sizeof(mce_banks_t));
+ printk(KERN_INFO "Starting machine check poll CPU %d\n", cpu);
+ machine_check_poll(0, &b);
+ mce_notify_user();
+ printk(KERN_INFO "Finished machine check poll on CPU %d\n",
+ cpu);
+ }
+ kfree(dm);
+}
+
+/* Error injection interface */
+static ssize_t mce_write(struct file *filp, const char __user *ubuf,
+ size_t usize, loff_t *off)
+{
+ struct delayed_mce *dm;
+ struct mce m;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /*
+ * There are some cases where real MSR reads could slip
+ * through.
+ */
+ if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA))
+ return -EIO;
+
+ if ((unsigned long)usize > sizeof(struct mce))
+ usize = sizeof(struct mce);
+ if (copy_from_user(&m, ubuf, usize))
+ return -EFAULT;
+
+ if (m.cpu >= NR_CPUS || !cpu_online(m.cpu))
+ return -EINVAL;
+
+ dm = kmalloc(sizeof(struct delayed_mce), GFP_KERNEL);
+ if (!dm)
+ return -ENOMEM;
+
+ /*
+ * Need to give user space some time to set everything up,
+ * so do it a jiffie or two later everywhere.
+ * Should we use a hrtimer here for better synchronization?
+ */
+ memcpy(&dm->m, &m, sizeof(struct mce));
+ setup_timer(&dm->timer, raise_mce, (unsigned long)dm);
+ dm->timer.expires = jiffies + 2;
+ add_timer_on(&dm->timer, m.cpu);
+ return usize;
+}
+
+static int inject_init(void)
+{
+ printk(KERN_INFO "Machine check injector initialized\n");
+ mce_chrdev_ops.write = mce_write;
+ return 0;
+}
+
+module_init(inject_init);
+/* Cannot tolerate unloading currently because we cannot
+ * guarantee all openers of mce_chrdev will get a reference to us.
+ */
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 76962ff..87f8198 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -98,6 +98,9 @@ void mce_setup(struct mce *m)
rdtscll(m->tsc);
}
+DEFINE_PER_CPU(struct mce, injectm);
+EXPORT_PER_CPU_SYMBOL_GPL(injectm);
+
/*
* Lockless MCE logging infrastructure.
* This avoids deadlocks on printk locks without having to break locks. Also
@@ -194,16 +197,46 @@ static void mce_panic(char *msg, struct mce *backup, u64 start)
panic(msg);
}
+/* Support code for software error injection */
+
+static int msr_to_offset(u32 msr)
+{
+ unsigned bank = __get_cpu_var(injectm.bank);
+ if (msr == rip_msr)
+ return offsetof(struct mce, ip);
+ if (msr == MSR_IA32_MC0_STATUS + bank*4)
+ return offsetof(struct mce, status);
+ if (msr == MSR_IA32_MC0_ADDR + bank*4)
+ return offsetof(struct mce, addr);
+ if (msr == MSR_IA32_MC0_MISC + bank*4)
+ return offsetof(struct mce, misc);
+ if (msr == MSR_IA32_MCG_STATUS)
+ return offsetof(struct mce, mcgstatus);
+ return -1;
+}
+
/* MSR access wrappers used for error injection */
static u64 mce_rdmsrl(u32 msr)
{
u64 v;
+ if (__get_cpu_var(injectm).finished) {
+ int offset = msr_to_offset(msr);
+ if (offset < 0)
+ return 0;
+ return *(u64 *)((char *)&__get_cpu_var(injectm) + offset);
+ }
rdmsrl(msr, v);
return v;
}
static void mce_wrmsrl(u32 msr, u64 v)
{
+ if (__get_cpu_var(injectm).finished) {
+ int offset = msr_to_offset(msr);
+ if (offset >= 0)
+ *(u64 *)((char *)&__get_cpu_var(injectm) + offset) = v;
+ return;
+ }
wrmsrl(msr, v);
}
@@ -296,6 +329,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* exceptions.
*/
}
+EXPORT_SYMBOL_GPL(machine_check_poll);
/*
* The actual machine check handler. This only handles real
@@ -468,6 +502,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
out2:
atomic_dec(&mce_entry);
}
+EXPORT_SYMBOL_GPL(do_machine_check);
#ifdef CONFIG_X86_MCE_INTEL
/***
@@ -568,6 +603,7 @@ int mce_notify_user(void)
}
return 0;
}
+EXPORT_SYMBOL_GPL(mce_notify_user);
/*
* Initialize Machine Checks for a CPU.
@@ -905,13 +941,14 @@ static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
}
}
-static const struct file_operations mce_chrdev_ops = {
+struct file_operations mce_chrdev_ops = {
.open = mce_open,
.release = mce_release,
.read = mce_read,
.poll = mce_poll,
.unlocked_ioctl = mce_ioctl,
};
+EXPORT_SYMBOL_GPL(mce_chrdev_ops);
static struct miscdevice mce_log_device = {
MISC_MCELOG_MINOR,
--
1.6.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2009-05-26 23:22 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-26 23:17 x86 Machine check 32bit merge series Andi Kleen
2009-05-26 23:18 ` [PATCH 01/17] x86: MCE: Initial steps to make 64bit mce code 32bit clean Andi Kleen
2009-05-26 23:18 ` [PATCH 02/17] x86: MCE: Implement the PPro bank 0 quirk in the 64bit machine check code Andi Kleen
2009-05-26 23:18 ` [PATCH 03/17] x86: MCE: Port K7 bank 0 quirk to 64bit mce code Andi Kleen
2009-05-26 23:18 ` [PATCH 04/17] x86: MCE: Use a call vector to call the 64bit mce handler Andi Kleen
2009-05-26 23:18 ` [PATCH 05/17] x86: MCE: Rename 64bit mce_dont_init to mce_disabled Andi Kleen
2009-05-26 23:18 ` [PATCH 06/17] x86: MCE: Move mce_disabled option into common 64bit/64bit code Andi Kleen
2009-05-26 23:18 ` [PATCH 07/17] x86: MCE: Remove machine check handler idle notify on 64bit Andi Kleen
2009-05-26 23:18 ` [PATCH 08/17] x86: MCE: Remove oops_begin() use in 64bit machine check Andi Kleen
2009-05-26 23:18 ` [PATCH 09/17] x86: MCE: Remove unused stop/restart_mce on 32bit Andi Kleen
2009-05-26 23:18 ` [PATCH 10/17] x86: MCE: Use 64bit machine check code " Andi Kleen
2009-05-26 23:18 ` [PATCH 11/17] x86: MCE: Deprecate old 32bit machine check code Andi Kleen
2009-05-26 23:18 ` [PATCH 12/17] x86: MCE: Enable MCE_INTEL for 32bit new MCE Andi Kleen
2009-05-26 23:18 ` [PATCH 13/17] x86: MCE: Enable MCE_AMD for 32bit NEW_MCE Andi Kleen
2009-05-26 23:18 ` [PATCH 14/17] x86: MCE: Document new 32bit mcelog requirement in Documentation/Changes Andi Kleen
2009-05-26 23:18 ` [PATCH 15/17] Export add_timer_on for modules Andi Kleen
2009-05-26 23:18 ` [PATCH 16/17] x86: MCE: Add MSR read wrappers for easier error injection Andi Kleen
2009-05-26 23:18 ` [PATCH 17/17] x86: MCE: Add basic error injection infrastructure Andi Kleen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox