diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-04-08 06:31:23 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-28 12:24:10 -0400 |
commit | a65d086235208a3b3546e209d2210048549099b2 (patch) | |
tree | 73a402994453de2e1c977826b163d4999b74226a | |
parent | 6cc6f3ebd19fea722c19630af5ad68af7f51d493 (diff) |
x86, mce: unify Intel thermal init
Mechanic unification. No change in code.
[ Impact: cleanup, 32-bit / 64-bit unification ]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/Makefile | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.h | 11 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_intel.c | 73 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_intel_64.c | 61 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/p4.c | 59 |
5 files changed, 89 insertions, 118 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index b2f89829bbe8..6def76942bf2 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | obj-y = mce_$(BITS).o therm_throt.o | 1 | obj-y = mce_$(BITS).o therm_throt.o |
2 | 2 | ||
3 | obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o | 3 | obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o |
4 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o | 4 | obj-$(CONFIG_X86_MCE_P4THERMAL) += mce_intel.o |
5 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o mce_intel.o | ||
5 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o | 6 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o |
6 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o | 7 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o |
7 | obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o | 8 | obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.h b/arch/x86/kernel/cpu/mcheck/mce.h index ae9f628838f1..2d1a54bdadfc 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.h +++ b/arch/x86/kernel/cpu/mcheck/mce.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #include <linux/init.h> | 1 | #include <linux/init.h> |
2 | #include <asm/mce.h> | 2 | #include <asm/mce.h> |
3 | 3 | ||
4 | #ifdef CONFIG_X86_32 | ||
5 | |||
4 | void amd_mcheck_init(struct cpuinfo_x86 *c); | 6 | void amd_mcheck_init(struct cpuinfo_x86 *c); |
5 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c); | 7 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c); |
6 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c); | 8 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c); |
@@ -12,3 +14,12 @@ extern void (*machine_check_vector)(struct pt_regs *, long error_code); | |||
12 | 14 | ||
13 | extern int nr_mce_banks; | 15 | extern int nr_mce_banks; |
14 | 16 | ||
17 | void intel_set_thermal_handler(void); | ||
18 | |||
19 | #else | ||
20 | |||
21 | static inline void intel_set_thermal_handler(void) { } | ||
22 | |||
23 | #endif | ||
24 | |||
25 | void intel_init_thermal(struct cpuinfo_x86 *c); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c new file mode 100644 index 000000000000..bad3cbb0e566 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -0,0 +1,73 @@ | |||
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 & (1 << 3)) && (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 & (1 << 13))) | ||
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, l | 0x03, h); | ||
58 | |||
59 | intel_set_thermal_handler(); | ||
60 | |||
61 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
62 | wrmsr(MSR_IA32_MISC_ENABLE, l | (1 << 3), h); | ||
63 | |||
64 | /* Unmask the thermal vector: */ | ||
65 | l = apic_read(APIC_LVTTHMR); | ||
66 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
67 | |||
68 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", | ||
69 | cpu, tm2 ? "TM2" : "TM1"); | ||
70 | |||
71 | /* enable thermal throttle processing */ | ||
72 | atomic_set(&therm_throt_en, 1); | ||
73 | } | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index b85d0c107c84..38f9632306fa 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <asm/therm_throt.h> | 17 | #include <asm/therm_throt.h> |
18 | #include <asm/apic.h> | 18 | #include <asm/apic.h> |
19 | 19 | ||
20 | #include "mce.h" | ||
21 | |||
20 | asmlinkage void smp_thermal_interrupt(void) | 22 | asmlinkage void smp_thermal_interrupt(void) |
21 | { | 23 | { |
22 | __u64 msr_val; | 24 | __u64 msr_val; |
@@ -34,65 +36,6 @@ asmlinkage void smp_thermal_interrupt(void) | |||
34 | irq_exit(); | 36 | irq_exit(); |
35 | } | 37 | } |
36 | 38 | ||
37 | static inline void intel_set_thermal_handler(void) { } | ||
38 | |||
39 | static void intel_init_thermal(struct cpuinfo_x86 *c) | ||
40 | { | ||
41 | unsigned int cpu = smp_processor_id(); | ||
42 | int tm2 = 0; | ||
43 | u32 l, h; | ||
44 | |||
45 | /* Thermal monitoring depends on ACPI and clock modulation*/ | ||
46 | if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) | ||
47 | return; | ||
48 | |||
49 | /* | ||
50 | * First check if its enabled already, in which case there might | ||
51 | * be some SMM goo which handles it, so we can't even put a handler | ||
52 | * since it might be delivered via SMI already: | ||
53 | */ | ||
54 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
55 | h = apic_read(APIC_LVTTHMR); | ||
56 | if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { | ||
57 | printk(KERN_DEBUG | ||
58 | "CPU%d: Thermal monitoring handled by SMI\n", cpu); | ||
59 | return; | ||
60 | } | ||
61 | |||
62 | if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2)) | ||
63 | tm2 = 1; | ||
64 | |||
65 | /* Check whether a vector already exists */ | ||
66 | if (h & APIC_VECTOR_MASK) { | ||
67 | printk(KERN_DEBUG | ||
68 | "CPU%d: Thermal LVT vector (%#x) already installed\n", | ||
69 | cpu, (h & APIC_VECTOR_MASK)); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | /* We'll mask the thermal vector in the lapic till we're ready: */ | ||
74 | h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED; | ||
75 | apic_write(APIC_LVTTHMR, h); | ||
76 | |||
77 | rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); | ||
78 | wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h); | ||
79 | |||
80 | intel_set_thermal_handler(); | ||
81 | |||
82 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
83 | wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); | ||
84 | |||
85 | /* Unmask the thermal vector: */ | ||
86 | l = apic_read(APIC_LVTTHMR); | ||
87 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
88 | |||
89 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", | ||
90 | cpu, tm2 ? "TM2" : "TM1"); | ||
91 | |||
92 | /* enable thermal throttle processing */ | ||
93 | atomic_set(&therm_throt_en, 1); | ||
94 | } | ||
95 | |||
96 | /* | 39 | /* |
97 | * Support for Intel Correct Machine Check Interrupts. This allows | 40 | * Support for Intel Correct Machine Check Interrupts. This allows |
98 | * the CPU to raise an interrupt when a corrected machine check happened. | 41 | * the CPU to raise an interrupt when a corrected machine check happened. |
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c index f70753a443bb..f979ffea330b 100644 --- a/arch/x86/kernel/cpu/mcheck/p4.c +++ b/arch/x86/kernel/cpu/mcheck/p4.c | |||
@@ -66,68 +66,11 @@ void smp_thermal_interrupt(struct pt_regs *regs) | |||
66 | irq_exit(); | 66 | irq_exit(); |
67 | } | 67 | } |
68 | 68 | ||
69 | static void intel_set_thermal_handler(void) | 69 | void intel_set_thermal_handler(void) |
70 | { | 70 | { |
71 | vendor_thermal_interrupt = intel_thermal_interrupt; | 71 | vendor_thermal_interrupt = intel_thermal_interrupt; |
72 | } | 72 | } |
73 | 73 | ||
74 | /* P4/Xeon Thermal regulation detect and init: */ | ||
75 | static void intel_init_thermal(struct cpuinfo_x86 *c) | ||
76 | { | ||
77 | unsigned int cpu = smp_processor_id(); | ||
78 | int tm2 = 0; | ||
79 | u32 l, h; | ||
80 | |||
81 | /* Thermal monitoring depends on ACPI and clock modulation*/ | ||
82 | if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) | ||
83 | return; | ||
84 | |||
85 | /* | ||
86 | * First check if its enabled already, in which case there might | ||
87 | * be some SMM goo which handles it, so we can't even put a handler | ||
88 | * since it might be delivered via SMI already: | ||
89 | */ | ||
90 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
91 | h = apic_read(APIC_LVTTHMR); | ||
92 | if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { | ||
93 | printk(KERN_DEBUG | ||
94 | "CPU%d: Thermal monitoring handled by SMI\n", cpu); | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2)) | ||
99 | tm2 = 1; | ||
100 | |||
101 | /* Check whether a vector already exists */ | ||
102 | if (h & APIC_VECTOR_MASK) { | ||
103 | printk(KERN_DEBUG | ||
104 | "CPU%d: Thermal LVT vector (%#x) already installed\n", | ||
105 | cpu, (h & APIC_VECTOR_MASK)); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | /* We'll mask the thermal vector in the lapic till we're ready: */ | ||
110 | h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED; | ||
111 | apic_write(APIC_LVTTHMR, h); | ||
112 | |||
113 | rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); | ||
114 | wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h); | ||
115 | |||
116 | intel_set_thermal_handler(); | ||
117 | |||
118 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
119 | wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); | ||
120 | |||
121 | /* Unmask the thermal vector: */ | ||
122 | l = apic_read(APIC_LVTTHMR); | ||
123 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
124 | |||
125 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", | ||
126 | cpu, tm2 ? "TM2" : "TM1"); | ||
127 | |||
128 | /* enable thermal throttle processing */ | ||
129 | atomic_set(&therm_throt_en, 1); | ||
130 | } | ||
131 | #endif /* CONFIG_X86_MCE_P4THERMAL */ | 74 | #endif /* CONFIG_X86_MCE_P4THERMAL */ |
132 | 75 | ||
133 | /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ | 76 | /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ |