Commit 57b47f9d authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64/i386: add mce tainting

This patch adds machine check tainting.  When a handled machine check
occurs the oops gets a new 'M' flag.  This is useful to ignore machines
with hardware problems in oops reports.

On i386 a thermal failure also sets this flag.

Done for x86-64 and i386 so far.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarNick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f5cda072
...@@ -54,6 +54,7 @@ static asmlinkage void k7_machine_check(struct pt_regs * regs, long error_code) ...@@ -54,6 +54,7 @@ static asmlinkage void k7_machine_check(struct pt_regs * regs, long error_code)
wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */ /* Serialize */
wmb(); wmb();
add_taint(TAINT_MACHINE_CHECK);
} }
} }
......
...@@ -48,6 +48,7 @@ static void mce_checkregs (void *info) ...@@ -48,6 +48,7 @@ static void mce_checkregs (void *info)
/* Serialize */ /* Serialize */
wmb(); wmb();
add_taint(TAINT_MACHINE_CHECK);
} }
} }
} }
......
...@@ -40,6 +40,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs) ...@@ -40,6 +40,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs)
{ {
printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
smp_processor_id()); smp_processor_id());
add_taint(TAINT_MACHINE_CHECK);
} }
/* P4/Xeon Thermal transition interrupt handler */ /* P4/Xeon Thermal transition interrupt handler */
...@@ -60,6 +61,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs) ...@@ -60,6 +61,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu); printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu);
printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n", printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n",
cpu); cpu);
add_taint(TAINT_MACHINE_CHECK);
} else { } else {
printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
} }
...@@ -222,6 +224,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod ...@@ -222,6 +224,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod
wrmsr(msr, 0UL, 0UL); wrmsr(msr, 0UL, 0UL);
/* Serialize */ /* Serialize */
wmb(); wmb();
add_taint(TAINT_MACHINE_CHECK);
} }
} }
mcgstl &= ~(1<<2); mcgstl &= ~(1<<2);
......
...@@ -25,6 +25,7 @@ static asmlinkage void pentium_machine_check(struct pt_regs * regs, long error_c ...@@ -25,6 +25,7 @@ static asmlinkage void pentium_machine_check(struct pt_regs * regs, long error_c
printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype); printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
if(lotype&(1<<5)) if(lotype&(1<<5))
printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id()); printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
add_taint(TAINT_MACHINE_CHECK);
} }
/* Set up machine check reporting for processors with Intel style MCE */ /* Set up machine check reporting for processors with Intel style MCE */
......
...@@ -72,6 +72,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod ...@@ -72,6 +72,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod
wrmsr (msr, 0UL, 0UL); wrmsr (msr, 0UL, 0UL);
/* Serialize */ /* Serialize */
wmb(); wmb();
add_taint(TAINT_MACHINE_CHECK);
} }
} }
mcgstl &= ~(1<<2); mcgstl &= ~(1<<2);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
static asmlinkage void winchip_machine_check(struct pt_regs * regs, long error_code) static asmlinkage void winchip_machine_check(struct pt_regs * regs, long error_code)
{ {
printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
add_taint(TAINT_MACHINE_CHECK);
} }
/* Set up machine check reporting on the Winchip C6 series */ /* Set up machine check reporting on the Winchip C6 series */
......
...@@ -191,6 +191,8 @@ void do_machine_check(struct pt_regs * regs, long error_code) ...@@ -191,6 +191,8 @@ void do_machine_check(struct pt_regs * regs, long error_code)
panicm = m; panicm = m;
panicm_found = 1; panicm_found = 1;
} }
tainted |= TAINT_MACHINE_CHECK;
} }
/* Never do anything final in the polling timer */ /* Never do anything final in the polling timer */
......
...@@ -136,6 +136,7 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in ...@@ -136,6 +136,7 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in
extern int panic_on_oops; extern int panic_on_oops;
extern int tainted; extern int tainted;
extern const char *print_tainted(void); extern const char *print_tainted(void);
extern void add_taint(unsigned);
/* Values used for system_state */ /* Values used for system_state */
extern enum system_states { extern enum system_states {
...@@ -150,6 +151,7 @@ extern enum system_states { ...@@ -150,6 +151,7 @@ extern enum system_states {
#define TAINT_FORCED_MODULE (1<<1) #define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2) #define TAINT_UNSAFE_SMP (1<<2)
#define TAINT_FORCED_RMMOD (1<<3) #define TAINT_FORCED_RMMOD (1<<3)
#define TAINT_MACHINE_CHECK (1<<4)
extern void dump_stack(void); extern void dump_stack(void);
......
...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(panic); ...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(panic);
* 'P' - Proprietary module has been loaded. * 'P' - Proprietary module has been loaded.
* 'F' - Module has been forcibly loaded. * 'F' - Module has been forcibly loaded.
* 'S' - SMP with CPUs not designed for SMP. * 'S' - SMP with CPUs not designed for SMP.
* 'M' - Machine had a machine check experience.
* *
* The string is overwritten by the next call to print_taint(). * The string is overwritten by the next call to print_taint().
*/ */
...@@ -118,12 +119,19 @@ const char *print_tainted(void) ...@@ -118,12 +119,19 @@ const char *print_tainted(void)
{ {
static char buf[20]; static char buf[20];
if (tainted) { if (tainted) {
snprintf(buf, sizeof(buf), "Tainted: %c%c%c", snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c",
tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ', tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_MACHINE_CHECK ? 'M' : ' ');
} }
else else
snprintf(buf, sizeof(buf), "Not tainted"); snprintf(buf, sizeof(buf), "Not tainted");
return(buf); return(buf);
} }
void add_taint(unsigned flag)
{
tainted |= flag;
}
EXPORT_SYMBOL(add_taint);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment