Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / arch / x86 / kernel / cpu / mcheck / mce_intel.c
1 /*
2  * Common code for Intel machine checks
3  */
4 #include <linux/interrupt.h>
5 #include <linux/kernel.h>
6 #include <linux/types.h>
7 #include <linux/init.h>
8 #include <linux/smp.h>
9
10 #include <asm/therm_throt.h>
11 #include <asm/processor.h>
12 #include <asm/system.h>
13 #include <asm/apic.h>
14 #include <asm/msr.h>
15
16 #include "mce.h"
17
18 void intel_init_thermal(struct cpuinfo_x86 *c)
19 {
20         unsigned int cpu = smp_processor_id();
21         int tm2 = 0;
22         u32 l, h;
23
24         /* Thermal monitoring depends on ACPI and clock modulation*/
25         if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
26                 return;
27
28         /*
29          * First check if its enabled already, in which case there might
30          * be some SMM goo which handles it, so we can't even put a handler
31          * since it might be delivered via SMI already:
32          */
33         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
34         h = apic_read(APIC_LVTTHMR);
35         if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
36                 printk(KERN_DEBUG
37                        "CPU%d: Thermal monitoring handled by SMI\n", cpu);
38                 return;
39         }
40
41         if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
42                 tm2 = 1;
43
44         /* Check whether a vector already exists */
45         if (h & APIC_VECTOR_MASK) {
46                 printk(KERN_DEBUG
47                        "CPU%d: Thermal LVT vector (%#x) already installed\n",
48                        cpu, (h & APIC_VECTOR_MASK));
49                 return;
50         }
51
52         /* We'll mask the thermal vector in the lapic till we're ready: */
53         h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
54         apic_write(APIC_LVTTHMR, h);
55
56         rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
57         wrmsr(MSR_IA32_THERM_INTERRUPT,
58                 l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
59
60         intel_set_thermal_handler();
61
62         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
63         wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
64
65         /* Unmask the thermal vector: */
66         l = apic_read(APIC_LVTTHMR);
67         apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
68
69         printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
70                cpu, tm2 ? "TM2" : "TM1");
71
72         /* enable thermal throttle processing */
73         atomic_set(&therm_throt_en, 1);
74 }