diff options
| -rw-r--r-- | arch/x86/include/asm/mce.h | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/therm_throt.c | 29 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 3 | 
5 files changed, 43 insertions, 5 deletions
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 161485da6838..858baa061cfc 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -120,8 +120,10 @@ extern int mce_disabled;  extern int mce_p5_enabled;  #ifdef CONFIG_X86_MCE +int mcheck_init(void);  void mcheck_cpu_init(struct cpuinfo_x86 *c);  #else +static inline int mcheck_init(void) { return 0; }  static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}  #endif @@ -215,5 +217,12 @@ extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);  void intel_init_thermal(struct cpuinfo_x86 *c);  void mce_log_therm_throt_event(__u64 status); + +#ifdef CONFIG_X86_THERMAL_VECTOR +extern void mcheck_intel_therm_init(void); +#else +static inline void mcheck_intel_therm_init(void) { } +#endif +  #endif /* __KERNEL__ */  #endif /* _ASM_X86_MCE_H */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 4df69a38be57..9053be5d95cd 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -837,10 +837,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)  			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];  	} -#ifdef CONFIG_X86_MCE  	/* Init Machine Check Exception if available. */  	mcheck_cpu_init(c); -#endif  	select_idle_routine(c); diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 80801705edd7..0d4102031a4c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1655,13 +1655,14 @@ static int __init mcheck_enable(char *str)  }  __setup("mce", mcheck_enable); -static int __init mcheck_init(void) +int __init mcheck_init(void)  {  	atomic_notifier_chain_register(&x86_mce_decoder_chain, &mce_dec_nb); +	mcheck_intel_therm_init(); +  	return 0;  } -early_initcall(mcheck_init);  /*   * Sysfs support diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index b3a1dba75330..7f3cf36ed124 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -49,6 +49,8 @@ static DEFINE_PER_CPU(struct thermal_state, thermal_state);  static atomic_t therm_throt_en	= ATOMIC_INIT(0); +static u32 lvtthmr_init __read_mostly; +  #ifdef CONFIG_SYSFS  #define define_therm_throt_sysdev_one_ro(_name)				\  	static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) @@ -254,6 +256,18 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)  	ack_APIC_irq();  } +void mcheck_intel_therm_init(void) +{ +	/* +	 * This function is only called on boot CPU. Save the init thermal +	 * LVT value on BSP and use that value to restore APs' thermal LVT +	 * entry BIOS programmed later +	 */ +	if (cpu_has(&boot_cpu_data, X86_FEATURE_ACPI) && +		cpu_has(&boot_cpu_data, X86_FEATURE_ACC)) +		lvtthmr_init = apic_read(APIC_LVTTHMR); +} +  void intel_init_thermal(struct cpuinfo_x86 *c)  {  	unsigned int cpu = smp_processor_id(); @@ -270,7 +284,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c)  	 * since it might be delivered via SMI already:  	 */  	rdmsr(MSR_IA32_MISC_ENABLE, l, h); -	h = apic_read(APIC_LVTTHMR); + +	/* +	 * The initial value of thermal LVT entries on all APs always reads +	 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI +	 * sequence to them and LVT registers are reset to 0s except for +	 * the mask bits which are set to 1s when APs receive INIT IPI. +	 * Always restore the value that BIOS has programmed on AP based on +	 * BSP's info we saved since BIOS is always setting the same value +	 * for all threads/cores +	 */ +	apic_write(APIC_LVTTHMR, lvtthmr_init); + +	h = lvtthmr_init; +  	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {  		printk(KERN_DEBUG  		       "CPU%d: Thermal monitoring handled by SMI\n", cpu); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index e09f0e2c14b5..179c1f2aa457 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -109,6 +109,7 @@  #ifdef CONFIG_X86_64  #include <asm/numa_64.h>  #endif +#include <asm/mce.h>  /*   * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. @@ -1024,6 +1025,8 @@ void __init setup_arch(char **cmdline_p)  #endif  #endif  	x86_init.oem.banner(); + +	mcheck_init();  }  #ifdef CONFIG_X86_32  | 
