diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/p4.c')
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/p4.c | 86 | 
1 files changed, 19 insertions, 67 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c index f53bdcbaf38..82cee108a2d 100644 --- a/arch/x86/kernel/cpu/mcheck/p4.c +++ b/arch/x86/kernel/cpu/mcheck/p4.c @@ -2,18 +2,17 @@   * P4 specific Machine Check Exception Reporting   */ -#include <linux/init.h> -#include <linux/types.h> -#include <linux/kernel.h>  #include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h>  #include <linux/smp.h> +#include <asm/therm_throt.h>  #include <asm/processor.h>  #include <asm/system.h> -#include <asm/msr.h>  #include <asm/apic.h> - -#include <asm/therm_throt.h> +#include <asm/msr.h>  #include "mce.h" @@ -36,6 +35,7 @@ static int mce_num_extended_msrs;  #ifdef CONFIG_X86_MCE_P4THERMAL +  static void unexpected_thermal_interrupt(struct pt_regs *regs)  {  	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", @@ -43,7 +43,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs)  	add_taint(TAINT_MACHINE_CHECK);  } -/* P4/Xeon Thermal transition interrupt handler */ +/* P4/Xeon Thermal transition interrupt handler: */  static void intel_thermal_interrupt(struct pt_regs *regs)  {  	__u64 msr_val; @@ -51,11 +51,12 @@ static void intel_thermal_interrupt(struct pt_regs *regs)  	ack_APIC_irq();  	rdmsrl(MSR_IA32_THERM_STATUS, msr_val); -	therm_throt_process(msr_val & 0x1); +	therm_throt_process(msr_val & THERM_STATUS_PROCHOT);  } -/* Thermal interrupt handler for this CPU setup */ -static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; +/* Thermal interrupt handler for this CPU setup: */ +static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = +						unexpected_thermal_interrupt;  void smp_thermal_interrupt(struct pt_regs *regs)  { @@ -65,67 +66,15 @@ void smp_thermal_interrupt(struct pt_regs *regs)  	irq_exit();  } -/* P4/Xeon Thermal regulation detect and init */ -static void intel_init_thermal(struct cpuinfo_x86 *c) +void intel_set_thermal_handler(void)  { -	u32 l, h; -	unsigned int cpu = smp_processor_id(); - -	/* Thermal monitoring */ -	if (!cpu_has(c, X86_FEATURE_ACPI)) -		return;	/* -ENODEV */ - -	/* Clock modulation */ -	if (!cpu_has(c, X86_FEATURE_ACC)) -		return;	/* -ENODEV */ - -	/* first check if its enabled already, in which case there might -	 * be some SMM goo which handles it, so we can't even put a handler -	 * since it might be delivered via SMI already -zwanem. -	 */ -	rdmsr(MSR_IA32_MISC_ENABLE, l, h); -	h = apic_read(APIC_LVTTHMR); -	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { -		printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", -				cpu); -		return; /* -EBUSY */ -	} - -	/* check whether a vector already exists, temporarily masked? */ -	if (h & APIC_VECTOR_MASK) { -		printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already " -				"installed\n", -			cpu, (h & APIC_VECTOR_MASK)); -		return; /* -EBUSY */ -	} - -	/* The temperature transition interrupt handler setup */ -	h = THERMAL_APIC_VECTOR;		/* our delivery vector */ -	h |= (APIC_DM_FIXED | APIC_LVT_MASKED);	/* we'll mask till we're ready */ -	apic_write(APIC_LVTTHMR, h); - -	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); -	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); - -	/* ok we're good to go... */  	vendor_thermal_interrupt = intel_thermal_interrupt; - -	rdmsr(MSR_IA32_MISC_ENABLE, l, h); -	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); - -	l = apic_read(APIC_LVTTHMR); -	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); -	printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); - -	/* enable thermal throttle processing */ -	atomic_set(&therm_throt_en, 1); -	return;  } -#endif /* CONFIG_X86_MCE_P4THERMAL */ +#endif /* CONFIG_X86_MCE_P4THERMAL */  /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ -static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r) +static void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)  {  	u32 h; @@ -143,9 +92,9 @@ static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)  static void intel_machine_check(struct pt_regs *regs, long error_code)  { -	int recover = 1;  	u32 alow, ahigh, high, low;  	u32 mcgstl, mcgsth; +	int recover = 1;  	int i;  	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); @@ -157,7 +106,9 @@ static void intel_machine_check(struct pt_regs *regs, long error_code)  	if (mce_num_extended_msrs > 0) {  		struct intel_mce_extended_msrs dbg; +  		intel_get_extended_msrs(&dbg); +  		printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n"  			"\teax: %08x ebx: %08x ecx: %08x edx: %08x\n"  			"\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", @@ -171,6 +122,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code)  		if (high & (1<<31)) {  			char misc[20];  			char addr[24]; +  			misc[0] = addr[0] = '\0';  			if (high & (1<<29))  				recover |= 1; @@ -196,6 +148,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code)  		panic("Unable to continue");  	printk(KERN_EMERG "Attempting to continue.\n"); +  	/*  	 * Do not clear the MSR_IA32_MCi_STATUS if the error is not  	 * recoverable/continuable.This will allow BIOS to look at the MSRs @@ -217,7 +170,6 @@ static void intel_machine_check(struct pt_regs *regs, long error_code)  	wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);  } -  void intel_p4_mcheck_init(struct cpuinfo_x86 *c)  {  	u32 l, h;  |