diff options
Diffstat (limited to 'arch/x86/kernel/cpu')
39 files changed, 2694 insertions, 2499 deletions
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 1d2cb383410e..c202b62f3671 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -19,8 +19,6 @@ obj-y += vmware.o hypervisor.o sched.o | |||
19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o | 19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o |
20 | obj-$(CONFIG_X86_64) += bugs_64.o | 20 | obj-$(CONFIG_X86_64) += bugs_64.o |
21 | 21 | ||
22 | obj-$(CONFIG_X86_CPU_DEBUG) += cpu_debug.o | ||
23 | |||
24 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o | 22 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o |
25 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o | 23 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o |
26 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o | 24 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o |
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 468489b57aae..97ad79cdf688 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c | |||
@@ -32,6 +32,10 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { | 32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { |
33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, | 33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, |
34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, | 34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, |
35 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, | ||
36 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, | ||
37 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, | ||
38 | { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, | ||
35 | { 0, 0, 0, 0 } | 39 | { 0, 0, 0, 0 } |
36 | }; | 40 | }; |
37 | 41 | ||
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c deleted file mode 100644 index b368cd862997..000000000000 --- a/arch/x86/kernel/cpu/cpu_debug.c +++ /dev/null | |||
@@ -1,688 +0,0 @@ | |||
1 | /* | ||
2 | * CPU x86 architecture debug code | ||
3 | * | ||
4 | * Copyright(C) 2009 Jaswinder Singh Rajput | ||
5 | * | ||
6 | * For licencing details see kernel-base/COPYING | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/compiler.h> | ||
11 | #include <linux/seq_file.h> | ||
12 | #include <linux/debugfs.h> | ||
13 | #include <linux/kprobes.h> | ||
14 | #include <linux/uaccess.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/percpu.h> | ||
18 | #include <linux/signal.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/smp.h> | ||
25 | |||
26 | #include <asm/cpu_debug.h> | ||
27 | #include <asm/paravirt.h> | ||
28 | #include <asm/system.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/apic.h> | ||
31 | #include <asm/desc.h> | ||
32 | |||
33 | static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpud_arr); | ||
34 | static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], cpud_priv_arr); | ||
35 | static DEFINE_PER_CPU(int, cpud_priv_count); | ||
36 | |||
37 | static DEFINE_MUTEX(cpu_debug_lock); | ||
38 | |||
39 | static struct dentry *cpu_debugfs_dir; | ||
40 | |||
41 | static struct cpu_debug_base cpu_base[] = { | ||
42 | { "mc", CPU_MC, 0 }, | ||
43 | { "monitor", CPU_MONITOR, 0 }, | ||
44 | { "time", CPU_TIME, 0 }, | ||
45 | { "pmc", CPU_PMC, 1 }, | ||
46 | { "platform", CPU_PLATFORM, 0 }, | ||
47 | { "apic", CPU_APIC, 0 }, | ||
48 | { "poweron", CPU_POWERON, 0 }, | ||
49 | { "control", CPU_CONTROL, 0 }, | ||
50 | { "features", CPU_FEATURES, 0 }, | ||
51 | { "lastbranch", CPU_LBRANCH, 0 }, | ||
52 | { "bios", CPU_BIOS, 0 }, | ||
53 | { "freq", CPU_FREQ, 0 }, | ||
54 | { "mtrr", CPU_MTRR, 0 }, | ||
55 | { "perf", CPU_PERF, 0 }, | ||
56 | { "cache", CPU_CACHE, 0 }, | ||
57 | { "sysenter", CPU_SYSENTER, 0 }, | ||
58 | { "therm", CPU_THERM, 0 }, | ||
59 | { "misc", CPU_MISC, 0 }, | ||
60 | { "debug", CPU_DEBUG, 0 }, | ||
61 | { "pat", CPU_PAT, 0 }, | ||
62 | { "vmx", CPU_VMX, 0 }, | ||
63 | { "call", CPU_CALL, 0 }, | ||
64 | { "base", CPU_BASE, 0 }, | ||
65 | { "ver", CPU_VER, 0 }, | ||
66 | { "conf", CPU_CONF, 0 }, | ||
67 | { "smm", CPU_SMM, 0 }, | ||
68 | { "svm", CPU_SVM, 0 }, | ||
69 | { "osvm", CPU_OSVM, 0 }, | ||
70 | { "tss", CPU_TSS, 0 }, | ||
71 | { "cr", CPU_CR, 0 }, | ||
72 | { "dt", CPU_DT, 0 }, | ||
73 | { "registers", CPU_REG_ALL, 0 }, | ||
74 | }; | ||
75 | |||
76 | static struct cpu_file_base cpu_file[] = { | ||
77 | { "index", CPU_REG_ALL, 0 }, | ||
78 | { "value", CPU_REG_ALL, 1 }, | ||
79 | }; | ||
80 | |||
81 | /* CPU Registers Range */ | ||
82 | static struct cpu_debug_range cpu_reg_range[] = { | ||
83 | { 0x00000000, 0x00000001, CPU_MC, }, | ||
84 | { 0x00000006, 0x00000007, CPU_MONITOR, }, | ||
85 | { 0x00000010, 0x00000010, CPU_TIME, }, | ||
86 | { 0x00000011, 0x00000013, CPU_PMC, }, | ||
87 | { 0x00000017, 0x00000017, CPU_PLATFORM, }, | ||
88 | { 0x0000001B, 0x0000001B, CPU_APIC, }, | ||
89 | { 0x0000002A, 0x0000002B, CPU_POWERON, }, | ||
90 | { 0x0000002C, 0x0000002C, CPU_FREQ, }, | ||
91 | { 0x0000003A, 0x0000003A, CPU_CONTROL, }, | ||
92 | { 0x00000040, 0x00000047, CPU_LBRANCH, }, | ||
93 | { 0x00000060, 0x00000067, CPU_LBRANCH, }, | ||
94 | { 0x00000079, 0x00000079, CPU_BIOS, }, | ||
95 | { 0x00000088, 0x0000008A, CPU_CACHE, }, | ||
96 | { 0x0000008B, 0x0000008B, CPU_BIOS, }, | ||
97 | { 0x0000009B, 0x0000009B, CPU_MONITOR, }, | ||
98 | { 0x000000C1, 0x000000C4, CPU_PMC, }, | ||
99 | { 0x000000CD, 0x000000CD, CPU_FREQ, }, | ||
100 | { 0x000000E7, 0x000000E8, CPU_PERF, }, | ||
101 | { 0x000000FE, 0x000000FE, CPU_MTRR, }, | ||
102 | |||
103 | { 0x00000116, 0x0000011E, CPU_CACHE, }, | ||
104 | { 0x00000174, 0x00000176, CPU_SYSENTER, }, | ||
105 | { 0x00000179, 0x0000017B, CPU_MC, }, | ||
106 | { 0x00000186, 0x00000189, CPU_PMC, }, | ||
107 | { 0x00000198, 0x00000199, CPU_PERF, }, | ||
108 | { 0x0000019A, 0x0000019A, CPU_TIME, }, | ||
109 | { 0x0000019B, 0x0000019D, CPU_THERM, }, | ||
110 | { 0x000001A0, 0x000001A0, CPU_MISC, }, | ||
111 | { 0x000001C9, 0x000001C9, CPU_LBRANCH, }, | ||
112 | { 0x000001D7, 0x000001D8, CPU_LBRANCH, }, | ||
113 | { 0x000001D9, 0x000001D9, CPU_DEBUG, }, | ||
114 | { 0x000001DA, 0x000001E0, CPU_LBRANCH, }, | ||
115 | |||
116 | { 0x00000200, 0x0000020F, CPU_MTRR, }, | ||
117 | { 0x00000250, 0x00000250, CPU_MTRR, }, | ||
118 | { 0x00000258, 0x00000259, CPU_MTRR, }, | ||
119 | { 0x00000268, 0x0000026F, CPU_MTRR, }, | ||
120 | { 0x00000277, 0x00000277, CPU_PAT, }, | ||
121 | { 0x000002FF, 0x000002FF, CPU_MTRR, }, | ||
122 | |||
123 | { 0x00000300, 0x00000311, CPU_PMC, }, | ||
124 | { 0x00000345, 0x00000345, CPU_PMC, }, | ||
125 | { 0x00000360, 0x00000371, CPU_PMC, }, | ||
126 | { 0x0000038D, 0x00000390, CPU_PMC, }, | ||
127 | { 0x000003A0, 0x000003BE, CPU_PMC, }, | ||
128 | { 0x000003C0, 0x000003CD, CPU_PMC, }, | ||
129 | { 0x000003E0, 0x000003E1, CPU_PMC, }, | ||
130 | { 0x000003F0, 0x000003F2, CPU_PMC, }, | ||
131 | |||
132 | { 0x00000400, 0x00000417, CPU_MC, }, | ||
133 | { 0x00000480, 0x0000048B, CPU_VMX, }, | ||
134 | |||
135 | { 0x00000600, 0x00000600, CPU_DEBUG, }, | ||
136 | { 0x00000680, 0x0000068F, CPU_LBRANCH, }, | ||
137 | { 0x000006C0, 0x000006CF, CPU_LBRANCH, }, | ||
138 | |||
139 | { 0x000107CC, 0x000107D3, CPU_PMC, }, | ||
140 | |||
141 | { 0xC0000080, 0xC0000080, CPU_FEATURES, }, | ||
142 | { 0xC0000081, 0xC0000084, CPU_CALL, }, | ||
143 | { 0xC0000100, 0xC0000102, CPU_BASE, }, | ||
144 | { 0xC0000103, 0xC0000103, CPU_TIME, }, | ||
145 | |||
146 | { 0xC0010000, 0xC0010007, CPU_PMC, }, | ||
147 | { 0xC0010010, 0xC0010010, CPU_CONF, }, | ||
148 | { 0xC0010015, 0xC0010015, CPU_CONF, }, | ||
149 | { 0xC0010016, 0xC001001A, CPU_MTRR, }, | ||
150 | { 0xC001001D, 0xC001001D, CPU_MTRR, }, | ||
151 | { 0xC001001F, 0xC001001F, CPU_CONF, }, | ||
152 | { 0xC0010030, 0xC0010035, CPU_BIOS, }, | ||
153 | { 0xC0010044, 0xC0010048, CPU_MC, }, | ||
154 | { 0xC0010050, 0xC0010056, CPU_SMM, }, | ||
155 | { 0xC0010058, 0xC0010058, CPU_CONF, }, | ||
156 | { 0xC0010060, 0xC0010060, CPU_CACHE, }, | ||
157 | { 0xC0010061, 0xC0010068, CPU_SMM, }, | ||
158 | { 0xC0010069, 0xC001006B, CPU_SMM, }, | ||
159 | { 0xC0010070, 0xC0010071, CPU_SMM, }, | ||
160 | { 0xC0010111, 0xC0010113, CPU_SMM, }, | ||
161 | { 0xC0010114, 0xC0010118, CPU_SVM, }, | ||
162 | { 0xC0010140, 0xC0010141, CPU_OSVM, }, | ||
163 | { 0xC0011022, 0xC0011023, CPU_CONF, }, | ||
164 | }; | ||
165 | |||
166 | static int is_typeflag_valid(unsigned cpu, unsigned flag) | ||
167 | { | ||
168 | int i; | ||
169 | |||
170 | /* Standard Registers should be always valid */ | ||
171 | if (flag >= CPU_TSS) | ||
172 | return 1; | ||
173 | |||
174 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
175 | if (cpu_reg_range[i].flag == flag) | ||
176 | return 1; | ||
177 | } | ||
178 | |||
179 | /* Invalid */ | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max, | ||
184 | int index, unsigned flag) | ||
185 | { | ||
186 | if (cpu_reg_range[index].flag == flag) { | ||
187 | *min = cpu_reg_range[index].min; | ||
188 | *max = cpu_reg_range[index].max; | ||
189 | } else | ||
190 | *max = 0; | ||
191 | |||
192 | return *max; | ||
193 | } | ||
194 | |||
195 | /* This function can also be called with seq = NULL for printk */ | ||
196 | static void print_cpu_data(struct seq_file *seq, unsigned type, | ||
197 | u32 low, u32 high) | ||
198 | { | ||
199 | struct cpu_private *priv; | ||
200 | u64 val = high; | ||
201 | |||
202 | if (seq) { | ||
203 | priv = seq->private; | ||
204 | if (priv->file) { | ||
205 | val = (val << 32) | low; | ||
206 | seq_printf(seq, "0x%llx\n", val); | ||
207 | } else | ||
208 | seq_printf(seq, " %08x: %08x_%08x\n", | ||
209 | type, high, low); | ||
210 | } else | ||
211 | printk(KERN_INFO " %08x: %08x_%08x\n", type, high, low); | ||
212 | } | ||
213 | |||
214 | /* This function can also be called with seq = NULL for printk */ | ||
215 | static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag) | ||
216 | { | ||
217 | unsigned msr, msr_min, msr_max; | ||
218 | struct cpu_private *priv; | ||
219 | u32 low, high; | ||
220 | int i; | ||
221 | |||
222 | if (seq) { | ||
223 | priv = seq->private; | ||
224 | if (priv->file) { | ||
225 | if (!rdmsr_safe_on_cpu(priv->cpu, priv->reg, | ||
226 | &low, &high)) | ||
227 | print_cpu_data(seq, priv->reg, low, high); | ||
228 | return; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
233 | if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag)) | ||
234 | continue; | ||
235 | |||
236 | for (msr = msr_min; msr <= msr_max; msr++) { | ||
237 | if (rdmsr_safe_on_cpu(cpu, msr, &low, &high)) | ||
238 | continue; | ||
239 | print_cpu_data(seq, msr, low, high); | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | static void print_tss(void *arg) | ||
245 | { | ||
246 | struct pt_regs *regs = task_pt_regs(current); | ||
247 | struct seq_file *seq = arg; | ||
248 | unsigned int seg; | ||
249 | |||
250 | seq_printf(seq, " RAX\t: %016lx\n", regs->ax); | ||
251 | seq_printf(seq, " RBX\t: %016lx\n", regs->bx); | ||
252 | seq_printf(seq, " RCX\t: %016lx\n", regs->cx); | ||
253 | seq_printf(seq, " RDX\t: %016lx\n", regs->dx); | ||
254 | |||
255 | seq_printf(seq, " RSI\t: %016lx\n", regs->si); | ||
256 | seq_printf(seq, " RDI\t: %016lx\n", regs->di); | ||
257 | seq_printf(seq, " RBP\t: %016lx\n", regs->bp); | ||
258 | seq_printf(seq, " ESP\t: %016lx\n", regs->sp); | ||
259 | |||
260 | #ifdef CONFIG_X86_64 | ||
261 | seq_printf(seq, " R08\t: %016lx\n", regs->r8); | ||
262 | seq_printf(seq, " R09\t: %016lx\n", regs->r9); | ||
263 | seq_printf(seq, " R10\t: %016lx\n", regs->r10); | ||
264 | seq_printf(seq, " R11\t: %016lx\n", regs->r11); | ||
265 | seq_printf(seq, " R12\t: %016lx\n", regs->r12); | ||
266 | seq_printf(seq, " R13\t: %016lx\n", regs->r13); | ||
267 | seq_printf(seq, " R14\t: %016lx\n", regs->r14); | ||
268 | seq_printf(seq, " R15\t: %016lx\n", regs->r15); | ||
269 | #endif | ||
270 | |||
271 | asm("movl %%cs,%0" : "=r" (seg)); | ||
272 | seq_printf(seq, " CS\t: %04x\n", seg); | ||
273 | asm("movl %%ds,%0" : "=r" (seg)); | ||
274 | seq_printf(seq, " DS\t: %04x\n", seg); | ||
275 | seq_printf(seq, " SS\t: %04lx\n", regs->ss & 0xffff); | ||
276 | asm("movl %%es,%0" : "=r" (seg)); | ||
277 | seq_printf(seq, " ES\t: %04x\n", seg); | ||
278 | asm("movl %%fs,%0" : "=r" (seg)); | ||
279 | seq_printf(seq, " FS\t: %04x\n", seg); | ||
280 | asm("movl %%gs,%0" : "=r" (seg)); | ||
281 | seq_printf(seq, " GS\t: %04x\n", seg); | ||
282 | |||
283 | seq_printf(seq, " EFLAGS\t: %016lx\n", regs->flags); | ||
284 | |||
285 | seq_printf(seq, " EIP\t: %016lx\n", regs->ip); | ||
286 | } | ||
287 | |||
288 | static void print_cr(void *arg) | ||
289 | { | ||
290 | struct seq_file *seq = arg; | ||
291 | |||
292 | seq_printf(seq, " cr0\t: %016lx\n", read_cr0()); | ||
293 | seq_printf(seq, " cr2\t: %016lx\n", read_cr2()); | ||
294 | seq_printf(seq, " cr3\t: %016lx\n", read_cr3()); | ||
295 | seq_printf(seq, " cr4\t: %016lx\n", read_cr4_safe()); | ||
296 | #ifdef CONFIG_X86_64 | ||
297 | seq_printf(seq, " cr8\t: %016lx\n", read_cr8()); | ||
298 | #endif | ||
299 | } | ||
300 | |||
301 | static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt) | ||
302 | { | ||
303 | seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size)); | ||
304 | } | ||
305 | |||
306 | static void print_dt(void *seq) | ||
307 | { | ||
308 | struct desc_ptr dt; | ||
309 | unsigned long ldt; | ||
310 | |||
311 | /* IDT */ | ||
312 | store_idt((struct desc_ptr *)&dt); | ||
313 | print_desc_ptr("IDT", seq, dt); | ||
314 | |||
315 | /* GDT */ | ||
316 | store_gdt((struct desc_ptr *)&dt); | ||
317 | print_desc_ptr("GDT", seq, dt); | ||
318 | |||
319 | /* LDT */ | ||
320 | store_ldt(ldt); | ||
321 | seq_printf(seq, " LDT\t: %016lx\n", ldt); | ||
322 | |||
323 | /* TR */ | ||
324 | store_tr(ldt); | ||
325 | seq_printf(seq, " TR\t: %016lx\n", ldt); | ||
326 | } | ||
327 | |||
328 | static void print_dr(void *arg) | ||
329 | { | ||
330 | struct seq_file *seq = arg; | ||
331 | unsigned long dr; | ||
332 | int i; | ||
333 | |||
334 | for (i = 0; i < 8; i++) { | ||
335 | /* Ignore db4, db5 */ | ||
336 | if ((i == 4) || (i == 5)) | ||
337 | continue; | ||
338 | get_debugreg(dr, i); | ||
339 | seq_printf(seq, " dr%d\t: %016lx\n", i, dr); | ||
340 | } | ||
341 | |||
342 | seq_printf(seq, "\n MSR\t:\n"); | ||
343 | } | ||
344 | |||
345 | static void print_apic(void *arg) | ||
346 | { | ||
347 | struct seq_file *seq = arg; | ||
348 | |||
349 | #ifdef CONFIG_X86_LOCAL_APIC | ||
350 | seq_printf(seq, " LAPIC\t:\n"); | ||
351 | seq_printf(seq, " ID\t\t: %08x\n", apic_read(APIC_ID) >> 24); | ||
352 | seq_printf(seq, " LVR\t\t: %08x\n", apic_read(APIC_LVR)); | ||
353 | seq_printf(seq, " TASKPRI\t: %08x\n", apic_read(APIC_TASKPRI)); | ||
354 | seq_printf(seq, " ARBPRI\t\t: %08x\n", apic_read(APIC_ARBPRI)); | ||
355 | seq_printf(seq, " PROCPRI\t: %08x\n", apic_read(APIC_PROCPRI)); | ||
356 | seq_printf(seq, " LDR\t\t: %08x\n", apic_read(APIC_LDR)); | ||
357 | seq_printf(seq, " DFR\t\t: %08x\n", apic_read(APIC_DFR)); | ||
358 | seq_printf(seq, " SPIV\t\t: %08x\n", apic_read(APIC_SPIV)); | ||
359 | seq_printf(seq, " ISR\t\t: %08x\n", apic_read(APIC_ISR)); | ||
360 | seq_printf(seq, " ESR\t\t: %08x\n", apic_read(APIC_ESR)); | ||
361 | seq_printf(seq, " ICR\t\t: %08x\n", apic_read(APIC_ICR)); | ||
362 | seq_printf(seq, " ICR2\t\t: %08x\n", apic_read(APIC_ICR2)); | ||
363 | seq_printf(seq, " LVTT\t\t: %08x\n", apic_read(APIC_LVTT)); | ||
364 | seq_printf(seq, " LVTTHMR\t: %08x\n", apic_read(APIC_LVTTHMR)); | ||
365 | seq_printf(seq, " LVTPC\t\t: %08x\n", apic_read(APIC_LVTPC)); | ||
366 | seq_printf(seq, " LVT0\t\t: %08x\n", apic_read(APIC_LVT0)); | ||
367 | seq_printf(seq, " LVT1\t\t: %08x\n", apic_read(APIC_LVT1)); | ||
368 | seq_printf(seq, " LVTERR\t\t: %08x\n", apic_read(APIC_LVTERR)); | ||
369 | seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT)); | ||
370 | seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT)); | ||
371 | seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR)); | ||
372 | if (boot_cpu_has(X86_FEATURE_EXTAPIC)) { | ||
373 | unsigned int i, v, maxeilvt; | ||
374 | |||
375 | v = apic_read(APIC_EFEAT); | ||
376 | maxeilvt = (v >> 16) & 0xff; | ||
377 | seq_printf(seq, " EFEAT\t\t: %08x\n", v); | ||
378 | seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL)); | ||
379 | |||
380 | for (i = 0; i < maxeilvt; i++) { | ||
381 | v = apic_read(APIC_EILVTn(i)); | ||
382 | seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v); | ||
383 | } | ||
384 | } | ||
385 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
386 | seq_printf(seq, "\n MSR\t:\n"); | ||
387 | } | ||
388 | |||
389 | static int cpu_seq_show(struct seq_file *seq, void *v) | ||
390 | { | ||
391 | struct cpu_private *priv = seq->private; | ||
392 | |||
393 | if (priv == NULL) | ||
394 | return -EINVAL; | ||
395 | |||
396 | switch (cpu_base[priv->type].flag) { | ||
397 | case CPU_TSS: | ||
398 | smp_call_function_single(priv->cpu, print_tss, seq, 1); | ||
399 | break; | ||
400 | case CPU_CR: | ||
401 | smp_call_function_single(priv->cpu, print_cr, seq, 1); | ||
402 | break; | ||
403 | case CPU_DT: | ||
404 | smp_call_function_single(priv->cpu, print_dt, seq, 1); | ||
405 | break; | ||
406 | case CPU_DEBUG: | ||
407 | if (priv->file == CPU_INDEX_BIT) | ||
408 | smp_call_function_single(priv->cpu, print_dr, seq, 1); | ||
409 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
410 | break; | ||
411 | case CPU_APIC: | ||
412 | if (priv->file == CPU_INDEX_BIT) | ||
413 | smp_call_function_single(priv->cpu, print_apic, seq, 1); | ||
414 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
415 | break; | ||
416 | |||
417 | default: | ||
418 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
419 | break; | ||
420 | } | ||
421 | seq_printf(seq, "\n"); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static void *cpu_seq_start(struct seq_file *seq, loff_t *pos) | ||
427 | { | ||
428 | if (*pos == 0) /* One time is enough ;-) */ | ||
429 | return seq; | ||
430 | |||
431 | return NULL; | ||
432 | } | ||
433 | |||
434 | static void *cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
435 | { | ||
436 | (*pos)++; | ||
437 | |||
438 | return cpu_seq_start(seq, pos); | ||
439 | } | ||
440 | |||
441 | static void cpu_seq_stop(struct seq_file *seq, void *v) | ||
442 | { | ||
443 | } | ||
444 | |||
445 | static const struct seq_operations cpu_seq_ops = { | ||
446 | .start = cpu_seq_start, | ||
447 | .next = cpu_seq_next, | ||
448 | .stop = cpu_seq_stop, | ||
449 | .show = cpu_seq_show, | ||
450 | }; | ||
451 | |||
452 | static int cpu_seq_open(struct inode *inode, struct file *file) | ||
453 | { | ||
454 | struct cpu_private *priv = inode->i_private; | ||
455 | struct seq_file *seq; | ||
456 | int err; | ||
457 | |||
458 | err = seq_open(file, &cpu_seq_ops); | ||
459 | if (!err) { | ||
460 | seq = file->private_data; | ||
461 | seq->private = priv; | ||
462 | } | ||
463 | |||
464 | return err; | ||
465 | } | ||
466 | |||
467 | static int write_msr(struct cpu_private *priv, u64 val) | ||
468 | { | ||
469 | u32 low, high; | ||
470 | |||
471 | high = (val >> 32) & 0xffffffff; | ||
472 | low = val & 0xffffffff; | ||
473 | |||
474 | if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high)) | ||
475 | return 0; | ||
476 | |||
477 | return -EPERM; | ||
478 | } | ||
479 | |||
480 | static int write_cpu_register(struct cpu_private *priv, const char *buf) | ||
481 | { | ||
482 | int ret = -EPERM; | ||
483 | u64 val; | ||
484 | |||
485 | ret = strict_strtoull(buf, 0, &val); | ||
486 | if (ret < 0) | ||
487 | return ret; | ||
488 | |||
489 | /* Supporting only MSRs */ | ||
490 | if (priv->type < CPU_TSS_BIT) | ||
491 | return write_msr(priv, val); | ||
492 | |||
493 | return ret; | ||
494 | } | ||
495 | |||
496 | static ssize_t cpu_write(struct file *file, const char __user *ubuf, | ||
497 | size_t count, loff_t *off) | ||
498 | { | ||
499 | struct seq_file *seq = file->private_data; | ||
500 | struct cpu_private *priv = seq->private; | ||
501 | char buf[19]; | ||
502 | |||
503 | if ((priv == NULL) || (count >= sizeof(buf))) | ||
504 | return -EINVAL; | ||
505 | |||
506 | if (copy_from_user(&buf, ubuf, count)) | ||
507 | return -EFAULT; | ||
508 | |||
509 | buf[count] = 0; | ||
510 | |||
511 | if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write)) | ||
512 | if (!write_cpu_register(priv, buf)) | ||
513 | return count; | ||
514 | |||
515 | return -EACCES; | ||
516 | } | ||
517 | |||
518 | static const struct file_operations cpu_fops = { | ||
519 | .owner = THIS_MODULE, | ||
520 | .open = cpu_seq_open, | ||
521 | .read = seq_read, | ||
522 | .write = cpu_write, | ||
523 | .llseek = seq_lseek, | ||
524 | .release = seq_release, | ||
525 | }; | ||
526 | |||
527 | static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, | ||
528 | unsigned file, struct dentry *dentry) | ||
529 | { | ||
530 | struct cpu_private *priv = NULL; | ||
531 | |||
532 | /* Already intialized */ | ||
533 | if (file == CPU_INDEX_BIT) | ||
534 | if (per_cpu(cpud_arr[type].init, cpu)) | ||
535 | return 0; | ||
536 | |||
537 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
538 | if (priv == NULL) | ||
539 | return -ENOMEM; | ||
540 | |||
541 | priv->cpu = cpu; | ||
542 | priv->type = type; | ||
543 | priv->reg = reg; | ||
544 | priv->file = file; | ||
545 | mutex_lock(&cpu_debug_lock); | ||
546 | per_cpu(cpud_priv_arr[type], cpu) = priv; | ||
547 | per_cpu(cpud_priv_count, cpu)++; | ||
548 | mutex_unlock(&cpu_debug_lock); | ||
549 | |||
550 | if (file) | ||
551 | debugfs_create_file(cpu_file[file].name, S_IRUGO, | ||
552 | dentry, (void *)priv, &cpu_fops); | ||
553 | else { | ||
554 | debugfs_create_file(cpu_base[type].name, S_IRUGO, | ||
555 | per_cpu(cpud_arr[type].dentry, cpu), | ||
556 | (void *)priv, &cpu_fops); | ||
557 | mutex_lock(&cpu_debug_lock); | ||
558 | per_cpu(cpud_arr[type].init, cpu) = 1; | ||
559 | mutex_unlock(&cpu_debug_lock); | ||
560 | } | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg, | ||
566 | struct dentry *dentry) | ||
567 | { | ||
568 | unsigned file; | ||
569 | int err = 0; | ||
570 | |||
571 | for (file = 0; file < ARRAY_SIZE(cpu_file); file++) { | ||
572 | err = cpu_create_file(cpu, type, reg, file, dentry); | ||
573 | if (err) | ||
574 | return err; | ||
575 | } | ||
576 | |||
577 | return err; | ||
578 | } | ||
579 | |||
580 | static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry) | ||
581 | { | ||
582 | struct dentry *cpu_dentry = NULL; | ||
583 | unsigned reg, reg_min, reg_max; | ||
584 | int i, err = 0; | ||
585 | char reg_dir[12]; | ||
586 | u32 low, high; | ||
587 | |||
588 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
589 | if (!get_cpu_range(cpu, ®_min, ®_max, i, | ||
590 | cpu_base[type].flag)) | ||
591 | continue; | ||
592 | |||
593 | for (reg = reg_min; reg <= reg_max; reg++) { | ||
594 | if (rdmsr_safe_on_cpu(cpu, reg, &low, &high)) | ||
595 | continue; | ||
596 | |||
597 | sprintf(reg_dir, "0x%x", reg); | ||
598 | cpu_dentry = debugfs_create_dir(reg_dir, dentry); | ||
599 | err = cpu_init_regfiles(cpu, type, reg, cpu_dentry); | ||
600 | if (err) | ||
601 | return err; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | return err; | ||
606 | } | ||
607 | |||
608 | static int cpu_init_allreg(unsigned cpu, struct dentry *dentry) | ||
609 | { | ||
610 | struct dentry *cpu_dentry = NULL; | ||
611 | unsigned type; | ||
612 | int err = 0; | ||
613 | |||
614 | for (type = 0; type < ARRAY_SIZE(cpu_base) - 1; type++) { | ||
615 | if (!is_typeflag_valid(cpu, cpu_base[type].flag)) | ||
616 | continue; | ||
617 | cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry); | ||
618 | per_cpu(cpud_arr[type].dentry, cpu) = cpu_dentry; | ||
619 | |||
620 | if (type < CPU_TSS_BIT) | ||
621 | err = cpu_init_msr(cpu, type, cpu_dentry); | ||
622 | else | ||
623 | err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT, | ||
624 | cpu_dentry); | ||
625 | if (err) | ||
626 | return err; | ||
627 | } | ||
628 | |||
629 | return err; | ||
630 | } | ||
631 | |||
632 | static int cpu_init_cpu(void) | ||
633 | { | ||
634 | struct dentry *cpu_dentry = NULL; | ||
635 | struct cpuinfo_x86 *cpui; | ||
636 | char cpu_dir[12]; | ||
637 | unsigned cpu; | ||
638 | int err = 0; | ||
639 | |||
640 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
641 | cpui = &cpu_data(cpu); | ||
642 | if (!cpu_has(cpui, X86_FEATURE_MSR)) | ||
643 | continue; | ||
644 | |||
645 | sprintf(cpu_dir, "cpu%d", cpu); | ||
646 | cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir); | ||
647 | err = cpu_init_allreg(cpu, cpu_dentry); | ||
648 | |||
649 | pr_info("cpu%d(%d) debug files %d\n", | ||
650 | cpu, nr_cpu_ids, per_cpu(cpud_priv_count, cpu)); | ||
651 | if (per_cpu(cpud_priv_count, cpu) > MAX_CPU_FILES) { | ||
652 | pr_err("Register files count %d exceeds limit %d\n", | ||
653 | per_cpu(cpud_priv_count, cpu), MAX_CPU_FILES); | ||
654 | per_cpu(cpud_priv_count, cpu) = MAX_CPU_FILES; | ||
655 | err = -ENFILE; | ||
656 | } | ||
657 | if (err) | ||
658 | return err; | ||
659 | } | ||
660 | |||
661 | return err; | ||
662 | } | ||
663 | |||
664 | static int __init cpu_debug_init(void) | ||
665 | { | ||
666 | cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir); | ||
667 | |||
668 | return cpu_init_cpu(); | ||
669 | } | ||
670 | |||
671 | static void __exit cpu_debug_exit(void) | ||
672 | { | ||
673 | int i, cpu; | ||
674 | |||
675 | if (cpu_debugfs_dir) | ||
676 | debugfs_remove_recursive(cpu_debugfs_dir); | ||
677 | |||
678 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) | ||
679 | for (i = 0; i < per_cpu(cpud_priv_count, cpu); i++) | ||
680 | kfree(per_cpu(cpud_priv_arr[i], cpu)); | ||
681 | } | ||
682 | |||
683 | module_init(cpu_debug_init); | ||
684 | module_exit(cpu_debug_exit); | ||
685 | |||
686 | MODULE_AUTHOR("Jaswinder Singh Rajput"); | ||
687 | MODULE_DESCRIPTION("CPU Debug module"); | ||
688 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig index f138c6c389b9..870e6cc6ad28 100644 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig | |||
@@ -10,6 +10,20 @@ if CPU_FREQ | |||
10 | 10 | ||
11 | comment "CPUFreq processor drivers" | 11 | comment "CPUFreq processor drivers" |
12 | 12 | ||
13 | config X86_PCC_CPUFREQ | ||
14 | tristate "Processor Clocking Control interface driver" | ||
15 | depends on ACPI && ACPI_PROCESSOR | ||
16 | help | ||
17 | This driver adds support for the PCC interface. | ||
18 | |||
19 | For details, take a look at: | ||
20 | <file:Documentation/cpu-freq/pcc-cpufreq.txt>. | ||
21 | |||
22 | To compile this driver as a module, choose M here: the | ||
23 | module will be called pcc-cpufreq. | ||
24 | |||
25 | If in doubt, say N. | ||
26 | |||
13 | config X86_ACPI_CPUFREQ | 27 | config X86_ACPI_CPUFREQ |
14 | tristate "ACPI Processor P-States driver" | 28 | tristate "ACPI Processor P-States driver" |
15 | select CPU_FREQ_TABLE | 29 | select CPU_FREQ_TABLE |
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile index 509296df294d..1840c0a5170b 100644 --- a/arch/x86/kernel/cpu/cpufreq/Makefile +++ b/arch/x86/kernel/cpu/cpufreq/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o | 5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o |
6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o | 6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o |
7 | obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o | ||
7 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o | 8 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o |
8 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o | 9 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o |
9 | obj-$(CONFIG_X86_LONGHAUL) += longhaul.o | 10 | obj-$(CONFIG_X86_LONGHAUL) += longhaul.o |
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 1b1920fa7c80..459168083b77 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/cpufreq.h> | 33 | #include <linux/cpufreq.h> |
34 | #include <linux/compiler.h> | 34 | #include <linux/compiler.h> |
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | #include <linux/slab.h> | ||
36 | #include <trace/events/power.h> | 37 | #include <trace/events/power.h> |
37 | 38 | ||
38 | #include <linux/acpi.h> | 39 | #include <linux/acpi.h> |
diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index 006b278b0d5d..c587db472a75 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | 22 | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
26 | 25 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c index ac27ec2264d5..16e3483be9e3 100644 --- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include <linux/cpufreq.h> | 80 | #include <linux/cpufreq.h> |
81 | #include <linux/pci.h> | 81 | #include <linux/pci.h> |
82 | #include <linux/errno.h> | 82 | #include <linux/errno.h> |
83 | #include <linux/slab.h> | ||
83 | 84 | ||
84 | #include <asm/processor-cyrix.h> | 85 | #include <asm/processor-cyrix.h> |
85 | 86 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c index da5f70fcb766..e7b559d74c52 100644 --- a/arch/x86/kernel/cpu/cpufreq/longrun.c +++ b/arch/x86/kernel/cpu/cpufreq/longrun.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/slab.h> | ||
13 | #include <linux/cpufreq.h> | 12 | #include <linux/cpufreq.h> |
14 | #include <linux/timex.h> | 13 | #include <linux/timex.h> |
15 | 14 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 869615193720..7b8a8ba67b07 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
27 | #include <linux/cpufreq.h> | 27 | #include <linux/cpufreq.h> |
28 | #include <linux/slab.h> | ||
29 | #include <linux/cpumask.h> | 28 | #include <linux/cpumask.h> |
30 | #include <linux/timex.h> | 29 | #include <linux/timex.h> |
31 | 30 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c new file mode 100644 index 000000000000..ce7cde713e71 --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c | |||
@@ -0,0 +1,621 @@ | |||
1 | /* | ||
2 | * pcc-cpufreq.c - Processor Clocking Control firmware cpufreq interface | ||
3 | * | ||
4 | * Copyright (C) 2009 Red Hat, Matthew Garrett <mjg@redhat.com> | ||
5 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | ||
6 | * Nagananda Chumbalkar <nagananda.chumbalkar@hp.com> | ||
7 | * | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; version 2 of the License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or NON | ||
17 | * INFRINGEMENT. See the GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/smp.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/cpufreq.h> | ||
32 | #include <linux/compiler.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | #include <linux/acpi.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/uaccess.h> | ||
39 | |||
40 | #include <acpi/processor.h> | ||
41 | |||
42 | #define PCC_VERSION "1.00.00" | ||
43 | #define POLL_LOOPS 300 | ||
44 | |||
45 | #define CMD_COMPLETE 0x1 | ||
46 | #define CMD_GET_FREQ 0x0 | ||
47 | #define CMD_SET_FREQ 0x1 | ||
48 | |||
49 | #define BUF_SZ 4 | ||
50 | |||
51 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ | ||
52 | "pcc-cpufreq", msg) | ||
53 | |||
54 | struct pcc_register_resource { | ||
55 | u8 descriptor; | ||
56 | u16 length; | ||
57 | u8 space_id; | ||
58 | u8 bit_width; | ||
59 | u8 bit_offset; | ||
60 | u8 access_size; | ||
61 | u64 address; | ||
62 | } __attribute__ ((packed)); | ||
63 | |||
64 | struct pcc_memory_resource { | ||
65 | u8 descriptor; | ||
66 | u16 length; | ||
67 | u8 space_id; | ||
68 | u8 resource_usage; | ||
69 | u8 type_specific; | ||
70 | u64 granularity; | ||
71 | u64 minimum; | ||
72 | u64 maximum; | ||
73 | u64 translation_offset; | ||
74 | u64 address_length; | ||
75 | } __attribute__ ((packed)); | ||
76 | |||
77 | static struct cpufreq_driver pcc_cpufreq_driver; | ||
78 | |||
79 | struct pcc_header { | ||
80 | u32 signature; | ||
81 | u16 length; | ||
82 | u8 major; | ||
83 | u8 minor; | ||
84 | u32 features; | ||
85 | u16 command; | ||
86 | u16 status; | ||
87 | u32 latency; | ||
88 | u32 minimum_time; | ||
89 | u32 maximum_time; | ||
90 | u32 nominal; | ||
91 | u32 throttled_frequency; | ||
92 | u32 minimum_frequency; | ||
93 | }; | ||
94 | |||
95 | static void __iomem *pcch_virt_addr; | ||
96 | static struct pcc_header __iomem *pcch_hdr; | ||
97 | |||
98 | static DEFINE_SPINLOCK(pcc_lock); | ||
99 | |||
100 | static struct acpi_generic_address doorbell; | ||
101 | |||
102 | static u64 doorbell_preserve; | ||
103 | static u64 doorbell_write; | ||
104 | |||
105 | static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f, | ||
106 | 0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46}; | ||
107 | |||
108 | struct pcc_cpu { | ||
109 | u32 input_offset; | ||
110 | u32 output_offset; | ||
111 | }; | ||
112 | |||
113 | static struct pcc_cpu *pcc_cpu_info; | ||
114 | |||
115 | static int pcc_cpufreq_verify(struct cpufreq_policy *policy) | ||
116 | { | ||
117 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
118 | policy->cpuinfo.max_freq); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static inline void pcc_cmd(void) | ||
123 | { | ||
124 | u64 doorbell_value; | ||
125 | int i; | ||
126 | |||
127 | acpi_read(&doorbell_value, &doorbell); | ||
128 | acpi_write((doorbell_value & doorbell_preserve) | doorbell_write, | ||
129 | &doorbell); | ||
130 | |||
131 | for (i = 0; i < POLL_LOOPS; i++) { | ||
132 | if (ioread16(&pcch_hdr->status) & CMD_COMPLETE) | ||
133 | break; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static inline void pcc_clear_mapping(void) | ||
138 | { | ||
139 | if (pcch_virt_addr) | ||
140 | iounmap(pcch_virt_addr); | ||
141 | pcch_virt_addr = NULL; | ||
142 | } | ||
143 | |||
144 | static unsigned int pcc_get_freq(unsigned int cpu) | ||
145 | { | ||
146 | struct pcc_cpu *pcc_cpu_data; | ||
147 | unsigned int curr_freq; | ||
148 | unsigned int freq_limit; | ||
149 | u16 status; | ||
150 | u32 input_buffer; | ||
151 | u32 output_buffer; | ||
152 | |||
153 | spin_lock(&pcc_lock); | ||
154 | |||
155 | dprintk("get: get_freq for CPU %d\n", cpu); | ||
156 | pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu); | ||
157 | |||
158 | input_buffer = 0x1; | ||
159 | iowrite32(input_buffer, | ||
160 | (pcch_virt_addr + pcc_cpu_data->input_offset)); | ||
161 | iowrite16(CMD_GET_FREQ, &pcch_hdr->command); | ||
162 | |||
163 | pcc_cmd(); | ||
164 | |||
165 | output_buffer = | ||
166 | ioread32(pcch_virt_addr + pcc_cpu_data->output_offset); | ||
167 | |||
168 | /* Clear the input buffer - we are done with the current command */ | ||
169 | memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ); | ||
170 | |||
171 | status = ioread16(&pcch_hdr->status); | ||
172 | if (status != CMD_COMPLETE) { | ||
173 | dprintk("get: FAILED: for CPU %d, status is %d\n", | ||
174 | cpu, status); | ||
175 | goto cmd_incomplete; | ||
176 | } | ||
177 | iowrite16(0, &pcch_hdr->status); | ||
178 | curr_freq = (((ioread32(&pcch_hdr->nominal) * (output_buffer & 0xff)) | ||
179 | / 100) * 1000); | ||
180 | |||
181 | dprintk("get: SUCCESS: (virtual) output_offset for cpu %d is " | ||
182 | "0x%x, contains a value of: 0x%x. Speed is: %d MHz\n", | ||
183 | cpu, (pcch_virt_addr + pcc_cpu_data->output_offset), | ||
184 | output_buffer, curr_freq); | ||
185 | |||
186 | freq_limit = (output_buffer >> 8) & 0xff; | ||
187 | if (freq_limit != 0xff) { | ||
188 | dprintk("get: frequency for cpu %d is being temporarily" | ||
189 | " capped at %d\n", cpu, curr_freq); | ||
190 | } | ||
191 | |||
192 | spin_unlock(&pcc_lock); | ||
193 | return curr_freq; | ||
194 | |||
195 | cmd_incomplete: | ||
196 | iowrite16(0, &pcch_hdr->status); | ||
197 | spin_unlock(&pcc_lock); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | static int pcc_cpufreq_target(struct cpufreq_policy *policy, | ||
202 | unsigned int target_freq, | ||
203 | unsigned int relation) | ||
204 | { | ||
205 | struct pcc_cpu *pcc_cpu_data; | ||
206 | struct cpufreq_freqs freqs; | ||
207 | u16 status; | ||
208 | u32 input_buffer; | ||
209 | int cpu; | ||
210 | |||
211 | spin_lock(&pcc_lock); | ||
212 | cpu = policy->cpu; | ||
213 | pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu); | ||
214 | |||
215 | dprintk("target: CPU %d should go to target freq: %d " | ||
216 | "(virtual) input_offset is 0x%x\n", | ||
217 | cpu, target_freq, | ||
218 | (pcch_virt_addr + pcc_cpu_data->input_offset)); | ||
219 | |||
220 | freqs.new = target_freq; | ||
221 | freqs.cpu = cpu; | ||
222 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
223 | |||
224 | input_buffer = 0x1 | (((target_freq * 100) | ||
225 | / (ioread32(&pcch_hdr->nominal) * 1000)) << 8); | ||
226 | iowrite32(input_buffer, | ||
227 | (pcch_virt_addr + pcc_cpu_data->input_offset)); | ||
228 | iowrite16(CMD_SET_FREQ, &pcch_hdr->command); | ||
229 | |||
230 | pcc_cmd(); | ||
231 | |||
232 | /* Clear the input buffer - we are done with the current command */ | ||
233 | memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ); | ||
234 | |||
235 | status = ioread16(&pcch_hdr->status); | ||
236 | if (status != CMD_COMPLETE) { | ||
237 | dprintk("target: FAILED for cpu %d, with status: 0x%x\n", | ||
238 | cpu, status); | ||
239 | goto cmd_incomplete; | ||
240 | } | ||
241 | iowrite16(0, &pcch_hdr->status); | ||
242 | |||
243 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
244 | dprintk("target: was SUCCESSFUL for cpu %d\n", cpu); | ||
245 | spin_unlock(&pcc_lock); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | cmd_incomplete: | ||
250 | iowrite16(0, &pcch_hdr->status); | ||
251 | spin_unlock(&pcc_lock); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | static int pcc_get_offset(int cpu) | ||
256 | { | ||
257 | acpi_status status; | ||
258 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
259 | union acpi_object *pccp, *offset; | ||
260 | struct pcc_cpu *pcc_cpu_data; | ||
261 | struct acpi_processor *pr; | ||
262 | int ret = 0; | ||
263 | |||
264 | pr = per_cpu(processors, cpu); | ||
265 | pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu); | ||
266 | |||
267 | status = acpi_evaluate_object(pr->handle, "PCCP", NULL, &buffer); | ||
268 | if (ACPI_FAILURE(status)) | ||
269 | return -ENODEV; | ||
270 | |||
271 | pccp = buffer.pointer; | ||
272 | if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) { | ||
273 | ret = -ENODEV; | ||
274 | goto out_free; | ||
275 | }; | ||
276 | |||
277 | offset = &(pccp->package.elements[0]); | ||
278 | if (!offset || offset->type != ACPI_TYPE_INTEGER) { | ||
279 | ret = -ENODEV; | ||
280 | goto out_free; | ||
281 | } | ||
282 | |||
283 | pcc_cpu_data->input_offset = offset->integer.value; | ||
284 | |||
285 | offset = &(pccp->package.elements[1]); | ||
286 | if (!offset || offset->type != ACPI_TYPE_INTEGER) { | ||
287 | ret = -ENODEV; | ||
288 | goto out_free; | ||
289 | } | ||
290 | |||
291 | pcc_cpu_data->output_offset = offset->integer.value; | ||
292 | |||
293 | memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ); | ||
294 | memset_io((pcch_virt_addr + pcc_cpu_data->output_offset), 0, BUF_SZ); | ||
295 | |||
296 | dprintk("pcc_get_offset: for CPU %d: pcc_cpu_data " | ||
297 | "input_offset: 0x%x, pcc_cpu_data output_offset: 0x%x\n", | ||
298 | cpu, pcc_cpu_data->input_offset, pcc_cpu_data->output_offset); | ||
299 | out_free: | ||
300 | kfree(buffer.pointer); | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static int __init pcc_cpufreq_do_osc(acpi_handle *handle) | ||
305 | { | ||
306 | acpi_status status; | ||
307 | struct acpi_object_list input; | ||
308 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
309 | union acpi_object in_params[4]; | ||
310 | union acpi_object *out_obj; | ||
311 | u32 capabilities[2]; | ||
312 | u32 errors; | ||
313 | u32 supported; | ||
314 | int ret = 0; | ||
315 | |||
316 | input.count = 4; | ||
317 | input.pointer = in_params; | ||
318 | input.count = 4; | ||
319 | input.pointer = in_params; | ||
320 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
321 | in_params[0].buffer.length = 16; | ||
322 | in_params[0].buffer.pointer = OSC_UUID; | ||
323 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
324 | in_params[1].integer.value = 1; | ||
325 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
326 | in_params[2].integer.value = 2; | ||
327 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
328 | in_params[3].buffer.length = 8; | ||
329 | in_params[3].buffer.pointer = (u8 *)&capabilities; | ||
330 | |||
331 | capabilities[0] = OSC_QUERY_ENABLE; | ||
332 | capabilities[1] = 0x1; | ||
333 | |||
334 | status = acpi_evaluate_object(*handle, "_OSC", &input, &output); | ||
335 | if (ACPI_FAILURE(status)) | ||
336 | return -ENODEV; | ||
337 | |||
338 | if (!output.length) | ||
339 | return -ENODEV; | ||
340 | |||
341 | out_obj = output.pointer; | ||
342 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
343 | ret = -ENODEV; | ||
344 | goto out_free; | ||
345 | } | ||
346 | |||
347 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
348 | if (errors) { | ||
349 | ret = -ENODEV; | ||
350 | goto out_free; | ||
351 | } | ||
352 | |||
353 | supported = *((u32 *)(out_obj->buffer.pointer + 4)); | ||
354 | if (!(supported & 0x1)) { | ||
355 | ret = -ENODEV; | ||
356 | goto out_free; | ||
357 | } | ||
358 | |||
359 | kfree(output.pointer); | ||
360 | capabilities[0] = 0x0; | ||
361 | capabilities[1] = 0x1; | ||
362 | |||
363 | status = acpi_evaluate_object(*handle, "_OSC", &input, &output); | ||
364 | if (ACPI_FAILURE(status)) | ||
365 | return -ENODEV; | ||
366 | |||
367 | if (!output.length) | ||
368 | return -ENODEV; | ||
369 | |||
370 | out_obj = output.pointer; | ||
371 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
372 | ret = -ENODEV; | ||
373 | goto out_free; | ||
374 | } | ||
375 | |||
376 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
377 | if (errors) { | ||
378 | ret = -ENODEV; | ||
379 | goto out_free; | ||
380 | } | ||
381 | |||
382 | supported = *((u32 *)(out_obj->buffer.pointer + 4)); | ||
383 | if (!(supported & 0x1)) { | ||
384 | ret = -ENODEV; | ||
385 | goto out_free; | ||
386 | } | ||
387 | |||
388 | out_free: | ||
389 | kfree(output.pointer); | ||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | static int __init pcc_cpufreq_probe(void) | ||
394 | { | ||
395 | acpi_status status; | ||
396 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
397 | struct pcc_memory_resource *mem_resource; | ||
398 | struct pcc_register_resource *reg_resource; | ||
399 | union acpi_object *out_obj, *member; | ||
400 | acpi_handle handle, osc_handle; | ||
401 | int ret = 0; | ||
402 | |||
403 | status = acpi_get_handle(NULL, "\\_SB", &handle); | ||
404 | if (ACPI_FAILURE(status)) | ||
405 | return -ENODEV; | ||
406 | |||
407 | status = acpi_get_handle(handle, "_OSC", &osc_handle); | ||
408 | if (ACPI_SUCCESS(status)) { | ||
409 | ret = pcc_cpufreq_do_osc(&osc_handle); | ||
410 | if (ret) | ||
411 | dprintk("probe: _OSC evaluation did not succeed\n"); | ||
412 | /* Firmware's use of _OSC is optional */ | ||
413 | ret = 0; | ||
414 | } | ||
415 | |||
416 | status = acpi_evaluate_object(handle, "PCCH", NULL, &output); | ||
417 | if (ACPI_FAILURE(status)) | ||
418 | return -ENODEV; | ||
419 | |||
420 | out_obj = output.pointer; | ||
421 | if (out_obj->type != ACPI_TYPE_PACKAGE) { | ||
422 | ret = -ENODEV; | ||
423 | goto out_free; | ||
424 | } | ||
425 | |||
426 | member = &out_obj->package.elements[0]; | ||
427 | if (member->type != ACPI_TYPE_BUFFER) { | ||
428 | ret = -ENODEV; | ||
429 | goto out_free; | ||
430 | } | ||
431 | |||
432 | mem_resource = (struct pcc_memory_resource *)member->buffer.pointer; | ||
433 | |||
434 | dprintk("probe: mem_resource descriptor: 0x%x," | ||
435 | " length: %d, space_id: %d, resource_usage: %d," | ||
436 | " type_specific: %d, granularity: 0x%llx," | ||
437 | " minimum: 0x%llx, maximum: 0x%llx," | ||
438 | " translation_offset: 0x%llx, address_length: 0x%llx\n", | ||
439 | mem_resource->descriptor, mem_resource->length, | ||
440 | mem_resource->space_id, mem_resource->resource_usage, | ||
441 | mem_resource->type_specific, mem_resource->granularity, | ||
442 | mem_resource->minimum, mem_resource->maximum, | ||
443 | mem_resource->translation_offset, | ||
444 | mem_resource->address_length); | ||
445 | |||
446 | if (mem_resource->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
447 | ret = -ENODEV; | ||
448 | goto out_free; | ||
449 | } | ||
450 | |||
451 | pcch_virt_addr = ioremap_nocache(mem_resource->minimum, | ||
452 | mem_resource->address_length); | ||
453 | if (pcch_virt_addr == NULL) { | ||
454 | dprintk("probe: could not map shared mem region\n"); | ||
455 | goto out_free; | ||
456 | } | ||
457 | pcch_hdr = pcch_virt_addr; | ||
458 | |||
459 | dprintk("probe: PCCH header (virtual) addr: 0x%p\n", pcch_hdr); | ||
460 | dprintk("probe: PCCH header is at physical address: 0x%llx," | ||
461 | " signature: 0x%x, length: %d bytes, major: %d, minor: %d," | ||
462 | " supported features: 0x%x, command field: 0x%x," | ||
463 | " status field: 0x%x, nominal latency: %d us\n", | ||
464 | mem_resource->minimum, ioread32(&pcch_hdr->signature), | ||
465 | ioread16(&pcch_hdr->length), ioread8(&pcch_hdr->major), | ||
466 | ioread8(&pcch_hdr->minor), ioread32(&pcch_hdr->features), | ||
467 | ioread16(&pcch_hdr->command), ioread16(&pcch_hdr->status), | ||
468 | ioread32(&pcch_hdr->latency)); | ||
469 | |||
470 | dprintk("probe: min time between commands: %d us," | ||
471 | " max time between commands: %d us," | ||
472 | " nominal CPU frequency: %d MHz," | ||
473 | " minimum CPU frequency: %d MHz," | ||
474 | " minimum CPU frequency without throttling: %d MHz\n", | ||
475 | ioread32(&pcch_hdr->minimum_time), | ||
476 | ioread32(&pcch_hdr->maximum_time), | ||
477 | ioread32(&pcch_hdr->nominal), | ||
478 | ioread32(&pcch_hdr->throttled_frequency), | ||
479 | ioread32(&pcch_hdr->minimum_frequency)); | ||
480 | |||
481 | member = &out_obj->package.elements[1]; | ||
482 | if (member->type != ACPI_TYPE_BUFFER) { | ||
483 | ret = -ENODEV; | ||
484 | goto pcch_free; | ||
485 | } | ||
486 | |||
487 | reg_resource = (struct pcc_register_resource *)member->buffer.pointer; | ||
488 | |||
489 | doorbell.space_id = reg_resource->space_id; | ||
490 | doorbell.bit_width = reg_resource->bit_width; | ||
491 | doorbell.bit_offset = reg_resource->bit_offset; | ||
492 | doorbell.access_width = 64; | ||
493 | doorbell.address = reg_resource->address; | ||
494 | |||
495 | dprintk("probe: doorbell: space_id is %d, bit_width is %d, " | ||
496 | "bit_offset is %d, access_width is %d, address is 0x%llx\n", | ||
497 | doorbell.space_id, doorbell.bit_width, doorbell.bit_offset, | ||
498 | doorbell.access_width, reg_resource->address); | ||
499 | |||
500 | member = &out_obj->package.elements[2]; | ||
501 | if (member->type != ACPI_TYPE_INTEGER) { | ||
502 | ret = -ENODEV; | ||
503 | goto pcch_free; | ||
504 | } | ||
505 | |||
506 | doorbell_preserve = member->integer.value; | ||
507 | |||
508 | member = &out_obj->package.elements[3]; | ||
509 | if (member->type != ACPI_TYPE_INTEGER) { | ||
510 | ret = -ENODEV; | ||
511 | goto pcch_free; | ||
512 | } | ||
513 | |||
514 | doorbell_write = member->integer.value; | ||
515 | |||
516 | dprintk("probe: doorbell_preserve: 0x%llx," | ||
517 | " doorbell_write: 0x%llx\n", | ||
518 | doorbell_preserve, doorbell_write); | ||
519 | |||
520 | pcc_cpu_info = alloc_percpu(struct pcc_cpu); | ||
521 | if (!pcc_cpu_info) { | ||
522 | ret = -ENOMEM; | ||
523 | goto pcch_free; | ||
524 | } | ||
525 | |||
526 | printk(KERN_DEBUG "pcc-cpufreq: (v%s) driver loaded with frequency" | ||
527 | " limits: %d MHz, %d MHz\n", PCC_VERSION, | ||
528 | ioread32(&pcch_hdr->minimum_frequency), | ||
529 | ioread32(&pcch_hdr->nominal)); | ||
530 | kfree(output.pointer); | ||
531 | return ret; | ||
532 | pcch_free: | ||
533 | pcc_clear_mapping(); | ||
534 | out_free: | ||
535 | kfree(output.pointer); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
540 | { | ||
541 | unsigned int cpu = policy->cpu; | ||
542 | unsigned int result = 0; | ||
543 | |||
544 | if (!pcch_virt_addr) { | ||
545 | result = -1; | ||
546 | goto pcch_null; | ||
547 | } | ||
548 | |||
549 | result = pcc_get_offset(cpu); | ||
550 | if (result) { | ||
551 | dprintk("init: PCCP evaluation failed\n"); | ||
552 | goto free; | ||
553 | } | ||
554 | |||
555 | policy->max = policy->cpuinfo.max_freq = | ||
556 | ioread32(&pcch_hdr->nominal) * 1000; | ||
557 | policy->min = policy->cpuinfo.min_freq = | ||
558 | ioread32(&pcch_hdr->minimum_frequency) * 1000; | ||
559 | policy->cur = pcc_get_freq(cpu); | ||
560 | |||
561 | dprintk("init: policy->max is %d, policy->min is %d\n", | ||
562 | policy->max, policy->min); | ||
563 | |||
564 | return 0; | ||
565 | free: | ||
566 | pcc_clear_mapping(); | ||
567 | free_percpu(pcc_cpu_info); | ||
568 | pcch_null: | ||
569 | return result; | ||
570 | } | ||
571 | |||
572 | static int pcc_cpufreq_cpu_exit(struct cpufreq_policy *policy) | ||
573 | { | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static struct cpufreq_driver pcc_cpufreq_driver = { | ||
578 | .flags = CPUFREQ_CONST_LOOPS, | ||
579 | .get = pcc_get_freq, | ||
580 | .verify = pcc_cpufreq_verify, | ||
581 | .target = pcc_cpufreq_target, | ||
582 | .init = pcc_cpufreq_cpu_init, | ||
583 | .exit = pcc_cpufreq_cpu_exit, | ||
584 | .name = "pcc-cpufreq", | ||
585 | .owner = THIS_MODULE, | ||
586 | }; | ||
587 | |||
588 | static int __init pcc_cpufreq_init(void) | ||
589 | { | ||
590 | int ret; | ||
591 | |||
592 | if (acpi_disabled) | ||
593 | return 0; | ||
594 | |||
595 | ret = pcc_cpufreq_probe(); | ||
596 | if (ret) { | ||
597 | dprintk("pcc_cpufreq_init: PCCH evaluation failed\n"); | ||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | ret = cpufreq_register_driver(&pcc_cpufreq_driver); | ||
602 | |||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static void __exit pcc_cpufreq_exit(void) | ||
607 | { | ||
608 | cpufreq_unregister_driver(&pcc_cpufreq_driver); | ||
609 | |||
610 | pcc_clear_mapping(); | ||
611 | |||
612 | free_percpu(pcc_cpu_info); | ||
613 | } | ||
614 | |||
615 | MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar"); | ||
616 | MODULE_VERSION(PCC_VERSION); | ||
617 | MODULE_DESCRIPTION("Processor Clocking Control interface driver"); | ||
618 | MODULE_LICENSE("GPL"); | ||
619 | |||
620 | late_initcall(pcc_cpufreq_init); | ||
621 | module_exit(pcc_cpufreq_exit); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index cb01dac267d3..b3379d6a5c57 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/cpufreq.h> | 14 | #include <linux/cpufreq.h> |
15 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
16 | #include <linux/slab.h> | ||
17 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
18 | #include <linux/io.h> | 17 | #include <linux/io.h> |
19 | 18 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index f125e5c551c0..b6215b9798e2 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -806,7 +806,7 @@ static int find_psb_table(struct powernow_k8_data *data) | |||
806 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, | 806 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, |
807 | unsigned int index) | 807 | unsigned int index) |
808 | { | 808 | { |
809 | acpi_integer control; | 809 | u64 control; |
810 | 810 | ||
811 | if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) | 811 | if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) |
812 | return; | 812 | return; |
@@ -824,7 +824,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
824 | { | 824 | { |
825 | struct cpufreq_frequency_table *powernow_table; | 825 | struct cpufreq_frequency_table *powernow_table; |
826 | int ret_val = -ENODEV; | 826 | int ret_val = -ENODEV; |
827 | acpi_integer control, status; | 827 | u64 control, status; |
828 | 828 | ||
829 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { | 829 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { |
830 | dprintk("register performance failed: bad ACPI data\n"); | 830 | dprintk("register performance failed: bad ACPI data\n"); |
@@ -929,7 +929,8 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, | |||
929 | powernow_table[i].index = index; | 929 | powernow_table[i].index = index; |
930 | 930 | ||
931 | /* Frequency may be rounded for these */ | 931 | /* Frequency may be rounded for these */ |
932 | if (boot_cpu_data.x86 == 0x10 || boot_cpu_data.x86 == 0x11) { | 932 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) |
933 | || boot_cpu_data.x86 == 0x11) { | ||
933 | powernow_table[i].frequency = | 934 | powernow_table[i].frequency = |
934 | freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); | 935 | freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); |
935 | } else | 936 | } else |
@@ -948,7 +949,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, | |||
948 | u32 fid; | 949 | u32 fid; |
949 | u32 vid; | 950 | u32 vid; |
950 | u32 freq, index; | 951 | u32 freq, index; |
951 | acpi_integer status, control; | 952 | u64 status, control; |
952 | 953 | ||
953 | if (data->exttype) { | 954 | if (data->exttype) { |
954 | status = data->acpi_data.states[i].status; | 955 | status = data->acpi_data.states[i].status; |
@@ -1356,6 +1357,7 @@ static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol) | |||
1356 | 1357 | ||
1357 | kfree(data->powernow_table); | 1358 | kfree(data->powernow_table); |
1358 | kfree(data); | 1359 | kfree(data); |
1360 | per_cpu(powernow_data, pol->cpu) = NULL; | ||
1359 | 1361 | ||
1360 | return 0; | 1362 | return 0; |
1361 | } | 1363 | } |
@@ -1375,7 +1377,7 @@ static unsigned int powernowk8_get(unsigned int cpu) | |||
1375 | int err; | 1377 | int err; |
1376 | 1378 | ||
1377 | if (!data) | 1379 | if (!data) |
1378 | return -EINVAL; | 1380 | return 0; |
1379 | 1381 | ||
1380 | smp_call_function_single(cpu, query_values_on_cpu, &err, true); | 1382 | smp_call_function_single(cpu, query_values_on_cpu, &err, true); |
1381 | if (err) | 1383 | if (err) |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 8d672ef162ce..9b1ff37de46a 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/sched.h> /* current */ | 20 | #include <linux/sched.h> /* current */ |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | #include <linux/gfp.h> | ||
23 | 24 | ||
24 | #include <asm/msr.h> | 25 | #include <asm/msr.h> |
25 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 2ce8e0b5cc54..561758e95180 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/slab.h> | ||
27 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
28 | 27 | ||
29 | #include "speedstep-lib.h" | 28 | #include "speedstep-lib.h" |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c index ad0083abfa23..a94ec6be69fa 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/cpufreq.h> | 15 | #include <linux/cpufreq.h> |
16 | #include <linux/slab.h> | ||
17 | 16 | ||
18 | #include <asm/msr.h> | 17 | #include <asm/msr.h> |
19 | #include <asm/tsc.h> | 18 | #include <asm/tsc.h> |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index 04d73c114e49..8abd869baabf 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/cpufreq.h> | 19 | #include <linux/cpufreq.h> |
20 | #include <linux/slab.h> | ||
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
23 | #include <asm/ist.h> | 22 | #include <asm/ist.h> |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 879666f4d871..1366c7cfd483 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -47,6 +47,27 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | |||
47 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) | 47 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) |
48 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 48 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
49 | 49 | ||
50 | /* | ||
51 | * Atom erratum AAE44/AAF40/AAG38/AAH41: | ||
52 | * | ||
53 | * A race condition between speculative fetches and invalidating | ||
54 | * a large page. This is worked around in microcode, but we | ||
55 | * need the microcode to have already been loaded... so if it is | ||
56 | * not, recommend a BIOS update and disable large pages. | ||
57 | */ | ||
58 | if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) { | ||
59 | u32 ucode, junk; | ||
60 | |||
61 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
62 | sync_core(); | ||
63 | rdmsr(MSR_IA32_UCODE_REV, junk, ucode); | ||
64 | |||
65 | if (ucode < 0x20e) { | ||
66 | printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n"); | ||
67 | clear_cpu_cap(c, X86_FEATURE_PSE); | ||
68 | } | ||
69 | } | ||
70 | |||
50 | #ifdef CONFIG_X86_64 | 71 | #ifdef CONFIG_X86_64 |
51 | set_cpu_cap(c, X86_FEATURE_SYSENTER32); | 72 | set_cpu_cap(c, X86_FEATURE_SYSENTER32); |
52 | #else | 73 | #else |
@@ -70,7 +91,8 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | |||
70 | if (c->x86_power & (1 << 8)) { | 91 | if (c->x86_power & (1 << 8)) { |
71 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 92 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
72 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); | 93 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); |
73 | sched_clock_stable = 1; | 94 | if (!check_tsc_unstable()) |
95 | sched_clock_stable = 1; | ||
74 | } | 96 | } |
75 | 97 | ||
76 | /* | 98 | /* |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index fc6c8ef92dcc..b3eeb66c0a51 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <asm/k8.h> | 20 | #include <asm/k8.h> |
21 | #include <asm/smp.h> | ||
21 | 22 | ||
22 | #define LVL_1_INST 1 | 23 | #define LVL_1_INST 1 |
23 | #define LVL_1_DATA 2 | 24 | #define LVL_1_DATA 2 |
@@ -31,6 +32,8 @@ struct _cache_table { | |||
31 | short size; | 32 | short size; |
32 | }; | 33 | }; |
33 | 34 | ||
35 | #define MB(x) ((x) * 1024) | ||
36 | |||
34 | /* All the cache descriptor types we care about (no TLB or | 37 | /* All the cache descriptor types we care about (no TLB or |
35 | trace cache entries) */ | 38 | trace cache entries) */ |
36 | 39 | ||
@@ -44,9 +47,9 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
44 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ | 47 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ |
45 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ | 48 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ |
46 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 49 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
47 | { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 50 | { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
48 | { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 51 | { 0x25, LVL_3, MB(2) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
49 | { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 52 | { 0x29, LVL_3, MB(4) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
50 | { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ | 53 | { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ |
51 | { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ | 54 | { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ |
52 | { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 55 | { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
@@ -59,16 +62,16 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
59 | { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ | 62 | { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ |
60 | { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ | 63 | { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ |
61 | { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ | 64 | { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ |
62 | { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */ | 65 | { 0x44, LVL_2, MB(1) }, /* 4-way set assoc, 32 byte line size */ |
63 | { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */ | 66 | { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */ |
64 | { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */ | 67 | { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */ |
65 | { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */ | 68 | { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */ |
66 | { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ | 69 | { 0x49, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */ |
67 | { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */ | 70 | { 0x4a, LVL_3, MB(6) }, /* 12-way set assoc, 64 byte line size */ |
68 | { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ | 71 | { 0x4b, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */ |
69 | { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */ | 72 | { 0x4c, LVL_3, MB(12) }, /* 12-way set assoc, 64 byte line size */ |
70 | { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */ | 73 | { 0x4d, LVL_3, MB(16) }, /* 16-way set assoc, 64 byte line size */ |
71 | { 0x4e, LVL_2, 6144 }, /* 24-way set assoc, 64 byte line size */ | 74 | { 0x4e, LVL_2, MB(6) }, /* 24-way set assoc, 64 byte line size */ |
72 | { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 75 | { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
73 | { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 76 | { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
74 | { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 77 | { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
@@ -77,34 +80,34 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
77 | { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ | 80 | { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ |
78 | { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ | 81 | { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ |
79 | { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ | 82 | { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ |
80 | { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */ | 83 | { 0x78, LVL_2, MB(1) }, /* 4-way set assoc, 64 byte line size */ |
81 | { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 84 | { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
82 | { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 85 | { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
83 | { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 86 | { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
84 | { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 87 | { 0x7c, LVL_2, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
85 | { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */ | 88 | { 0x7d, LVL_2, MB(2) }, /* 8-way set assoc, 64 byte line size */ |
86 | { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ | 89 | { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ |
87 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ | 90 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ |
88 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ | 91 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ |
89 | { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */ | 92 | { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */ |
90 | { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */ | 93 | { 0x85, LVL_2, MB(2) }, /* 8-way set assoc, 32 byte line size */ |
91 | { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ | 94 | { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ |
92 | { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */ | 95 | { 0x87, LVL_2, MB(1) }, /* 8-way set assoc, 64 byte line size */ |
93 | { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */ | 96 | { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */ |
94 | { 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */ | 97 | { 0xd1, LVL_3, MB(1) }, /* 4-way set assoc, 64 byte line size */ |
95 | { 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */ | 98 | { 0xd2, LVL_3, MB(2) }, /* 4-way set assoc, 64 byte line size */ |
96 | { 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */ | 99 | { 0xd6, LVL_3, MB(1) }, /* 8-way set assoc, 64 byte line size */ |
97 | { 0xd7, LVL_3, 2048 }, /* 8-way set assoc, 64 byte line size */ | 100 | { 0xd7, LVL_3, MB(2) }, /* 8-way set assoc, 64 byte line size */ |
98 | { 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ | 101 | { 0xd8, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */ |
99 | { 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */ | 102 | { 0xdc, LVL_3, MB(2) }, /* 12-way set assoc, 64 byte line size */ |
100 | { 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ | 103 | { 0xdd, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */ |
101 | { 0xde, LVL_3, 8192 }, /* 12-way set assoc, 64 byte line size */ | 104 | { 0xde, LVL_3, MB(8) }, /* 12-way set assoc, 64 byte line size */ |
102 | { 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */ | 105 | { 0xe2, LVL_3, MB(2) }, /* 16-way set assoc, 64 byte line size */ |
103 | { 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ | 106 | { 0xe3, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */ |
104 | { 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ | 107 | { 0xe4, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */ |
105 | { 0xea, LVL_3, 12288 }, /* 24-way set assoc, 64 byte line size */ | 108 | { 0xea, LVL_3, MB(12) }, /* 24-way set assoc, 64 byte line size */ |
106 | { 0xeb, LVL_3, 18432 }, /* 24-way set assoc, 64 byte line size */ | 109 | { 0xeb, LVL_3, MB(18) }, /* 24-way set assoc, 64 byte line size */ |
107 | { 0xec, LVL_3, 24576 }, /* 24-way set assoc, 64 byte line size */ | 110 | { 0xec, LVL_3, MB(24) }, /* 24-way set assoc, 64 byte line size */ |
108 | { 0x00, 0, 0} | 111 | { 0x00, 0, 0} |
109 | }; | 112 | }; |
110 | 113 | ||
@@ -150,7 +153,8 @@ struct _cpuid4_info { | |||
150 | union _cpuid4_leaf_ebx ebx; | 153 | union _cpuid4_leaf_ebx ebx; |
151 | union _cpuid4_leaf_ecx ecx; | 154 | union _cpuid4_leaf_ecx ecx; |
152 | unsigned long size; | 155 | unsigned long size; |
153 | unsigned long can_disable; | 156 | bool can_disable; |
157 | unsigned int l3_indices; | ||
154 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | 158 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); |
155 | }; | 159 | }; |
156 | 160 | ||
@@ -160,7 +164,8 @@ struct _cpuid4_info_regs { | |||
160 | union _cpuid4_leaf_ebx ebx; | 164 | union _cpuid4_leaf_ebx ebx; |
161 | union _cpuid4_leaf_ecx ecx; | 165 | union _cpuid4_leaf_ecx ecx; |
162 | unsigned long size; | 166 | unsigned long size; |
163 | unsigned long can_disable; | 167 | bool can_disable; |
168 | unsigned int l3_indices; | ||
164 | }; | 169 | }; |
165 | 170 | ||
166 | unsigned short num_cache_leaves; | 171 | unsigned short num_cache_leaves; |
@@ -290,6 +295,36 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, | |||
290 | (ebx->split.ways_of_associativity + 1) - 1; | 295 | (ebx->split.ways_of_associativity + 1) - 1; |
291 | } | 296 | } |
292 | 297 | ||
298 | struct _cache_attr { | ||
299 | struct attribute attr; | ||
300 | ssize_t (*show)(struct _cpuid4_info *, char *); | ||
301 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); | ||
302 | }; | ||
303 | |||
304 | #ifdef CONFIG_CPU_SUP_AMD | ||
305 | static unsigned int __cpuinit amd_calc_l3_indices(void) | ||
306 | { | ||
307 | /* | ||
308 | * We're called over smp_call_function_single() and therefore | ||
309 | * are on the correct cpu. | ||
310 | */ | ||
311 | int cpu = smp_processor_id(); | ||
312 | int node = cpu_to_node(cpu); | ||
313 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
314 | unsigned int sc0, sc1, sc2, sc3; | ||
315 | u32 val = 0; | ||
316 | |||
317 | pci_read_config_dword(dev, 0x1C4, &val); | ||
318 | |||
319 | /* calculate subcache sizes */ | ||
320 | sc0 = !(val & BIT(0)); | ||
321 | sc1 = !(val & BIT(4)); | ||
322 | sc2 = !(val & BIT(8)) + !(val & BIT(9)); | ||
323 | sc3 = !(val & BIT(12)) + !(val & BIT(13)); | ||
324 | |||
325 | return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; | ||
326 | } | ||
327 | |||
293 | static void __cpuinit | 328 | static void __cpuinit |
294 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 329 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) |
295 | { | 330 | { |
@@ -299,12 +334,103 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | |||
299 | if (boot_cpu_data.x86 == 0x11) | 334 | if (boot_cpu_data.x86 == 0x11) |
300 | return; | 335 | return; |
301 | 336 | ||
302 | /* see erratum #382 */ | 337 | /* see errata #382 and #388 */ |
303 | if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8)) | 338 | if ((boot_cpu_data.x86 == 0x10) && |
339 | ((boot_cpu_data.x86_model < 0x8) || | ||
340 | (boot_cpu_data.x86_mask < 0x1))) | ||
304 | return; | 341 | return; |
305 | 342 | ||
306 | this_leaf->can_disable = 1; | 343 | this_leaf->can_disable = true; |
344 | this_leaf->l3_indices = amd_calc_l3_indices(); | ||
345 | } | ||
346 | |||
347 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | ||
348 | unsigned int index) | ||
349 | { | ||
350 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
351 | int node = amd_get_nb_id(cpu); | ||
352 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
353 | unsigned int reg = 0; | ||
354 | |||
355 | if (!this_leaf->can_disable) | ||
356 | return -EINVAL; | ||
357 | |||
358 | if (!dev) | ||
359 | return -EINVAL; | ||
360 | |||
361 | pci_read_config_dword(dev, 0x1BC + index * 4, ®); | ||
362 | return sprintf(buf, "0x%08x\n", reg); | ||
363 | } | ||
364 | |||
365 | #define SHOW_CACHE_DISABLE(index) \ | ||
366 | static ssize_t \ | ||
367 | show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ | ||
368 | { \ | ||
369 | return show_cache_disable(this_leaf, buf, index); \ | ||
307 | } | 370 | } |
371 | SHOW_CACHE_DISABLE(0) | ||
372 | SHOW_CACHE_DISABLE(1) | ||
373 | |||
374 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | ||
375 | const char *buf, size_t count, unsigned int index) | ||
376 | { | ||
377 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
378 | int node = amd_get_nb_id(cpu); | ||
379 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
380 | unsigned long val = 0; | ||
381 | |||
382 | #define SUBCACHE_MASK (3UL << 20) | ||
383 | #define SUBCACHE_INDEX 0xfff | ||
384 | |||
385 | if (!this_leaf->can_disable) | ||
386 | return -EINVAL; | ||
387 | |||
388 | if (!capable(CAP_SYS_ADMIN)) | ||
389 | return -EPERM; | ||
390 | |||
391 | if (!dev) | ||
392 | return -EINVAL; | ||
393 | |||
394 | if (strict_strtoul(buf, 10, &val) < 0) | ||
395 | return -EINVAL; | ||
396 | |||
397 | /* do not allow writes outside of allowed bits */ | ||
398 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || | ||
399 | ((val & SUBCACHE_INDEX) > this_leaf->l3_indices)) | ||
400 | return -EINVAL; | ||
401 | |||
402 | val |= BIT(30); | ||
403 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | ||
404 | /* | ||
405 | * We need to WBINVD on a core on the node containing the L3 cache which | ||
406 | * indices we disable therefore a simple wbinvd() is not sufficient. | ||
407 | */ | ||
408 | wbinvd_on_cpu(cpu); | ||
409 | pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31)); | ||
410 | return count; | ||
411 | } | ||
412 | |||
413 | #define STORE_CACHE_DISABLE(index) \ | ||
414 | static ssize_t \ | ||
415 | store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ | ||
416 | const char *buf, size_t count) \ | ||
417 | { \ | ||
418 | return store_cache_disable(this_leaf, buf, count, index); \ | ||
419 | } | ||
420 | STORE_CACHE_DISABLE(0) | ||
421 | STORE_CACHE_DISABLE(1) | ||
422 | |||
423 | static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644, | ||
424 | show_cache_disable_0, store_cache_disable_0); | ||
425 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | ||
426 | show_cache_disable_1, store_cache_disable_1); | ||
427 | |||
428 | #else /* CONFIG_CPU_SUP_AMD */ | ||
429 | static void __cpuinit | ||
430 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | ||
431 | { | ||
432 | }; | ||
433 | #endif /* CONFIG_CPU_SUP_AMD */ | ||
308 | 434 | ||
309 | static int | 435 | static int |
310 | __cpuinit cpuid4_cache_lookup_regs(int index, | 436 | __cpuinit cpuid4_cache_lookup_regs(int index, |
@@ -711,82 +837,6 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) | |||
711 | #define to_object(k) container_of(k, struct _index_kobject, kobj) | 837 | #define to_object(k) container_of(k, struct _index_kobject, kobj) |
712 | #define to_attr(a) container_of(a, struct _cache_attr, attr) | 838 | #define to_attr(a) container_of(a, struct _cache_attr, attr) |
713 | 839 | ||
714 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | ||
715 | unsigned int index) | ||
716 | { | ||
717 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
718 | int node = cpu_to_node(cpu); | ||
719 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
720 | unsigned int reg = 0; | ||
721 | |||
722 | if (!this_leaf->can_disable) | ||
723 | return -EINVAL; | ||
724 | |||
725 | if (!dev) | ||
726 | return -EINVAL; | ||
727 | |||
728 | pci_read_config_dword(dev, 0x1BC + index * 4, ®); | ||
729 | return sprintf(buf, "%x\n", reg); | ||
730 | } | ||
731 | |||
732 | #define SHOW_CACHE_DISABLE(index) \ | ||
733 | static ssize_t \ | ||
734 | show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ | ||
735 | { \ | ||
736 | return show_cache_disable(this_leaf, buf, index); \ | ||
737 | } | ||
738 | SHOW_CACHE_DISABLE(0) | ||
739 | SHOW_CACHE_DISABLE(1) | ||
740 | |||
741 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | ||
742 | const char *buf, size_t count, unsigned int index) | ||
743 | { | ||
744 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
745 | int node = cpu_to_node(cpu); | ||
746 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
747 | unsigned long val = 0; | ||
748 | unsigned int scrubber = 0; | ||
749 | |||
750 | if (!this_leaf->can_disable) | ||
751 | return -EINVAL; | ||
752 | |||
753 | if (!capable(CAP_SYS_ADMIN)) | ||
754 | return -EPERM; | ||
755 | |||
756 | if (!dev) | ||
757 | return -EINVAL; | ||
758 | |||
759 | if (strict_strtoul(buf, 10, &val) < 0) | ||
760 | return -EINVAL; | ||
761 | |||
762 | val |= 0xc0000000; | ||
763 | |||
764 | pci_read_config_dword(dev, 0x58, &scrubber); | ||
765 | scrubber &= ~0x1f000000; | ||
766 | pci_write_config_dword(dev, 0x58, scrubber); | ||
767 | |||
768 | pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); | ||
769 | wbinvd(); | ||
770 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | ||
771 | return count; | ||
772 | } | ||
773 | |||
774 | #define STORE_CACHE_DISABLE(index) \ | ||
775 | static ssize_t \ | ||
776 | store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ | ||
777 | const char *buf, size_t count) \ | ||
778 | { \ | ||
779 | return store_cache_disable(this_leaf, buf, count, index); \ | ||
780 | } | ||
781 | STORE_CACHE_DISABLE(0) | ||
782 | STORE_CACHE_DISABLE(1) | ||
783 | |||
784 | struct _cache_attr { | ||
785 | struct attribute attr; | ||
786 | ssize_t (*show)(struct _cpuid4_info *, char *); | ||
787 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); | ||
788 | }; | ||
789 | |||
790 | #define define_one_ro(_name) \ | 840 | #define define_one_ro(_name) \ |
791 | static struct _cache_attr _name = \ | 841 | static struct _cache_attr _name = \ |
792 | __ATTR(_name, 0444, show_##_name, NULL) | 842 | __ATTR(_name, 0444, show_##_name, NULL) |
@@ -801,23 +851,28 @@ define_one_ro(size); | |||
801 | define_one_ro(shared_cpu_map); | 851 | define_one_ro(shared_cpu_map); |
802 | define_one_ro(shared_cpu_list); | 852 | define_one_ro(shared_cpu_list); |
803 | 853 | ||
804 | static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644, | 854 | #define DEFAULT_SYSFS_CACHE_ATTRS \ |
805 | show_cache_disable_0, store_cache_disable_0); | 855 | &type.attr, \ |
806 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | 856 | &level.attr, \ |
807 | show_cache_disable_1, store_cache_disable_1); | 857 | &coherency_line_size.attr, \ |
858 | &physical_line_partition.attr, \ | ||
859 | &ways_of_associativity.attr, \ | ||
860 | &number_of_sets.attr, \ | ||
861 | &size.attr, \ | ||
862 | &shared_cpu_map.attr, \ | ||
863 | &shared_cpu_list.attr | ||
808 | 864 | ||
809 | static struct attribute *default_attrs[] = { | 865 | static struct attribute *default_attrs[] = { |
810 | &type.attr, | 866 | DEFAULT_SYSFS_CACHE_ATTRS, |
811 | &level.attr, | 867 | NULL |
812 | &coherency_line_size.attr, | 868 | }; |
813 | &physical_line_partition.attr, | 869 | |
814 | &ways_of_associativity.attr, | 870 | static struct attribute *default_l3_attrs[] = { |
815 | &number_of_sets.attr, | 871 | DEFAULT_SYSFS_CACHE_ATTRS, |
816 | &size.attr, | 872 | #ifdef CONFIG_CPU_SUP_AMD |
817 | &shared_cpu_map.attr, | ||
818 | &shared_cpu_list.attr, | ||
819 | &cache_disable_0.attr, | 873 | &cache_disable_0.attr, |
820 | &cache_disable_1.attr, | 874 | &cache_disable_1.attr, |
875 | #endif | ||
821 | NULL | 876 | NULL |
822 | }; | 877 | }; |
823 | 878 | ||
@@ -848,7 +903,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
848 | return ret; | 903 | return ret; |
849 | } | 904 | } |
850 | 905 | ||
851 | static struct sysfs_ops sysfs_ops = { | 906 | static const struct sysfs_ops sysfs_ops = { |
852 | .show = show, | 907 | .show = show, |
853 | .store = store, | 908 | .store = store, |
854 | }; | 909 | }; |
@@ -908,6 +963,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
908 | unsigned int cpu = sys_dev->id; | 963 | unsigned int cpu = sys_dev->id; |
909 | unsigned long i, j; | 964 | unsigned long i, j; |
910 | struct _index_kobject *this_object; | 965 | struct _index_kobject *this_object; |
966 | struct _cpuid4_info *this_leaf; | ||
911 | int retval; | 967 | int retval; |
912 | 968 | ||
913 | retval = cpuid4_cache_sysfs_init(cpu); | 969 | retval = cpuid4_cache_sysfs_init(cpu); |
@@ -926,6 +982,14 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
926 | this_object = INDEX_KOBJECT_PTR(cpu, i); | 982 | this_object = INDEX_KOBJECT_PTR(cpu, i); |
927 | this_object->cpu = cpu; | 983 | this_object->cpu = cpu; |
928 | this_object->index = i; | 984 | this_object->index = i; |
985 | |||
986 | this_leaf = CPUID4_INFO_IDX(cpu, i); | ||
987 | |||
988 | if (this_leaf->can_disable) | ||
989 | ktype_cache.default_attrs = default_l3_attrs; | ||
990 | else | ||
991 | ktype_cache.default_attrs = default_attrs; | ||
992 | |||
929 | retval = kobject_init_and_add(&(this_object->kobj), | 993 | retval = kobject_init_and_add(&(this_object->kobj), |
930 | &ktype_cache, | 994 | &ktype_cache, |
931 | per_cpu(ici_cache_kobject, cpu), | 995 | per_cpu(ici_cache_kobject, cpu), |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 73734baa50f2..e7dbde7bfedb 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kdebug.h> | 22 | #include <linux/kdebug.h> |
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/gfp.h> | ||
25 | #include <asm/mce.h> | 26 | #include <asm/mce.h> |
26 | #include <asm/apic.h> | 27 | #include <asm/apic.h> |
27 | 28 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index a8aacd4b513c..8a6f0afa767e 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/sysfs.h> | 27 | #include <linux/sysfs.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/init.h> | 30 | #include <linux/init.h> |
30 | #include <linux/kmod.h> | 31 | #include <linux/kmod.h> |
31 | #include <linux/poll.h> | 32 | #include <linux/poll.h> |
@@ -46,6 +47,13 @@ | |||
46 | 47 | ||
47 | #include "mce-internal.h" | 48 | #include "mce-internal.h" |
48 | 49 | ||
50 | static DEFINE_MUTEX(mce_read_mutex); | ||
51 | |||
52 | #define rcu_dereference_check_mce(p) \ | ||
53 | rcu_dereference_check((p), \ | ||
54 | rcu_read_lock_sched_held() || \ | ||
55 | lockdep_is_held(&mce_read_mutex)) | ||
56 | |||
49 | #define CREATE_TRACE_POINTS | 57 | #define CREATE_TRACE_POINTS |
50 | #include <trace/events/mce.h> | 58 | #include <trace/events/mce.h> |
51 | 59 | ||
@@ -158,7 +166,7 @@ void mce_log(struct mce *mce) | |||
158 | mce->finished = 0; | 166 | mce->finished = 0; |
159 | wmb(); | 167 | wmb(); |
160 | for (;;) { | 168 | for (;;) { |
161 | entry = rcu_dereference(mcelog.next); | 169 | entry = rcu_dereference_check_mce(mcelog.next); |
162 | for (;;) { | 170 | for (;;) { |
163 | /* | 171 | /* |
164 | * When the buffer fills up discard new entries. | 172 | * When the buffer fills up discard new entries. |
@@ -1485,8 +1493,6 @@ static void collect_tscs(void *data) | |||
1485 | rdtscll(cpu_tsc[smp_processor_id()]); | 1493 | rdtscll(cpu_tsc[smp_processor_id()]); |
1486 | } | 1494 | } |
1487 | 1495 | ||
1488 | static DEFINE_MUTEX(mce_read_mutex); | ||
1489 | |||
1490 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | 1496 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, |
1491 | loff_t *off) | 1497 | loff_t *off) |
1492 | { | 1498 | { |
@@ -1500,7 +1506,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | |||
1500 | return -ENOMEM; | 1506 | return -ENOMEM; |
1501 | 1507 | ||
1502 | mutex_lock(&mce_read_mutex); | 1508 | mutex_lock(&mce_read_mutex); |
1503 | next = rcu_dereference(mcelog.next); | 1509 | next = rcu_dereference_check_mce(mcelog.next); |
1504 | 1510 | ||
1505 | /* Only supports full reads right now */ | 1511 | /* Only supports full reads right now */ |
1506 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { | 1512 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { |
@@ -1565,7 +1571,7 @@ timeout: | |||
1565 | static unsigned int mce_poll(struct file *file, poll_table *wait) | 1571 | static unsigned int mce_poll(struct file *file, poll_table *wait) |
1566 | { | 1572 | { |
1567 | poll_wait(file, &mce_wait, wait); | 1573 | poll_wait(file, &mce_wait, wait); |
1568 | if (rcu_dereference(mcelog.next)) | 1574 | if (rcu_dereference_check_mce(mcelog.next)) |
1569 | return POLLIN | POLLRDNORM; | 1575 | return POLLIN | POLLRDNORM; |
1570 | return 0; | 1576 | return 0; |
1571 | } | 1577 | } |
@@ -2044,6 +2050,7 @@ static __init void mce_init_banks(void) | |||
2044 | struct mce_bank *b = &mce_banks[i]; | 2050 | struct mce_bank *b = &mce_banks[i]; |
2045 | struct sysdev_attribute *a = &b->attr; | 2051 | struct sysdev_attribute *a = &b->attr; |
2046 | 2052 | ||
2053 | sysfs_attr_init(&a->attr); | ||
2047 | a->attr.name = b->attrname; | 2054 | a->attr.name = b->attrname; |
2048 | snprintf(b->attrname, ATTR_LEN, "bank%d", i); | 2055 | snprintf(b->attrname, ATTR_LEN, "bank%d", i); |
2049 | 2056 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 83a3d1f4efca..224392d8fe8c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/sysfs.h> | 23 | #include <linux/sysfs.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
26 | #include <linux/smp.h> | 27 | #include <linux/smp.h> |
@@ -388,7 +389,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
388 | return ret; | 389 | return ret; |
389 | } | 390 | } |
390 | 391 | ||
391 | static struct sysfs_ops threshold_ops = { | 392 | static const struct sysfs_ops threshold_ops = { |
392 | .show = show, | 393 | .show = show, |
393 | .store = store, | 394 | .store = store, |
394 | }; | 395 | }; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 7c785634af2b..62b48e40920a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Author: Andi Kleen | 5 | * Author: Andi Kleen |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/gfp.h> | ||
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
10 | #include <linux/percpu.h> | 11 | #include <linux/percpu.h> |
@@ -95,7 +96,7 @@ static void cmci_discover(int banks, int boot) | |||
95 | 96 | ||
96 | /* Already owned by someone else? */ | 97 | /* Already owned by someone else? */ |
97 | if (val & CMCI_EN) { | 98 | if (val & CMCI_EN) { |
98 | if (test_and_clear_bit(i, owned) || boot) | 99 | if (test_and_clear_bit(i, owned) && !boot) |
99 | print_update("SHD", &hdr, i); | 100 | print_update("SHD", &hdr, i); |
100 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); | 101 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); |
101 | continue; | 102 | continue; |
@@ -107,7 +108,7 @@ static void cmci_discover(int banks, int boot) | |||
107 | 108 | ||
108 | /* Did the enable bit stick? -- the bank supports CMCI */ | 109 | /* Did the enable bit stick? -- the bank supports CMCI */ |
109 | if (val & CMCI_EN) { | 110 | if (val & CMCI_EN) { |
110 | if (!test_and_set_bit(i, owned) || boot) | 111 | if (!test_and_set_bit(i, owned) && !boot) |
111 | print_update("CMCI", &hdr, i); | 112 | print_update("CMCI", &hdr, i); |
112 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); | 113 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); |
113 | } else { | 114 | } else { |
diff --git a/arch/x86/kernel/cpu/mtrr/Makefile b/arch/x86/kernel/cpu/mtrr/Makefile index f4361b56f8e9..ad9e5ed81181 100644 --- a/arch/x86/kernel/cpu/mtrr/Makefile +++ b/arch/x86/kernel/cpu/mtrr/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-y := main.o if.o generic.o state.o cleanup.o | 1 | obj-y := main.o if.o generic.o cleanup.o |
2 | obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o | 2 | obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o |
3 | 3 | ||
diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c index 33af14110dfd..92ba9cd31c9a 100644 --- a/arch/x86/kernel/cpu/mtrr/amd.c +++ b/arch/x86/kernel/cpu/mtrr/amd.c | |||
@@ -108,7 +108,7 @@ amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static struct mtrr_ops amd_mtrr_ops = { | 111 | static const struct mtrr_ops amd_mtrr_ops = { |
112 | .vendor = X86_VENDOR_AMD, | 112 | .vendor = X86_VENDOR_AMD, |
113 | .set = amd_set_mtrr, | 113 | .set = amd_set_mtrr, |
114 | .get = amd_get_mtrr, | 114 | .get = amd_get_mtrr, |
diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c index de89f14eff3a..316fe3e60a97 100644 --- a/arch/x86/kernel/cpu/mtrr/centaur.c +++ b/arch/x86/kernel/cpu/mtrr/centaur.c | |||
@@ -110,7 +110,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t | |||
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
113 | static struct mtrr_ops centaur_mtrr_ops = { | 113 | static const struct mtrr_ops centaur_mtrr_ops = { |
114 | .vendor = X86_VENDOR_CENTAUR, | 114 | .vendor = X86_VENDOR_CENTAUR, |
115 | .set = centaur_set_mcr, | 115 | .set = centaur_set_mcr, |
116 | .get = centaur_get_mcr, | 116 | .get = centaur_get_mcr, |
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 09b1698e0466..06130b52f012 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c | |||
@@ -22,10 +22,10 @@ | |||
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/smp.h> | 23 | #include <linux/smp.h> |
24 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
25 | #include <linux/sort.h> | ||
26 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
27 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
28 | #include <linux/kvm_para.h> | 27 | #include <linux/kvm_para.h> |
28 | #include <linux/range.h> | ||
29 | 29 | ||
30 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
31 | #include <asm/e820.h> | 31 | #include <asm/e820.h> |
@@ -34,11 +34,6 @@ | |||
34 | 34 | ||
35 | #include "mtrr.h" | 35 | #include "mtrr.h" |
36 | 36 | ||
37 | struct res_range { | ||
38 | unsigned long start; | ||
39 | unsigned long end; | ||
40 | }; | ||
41 | |||
42 | struct var_mtrr_range_state { | 37 | struct var_mtrr_range_state { |
43 | unsigned long base_pfn; | 38 | unsigned long base_pfn; |
44 | unsigned long size_pfn; | 39 | unsigned long size_pfn; |
@@ -56,7 +51,7 @@ struct var_mtrr_state { | |||
56 | /* Should be related to MTRR_VAR_RANGES nums */ | 51 | /* Should be related to MTRR_VAR_RANGES nums */ |
57 | #define RANGE_NUM 256 | 52 | #define RANGE_NUM 256 |
58 | 53 | ||
59 | static struct res_range __initdata range[RANGE_NUM]; | 54 | static struct range __initdata range[RANGE_NUM]; |
60 | static int __initdata nr_range; | 55 | static int __initdata nr_range; |
61 | 56 | ||
62 | static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; | 57 | static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; |
@@ -64,152 +59,11 @@ static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; | |||
64 | static int __initdata debug_print; | 59 | static int __initdata debug_print; |
65 | #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) | 60 | #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) |
66 | 61 | ||
67 | |||
68 | static int __init | ||
69 | add_range(struct res_range *range, int nr_range, | ||
70 | unsigned long start, unsigned long end) | ||
71 | { | ||
72 | /* Out of slots: */ | ||
73 | if (nr_range >= RANGE_NUM) | ||
74 | return nr_range; | ||
75 | |||
76 | range[nr_range].start = start; | ||
77 | range[nr_range].end = end; | ||
78 | |||
79 | nr_range++; | ||
80 | |||
81 | return nr_range; | ||
82 | } | ||
83 | |||
84 | static int __init | ||
85 | add_range_with_merge(struct res_range *range, int nr_range, | ||
86 | unsigned long start, unsigned long end) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | /* Try to merge it with old one: */ | ||
91 | for (i = 0; i < nr_range; i++) { | ||
92 | unsigned long final_start, final_end; | ||
93 | unsigned long common_start, common_end; | ||
94 | |||
95 | if (!range[i].end) | ||
96 | continue; | ||
97 | |||
98 | common_start = max(range[i].start, start); | ||
99 | common_end = min(range[i].end, end); | ||
100 | if (common_start > common_end + 1) | ||
101 | continue; | ||
102 | |||
103 | final_start = min(range[i].start, start); | ||
104 | final_end = max(range[i].end, end); | ||
105 | |||
106 | range[i].start = final_start; | ||
107 | range[i].end = final_end; | ||
108 | return nr_range; | ||
109 | } | ||
110 | |||
111 | /* Need to add it: */ | ||
112 | return add_range(range, nr_range, start, end); | ||
113 | } | ||
114 | |||
115 | static void __init | ||
116 | subtract_range(struct res_range *range, unsigned long start, unsigned long end) | ||
117 | { | ||
118 | int i, j; | ||
119 | |||
120 | for (j = 0; j < RANGE_NUM; j++) { | ||
121 | if (!range[j].end) | ||
122 | continue; | ||
123 | |||
124 | if (start <= range[j].start && end >= range[j].end) { | ||
125 | range[j].start = 0; | ||
126 | range[j].end = 0; | ||
127 | continue; | ||
128 | } | ||
129 | |||
130 | if (start <= range[j].start && end < range[j].end && | ||
131 | range[j].start < end + 1) { | ||
132 | range[j].start = end + 1; | ||
133 | continue; | ||
134 | } | ||
135 | |||
136 | |||
137 | if (start > range[j].start && end >= range[j].end && | ||
138 | range[j].end > start - 1) { | ||
139 | range[j].end = start - 1; | ||
140 | continue; | ||
141 | } | ||
142 | |||
143 | if (start > range[j].start && end < range[j].end) { | ||
144 | /* Find the new spare: */ | ||
145 | for (i = 0; i < RANGE_NUM; i++) { | ||
146 | if (range[i].end == 0) | ||
147 | break; | ||
148 | } | ||
149 | if (i < RANGE_NUM) { | ||
150 | range[i].end = range[j].end; | ||
151 | range[i].start = end + 1; | ||
152 | } else { | ||
153 | printk(KERN_ERR "run of slot in ranges\n"); | ||
154 | } | ||
155 | range[j].end = start - 1; | ||
156 | continue; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static int __init cmp_range(const void *x1, const void *x2) | ||
162 | { | ||
163 | const struct res_range *r1 = x1; | ||
164 | const struct res_range *r2 = x2; | ||
165 | long start1, start2; | ||
166 | |||
167 | start1 = r1->start; | ||
168 | start2 = r2->start; | ||
169 | |||
170 | return start1 - start2; | ||
171 | } | ||
172 | |||
173 | static int __init clean_sort_range(struct res_range *range, int az) | ||
174 | { | ||
175 | int i, j, k = az - 1, nr_range = 0; | ||
176 | |||
177 | for (i = 0; i < k; i++) { | ||
178 | if (range[i].end) | ||
179 | continue; | ||
180 | for (j = k; j > i; j--) { | ||
181 | if (range[j].end) { | ||
182 | k = j; | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | if (j == i) | ||
187 | break; | ||
188 | range[i].start = range[k].start; | ||
189 | range[i].end = range[k].end; | ||
190 | range[k].start = 0; | ||
191 | range[k].end = 0; | ||
192 | k--; | ||
193 | } | ||
194 | /* count it */ | ||
195 | for (i = 0; i < az; i++) { | ||
196 | if (!range[i].end) { | ||
197 | nr_range = i; | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* sort them */ | ||
203 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | ||
204 | |||
205 | return nr_range; | ||
206 | } | ||
207 | |||
208 | #define BIOS_BUG_MSG KERN_WARNING \ | 62 | #define BIOS_BUG_MSG KERN_WARNING \ |
209 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" | 63 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" |
210 | 64 | ||
211 | static int __init | 65 | static int __init |
212 | x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | 66 | x86_get_mtrr_mem_range(struct range *range, int nr_range, |
213 | unsigned long extra_remove_base, | 67 | unsigned long extra_remove_base, |
214 | unsigned long extra_remove_size) | 68 | unsigned long extra_remove_size) |
215 | { | 69 | { |
@@ -223,14 +77,14 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
223 | continue; | 77 | continue; |
224 | base = range_state[i].base_pfn; | 78 | base = range_state[i].base_pfn; |
225 | size = range_state[i].size_pfn; | 79 | size = range_state[i].size_pfn; |
226 | nr_range = add_range_with_merge(range, nr_range, base, | 80 | nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, |
227 | base + size - 1); | 81 | base, base + size); |
228 | } | 82 | } |
229 | if (debug_print) { | 83 | if (debug_print) { |
230 | printk(KERN_DEBUG "After WB checking\n"); | 84 | printk(KERN_DEBUG "After WB checking\n"); |
231 | for (i = 0; i < nr_range; i++) | 85 | for (i = 0; i < nr_range; i++) |
232 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 86 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
233 | range[i].start, range[i].end + 1); | 87 | range[i].start, range[i].end); |
234 | } | 88 | } |
235 | 89 | ||
236 | /* Take out UC ranges: */ | 90 | /* Take out UC ranges: */ |
@@ -252,19 +106,19 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
252 | size -= (1<<(20-PAGE_SHIFT)) - base; | 106 | size -= (1<<(20-PAGE_SHIFT)) - base; |
253 | base = 1<<(20-PAGE_SHIFT); | 107 | base = 1<<(20-PAGE_SHIFT); |
254 | } | 108 | } |
255 | subtract_range(range, base, base + size - 1); | 109 | subtract_range(range, RANGE_NUM, base, base + size); |
256 | } | 110 | } |
257 | if (extra_remove_size) | 111 | if (extra_remove_size) |
258 | subtract_range(range, extra_remove_base, | 112 | subtract_range(range, RANGE_NUM, extra_remove_base, |
259 | extra_remove_base + extra_remove_size - 1); | 113 | extra_remove_base + extra_remove_size); |
260 | 114 | ||
261 | if (debug_print) { | 115 | if (debug_print) { |
262 | printk(KERN_DEBUG "After UC checking\n"); | 116 | printk(KERN_DEBUG "After UC checking\n"); |
263 | for (i = 0; i < RANGE_NUM; i++) { | 117 | for (i = 0; i < RANGE_NUM; i++) { |
264 | if (!range[i].end) | 118 | if (!range[i].end) |
265 | continue; | 119 | continue; |
266 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 120 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
267 | range[i].start, range[i].end + 1); | 121 | range[i].start, range[i].end); |
268 | } | 122 | } |
269 | } | 123 | } |
270 | 124 | ||
@@ -273,26 +127,22 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
273 | if (debug_print) { | 127 | if (debug_print) { |
274 | printk(KERN_DEBUG "After sorting\n"); | 128 | printk(KERN_DEBUG "After sorting\n"); |
275 | for (i = 0; i < nr_range; i++) | 129 | for (i = 0; i < nr_range; i++) |
276 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 130 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
277 | range[i].start, range[i].end + 1); | 131 | range[i].start, range[i].end); |
278 | } | 132 | } |
279 | 133 | ||
280 | /* clear those is not used */ | ||
281 | for (i = nr_range; i < RANGE_NUM; i++) | ||
282 | memset(&range[i], 0, sizeof(range[i])); | ||
283 | |||
284 | return nr_range; | 134 | return nr_range; |
285 | } | 135 | } |
286 | 136 | ||
287 | #ifdef CONFIG_MTRR_SANITIZER | 137 | #ifdef CONFIG_MTRR_SANITIZER |
288 | 138 | ||
289 | static unsigned long __init sum_ranges(struct res_range *range, int nr_range) | 139 | static unsigned long __init sum_ranges(struct range *range, int nr_range) |
290 | { | 140 | { |
291 | unsigned long sum = 0; | 141 | unsigned long sum = 0; |
292 | int i; | 142 | int i; |
293 | 143 | ||
294 | for (i = 0; i < nr_range; i++) | 144 | for (i = 0; i < nr_range; i++) |
295 | sum += range[i].end + 1 - range[i].start; | 145 | sum += range[i].end - range[i].start; |
296 | 146 | ||
297 | return sum; | 147 | return sum; |
298 | } | 148 | } |
@@ -621,7 +471,7 @@ static int __init parse_mtrr_spare_reg(char *arg) | |||
621 | early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg); | 471 | early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg); |
622 | 472 | ||
623 | static int __init | 473 | static int __init |
624 | x86_setup_var_mtrrs(struct res_range *range, int nr_range, | 474 | x86_setup_var_mtrrs(struct range *range, int nr_range, |
625 | u64 chunk_size, u64 gran_size) | 475 | u64 chunk_size, u64 gran_size) |
626 | { | 476 | { |
627 | struct var_mtrr_state var_state; | 477 | struct var_mtrr_state var_state; |
@@ -639,7 +489,7 @@ x86_setup_var_mtrrs(struct res_range *range, int nr_range, | |||
639 | /* Write the range: */ | 489 | /* Write the range: */ |
640 | for (i = 0; i < nr_range; i++) { | 490 | for (i = 0; i < nr_range; i++) { |
641 | set_var_mtrr_range(&var_state, range[i].start, | 491 | set_var_mtrr_range(&var_state, range[i].start, |
642 | range[i].end - range[i].start + 1); | 492 | range[i].end - range[i].start); |
643 | } | 493 | } |
644 | 494 | ||
645 | /* Write the last range: */ | 495 | /* Write the last range: */ |
@@ -742,7 +592,7 @@ mtrr_calc_range_state(u64 chunk_size, u64 gran_size, | |||
742 | unsigned long x_remove_base, | 592 | unsigned long x_remove_base, |
743 | unsigned long x_remove_size, int i) | 593 | unsigned long x_remove_size, int i) |
744 | { | 594 | { |
745 | static struct res_range range_new[RANGE_NUM]; | 595 | static struct range range_new[RANGE_NUM]; |
746 | unsigned long range_sums_new; | 596 | unsigned long range_sums_new; |
747 | static int nr_range_new; | 597 | static int nr_range_new; |
748 | int num_reg; | 598 | int num_reg; |
@@ -869,10 +719,10 @@ int __init mtrr_cleanup(unsigned address_bits) | |||
869 | * [0, 1M) should always be covered by var mtrr with WB | 719 | * [0, 1M) should always be covered by var mtrr with WB |
870 | * and fixed mtrrs should take effect before var mtrr for it: | 720 | * and fixed mtrrs should take effect before var mtrr for it: |
871 | */ | 721 | */ |
872 | nr_range = add_range_with_merge(range, nr_range, 0, | 722 | nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0, |
873 | (1ULL<<(20 - PAGE_SHIFT)) - 1); | 723 | 1ULL<<(20 - PAGE_SHIFT)); |
874 | /* Sort the ranges: */ | 724 | /* Sort the ranges: */ |
875 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | 725 | sort_range(range, nr_range); |
876 | 726 | ||
877 | range_sums = sum_ranges(range, nr_range); | 727 | range_sums = sum_ranges(range, nr_range); |
878 | printk(KERN_INFO "total RAM covered: %ldM\n", | 728 | printk(KERN_INFO "total RAM covered: %ldM\n", |
@@ -1089,9 +939,9 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
1089 | nr_range = 0; | 939 | nr_range = 0; |
1090 | if (mtrr_tom2) { | 940 | if (mtrr_tom2) { |
1091 | range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT)); | 941 | range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT)); |
1092 | range[nr_range].end = (mtrr_tom2 >> PAGE_SHIFT) - 1; | 942 | range[nr_range].end = mtrr_tom2 >> PAGE_SHIFT; |
1093 | if (highest_pfn < range[nr_range].end + 1) | 943 | if (highest_pfn < range[nr_range].end) |
1094 | highest_pfn = range[nr_range].end + 1; | 944 | highest_pfn = range[nr_range].end; |
1095 | nr_range++; | 945 | nr_range++; |
1096 | } | 946 | } |
1097 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); | 947 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); |
@@ -1103,15 +953,15 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
1103 | 953 | ||
1104 | /* Check the holes: */ | 954 | /* Check the holes: */ |
1105 | for (i = 0; i < nr_range - 1; i++) { | 955 | for (i = 0; i < nr_range - 1; i++) { |
1106 | if (range[i].end + 1 < range[i+1].start) | 956 | if (range[i].end < range[i+1].start) |
1107 | total_trim_size += real_trim_memory(range[i].end + 1, | 957 | total_trim_size += real_trim_memory(range[i].end, |
1108 | range[i+1].start); | 958 | range[i+1].start); |
1109 | } | 959 | } |
1110 | 960 | ||
1111 | /* Check the top: */ | 961 | /* Check the top: */ |
1112 | i = nr_range - 1; | 962 | i = nr_range - 1; |
1113 | if (range[i].end + 1 < end_pfn) | 963 | if (range[i].end < end_pfn) |
1114 | total_trim_size += real_trim_memory(range[i].end + 1, | 964 | total_trim_size += real_trim_memory(range[i].end, |
1115 | end_pfn); | 965 | end_pfn); |
1116 | 966 | ||
1117 | if (total_trim_size) { | 967 | if (total_trim_size) { |
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 228d982ce09c..68a3343e5798 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c | |||
@@ -265,7 +265,7 @@ static void cyrix_set_all(void) | |||
265 | post_set(); | 265 | post_set(); |
266 | } | 266 | } |
267 | 267 | ||
268 | static struct mtrr_ops cyrix_mtrr_ops = { | 268 | static const struct mtrr_ops cyrix_mtrr_ops = { |
269 | .vendor = X86_VENDOR_CYRIX, | 269 | .vendor = X86_VENDOR_CYRIX, |
270 | .set_all = cyrix_set_all, | 270 | .set_all = cyrix_set_all, |
271 | .set = cyrix_set_arr, | 271 | .set = cyrix_set_arr, |
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 55da0c5f68dd..fd31a441c61c 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
@@ -6,7 +6,6 @@ | |||
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/slab.h> | ||
10 | #include <linux/io.h> | 9 | #include <linux/io.h> |
11 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
12 | 11 | ||
@@ -464,7 +463,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, | |||
464 | tmp |= ~((1<<(hi - 1)) - 1); | 463 | tmp |= ~((1<<(hi - 1)) - 1); |
465 | 464 | ||
466 | if (tmp != mask_lo) { | 465 | if (tmp != mask_lo) { |
467 | WARN_ONCE(1, KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); | 466 | printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); |
468 | mask_lo = tmp; | 467 | mask_lo = tmp; |
469 | } | 468 | } |
470 | } | 469 | } |
@@ -570,7 +569,7 @@ static unsigned long set_mtrr_state(void) | |||
570 | 569 | ||
571 | 570 | ||
572 | static unsigned long cr4; | 571 | static unsigned long cr4; |
573 | static DEFINE_SPINLOCK(set_atomicity_lock); | 572 | static DEFINE_RAW_SPINLOCK(set_atomicity_lock); |
574 | 573 | ||
575 | /* | 574 | /* |
576 | * Since we are disabling the cache don't allow any interrupts, | 575 | * Since we are disabling the cache don't allow any interrupts, |
@@ -590,7 +589,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) | |||
590 | * changes to the way the kernel boots | 589 | * changes to the way the kernel boots |
591 | */ | 590 | */ |
592 | 591 | ||
593 | spin_lock(&set_atomicity_lock); | 592 | raw_spin_lock(&set_atomicity_lock); |
594 | 593 | ||
595 | /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */ | 594 | /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */ |
596 | cr0 = read_cr0() | X86_CR0_CD; | 595 | cr0 = read_cr0() | X86_CR0_CD; |
@@ -627,7 +626,7 @@ static void post_set(void) __releases(set_atomicity_lock) | |||
627 | /* Restore value of CR4 */ | 626 | /* Restore value of CR4 */ |
628 | if (cpu_has_pge) | 627 | if (cpu_has_pge) |
629 | write_cr4(cr4); | 628 | write_cr4(cr4); |
630 | spin_unlock(&set_atomicity_lock); | 629 | raw_spin_unlock(&set_atomicity_lock); |
631 | } | 630 | } |
632 | 631 | ||
633 | static void generic_set_all(void) | 632 | static void generic_set_all(void) |
@@ -752,7 +751,7 @@ int positive_have_wrcomb(void) | |||
752 | /* | 751 | /* |
753 | * Generic structure... | 752 | * Generic structure... |
754 | */ | 753 | */ |
755 | struct mtrr_ops generic_mtrr_ops = { | 754 | const struct mtrr_ops generic_mtrr_ops = { |
756 | .use_intel_if = 1, | 755 | .use_intel_if = 1, |
757 | .set_all = generic_set_all, | 756 | .set_all = generic_set_all, |
758 | .get = generic_get_mtrr, | 757 | .get = generic_get_mtrr, |
diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index e006e56f699c..79289632cb27 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <linux/slab.h> | ||
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | 10 | ||
10 | #define LINE_SIZE 80 | 11 | #define LINE_SIZE 80 |
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 84e83de54575..79556bd9b602 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
@@ -60,14 +60,14 @@ static DEFINE_MUTEX(mtrr_mutex); | |||
60 | u64 size_or_mask, size_and_mask; | 60 | u64 size_or_mask, size_and_mask; |
61 | static bool mtrr_aps_delayed_init; | 61 | static bool mtrr_aps_delayed_init; |
62 | 62 | ||
63 | static struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM]; | 63 | static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM]; |
64 | 64 | ||
65 | struct mtrr_ops *mtrr_if; | 65 | const struct mtrr_ops *mtrr_if; |
66 | 66 | ||
67 | static void set_mtrr(unsigned int reg, unsigned long base, | 67 | static void set_mtrr(unsigned int reg, unsigned long base, |
68 | unsigned long size, mtrr_type type); | 68 | unsigned long size, mtrr_type type); |
69 | 69 | ||
70 | void set_mtrr_ops(struct mtrr_ops *ops) | 70 | void set_mtrr_ops(const struct mtrr_ops *ops) |
71 | { | 71 | { |
72 | if (ops->vendor && ops->vendor < X86_VENDOR_NUM) | 72 | if (ops->vendor && ops->vendor < X86_VENDOR_NUM) |
73 | mtrr_ops[ops->vendor] = ops; | 73 | mtrr_ops[ops->vendor] = ops; |
@@ -145,6 +145,7 @@ struct set_mtrr_data { | |||
145 | 145 | ||
146 | /** | 146 | /** |
147 | * ipi_handler - Synchronisation handler. Executed by "other" CPUs. | 147 | * ipi_handler - Synchronisation handler. Executed by "other" CPUs. |
148 | * @info: pointer to mtrr configuration data | ||
148 | * | 149 | * |
149 | * Returns nothing. | 150 | * Returns nothing. |
150 | */ | 151 | */ |
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index a501dee9a87a..df5e41f31a27 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h | |||
@@ -32,7 +32,7 @@ extern int generic_get_free_region(unsigned long base, unsigned long size, | |||
32 | extern int generic_validate_add_page(unsigned long base, unsigned long size, | 32 | extern int generic_validate_add_page(unsigned long base, unsigned long size, |
33 | unsigned int type); | 33 | unsigned int type); |
34 | 34 | ||
35 | extern struct mtrr_ops generic_mtrr_ops; | 35 | extern const struct mtrr_ops generic_mtrr_ops; |
36 | 36 | ||
37 | extern int positive_have_wrcomb(void); | 37 | extern int positive_have_wrcomb(void); |
38 | 38 | ||
@@ -53,10 +53,10 @@ void fill_mtrr_var_range(unsigned int index, | |||
53 | u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); | 53 | u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); |
54 | void get_mtrr_state(void); | 54 | void get_mtrr_state(void); |
55 | 55 | ||
56 | extern void set_mtrr_ops(struct mtrr_ops *ops); | 56 | extern void set_mtrr_ops(const struct mtrr_ops *ops); |
57 | 57 | ||
58 | extern u64 size_or_mask, size_and_mask; | 58 | extern u64 size_or_mask, size_and_mask; |
59 | extern struct mtrr_ops *mtrr_if; | 59 | extern const struct mtrr_ops *mtrr_if; |
60 | 60 | ||
61 | #define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd) | 61 | #define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd) |
62 | #define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1) | 62 | #define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1) |
diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c deleted file mode 100644 index dfc80b4e6b0d..000000000000 --- a/arch/x86/kernel/cpu/mtrr/state.c +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/io.h> | ||
3 | #include <linux/mm.h> | ||
4 | |||
5 | #include <asm/processor-cyrix.h> | ||
6 | #include <asm/processor-flags.h> | ||
7 | #include <asm/mtrr.h> | ||
8 | #include <asm/msr.h> | ||
9 | |||
10 | #include "mtrr.h" | ||
11 | |||
12 | /* Put the processor into a state where MTRRs can be safely set */ | ||
13 | void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) | ||
14 | { | ||
15 | unsigned int cr0; | ||
16 | |||
17 | /* Disable interrupts locally */ | ||
18 | local_irq_save(ctxt->flags); | ||
19 | |||
20 | if (use_intel() || is_cpu(CYRIX)) { | ||
21 | |||
22 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ | ||
23 | if (cpu_has_pge) { | ||
24 | ctxt->cr4val = read_cr4(); | ||
25 | write_cr4(ctxt->cr4val & ~X86_CR4_PGE); | ||
26 | } | ||
27 | |||
28 | /* | ||
29 | * Disable and flush caches. Note that wbinvd flushes the TLBs | ||
30 | * as a side-effect | ||
31 | */ | ||
32 | cr0 = read_cr0() | X86_CR0_CD; | ||
33 | wbinvd(); | ||
34 | write_cr0(cr0); | ||
35 | wbinvd(); | ||
36 | |||
37 | if (use_intel()) { | ||
38 | /* Save MTRR state */ | ||
39 | rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi); | ||
40 | } else { | ||
41 | /* | ||
42 | * Cyrix ARRs - | ||
43 | * everything else were excluded at the top | ||
44 | */ | ||
45 | ctxt->ccr3 = getCx86(CX86_CCR3); | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void set_mtrr_cache_disable(struct set_mtrr_context *ctxt) | ||
51 | { | ||
52 | if (use_intel()) { | ||
53 | /* Disable MTRRs, and set the default type to uncached */ | ||
54 | mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, | ||
55 | ctxt->deftype_hi); | ||
56 | } else { | ||
57 | if (is_cpu(CYRIX)) { | ||
58 | /* Cyrix ARRs - everything else were excluded at the top */ | ||
59 | setCx86(CX86_CCR3, (ctxt->ccr3 & 0x0f) | 0x10); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /* Restore the processor after a set_mtrr_prepare */ | ||
65 | void set_mtrr_done(struct set_mtrr_context *ctxt) | ||
66 | { | ||
67 | if (use_intel() || is_cpu(CYRIX)) { | ||
68 | |||
69 | /* Flush caches and TLBs */ | ||
70 | wbinvd(); | ||
71 | |||
72 | /* Restore MTRRdefType */ | ||
73 | if (use_intel()) { | ||
74 | /* Intel (P6) standard MTRRs */ | ||
75 | mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, | ||
76 | ctxt->deftype_hi); | ||
77 | } else { | ||
78 | /* | ||
79 | * Cyrix ARRs - | ||
80 | * everything else was excluded at the top | ||
81 | */ | ||
82 | setCx86(CX86_CCR3, ctxt->ccr3); | ||
83 | } | ||
84 | |||
85 | /* Enable caches */ | ||
86 | write_cr0(read_cr0() & 0xbfffffff); | ||
87 | |||
88 | /* Restore value of CR4 */ | ||
89 | if (cpu_has_pge) | ||
90 | write_cr4(ctxt->cr4val); | ||
91 | } | ||
92 | /* Re-enable interrupts locally (if enabled previously) */ | ||
93 | local_irq_restore(ctxt->flags); | ||
94 | } | ||
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index a920f173a220..db5bdc8addf8 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kdebug.h> | 21 | #include <linux/kdebug.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/highmem.h> | 25 | #include <linux/highmem.h> |
25 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
26 | #include <linux/bitops.h> | 27 | #include <linux/bitops.h> |
@@ -28,6 +29,7 @@ | |||
28 | #include <asm/apic.h> | 29 | #include <asm/apic.h> |
29 | #include <asm/stacktrace.h> | 30 | #include <asm/stacktrace.h> |
30 | #include <asm/nmi.h> | 31 | #include <asm/nmi.h> |
32 | #include <asm/compat.h> | ||
31 | 33 | ||
32 | static u64 perf_event_mask __read_mostly; | 34 | static u64 perf_event_mask __read_mostly; |
33 | 35 | ||
@@ -73,13 +75,20 @@ struct debug_store { | |||
73 | struct event_constraint { | 75 | struct event_constraint { |
74 | union { | 76 | union { |
75 | unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 77 | unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
76 | u64 idxmsk64[1]; | 78 | u64 idxmsk64; |
77 | }; | 79 | }; |
78 | int code; | 80 | u64 code; |
79 | int cmask; | 81 | u64 cmask; |
80 | int weight; | 82 | int weight; |
81 | }; | 83 | }; |
82 | 84 | ||
85 | struct amd_nb { | ||
86 | int nb_id; /* NorthBridge id */ | ||
87 | int refcnt; /* reference count */ | ||
88 | struct perf_event *owners[X86_PMC_IDX_MAX]; | ||
89 | struct event_constraint event_constraints[X86_PMC_IDX_MAX]; | ||
90 | }; | ||
91 | |||
83 | struct cpu_hw_events { | 92 | struct cpu_hw_events { |
84 | struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ | 93 | struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ |
85 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 94 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
@@ -92,10 +101,11 @@ struct cpu_hw_events { | |||
92 | int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ | 101 | int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ |
93 | u64 tags[X86_PMC_IDX_MAX]; | 102 | u64 tags[X86_PMC_IDX_MAX]; |
94 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ | 103 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ |
104 | struct amd_nb *amd_nb; | ||
95 | }; | 105 | }; |
96 | 106 | ||
97 | #define __EVENT_CONSTRAINT(c, n, m, w) {\ | 107 | #define __EVENT_CONSTRAINT(c, n, m, w) {\ |
98 | { .idxmsk64[0] = (n) }, \ | 108 | { .idxmsk64 = (n) }, \ |
99 | .code = (c), \ | 109 | .code = (c), \ |
100 | .cmask = (m), \ | 110 | .cmask = (m), \ |
101 | .weight = (w), \ | 111 | .weight = (w), \ |
@@ -108,7 +118,7 @@ struct cpu_hw_events { | |||
108 | EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) | 118 | EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) |
109 | 119 | ||
110 | #define FIXED_EVENT_CONSTRAINT(c, n) \ | 120 | #define FIXED_EVENT_CONSTRAINT(c, n) \ |
111 | EVENT_CONSTRAINT(c, n, INTEL_ARCH_FIXED_MASK) | 121 | EVENT_CONSTRAINT(c, (1ULL << (32+n)), INTEL_ARCH_FIXED_MASK) |
112 | 122 | ||
113 | #define EVENT_CONSTRAINT_END \ | 123 | #define EVENT_CONSTRAINT_END \ |
114 | EVENT_CONSTRAINT(0, 0, 0) | 124 | EVENT_CONSTRAINT(0, 0, 0) |
@@ -125,8 +135,8 @@ struct x86_pmu { | |||
125 | int (*handle_irq)(struct pt_regs *); | 135 | int (*handle_irq)(struct pt_regs *); |
126 | void (*disable_all)(void); | 136 | void (*disable_all)(void); |
127 | void (*enable_all)(void); | 137 | void (*enable_all)(void); |
128 | void (*enable)(struct hw_perf_event *, int); | 138 | void (*enable)(struct perf_event *); |
129 | void (*disable)(struct hw_perf_event *, int); | 139 | void (*disable)(struct perf_event *); |
130 | unsigned eventsel; | 140 | unsigned eventsel; |
131 | unsigned perfctr; | 141 | unsigned perfctr; |
132 | u64 (*event_map)(int); | 142 | u64 (*event_map)(int); |
@@ -149,6 +159,11 @@ struct x86_pmu { | |||
149 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, | 159 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, |
150 | struct perf_event *event); | 160 | struct perf_event *event); |
151 | struct event_constraint *event_constraints; | 161 | struct event_constraint *event_constraints; |
162 | |||
163 | int (*cpu_prepare)(int cpu); | ||
164 | void (*cpu_starting)(int cpu); | ||
165 | void (*cpu_dying)(int cpu); | ||
166 | void (*cpu_dead)(int cpu); | ||
152 | }; | 167 | }; |
153 | 168 | ||
154 | static struct x86_pmu x86_pmu __read_mostly; | 169 | static struct x86_pmu x86_pmu __read_mostly; |
@@ -157,142 +172,7 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | |||
157 | .enabled = 1, | 172 | .enabled = 1, |
158 | }; | 173 | }; |
159 | 174 | ||
160 | static int x86_perf_event_set_period(struct perf_event *event, | 175 | static int x86_perf_event_set_period(struct perf_event *event); |
161 | struct hw_perf_event *hwc, int idx); | ||
162 | |||
163 | /* | ||
164 | * Not sure about some of these | ||
165 | */ | ||
166 | static const u64 p6_perfmon_event_map[] = | ||
167 | { | ||
168 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
169 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
170 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, | ||
171 | [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, | ||
172 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
173 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
174 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
175 | }; | ||
176 | |||
177 | static u64 p6_pmu_event_map(int hw_event) | ||
178 | { | ||
179 | return p6_perfmon_event_map[hw_event]; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Event setting that is specified not to count anything. | ||
184 | * We use this to effectively disable a counter. | ||
185 | * | ||
186 | * L2_RQSTS with 0 MESI unit mask. | ||
187 | */ | ||
188 | #define P6_NOP_EVENT 0x0000002EULL | ||
189 | |||
190 | static u64 p6_pmu_raw_event(u64 hw_event) | ||
191 | { | ||
192 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
193 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
194 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
195 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
196 | #define P6_EVNTSEL_REG_MASK 0xFF000000ULL | ||
197 | |||
198 | #define P6_EVNTSEL_MASK \ | ||
199 | (P6_EVNTSEL_EVENT_MASK | \ | ||
200 | P6_EVNTSEL_UNIT_MASK | \ | ||
201 | P6_EVNTSEL_EDGE_MASK | \ | ||
202 | P6_EVNTSEL_INV_MASK | \ | ||
203 | P6_EVNTSEL_REG_MASK) | ||
204 | |||
205 | return hw_event & P6_EVNTSEL_MASK; | ||
206 | } | ||
207 | |||
208 | static struct event_constraint intel_p6_event_constraints[] = | ||
209 | { | ||
210 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ | ||
211 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
212 | INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ | ||
213 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
214 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
215 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
216 | EVENT_CONSTRAINT_END | ||
217 | }; | ||
218 | |||
219 | /* | ||
220 | * Intel PerfMon v3. Used on Core2 and later. | ||
221 | */ | ||
222 | static const u64 intel_perfmon_event_map[] = | ||
223 | { | ||
224 | [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, | ||
225 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
226 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e, | ||
227 | [PERF_COUNT_HW_CACHE_MISSES] = 0x412e, | ||
228 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
229 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
230 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, | ||
231 | }; | ||
232 | |||
233 | static struct event_constraint intel_core_event_constraints[] = | ||
234 | { | ||
235 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
236 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
237 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
238 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
239 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
240 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */ | ||
241 | EVENT_CONSTRAINT_END | ||
242 | }; | ||
243 | |||
244 | static struct event_constraint intel_core2_event_constraints[] = | ||
245 | { | ||
246 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
247 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
248 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
249 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
250 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
251 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
252 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
253 | INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ | ||
254 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
255 | INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ | ||
256 | INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ | ||
257 | EVENT_CONSTRAINT_END | ||
258 | }; | ||
259 | |||
260 | static struct event_constraint intel_nehalem_event_constraints[] = | ||
261 | { | ||
262 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
263 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
264 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | ||
265 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | ||
266 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | ||
267 | INTEL_EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */ | ||
268 | INTEL_EVENT_CONSTRAINT(0x48, 0x3), /* L1D_PEND_MISS */ | ||
269 | INTEL_EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */ | ||
270 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
271 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
272 | EVENT_CONSTRAINT_END | ||
273 | }; | ||
274 | |||
275 | static struct event_constraint intel_westmere_event_constraints[] = | ||
276 | { | ||
277 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
278 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
279 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
280 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ | ||
281 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
282 | EVENT_CONSTRAINT_END | ||
283 | }; | ||
284 | |||
285 | static struct event_constraint intel_gen_event_constraints[] = | ||
286 | { | ||
287 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
288 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
289 | EVENT_CONSTRAINT_END | ||
290 | }; | ||
291 | |||
292 | static u64 intel_pmu_event_map(int hw_event) | ||
293 | { | ||
294 | return intel_perfmon_event_map[hw_event]; | ||
295 | } | ||
296 | 176 | ||
297 | /* | 177 | /* |
298 | * Generalized hw caching related hw_event table, filled | 178 | * Generalized hw caching related hw_event table, filled |
@@ -309,526 +189,18 @@ static u64 __read_mostly hw_cache_event_ids | |||
309 | [PERF_COUNT_HW_CACHE_OP_MAX] | 189 | [PERF_COUNT_HW_CACHE_OP_MAX] |
310 | [PERF_COUNT_HW_CACHE_RESULT_MAX]; | 190 | [PERF_COUNT_HW_CACHE_RESULT_MAX]; |
311 | 191 | ||
312 | static __initconst u64 westmere_hw_cache_event_ids | ||
313 | [PERF_COUNT_HW_CACHE_MAX] | ||
314 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
315 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
316 | { | ||
317 | [ C(L1D) ] = { | ||
318 | [ C(OP_READ) ] = { | ||
319 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
320 | [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */ | ||
321 | }, | ||
322 | [ C(OP_WRITE) ] = { | ||
323 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
324 | [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */ | ||
325 | }, | ||
326 | [ C(OP_PREFETCH) ] = { | ||
327 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
328 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
329 | }, | ||
330 | }, | ||
331 | [ C(L1I ) ] = { | ||
332 | [ C(OP_READ) ] = { | ||
333 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
334 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
335 | }, | ||
336 | [ C(OP_WRITE) ] = { | ||
337 | [ C(RESULT_ACCESS) ] = -1, | ||
338 | [ C(RESULT_MISS) ] = -1, | ||
339 | }, | ||
340 | [ C(OP_PREFETCH) ] = { | ||
341 | [ C(RESULT_ACCESS) ] = 0x0, | ||
342 | [ C(RESULT_MISS) ] = 0x0, | ||
343 | }, | ||
344 | }, | ||
345 | [ C(LL ) ] = { | ||
346 | [ C(OP_READ) ] = { | ||
347 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
348 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
349 | }, | ||
350 | [ C(OP_WRITE) ] = { | ||
351 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
352 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
353 | }, | ||
354 | [ C(OP_PREFETCH) ] = { | ||
355 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
356 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
357 | }, | ||
358 | }, | ||
359 | [ C(DTLB) ] = { | ||
360 | [ C(OP_READ) ] = { | ||
361 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
362 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
363 | }, | ||
364 | [ C(OP_WRITE) ] = { | ||
365 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
366 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
367 | }, | ||
368 | [ C(OP_PREFETCH) ] = { | ||
369 | [ C(RESULT_ACCESS) ] = 0x0, | ||
370 | [ C(RESULT_MISS) ] = 0x0, | ||
371 | }, | ||
372 | }, | ||
373 | [ C(ITLB) ] = { | ||
374 | [ C(OP_READ) ] = { | ||
375 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
376 | [ C(RESULT_MISS) ] = 0x0185, /* ITLB_MISSES.ANY */ | ||
377 | }, | ||
378 | [ C(OP_WRITE) ] = { | ||
379 | [ C(RESULT_ACCESS) ] = -1, | ||
380 | [ C(RESULT_MISS) ] = -1, | ||
381 | }, | ||
382 | [ C(OP_PREFETCH) ] = { | ||
383 | [ C(RESULT_ACCESS) ] = -1, | ||
384 | [ C(RESULT_MISS) ] = -1, | ||
385 | }, | ||
386 | }, | ||
387 | [ C(BPU ) ] = { | ||
388 | [ C(OP_READ) ] = { | ||
389 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
390 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
391 | }, | ||
392 | [ C(OP_WRITE) ] = { | ||
393 | [ C(RESULT_ACCESS) ] = -1, | ||
394 | [ C(RESULT_MISS) ] = -1, | ||
395 | }, | ||
396 | [ C(OP_PREFETCH) ] = { | ||
397 | [ C(RESULT_ACCESS) ] = -1, | ||
398 | [ C(RESULT_MISS) ] = -1, | ||
399 | }, | ||
400 | }, | ||
401 | }; | ||
402 | |||
403 | static __initconst u64 nehalem_hw_cache_event_ids | ||
404 | [PERF_COUNT_HW_CACHE_MAX] | ||
405 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
406 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
407 | { | ||
408 | [ C(L1D) ] = { | ||
409 | [ C(OP_READ) ] = { | ||
410 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
411 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
412 | }, | ||
413 | [ C(OP_WRITE) ] = { | ||
414 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
415 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
416 | }, | ||
417 | [ C(OP_PREFETCH) ] = { | ||
418 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
419 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
420 | }, | ||
421 | }, | ||
422 | [ C(L1I ) ] = { | ||
423 | [ C(OP_READ) ] = { | ||
424 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
425 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
426 | }, | ||
427 | [ C(OP_WRITE) ] = { | ||
428 | [ C(RESULT_ACCESS) ] = -1, | ||
429 | [ C(RESULT_MISS) ] = -1, | ||
430 | }, | ||
431 | [ C(OP_PREFETCH) ] = { | ||
432 | [ C(RESULT_ACCESS) ] = 0x0, | ||
433 | [ C(RESULT_MISS) ] = 0x0, | ||
434 | }, | ||
435 | }, | ||
436 | [ C(LL ) ] = { | ||
437 | [ C(OP_READ) ] = { | ||
438 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
439 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
440 | }, | ||
441 | [ C(OP_WRITE) ] = { | ||
442 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
443 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
444 | }, | ||
445 | [ C(OP_PREFETCH) ] = { | ||
446 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
447 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
448 | }, | ||
449 | }, | ||
450 | [ C(DTLB) ] = { | ||
451 | [ C(OP_READ) ] = { | ||
452 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
453 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
454 | }, | ||
455 | [ C(OP_WRITE) ] = { | ||
456 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
457 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
458 | }, | ||
459 | [ C(OP_PREFETCH) ] = { | ||
460 | [ C(RESULT_ACCESS) ] = 0x0, | ||
461 | [ C(RESULT_MISS) ] = 0x0, | ||
462 | }, | ||
463 | }, | ||
464 | [ C(ITLB) ] = { | ||
465 | [ C(OP_READ) ] = { | ||
466 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
467 | [ C(RESULT_MISS) ] = 0x20c8, /* ITLB_MISS_RETIRED */ | ||
468 | }, | ||
469 | [ C(OP_WRITE) ] = { | ||
470 | [ C(RESULT_ACCESS) ] = -1, | ||
471 | [ C(RESULT_MISS) ] = -1, | ||
472 | }, | ||
473 | [ C(OP_PREFETCH) ] = { | ||
474 | [ C(RESULT_ACCESS) ] = -1, | ||
475 | [ C(RESULT_MISS) ] = -1, | ||
476 | }, | ||
477 | }, | ||
478 | [ C(BPU ) ] = { | ||
479 | [ C(OP_READ) ] = { | ||
480 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
481 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
482 | }, | ||
483 | [ C(OP_WRITE) ] = { | ||
484 | [ C(RESULT_ACCESS) ] = -1, | ||
485 | [ C(RESULT_MISS) ] = -1, | ||
486 | }, | ||
487 | [ C(OP_PREFETCH) ] = { | ||
488 | [ C(RESULT_ACCESS) ] = -1, | ||
489 | [ C(RESULT_MISS) ] = -1, | ||
490 | }, | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | static __initconst u64 core2_hw_cache_event_ids | ||
495 | [PERF_COUNT_HW_CACHE_MAX] | ||
496 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
497 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
498 | { | ||
499 | [ C(L1D) ] = { | ||
500 | [ C(OP_READ) ] = { | ||
501 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
502 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
503 | }, | ||
504 | [ C(OP_WRITE) ] = { | ||
505 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
506 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
507 | }, | ||
508 | [ C(OP_PREFETCH) ] = { | ||
509 | [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS */ | ||
510 | [ C(RESULT_MISS) ] = 0, | ||
511 | }, | ||
512 | }, | ||
513 | [ C(L1I ) ] = { | ||
514 | [ C(OP_READ) ] = { | ||
515 | [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS */ | ||
516 | [ C(RESULT_MISS) ] = 0x0081, /* L1I.MISSES */ | ||
517 | }, | ||
518 | [ C(OP_WRITE) ] = { | ||
519 | [ C(RESULT_ACCESS) ] = -1, | ||
520 | [ C(RESULT_MISS) ] = -1, | ||
521 | }, | ||
522 | [ C(OP_PREFETCH) ] = { | ||
523 | [ C(RESULT_ACCESS) ] = 0, | ||
524 | [ C(RESULT_MISS) ] = 0, | ||
525 | }, | ||
526 | }, | ||
527 | [ C(LL ) ] = { | ||
528 | [ C(OP_READ) ] = { | ||
529 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
530 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
531 | }, | ||
532 | [ C(OP_WRITE) ] = { | ||
533 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
534 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
535 | }, | ||
536 | [ C(OP_PREFETCH) ] = { | ||
537 | [ C(RESULT_ACCESS) ] = 0, | ||
538 | [ C(RESULT_MISS) ] = 0, | ||
539 | }, | ||
540 | }, | ||
541 | [ C(DTLB) ] = { | ||
542 | [ C(OP_READ) ] = { | ||
543 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
544 | [ C(RESULT_MISS) ] = 0x0208, /* DTLB_MISSES.MISS_LD */ | ||
545 | }, | ||
546 | [ C(OP_WRITE) ] = { | ||
547 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
548 | [ C(RESULT_MISS) ] = 0x0808, /* DTLB_MISSES.MISS_ST */ | ||
549 | }, | ||
550 | [ C(OP_PREFETCH) ] = { | ||
551 | [ C(RESULT_ACCESS) ] = 0, | ||
552 | [ C(RESULT_MISS) ] = 0, | ||
553 | }, | ||
554 | }, | ||
555 | [ C(ITLB) ] = { | ||
556 | [ C(OP_READ) ] = { | ||
557 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
558 | [ C(RESULT_MISS) ] = 0x1282, /* ITLBMISSES */ | ||
559 | }, | ||
560 | [ C(OP_WRITE) ] = { | ||
561 | [ C(RESULT_ACCESS) ] = -1, | ||
562 | [ C(RESULT_MISS) ] = -1, | ||
563 | }, | ||
564 | [ C(OP_PREFETCH) ] = { | ||
565 | [ C(RESULT_ACCESS) ] = -1, | ||
566 | [ C(RESULT_MISS) ] = -1, | ||
567 | }, | ||
568 | }, | ||
569 | [ C(BPU ) ] = { | ||
570 | [ C(OP_READ) ] = { | ||
571 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
572 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
573 | }, | ||
574 | [ C(OP_WRITE) ] = { | ||
575 | [ C(RESULT_ACCESS) ] = -1, | ||
576 | [ C(RESULT_MISS) ] = -1, | ||
577 | }, | ||
578 | [ C(OP_PREFETCH) ] = { | ||
579 | [ C(RESULT_ACCESS) ] = -1, | ||
580 | [ C(RESULT_MISS) ] = -1, | ||
581 | }, | ||
582 | }, | ||
583 | }; | ||
584 | |||
585 | static __initconst u64 atom_hw_cache_event_ids | ||
586 | [PERF_COUNT_HW_CACHE_MAX] | ||
587 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
588 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
589 | { | ||
590 | [ C(L1D) ] = { | ||
591 | [ C(OP_READ) ] = { | ||
592 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE.LD */ | ||
593 | [ C(RESULT_MISS) ] = 0, | ||
594 | }, | ||
595 | [ C(OP_WRITE) ] = { | ||
596 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST */ | ||
597 | [ C(RESULT_MISS) ] = 0, | ||
598 | }, | ||
599 | [ C(OP_PREFETCH) ] = { | ||
600 | [ C(RESULT_ACCESS) ] = 0x0, | ||
601 | [ C(RESULT_MISS) ] = 0, | ||
602 | }, | ||
603 | }, | ||
604 | [ C(L1I ) ] = { | ||
605 | [ C(OP_READ) ] = { | ||
606 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
607 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
608 | }, | ||
609 | [ C(OP_WRITE) ] = { | ||
610 | [ C(RESULT_ACCESS) ] = -1, | ||
611 | [ C(RESULT_MISS) ] = -1, | ||
612 | }, | ||
613 | [ C(OP_PREFETCH) ] = { | ||
614 | [ C(RESULT_ACCESS) ] = 0, | ||
615 | [ C(RESULT_MISS) ] = 0, | ||
616 | }, | ||
617 | }, | ||
618 | [ C(LL ) ] = { | ||
619 | [ C(OP_READ) ] = { | ||
620 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
621 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
622 | }, | ||
623 | [ C(OP_WRITE) ] = { | ||
624 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
625 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
626 | }, | ||
627 | [ C(OP_PREFETCH) ] = { | ||
628 | [ C(RESULT_ACCESS) ] = 0, | ||
629 | [ C(RESULT_MISS) ] = 0, | ||
630 | }, | ||
631 | }, | ||
632 | [ C(DTLB) ] = { | ||
633 | [ C(OP_READ) ] = { | ||
634 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI (alias) */ | ||
635 | [ C(RESULT_MISS) ] = 0x0508, /* DTLB_MISSES.MISS_LD */ | ||
636 | }, | ||
637 | [ C(OP_WRITE) ] = { | ||
638 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI (alias) */ | ||
639 | [ C(RESULT_MISS) ] = 0x0608, /* DTLB_MISSES.MISS_ST */ | ||
640 | }, | ||
641 | [ C(OP_PREFETCH) ] = { | ||
642 | [ C(RESULT_ACCESS) ] = 0, | ||
643 | [ C(RESULT_MISS) ] = 0, | ||
644 | }, | ||
645 | }, | ||
646 | [ C(ITLB) ] = { | ||
647 | [ C(OP_READ) ] = { | ||
648 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
649 | [ C(RESULT_MISS) ] = 0x0282, /* ITLB.MISSES */ | ||
650 | }, | ||
651 | [ C(OP_WRITE) ] = { | ||
652 | [ C(RESULT_ACCESS) ] = -1, | ||
653 | [ C(RESULT_MISS) ] = -1, | ||
654 | }, | ||
655 | [ C(OP_PREFETCH) ] = { | ||
656 | [ C(RESULT_ACCESS) ] = -1, | ||
657 | [ C(RESULT_MISS) ] = -1, | ||
658 | }, | ||
659 | }, | ||
660 | [ C(BPU ) ] = { | ||
661 | [ C(OP_READ) ] = { | ||
662 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
663 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
664 | }, | ||
665 | [ C(OP_WRITE) ] = { | ||
666 | [ C(RESULT_ACCESS) ] = -1, | ||
667 | [ C(RESULT_MISS) ] = -1, | ||
668 | }, | ||
669 | [ C(OP_PREFETCH) ] = { | ||
670 | [ C(RESULT_ACCESS) ] = -1, | ||
671 | [ C(RESULT_MISS) ] = -1, | ||
672 | }, | ||
673 | }, | ||
674 | }; | ||
675 | |||
676 | static u64 intel_pmu_raw_event(u64 hw_event) | ||
677 | { | ||
678 | #define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
679 | #define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
680 | #define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
681 | #define CORE_EVNTSEL_INV_MASK 0x00800000ULL | ||
682 | #define CORE_EVNTSEL_REG_MASK 0xFF000000ULL | ||
683 | |||
684 | #define CORE_EVNTSEL_MASK \ | ||
685 | (INTEL_ARCH_EVTSEL_MASK | \ | ||
686 | INTEL_ARCH_UNIT_MASK | \ | ||
687 | INTEL_ARCH_EDGE_MASK | \ | ||
688 | INTEL_ARCH_INV_MASK | \ | ||
689 | INTEL_ARCH_CNT_MASK) | ||
690 | |||
691 | return hw_event & CORE_EVNTSEL_MASK; | ||
692 | } | ||
693 | |||
694 | static __initconst u64 amd_hw_cache_event_ids | ||
695 | [PERF_COUNT_HW_CACHE_MAX] | ||
696 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
697 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
698 | { | ||
699 | [ C(L1D) ] = { | ||
700 | [ C(OP_READ) ] = { | ||
701 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
702 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ | ||
703 | }, | ||
704 | [ C(OP_WRITE) ] = { | ||
705 | [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ | ||
706 | [ C(RESULT_MISS) ] = 0, | ||
707 | }, | ||
708 | [ C(OP_PREFETCH) ] = { | ||
709 | [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts */ | ||
710 | [ C(RESULT_MISS) ] = 0x0167, /* Data Prefetcher :cancelled */ | ||
711 | }, | ||
712 | }, | ||
713 | [ C(L1I ) ] = { | ||
714 | [ C(OP_READ) ] = { | ||
715 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches */ | ||
716 | [ C(RESULT_MISS) ] = 0x0081, /* Instruction cache misses */ | ||
717 | }, | ||
718 | [ C(OP_WRITE) ] = { | ||
719 | [ C(RESULT_ACCESS) ] = -1, | ||
720 | [ C(RESULT_MISS) ] = -1, | ||
721 | }, | ||
722 | [ C(OP_PREFETCH) ] = { | ||
723 | [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */ | ||
724 | [ C(RESULT_MISS) ] = 0, | ||
725 | }, | ||
726 | }, | ||
727 | [ C(LL ) ] = { | ||
728 | [ C(OP_READ) ] = { | ||
729 | [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */ | ||
730 | [ C(RESULT_MISS) ] = 0x037E, /* L2 Cache Misses : IC+DC */ | ||
731 | }, | ||
732 | [ C(OP_WRITE) ] = { | ||
733 | [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback */ | ||
734 | [ C(RESULT_MISS) ] = 0, | ||
735 | }, | ||
736 | [ C(OP_PREFETCH) ] = { | ||
737 | [ C(RESULT_ACCESS) ] = 0, | ||
738 | [ C(RESULT_MISS) ] = 0, | ||
739 | }, | ||
740 | }, | ||
741 | [ C(DTLB) ] = { | ||
742 | [ C(OP_READ) ] = { | ||
743 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
744 | [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ | ||
745 | }, | ||
746 | [ C(OP_WRITE) ] = { | ||
747 | [ C(RESULT_ACCESS) ] = 0, | ||
748 | [ C(RESULT_MISS) ] = 0, | ||
749 | }, | ||
750 | [ C(OP_PREFETCH) ] = { | ||
751 | [ C(RESULT_ACCESS) ] = 0, | ||
752 | [ C(RESULT_MISS) ] = 0, | ||
753 | }, | ||
754 | }, | ||
755 | [ C(ITLB) ] = { | ||
756 | [ C(OP_READ) ] = { | ||
757 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */ | ||
758 | [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */ | ||
759 | }, | ||
760 | [ C(OP_WRITE) ] = { | ||
761 | [ C(RESULT_ACCESS) ] = -1, | ||
762 | [ C(RESULT_MISS) ] = -1, | ||
763 | }, | ||
764 | [ C(OP_PREFETCH) ] = { | ||
765 | [ C(RESULT_ACCESS) ] = -1, | ||
766 | [ C(RESULT_MISS) ] = -1, | ||
767 | }, | ||
768 | }, | ||
769 | [ C(BPU ) ] = { | ||
770 | [ C(OP_READ) ] = { | ||
771 | [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr. */ | ||
772 | [ C(RESULT_MISS) ] = 0x00c3, /* Retired Mispredicted BI */ | ||
773 | }, | ||
774 | [ C(OP_WRITE) ] = { | ||
775 | [ C(RESULT_ACCESS) ] = -1, | ||
776 | [ C(RESULT_MISS) ] = -1, | ||
777 | }, | ||
778 | [ C(OP_PREFETCH) ] = { | ||
779 | [ C(RESULT_ACCESS) ] = -1, | ||
780 | [ C(RESULT_MISS) ] = -1, | ||
781 | }, | ||
782 | }, | ||
783 | }; | ||
784 | |||
785 | /* | ||
786 | * AMD Performance Monitor K7 and later. | ||
787 | */ | ||
788 | static const u64 amd_perfmon_event_map[] = | ||
789 | { | ||
790 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | ||
791 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
792 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, | ||
793 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, | ||
794 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
795 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
796 | }; | ||
797 | |||
798 | static u64 amd_pmu_event_map(int hw_event) | ||
799 | { | ||
800 | return amd_perfmon_event_map[hw_event]; | ||
801 | } | ||
802 | |||
803 | static u64 amd_pmu_raw_event(u64 hw_event) | ||
804 | { | ||
805 | #define K7_EVNTSEL_EVENT_MASK 0x7000000FFULL | ||
806 | #define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL | ||
807 | #define K7_EVNTSEL_EDGE_MASK 0x000040000ULL | ||
808 | #define K7_EVNTSEL_INV_MASK 0x000800000ULL | ||
809 | #define K7_EVNTSEL_REG_MASK 0x0FF000000ULL | ||
810 | |||
811 | #define K7_EVNTSEL_MASK \ | ||
812 | (K7_EVNTSEL_EVENT_MASK | \ | ||
813 | K7_EVNTSEL_UNIT_MASK | \ | ||
814 | K7_EVNTSEL_EDGE_MASK | \ | ||
815 | K7_EVNTSEL_INV_MASK | \ | ||
816 | K7_EVNTSEL_REG_MASK) | ||
817 | |||
818 | return hw_event & K7_EVNTSEL_MASK; | ||
819 | } | ||
820 | |||
821 | /* | 192 | /* |
822 | * Propagate event elapsed time into the generic event. | 193 | * Propagate event elapsed time into the generic event. |
823 | * Can only be executed on the CPU where the event is active. | 194 | * Can only be executed on the CPU where the event is active. |
824 | * Returns the delta events processed. | 195 | * Returns the delta events processed. |
825 | */ | 196 | */ |
826 | static u64 | 197 | static u64 |
827 | x86_perf_event_update(struct perf_event *event, | 198 | x86_perf_event_update(struct perf_event *event) |
828 | struct hw_perf_event *hwc, int idx) | ||
829 | { | 199 | { |
200 | struct hw_perf_event *hwc = &event->hw; | ||
830 | int shift = 64 - x86_pmu.event_bits; | 201 | int shift = 64 - x86_pmu.event_bits; |
831 | u64 prev_raw_count, new_raw_count; | 202 | u64 prev_raw_count, new_raw_count; |
203 | int idx = hwc->idx; | ||
832 | s64 delta; | 204 | s64 delta; |
833 | 205 | ||
834 | if (idx == X86_PMC_IDX_FIXED_BTS) | 206 | if (idx == X86_PMC_IDX_FIXED_BTS) |
@@ -928,7 +300,7 @@ static inline bool bts_available(void) | |||
928 | return x86_pmu.enable_bts != NULL; | 300 | return x86_pmu.enable_bts != NULL; |
929 | } | 301 | } |
930 | 302 | ||
931 | static inline void init_debug_store_on_cpu(int cpu) | 303 | static void init_debug_store_on_cpu(int cpu) |
932 | { | 304 | { |
933 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; | 305 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; |
934 | 306 | ||
@@ -940,7 +312,7 @@ static inline void init_debug_store_on_cpu(int cpu) | |||
940 | (u32)((u64)(unsigned long)ds >> 32)); | 312 | (u32)((u64)(unsigned long)ds >> 32)); |
941 | } | 313 | } |
942 | 314 | ||
943 | static inline void fini_debug_store_on_cpu(int cpu) | 315 | static void fini_debug_store_on_cpu(int cpu) |
944 | { | 316 | { |
945 | if (!per_cpu(cpu_hw_events, cpu).ds) | 317 | if (!per_cpu(cpu_hw_events, cpu).ds) |
946 | return; | 318 | return; |
@@ -1069,42 +441,6 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) | |||
1069 | return 0; | 441 | return 0; |
1070 | } | 442 | } |
1071 | 443 | ||
1072 | static void intel_pmu_enable_bts(u64 config) | ||
1073 | { | ||
1074 | unsigned long debugctlmsr; | ||
1075 | |||
1076 | debugctlmsr = get_debugctlmsr(); | ||
1077 | |||
1078 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
1079 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
1080 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
1081 | |||
1082 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
1083 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
1084 | |||
1085 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
1086 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
1087 | |||
1088 | update_debugctlmsr(debugctlmsr); | ||
1089 | } | ||
1090 | |||
1091 | static void intel_pmu_disable_bts(void) | ||
1092 | { | ||
1093 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1094 | unsigned long debugctlmsr; | ||
1095 | |||
1096 | if (!cpuc->ds) | ||
1097 | return; | ||
1098 | |||
1099 | debugctlmsr = get_debugctlmsr(); | ||
1100 | |||
1101 | debugctlmsr &= | ||
1102 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
1103 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
1104 | |||
1105 | update_debugctlmsr(debugctlmsr); | ||
1106 | } | ||
1107 | |||
1108 | /* | 444 | /* |
1109 | * Setup the hardware configuration for a given attr_type | 445 | * Setup the hardware configuration for a given attr_type |
1110 | */ | 446 | */ |
@@ -1174,6 +510,9 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
1174 | */ | 510 | */ |
1175 | if (attr->type == PERF_TYPE_RAW) { | 511 | if (attr->type == PERF_TYPE_RAW) { |
1176 | hwc->config |= x86_pmu.raw_event(attr->config); | 512 | hwc->config |= x86_pmu.raw_event(attr->config); |
513 | if ((hwc->config & ARCH_PERFMON_EVENTSEL_ANY) && | ||
514 | perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) | ||
515 | return -EACCES; | ||
1177 | return 0; | 516 | return 0; |
1178 | } | 517 | } |
1179 | 518 | ||
@@ -1213,26 +552,6 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
1213 | return 0; | 552 | return 0; |
1214 | } | 553 | } |
1215 | 554 | ||
1216 | static void p6_pmu_disable_all(void) | ||
1217 | { | ||
1218 | u64 val; | ||
1219 | |||
1220 | /* p6 only has one enable register */ | ||
1221 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
1222 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
1223 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
1224 | } | ||
1225 | |||
1226 | static void intel_pmu_disable_all(void) | ||
1227 | { | ||
1228 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1229 | |||
1230 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | ||
1231 | |||
1232 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
1233 | intel_pmu_disable_bts(); | ||
1234 | } | ||
1235 | |||
1236 | static void x86_pmu_disable_all(void) | 555 | static void x86_pmu_disable_all(void) |
1237 | { | 556 | { |
1238 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 557 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
@@ -1244,9 +563,9 @@ static void x86_pmu_disable_all(void) | |||
1244 | if (!test_bit(idx, cpuc->active_mask)) | 563 | if (!test_bit(idx, cpuc->active_mask)) |
1245 | continue; | 564 | continue; |
1246 | rdmsrl(x86_pmu.eventsel + idx, val); | 565 | rdmsrl(x86_pmu.eventsel + idx, val); |
1247 | if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE)) | 566 | if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE)) |
1248 | continue; | 567 | continue; |
1249 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | 568 | val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; |
1250 | wrmsrl(x86_pmu.eventsel + idx, val); | 569 | wrmsrl(x86_pmu.eventsel + idx, val); |
1251 | } | 570 | } |
1252 | } | 571 | } |
@@ -1268,33 +587,6 @@ void hw_perf_disable(void) | |||
1268 | x86_pmu.disable_all(); | 587 | x86_pmu.disable_all(); |
1269 | } | 588 | } |
1270 | 589 | ||
1271 | static void p6_pmu_enable_all(void) | ||
1272 | { | ||
1273 | unsigned long val; | ||
1274 | |||
1275 | /* p6 only has one enable register */ | ||
1276 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
1277 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
1278 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
1279 | } | ||
1280 | |||
1281 | static void intel_pmu_enable_all(void) | ||
1282 | { | ||
1283 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1284 | |||
1285 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | ||
1286 | |||
1287 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | ||
1288 | struct perf_event *event = | ||
1289 | cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
1290 | |||
1291 | if (WARN_ON_ONCE(!event)) | ||
1292 | return; | ||
1293 | |||
1294 | intel_pmu_enable_bts(event->hw.config); | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | static void x86_pmu_enable_all(void) | 590 | static void x86_pmu_enable_all(void) |
1299 | { | 591 | { |
1300 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 592 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
@@ -1308,7 +600,7 @@ static void x86_pmu_enable_all(void) | |||
1308 | continue; | 600 | continue; |
1309 | 601 | ||
1310 | val = event->hw.config; | 602 | val = event->hw.config; |
1311 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 603 | val |= ARCH_PERFMON_EVENTSEL_ENABLE; |
1312 | wrmsrl(x86_pmu.eventsel + idx, val); | 604 | wrmsrl(x86_pmu.eventsel + idx, val); |
1313 | } | 605 | } |
1314 | } | 606 | } |
@@ -1330,8 +622,8 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1330 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | 622 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); |
1331 | 623 | ||
1332 | for (i = 0; i < n; i++) { | 624 | for (i = 0; i < n; i++) { |
1333 | constraints[i] = | 625 | c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); |
1334 | x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); | 626 | constraints[i] = c; |
1335 | } | 627 | } |
1336 | 628 | ||
1337 | /* | 629 | /* |
@@ -1353,7 +645,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1353 | if (test_bit(hwc->idx, used_mask)) | 645 | if (test_bit(hwc->idx, used_mask)) |
1354 | break; | 646 | break; |
1355 | 647 | ||
1356 | set_bit(hwc->idx, used_mask); | 648 | __set_bit(hwc->idx, used_mask); |
1357 | if (assign) | 649 | if (assign) |
1358 | assign[i] = hwc->idx; | 650 | assign[i] = hwc->idx; |
1359 | } | 651 | } |
@@ -1394,7 +686,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1394 | if (c->weight != w) | 686 | if (c->weight != w) |
1395 | continue; | 687 | continue; |
1396 | 688 | ||
1397 | for_each_bit(j, c->idxmsk, X86_PMC_IDX_MAX) { | 689 | for_each_set_bit(j, c->idxmsk, X86_PMC_IDX_MAX) { |
1398 | if (!test_bit(j, used_mask)) | 690 | if (!test_bit(j, used_mask)) |
1399 | break; | 691 | break; |
1400 | } | 692 | } |
@@ -1402,7 +694,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1402 | if (j == X86_PMC_IDX_MAX) | 694 | if (j == X86_PMC_IDX_MAX) |
1403 | break; | 695 | break; |
1404 | 696 | ||
1405 | set_bit(j, used_mask); | 697 | __set_bit(j, used_mask); |
1406 | 698 | ||
1407 | if (assign) | 699 | if (assign) |
1408 | assign[i] = j; | 700 | assign[i] = j; |
@@ -1495,7 +787,8 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc, | |||
1495 | hwc->last_tag == cpuc->tags[i]; | 787 | hwc->last_tag == cpuc->tags[i]; |
1496 | } | 788 | } |
1497 | 789 | ||
1498 | static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc); | 790 | static int x86_pmu_start(struct perf_event *event); |
791 | static void x86_pmu_stop(struct perf_event *event); | ||
1499 | 792 | ||
1500 | void hw_perf_enable(void) | 793 | void hw_perf_enable(void) |
1501 | { | 794 | { |
@@ -1511,6 +804,7 @@ void hw_perf_enable(void) | |||
1511 | return; | 804 | return; |
1512 | 805 | ||
1513 | if (cpuc->n_added) { | 806 | if (cpuc->n_added) { |
807 | int n_running = cpuc->n_events - cpuc->n_added; | ||
1514 | /* | 808 | /* |
1515 | * apply assignment obtained either from | 809 | * apply assignment obtained either from |
1516 | * hw_perf_group_sched_in() or x86_pmu_enable() | 810 | * hw_perf_group_sched_in() or x86_pmu_enable() |
@@ -1518,8 +812,7 @@ void hw_perf_enable(void) | |||
1518 | * step1: save events moving to new counters | 812 | * step1: save events moving to new counters |
1519 | * step2: reprogram moved events into new counters | 813 | * step2: reprogram moved events into new counters |
1520 | */ | 814 | */ |
1521 | for (i = 0; i < cpuc->n_events; i++) { | 815 | for (i = 0; i < n_running; i++) { |
1522 | |||
1523 | event = cpuc->event_list[i]; | 816 | event = cpuc->event_list[i]; |
1524 | hwc = &event->hw; | 817 | hwc = &event->hw; |
1525 | 818 | ||
@@ -1533,30 +826,19 @@ void hw_perf_enable(void) | |||
1533 | match_prev_assignment(hwc, cpuc, i)) | 826 | match_prev_assignment(hwc, cpuc, i)) |
1534 | continue; | 827 | continue; |
1535 | 828 | ||
1536 | __x86_pmu_disable(event, cpuc); | 829 | x86_pmu_stop(event); |
1537 | |||
1538 | hwc->idx = -1; | ||
1539 | } | 830 | } |
1540 | 831 | ||
1541 | for (i = 0; i < cpuc->n_events; i++) { | 832 | for (i = 0; i < cpuc->n_events; i++) { |
1542 | |||
1543 | event = cpuc->event_list[i]; | 833 | event = cpuc->event_list[i]; |
1544 | hwc = &event->hw; | 834 | hwc = &event->hw; |
1545 | 835 | ||
1546 | if (hwc->idx == -1) { | 836 | if (!match_prev_assignment(hwc, cpuc, i)) |
1547 | x86_assign_hw_event(event, cpuc, i); | 837 | x86_assign_hw_event(event, cpuc, i); |
1548 | x86_perf_event_set_period(event, hwc, hwc->idx); | 838 | else if (i < n_running) |
1549 | } | 839 | continue; |
1550 | /* | ||
1551 | * need to mark as active because x86_pmu_disable() | ||
1552 | * clear active_mask and events[] yet it preserves | ||
1553 | * idx | ||
1554 | */ | ||
1555 | set_bit(hwc->idx, cpuc->active_mask); | ||
1556 | cpuc->events[hwc->idx] = event; | ||
1557 | 840 | ||
1558 | x86_pmu.enable(hwc, hwc->idx); | 841 | x86_pmu_start(event); |
1559 | perf_event_update_userpage(event); | ||
1560 | } | 842 | } |
1561 | cpuc->n_added = 0; | 843 | cpuc->n_added = 0; |
1562 | perf_events_lapic_init(); | 844 | perf_events_lapic_init(); |
@@ -1568,70 +850,16 @@ void hw_perf_enable(void) | |||
1568 | x86_pmu.enable_all(); | 850 | x86_pmu.enable_all(); |
1569 | } | 851 | } |
1570 | 852 | ||
1571 | static inline u64 intel_pmu_get_status(void) | 853 | static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) |
1572 | { | ||
1573 | u64 status; | ||
1574 | |||
1575 | rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); | ||
1576 | |||
1577 | return status; | ||
1578 | } | ||
1579 | |||
1580 | static inline void intel_pmu_ack_status(u64 ack) | ||
1581 | { | ||
1582 | wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); | ||
1583 | } | ||
1584 | |||
1585 | static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
1586 | { | ||
1587 | (void)checking_wrmsrl(hwc->config_base + idx, | ||
1588 | hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); | ||
1589 | } | ||
1590 | |||
1591 | static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
1592 | { | 854 | { |
1593 | (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); | 855 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, |
1594 | } | 856 | hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); |
1595 | |||
1596 | static inline void | ||
1597 | intel_pmu_disable_fixed(struct hw_perf_event *hwc, int __idx) | ||
1598 | { | ||
1599 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
1600 | u64 ctrl_val, mask; | ||
1601 | |||
1602 | mask = 0xfULL << (idx * 4); | ||
1603 | |||
1604 | rdmsrl(hwc->config_base, ctrl_val); | ||
1605 | ctrl_val &= ~mask; | ||
1606 | (void)checking_wrmsrl(hwc->config_base, ctrl_val); | ||
1607 | } | 857 | } |
1608 | 858 | ||
1609 | static inline void | 859 | static inline void x86_pmu_disable_event(struct perf_event *event) |
1610 | p6_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
1611 | { | 860 | { |
1612 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 861 | struct hw_perf_event *hwc = &event->hw; |
1613 | u64 val = P6_NOP_EVENT; | 862 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, hwc->config); |
1614 | |||
1615 | if (cpuc->enabled) | ||
1616 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
1617 | |||
1618 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
1619 | } | ||
1620 | |||
1621 | static inline void | ||
1622 | intel_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
1623 | { | ||
1624 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
1625 | intel_pmu_disable_bts(); | ||
1626 | return; | ||
1627 | } | ||
1628 | |||
1629 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
1630 | intel_pmu_disable_fixed(hwc, idx); | ||
1631 | return; | ||
1632 | } | ||
1633 | |||
1634 | x86_pmu_disable_event(hwc, idx); | ||
1635 | } | 863 | } |
1636 | 864 | ||
1637 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); | 865 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); |
@@ -1641,12 +869,12 @@ static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); | |||
1641 | * To be called with the event disabled in hw: | 869 | * To be called with the event disabled in hw: |
1642 | */ | 870 | */ |
1643 | static int | 871 | static int |
1644 | x86_perf_event_set_period(struct perf_event *event, | 872 | x86_perf_event_set_period(struct perf_event *event) |
1645 | struct hw_perf_event *hwc, int idx) | ||
1646 | { | 873 | { |
874 | struct hw_perf_event *hwc = &event->hw; | ||
1647 | s64 left = atomic64_read(&hwc->period_left); | 875 | s64 left = atomic64_read(&hwc->period_left); |
1648 | s64 period = hwc->sample_period; | 876 | s64 period = hwc->sample_period; |
1649 | int err, ret = 0; | 877 | int err, ret = 0, idx = hwc->idx; |
1650 | 878 | ||
1651 | if (idx == X86_PMC_IDX_FIXED_BTS) | 879 | if (idx == X86_PMC_IDX_FIXED_BTS) |
1652 | return 0; | 880 | return 0; |
@@ -1692,75 +920,11 @@ x86_perf_event_set_period(struct perf_event *event, | |||
1692 | return ret; | 920 | return ret; |
1693 | } | 921 | } |
1694 | 922 | ||
1695 | static inline void | 923 | static void x86_pmu_enable_event(struct perf_event *event) |
1696 | intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | ||
1697 | { | ||
1698 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
1699 | u64 ctrl_val, bits, mask; | ||
1700 | int err; | ||
1701 | |||
1702 | /* | ||
1703 | * Enable IRQ generation (0x8), | ||
1704 | * and enable ring-3 counting (0x2) and ring-0 counting (0x1) | ||
1705 | * if requested: | ||
1706 | */ | ||
1707 | bits = 0x8ULL; | ||
1708 | if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) | ||
1709 | bits |= 0x2; | ||
1710 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | ||
1711 | bits |= 0x1; | ||
1712 | |||
1713 | /* | ||
1714 | * ANY bit is supported in v3 and up | ||
1715 | */ | ||
1716 | if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) | ||
1717 | bits |= 0x4; | ||
1718 | |||
1719 | bits <<= (idx * 4); | ||
1720 | mask = 0xfULL << (idx * 4); | ||
1721 | |||
1722 | rdmsrl(hwc->config_base, ctrl_val); | ||
1723 | ctrl_val &= ~mask; | ||
1724 | ctrl_val |= bits; | ||
1725 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | ||
1726 | } | ||
1727 | |||
1728 | static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
1729 | { | 924 | { |
1730 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 925 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
1731 | u64 val; | ||
1732 | |||
1733 | val = hwc->config; | ||
1734 | if (cpuc->enabled) | 926 | if (cpuc->enabled) |
1735 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 927 | __x86_pmu_enable_event(&event->hw); |
1736 | |||
1737 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
1738 | } | ||
1739 | |||
1740 | |||
1741 | static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
1742 | { | ||
1743 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
1744 | if (!__get_cpu_var(cpu_hw_events).enabled) | ||
1745 | return; | ||
1746 | |||
1747 | intel_pmu_enable_bts(hwc->config); | ||
1748 | return; | ||
1749 | } | ||
1750 | |||
1751 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
1752 | intel_pmu_enable_fixed(hwc, idx); | ||
1753 | return; | ||
1754 | } | ||
1755 | |||
1756 | __x86_pmu_enable_event(hwc, idx); | ||
1757 | } | ||
1758 | |||
1759 | static void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
1760 | { | ||
1761 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1762 | if (cpuc->enabled) | ||
1763 | __x86_pmu_enable_event(hwc, idx); | ||
1764 | } | 928 | } |
1765 | 929 | ||
1766 | /* | 930 | /* |
@@ -1796,21 +960,32 @@ static int x86_pmu_enable(struct perf_event *event) | |||
1796 | memcpy(cpuc->assign, assign, n*sizeof(int)); | 960 | memcpy(cpuc->assign, assign, n*sizeof(int)); |
1797 | 961 | ||
1798 | cpuc->n_events = n; | 962 | cpuc->n_events = n; |
1799 | cpuc->n_added = n - n0; | 963 | cpuc->n_added += n - n0; |
1800 | 964 | ||
1801 | return 0; | 965 | return 0; |
1802 | } | 966 | } |
1803 | 967 | ||
1804 | static void x86_pmu_unthrottle(struct perf_event *event) | 968 | static int x86_pmu_start(struct perf_event *event) |
1805 | { | 969 | { |
1806 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 970 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
1807 | struct hw_perf_event *hwc = &event->hw; | 971 | int idx = event->hw.idx; |
1808 | 972 | ||
1809 | if (WARN_ON_ONCE(hwc->idx >= X86_PMC_IDX_MAX || | 973 | if (idx == -1) |
1810 | cpuc->events[hwc->idx] != event)) | 974 | return -EAGAIN; |
1811 | return; | 975 | |
976 | x86_perf_event_set_period(event); | ||
977 | cpuc->events[idx] = event; | ||
978 | __set_bit(idx, cpuc->active_mask); | ||
979 | x86_pmu.enable(event); | ||
980 | perf_event_update_userpage(event); | ||
1812 | 981 | ||
1813 | x86_pmu.enable(hwc, hwc->idx); | 982 | return 0; |
983 | } | ||
984 | |||
985 | static void x86_pmu_unthrottle(struct perf_event *event) | ||
986 | { | ||
987 | int ret = x86_pmu_start(event); | ||
988 | WARN_ON_ONCE(ret); | ||
1814 | } | 989 | } |
1815 | 990 | ||
1816 | void perf_event_print_debug(void) | 991 | void perf_event_print_debug(void) |
@@ -1864,87 +1039,22 @@ void perf_event_print_debug(void) | |||
1864 | local_irq_restore(flags); | 1039 | local_irq_restore(flags); |
1865 | } | 1040 | } |
1866 | 1041 | ||
1867 | static void intel_pmu_drain_bts_buffer(struct cpu_hw_events *cpuc) | 1042 | static void x86_pmu_stop(struct perf_event *event) |
1868 | { | ||
1869 | struct debug_store *ds = cpuc->ds; | ||
1870 | struct bts_record { | ||
1871 | u64 from; | ||
1872 | u64 to; | ||
1873 | u64 flags; | ||
1874 | }; | ||
1875 | struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
1876 | struct bts_record *at, *top; | ||
1877 | struct perf_output_handle handle; | ||
1878 | struct perf_event_header header; | ||
1879 | struct perf_sample_data data; | ||
1880 | struct pt_regs regs; | ||
1881 | |||
1882 | if (!event) | ||
1883 | return; | ||
1884 | |||
1885 | if (!ds) | ||
1886 | return; | ||
1887 | |||
1888 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; | ||
1889 | top = (struct bts_record *)(unsigned long)ds->bts_index; | ||
1890 | |||
1891 | if (top <= at) | ||
1892 | return; | ||
1893 | |||
1894 | ds->bts_index = ds->bts_buffer_base; | ||
1895 | |||
1896 | |||
1897 | data.period = event->hw.last_period; | ||
1898 | data.addr = 0; | ||
1899 | data.raw = NULL; | ||
1900 | regs.ip = 0; | ||
1901 | |||
1902 | /* | ||
1903 | * Prepare a generic sample, i.e. fill in the invariant fields. | ||
1904 | * We will overwrite the from and to address before we output | ||
1905 | * the sample. | ||
1906 | */ | ||
1907 | perf_prepare_sample(&header, &data, event, ®s); | ||
1908 | |||
1909 | if (perf_output_begin(&handle, event, | ||
1910 | header.size * (top - at), 1, 1)) | ||
1911 | return; | ||
1912 | |||
1913 | for (; at < top; at++) { | ||
1914 | data.ip = at->from; | ||
1915 | data.addr = at->to; | ||
1916 | |||
1917 | perf_output_sample(&handle, &header, &data, event); | ||
1918 | } | ||
1919 | |||
1920 | perf_output_end(&handle); | ||
1921 | |||
1922 | /* There's new data available. */ | ||
1923 | event->hw.interrupts++; | ||
1924 | event->pending_kill = POLL_IN; | ||
1925 | } | ||
1926 | |||
1927 | static void __x86_pmu_disable(struct perf_event *event, struct cpu_hw_events *cpuc) | ||
1928 | { | 1043 | { |
1044 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
1929 | struct hw_perf_event *hwc = &event->hw; | 1045 | struct hw_perf_event *hwc = &event->hw; |
1930 | int idx = hwc->idx; | 1046 | int idx = hwc->idx; |
1931 | 1047 | ||
1932 | /* | 1048 | if (!__test_and_clear_bit(idx, cpuc->active_mask)) |
1933 | * Must be done before we disable, otherwise the nmi handler | 1049 | return; |
1934 | * could reenable again: | 1050 | |
1935 | */ | 1051 | x86_pmu.disable(event); |
1936 | clear_bit(idx, cpuc->active_mask); | ||
1937 | x86_pmu.disable(hwc, idx); | ||
1938 | 1052 | ||
1939 | /* | 1053 | /* |
1940 | * Drain the remaining delta count out of a event | 1054 | * Drain the remaining delta count out of a event |
1941 | * that we are disabling: | 1055 | * that we are disabling: |
1942 | */ | 1056 | */ |
1943 | x86_perf_event_update(event, hwc, idx); | 1057 | x86_perf_event_update(event); |
1944 | |||
1945 | /* Drain the remaining BTS records. */ | ||
1946 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) | ||
1947 | intel_pmu_drain_bts_buffer(cpuc); | ||
1948 | 1058 | ||
1949 | cpuc->events[idx] = NULL; | 1059 | cpuc->events[idx] = NULL; |
1950 | } | 1060 | } |
@@ -1954,7 +1064,7 @@ static void x86_pmu_disable(struct perf_event *event) | |||
1954 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1064 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
1955 | int i; | 1065 | int i; |
1956 | 1066 | ||
1957 | __x86_pmu_disable(event, cpuc); | 1067 | x86_pmu_stop(event); |
1958 | 1068 | ||
1959 | for (i = 0; i < cpuc->n_events; i++) { | 1069 | for (i = 0; i < cpuc->n_events; i++) { |
1960 | if (event == cpuc->event_list[i]) { | 1070 | if (event == cpuc->event_list[i]) { |
@@ -1972,117 +1082,6 @@ static void x86_pmu_disable(struct perf_event *event) | |||
1972 | perf_event_update_userpage(event); | 1082 | perf_event_update_userpage(event); |
1973 | } | 1083 | } |
1974 | 1084 | ||
1975 | /* | ||
1976 | * Save and restart an expired event. Called by NMI contexts, | ||
1977 | * so it has to be careful about preempting normal event ops: | ||
1978 | */ | ||
1979 | static int intel_pmu_save_and_restart(struct perf_event *event) | ||
1980 | { | ||
1981 | struct hw_perf_event *hwc = &event->hw; | ||
1982 | int idx = hwc->idx; | ||
1983 | int ret; | ||
1984 | |||
1985 | x86_perf_event_update(event, hwc, idx); | ||
1986 | ret = x86_perf_event_set_period(event, hwc, idx); | ||
1987 | |||
1988 | if (event->state == PERF_EVENT_STATE_ACTIVE) | ||
1989 | intel_pmu_enable_event(hwc, idx); | ||
1990 | |||
1991 | return ret; | ||
1992 | } | ||
1993 | |||
1994 | static void intel_pmu_reset(void) | ||
1995 | { | ||
1996 | struct debug_store *ds = __get_cpu_var(cpu_hw_events).ds; | ||
1997 | unsigned long flags; | ||
1998 | int idx; | ||
1999 | |||
2000 | if (!x86_pmu.num_events) | ||
2001 | return; | ||
2002 | |||
2003 | local_irq_save(flags); | ||
2004 | |||
2005 | printk("clearing PMU state on CPU#%d\n", smp_processor_id()); | ||
2006 | |||
2007 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | ||
2008 | checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); | ||
2009 | checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); | ||
2010 | } | ||
2011 | for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { | ||
2012 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | ||
2013 | } | ||
2014 | if (ds) | ||
2015 | ds->bts_index = ds->bts_buffer_base; | ||
2016 | |||
2017 | local_irq_restore(flags); | ||
2018 | } | ||
2019 | |||
2020 | /* | ||
2021 | * This handler is triggered by the local APIC, so the APIC IRQ handling | ||
2022 | * rules apply: | ||
2023 | */ | ||
2024 | static int intel_pmu_handle_irq(struct pt_regs *regs) | ||
2025 | { | ||
2026 | struct perf_sample_data data; | ||
2027 | struct cpu_hw_events *cpuc; | ||
2028 | int bit, loops; | ||
2029 | u64 ack, status; | ||
2030 | |||
2031 | data.addr = 0; | ||
2032 | data.raw = NULL; | ||
2033 | |||
2034 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
2035 | |||
2036 | perf_disable(); | ||
2037 | intel_pmu_drain_bts_buffer(cpuc); | ||
2038 | status = intel_pmu_get_status(); | ||
2039 | if (!status) { | ||
2040 | perf_enable(); | ||
2041 | return 0; | ||
2042 | } | ||
2043 | |||
2044 | loops = 0; | ||
2045 | again: | ||
2046 | if (++loops > 100) { | ||
2047 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); | ||
2048 | perf_event_print_debug(); | ||
2049 | intel_pmu_reset(); | ||
2050 | perf_enable(); | ||
2051 | return 1; | ||
2052 | } | ||
2053 | |||
2054 | inc_irq_stat(apic_perf_irqs); | ||
2055 | ack = status; | ||
2056 | for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | ||
2057 | struct perf_event *event = cpuc->events[bit]; | ||
2058 | |||
2059 | clear_bit(bit, (unsigned long *) &status); | ||
2060 | if (!test_bit(bit, cpuc->active_mask)) | ||
2061 | continue; | ||
2062 | |||
2063 | if (!intel_pmu_save_and_restart(event)) | ||
2064 | continue; | ||
2065 | |||
2066 | data.period = event->hw.last_period; | ||
2067 | |||
2068 | if (perf_event_overflow(event, 1, &data, regs)) | ||
2069 | intel_pmu_disable_event(&event->hw, bit); | ||
2070 | } | ||
2071 | |||
2072 | intel_pmu_ack_status(ack); | ||
2073 | |||
2074 | /* | ||
2075 | * Repeat if there is more work to be done: | ||
2076 | */ | ||
2077 | status = intel_pmu_get_status(); | ||
2078 | if (status) | ||
2079 | goto again; | ||
2080 | |||
2081 | perf_enable(); | ||
2082 | |||
2083 | return 1; | ||
2084 | } | ||
2085 | |||
2086 | static int x86_pmu_handle_irq(struct pt_regs *regs) | 1085 | static int x86_pmu_handle_irq(struct pt_regs *regs) |
2087 | { | 1086 | { |
2088 | struct perf_sample_data data; | 1087 | struct perf_sample_data data; |
@@ -2092,8 +1091,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
2092 | int idx, handled = 0; | 1091 | int idx, handled = 0; |
2093 | u64 val; | 1092 | u64 val; |
2094 | 1093 | ||
2095 | data.addr = 0; | 1094 | perf_sample_data_init(&data, 0); |
2096 | data.raw = NULL; | ||
2097 | 1095 | ||
2098 | cpuc = &__get_cpu_var(cpu_hw_events); | 1096 | cpuc = &__get_cpu_var(cpu_hw_events); |
2099 | 1097 | ||
@@ -2104,7 +1102,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
2104 | event = cpuc->events[idx]; | 1102 | event = cpuc->events[idx]; |
2105 | hwc = &event->hw; | 1103 | hwc = &event->hw; |
2106 | 1104 | ||
2107 | val = x86_perf_event_update(event, hwc, idx); | 1105 | val = x86_perf_event_update(event); |
2108 | if (val & (1ULL << (x86_pmu.event_bits - 1))) | 1106 | if (val & (1ULL << (x86_pmu.event_bits - 1))) |
2109 | continue; | 1107 | continue; |
2110 | 1108 | ||
@@ -2114,11 +1112,11 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
2114 | handled = 1; | 1112 | handled = 1; |
2115 | data.period = event->hw.last_period; | 1113 | data.period = event->hw.last_period; |
2116 | 1114 | ||
2117 | if (!x86_perf_event_set_period(event, hwc, idx)) | 1115 | if (!x86_perf_event_set_period(event)) |
2118 | continue; | 1116 | continue; |
2119 | 1117 | ||
2120 | if (perf_event_overflow(event, 1, &data, regs)) | 1118 | if (perf_event_overflow(event, 1, &data, regs)) |
2121 | x86_pmu.disable(hwc, idx); | 1119 | x86_pmu_stop(event); |
2122 | } | 1120 | } |
2123 | 1121 | ||
2124 | if (handled) | 1122 | if (handled) |
@@ -2195,36 +1193,20 @@ perf_event_nmi_handler(struct notifier_block *self, | |||
2195 | return NOTIFY_STOP; | 1193 | return NOTIFY_STOP; |
2196 | } | 1194 | } |
2197 | 1195 | ||
2198 | static struct event_constraint unconstrained; | 1196 | static __read_mostly struct notifier_block perf_event_nmi_notifier = { |
2199 | 1197 | .notifier_call = perf_event_nmi_handler, | |
2200 | static struct event_constraint bts_constraint = | 1198 | .next = NULL, |
2201 | EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); | 1199 | .priority = 1 |
2202 | 1200 | }; | |
2203 | static struct event_constraint * | ||
2204 | intel_special_constraints(struct perf_event *event) | ||
2205 | { | ||
2206 | unsigned int hw_event; | ||
2207 | |||
2208 | hw_event = event->hw.config & INTEL_ARCH_EVENT_MASK; | ||
2209 | |||
2210 | if (unlikely((hw_event == | ||
2211 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
2212 | (event->hw.sample_period == 1))) { | ||
2213 | 1201 | ||
2214 | return &bts_constraint; | 1202 | static struct event_constraint unconstrained; |
2215 | } | 1203 | static struct event_constraint emptyconstraint; |
2216 | return NULL; | ||
2217 | } | ||
2218 | 1204 | ||
2219 | static struct event_constraint * | 1205 | static struct event_constraint * |
2220 | intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | 1206 | x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) |
2221 | { | 1207 | { |
2222 | struct event_constraint *c; | 1208 | struct event_constraint *c; |
2223 | 1209 | ||
2224 | c = intel_special_constraints(event); | ||
2225 | if (c) | ||
2226 | return c; | ||
2227 | |||
2228 | if (x86_pmu.event_constraints) { | 1210 | if (x86_pmu.event_constraints) { |
2229 | for_each_event_constraint(c, x86_pmu.event_constraints) { | 1211 | for_each_event_constraint(c, x86_pmu.event_constraints) { |
2230 | if ((event->hw.config & c->cmask) == c->code) | 1212 | if ((event->hw.config & c->cmask) == c->code) |
@@ -2235,19 +1217,13 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event | |||
2235 | return &unconstrained; | 1217 | return &unconstrained; |
2236 | } | 1218 | } |
2237 | 1219 | ||
2238 | static struct event_constraint * | ||
2239 | amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | ||
2240 | { | ||
2241 | return &unconstrained; | ||
2242 | } | ||
2243 | |||
2244 | static int x86_event_sched_in(struct perf_event *event, | 1220 | static int x86_event_sched_in(struct perf_event *event, |
2245 | struct perf_cpu_context *cpuctx, int cpu) | 1221 | struct perf_cpu_context *cpuctx) |
2246 | { | 1222 | { |
2247 | int ret = 0; | 1223 | int ret = 0; |
2248 | 1224 | ||
2249 | event->state = PERF_EVENT_STATE_ACTIVE; | 1225 | event->state = PERF_EVENT_STATE_ACTIVE; |
2250 | event->oncpu = cpu; | 1226 | event->oncpu = smp_processor_id(); |
2251 | event->tstamp_running += event->ctx->time - event->tstamp_stopped; | 1227 | event->tstamp_running += event->ctx->time - event->tstamp_stopped; |
2252 | 1228 | ||
2253 | if (!is_x86_event(event)) | 1229 | if (!is_x86_event(event)) |
@@ -2263,7 +1239,7 @@ static int x86_event_sched_in(struct perf_event *event, | |||
2263 | } | 1239 | } |
2264 | 1240 | ||
2265 | static void x86_event_sched_out(struct perf_event *event, | 1241 | static void x86_event_sched_out(struct perf_event *event, |
2266 | struct perf_cpu_context *cpuctx, int cpu) | 1242 | struct perf_cpu_context *cpuctx) |
2267 | { | 1243 | { |
2268 | event->state = PERF_EVENT_STATE_INACTIVE; | 1244 | event->state = PERF_EVENT_STATE_INACTIVE; |
2269 | event->oncpu = -1; | 1245 | event->oncpu = -1; |
@@ -2291,9 +1267,9 @@ static void x86_event_sched_out(struct perf_event *event, | |||
2291 | */ | 1267 | */ |
2292 | int hw_perf_group_sched_in(struct perf_event *leader, | 1268 | int hw_perf_group_sched_in(struct perf_event *leader, |
2293 | struct perf_cpu_context *cpuctx, | 1269 | struct perf_cpu_context *cpuctx, |
2294 | struct perf_event_context *ctx, int cpu) | 1270 | struct perf_event_context *ctx) |
2295 | { | 1271 | { |
2296 | struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); | 1272 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
2297 | struct perf_event *sub; | 1273 | struct perf_event *sub; |
2298 | int assign[X86_PMC_IDX_MAX]; | 1274 | int assign[X86_PMC_IDX_MAX]; |
2299 | int n0, n1, ret; | 1275 | int n0, n1, ret; |
@@ -2307,14 +1283,14 @@ int hw_perf_group_sched_in(struct perf_event *leader, | |||
2307 | if (ret) | 1283 | if (ret) |
2308 | return ret; | 1284 | return ret; |
2309 | 1285 | ||
2310 | ret = x86_event_sched_in(leader, cpuctx, cpu); | 1286 | ret = x86_event_sched_in(leader, cpuctx); |
2311 | if (ret) | 1287 | if (ret) |
2312 | return ret; | 1288 | return ret; |
2313 | 1289 | ||
2314 | n1 = 1; | 1290 | n1 = 1; |
2315 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { | 1291 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { |
2316 | if (sub->state > PERF_EVENT_STATE_OFF) { | 1292 | if (sub->state > PERF_EVENT_STATE_OFF) { |
2317 | ret = x86_event_sched_in(sub, cpuctx, cpu); | 1293 | ret = x86_event_sched_in(sub, cpuctx); |
2318 | if (ret) | 1294 | if (ret) |
2319 | goto undo; | 1295 | goto undo; |
2320 | ++n1; | 1296 | ++n1; |
@@ -2327,7 +1303,7 @@ int hw_perf_group_sched_in(struct perf_event *leader, | |||
2327 | memcpy(cpuc->assign, assign, n0*sizeof(int)); | 1303 | memcpy(cpuc->assign, assign, n0*sizeof(int)); |
2328 | 1304 | ||
2329 | cpuc->n_events = n0; | 1305 | cpuc->n_events = n0; |
2330 | cpuc->n_added = n1; | 1306 | cpuc->n_added += n1; |
2331 | ctx->nr_active += n1; | 1307 | ctx->nr_active += n1; |
2332 | 1308 | ||
2333 | /* | 1309 | /* |
@@ -2339,11 +1315,11 @@ int hw_perf_group_sched_in(struct perf_event *leader, | |||
2339 | */ | 1315 | */ |
2340 | return 1; | 1316 | return 1; |
2341 | undo: | 1317 | undo: |
2342 | x86_event_sched_out(leader, cpuctx, cpu); | 1318 | x86_event_sched_out(leader, cpuctx); |
2343 | n0 = 1; | 1319 | n0 = 1; |
2344 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { | 1320 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { |
2345 | if (sub->state == PERF_EVENT_STATE_ACTIVE) { | 1321 | if (sub->state == PERF_EVENT_STATE_ACTIVE) { |
2346 | x86_event_sched_out(sub, cpuctx, cpu); | 1322 | x86_event_sched_out(sub, cpuctx); |
2347 | if (++n0 == n1) | 1323 | if (++n0 == n1) |
2348 | break; | 1324 | break; |
2349 | } | 1325 | } |
@@ -2351,243 +1327,43 @@ undo: | |||
2351 | return ret; | 1327 | return ret; |
2352 | } | 1328 | } |
2353 | 1329 | ||
2354 | static __read_mostly struct notifier_block perf_event_nmi_notifier = { | 1330 | #include "perf_event_amd.c" |
2355 | .notifier_call = perf_event_nmi_handler, | 1331 | #include "perf_event_p6.c" |
2356 | .next = NULL, | 1332 | #include "perf_event_intel.c" |
2357 | .priority = 1 | ||
2358 | }; | ||
2359 | |||
2360 | static __initconst struct x86_pmu p6_pmu = { | ||
2361 | .name = "p6", | ||
2362 | .handle_irq = x86_pmu_handle_irq, | ||
2363 | .disable_all = p6_pmu_disable_all, | ||
2364 | .enable_all = p6_pmu_enable_all, | ||
2365 | .enable = p6_pmu_enable_event, | ||
2366 | .disable = p6_pmu_disable_event, | ||
2367 | .eventsel = MSR_P6_EVNTSEL0, | ||
2368 | .perfctr = MSR_P6_PERFCTR0, | ||
2369 | .event_map = p6_pmu_event_map, | ||
2370 | .raw_event = p6_pmu_raw_event, | ||
2371 | .max_events = ARRAY_SIZE(p6_perfmon_event_map), | ||
2372 | .apic = 1, | ||
2373 | .max_period = (1ULL << 31) - 1, | ||
2374 | .version = 0, | ||
2375 | .num_events = 2, | ||
2376 | /* | ||
2377 | * Events have 40 bits implemented. However they are designed such | ||
2378 | * that bits [32-39] are sign extensions of bit 31. As such the | ||
2379 | * effective width of a event for P6-like PMU is 32 bits only. | ||
2380 | * | ||
2381 | * See IA-32 Intel Architecture Software developer manual Vol 3B | ||
2382 | */ | ||
2383 | .event_bits = 32, | ||
2384 | .event_mask = (1ULL << 32) - 1, | ||
2385 | .get_event_constraints = intel_get_event_constraints, | ||
2386 | .event_constraints = intel_p6_event_constraints | ||
2387 | }; | ||
2388 | |||
2389 | static __initconst struct x86_pmu core_pmu = { | ||
2390 | .name = "core", | ||
2391 | .handle_irq = x86_pmu_handle_irq, | ||
2392 | .disable_all = x86_pmu_disable_all, | ||
2393 | .enable_all = x86_pmu_enable_all, | ||
2394 | .enable = x86_pmu_enable_event, | ||
2395 | .disable = x86_pmu_disable_event, | ||
2396 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
2397 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
2398 | .event_map = intel_pmu_event_map, | ||
2399 | .raw_event = intel_pmu_raw_event, | ||
2400 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
2401 | .apic = 1, | ||
2402 | /* | ||
2403 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
2404 | * so we install an artificial 1<<31 period regardless of | ||
2405 | * the generic event period: | ||
2406 | */ | ||
2407 | .max_period = (1ULL << 31) - 1, | ||
2408 | .get_event_constraints = intel_get_event_constraints, | ||
2409 | .event_constraints = intel_core_event_constraints, | ||
2410 | }; | ||
2411 | |||
2412 | static __initconst struct x86_pmu intel_pmu = { | ||
2413 | .name = "Intel", | ||
2414 | .handle_irq = intel_pmu_handle_irq, | ||
2415 | .disable_all = intel_pmu_disable_all, | ||
2416 | .enable_all = intel_pmu_enable_all, | ||
2417 | .enable = intel_pmu_enable_event, | ||
2418 | .disable = intel_pmu_disable_event, | ||
2419 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
2420 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
2421 | .event_map = intel_pmu_event_map, | ||
2422 | .raw_event = intel_pmu_raw_event, | ||
2423 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
2424 | .apic = 1, | ||
2425 | /* | ||
2426 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
2427 | * so we install an artificial 1<<31 period regardless of | ||
2428 | * the generic event period: | ||
2429 | */ | ||
2430 | .max_period = (1ULL << 31) - 1, | ||
2431 | .enable_bts = intel_pmu_enable_bts, | ||
2432 | .disable_bts = intel_pmu_disable_bts, | ||
2433 | .get_event_constraints = intel_get_event_constraints | ||
2434 | }; | ||
2435 | |||
2436 | static __initconst struct x86_pmu amd_pmu = { | ||
2437 | .name = "AMD", | ||
2438 | .handle_irq = x86_pmu_handle_irq, | ||
2439 | .disable_all = x86_pmu_disable_all, | ||
2440 | .enable_all = x86_pmu_enable_all, | ||
2441 | .enable = x86_pmu_enable_event, | ||
2442 | .disable = x86_pmu_disable_event, | ||
2443 | .eventsel = MSR_K7_EVNTSEL0, | ||
2444 | .perfctr = MSR_K7_PERFCTR0, | ||
2445 | .event_map = amd_pmu_event_map, | ||
2446 | .raw_event = amd_pmu_raw_event, | ||
2447 | .max_events = ARRAY_SIZE(amd_perfmon_event_map), | ||
2448 | .num_events = 4, | ||
2449 | .event_bits = 48, | ||
2450 | .event_mask = (1ULL << 48) - 1, | ||
2451 | .apic = 1, | ||
2452 | /* use highest bit to detect overflow */ | ||
2453 | .max_period = (1ULL << 47) - 1, | ||
2454 | .get_event_constraints = amd_get_event_constraints | ||
2455 | }; | ||
2456 | |||
2457 | static __init int p6_pmu_init(void) | ||
2458 | { | ||
2459 | switch (boot_cpu_data.x86_model) { | ||
2460 | case 1: | ||
2461 | case 3: /* Pentium Pro */ | ||
2462 | case 5: | ||
2463 | case 6: /* Pentium II */ | ||
2464 | case 7: | ||
2465 | case 8: | ||
2466 | case 11: /* Pentium III */ | ||
2467 | case 9: | ||
2468 | case 13: | ||
2469 | /* Pentium M */ | ||
2470 | break; | ||
2471 | default: | ||
2472 | pr_cont("unsupported p6 CPU model %d ", | ||
2473 | boot_cpu_data.x86_model); | ||
2474 | return -ENODEV; | ||
2475 | } | ||
2476 | |||
2477 | x86_pmu = p6_pmu; | ||
2478 | |||
2479 | return 0; | ||
2480 | } | ||
2481 | 1333 | ||
2482 | static __init int intel_pmu_init(void) | 1334 | static int __cpuinit |
1335 | x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | ||
2483 | { | 1336 | { |
2484 | union cpuid10_edx edx; | 1337 | unsigned int cpu = (long)hcpu; |
2485 | union cpuid10_eax eax; | 1338 | int ret = NOTIFY_OK; |
2486 | unsigned int unused; | ||
2487 | unsigned int ebx; | ||
2488 | int version; | ||
2489 | |||
2490 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | ||
2491 | /* check for P6 processor family */ | ||
2492 | if (boot_cpu_data.x86 == 6) { | ||
2493 | return p6_pmu_init(); | ||
2494 | } else { | ||
2495 | return -ENODEV; | ||
2496 | } | ||
2497 | } | ||
2498 | |||
2499 | /* | ||
2500 | * Check whether the Architectural PerfMon supports | ||
2501 | * Branch Misses Retired hw_event or not. | ||
2502 | */ | ||
2503 | cpuid(10, &eax.full, &ebx, &unused, &edx.full); | ||
2504 | if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED) | ||
2505 | return -ENODEV; | ||
2506 | |||
2507 | version = eax.split.version_id; | ||
2508 | if (version < 2) | ||
2509 | x86_pmu = core_pmu; | ||
2510 | else | ||
2511 | x86_pmu = intel_pmu; | ||
2512 | |||
2513 | x86_pmu.version = version; | ||
2514 | x86_pmu.num_events = eax.split.num_events; | ||
2515 | x86_pmu.event_bits = eax.split.bit_width; | ||
2516 | x86_pmu.event_mask = (1ULL << eax.split.bit_width) - 1; | ||
2517 | 1339 | ||
2518 | /* | 1340 | switch (action & ~CPU_TASKS_FROZEN) { |
2519 | * Quirk: v2 perfmon does not report fixed-purpose events, so | 1341 | case CPU_UP_PREPARE: |
2520 | * assume at least 3 events: | 1342 | if (x86_pmu.cpu_prepare) |
2521 | */ | 1343 | ret = x86_pmu.cpu_prepare(cpu); |
2522 | if (version > 1) | ||
2523 | x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); | ||
2524 | |||
2525 | /* | ||
2526 | * Install the hw-cache-events table: | ||
2527 | */ | ||
2528 | switch (boot_cpu_data.x86_model) { | ||
2529 | case 14: /* 65 nm core solo/duo, "Yonah" */ | ||
2530 | pr_cont("Core events, "); | ||
2531 | break; | 1344 | break; |
2532 | 1345 | ||
2533 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ | 1346 | case CPU_STARTING: |
2534 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ | 1347 | if (x86_pmu.cpu_starting) |
2535 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ | 1348 | x86_pmu.cpu_starting(cpu); |
2536 | case 29: /* six-core 45 nm xeon "Dunnington" */ | ||
2537 | memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, | ||
2538 | sizeof(hw_cache_event_ids)); | ||
2539 | |||
2540 | x86_pmu.event_constraints = intel_core2_event_constraints; | ||
2541 | pr_cont("Core2 events, "); | ||
2542 | break; | 1349 | break; |
2543 | 1350 | ||
2544 | case 26: /* 45 nm nehalem, "Bloomfield" */ | 1351 | case CPU_DYING: |
2545 | case 30: /* 45 nm nehalem, "Lynnfield" */ | 1352 | if (x86_pmu.cpu_dying) |
2546 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, | 1353 | x86_pmu.cpu_dying(cpu); |
2547 | sizeof(hw_cache_event_ids)); | ||
2548 | |||
2549 | x86_pmu.event_constraints = intel_nehalem_event_constraints; | ||
2550 | pr_cont("Nehalem/Corei7 events, "); | ||
2551 | break; | 1354 | break; |
2552 | case 28: | ||
2553 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | ||
2554 | sizeof(hw_cache_event_ids)); | ||
2555 | 1355 | ||
2556 | x86_pmu.event_constraints = intel_gen_event_constraints; | 1356 | case CPU_UP_CANCELED: |
2557 | pr_cont("Atom events, "); | 1357 | case CPU_DEAD: |
1358 | if (x86_pmu.cpu_dead) | ||
1359 | x86_pmu.cpu_dead(cpu); | ||
2558 | break; | 1360 | break; |
2559 | 1361 | ||
2560 | case 37: /* 32 nm nehalem, "Clarkdale" */ | ||
2561 | case 44: /* 32 nm nehalem, "Gulftown" */ | ||
2562 | memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, | ||
2563 | sizeof(hw_cache_event_ids)); | ||
2564 | |||
2565 | x86_pmu.event_constraints = intel_westmere_event_constraints; | ||
2566 | pr_cont("Westmere events, "); | ||
2567 | break; | ||
2568 | default: | 1362 | default: |
2569 | /* | 1363 | break; |
2570 | * default constraints for v2 and up | ||
2571 | */ | ||
2572 | x86_pmu.event_constraints = intel_gen_event_constraints; | ||
2573 | pr_cont("generic architected perfmon, "); | ||
2574 | } | 1364 | } |
2575 | return 0; | ||
2576 | } | ||
2577 | |||
2578 | static __init int amd_pmu_init(void) | ||
2579 | { | ||
2580 | /* Performance-monitoring supported from K7 and later: */ | ||
2581 | if (boot_cpu_data.x86 < 6) | ||
2582 | return -ENODEV; | ||
2583 | 1365 | ||
2584 | x86_pmu = amd_pmu; | 1366 | return ret; |
2585 | |||
2586 | /* Events are common for all AMDs */ | ||
2587 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, | ||
2588 | sizeof(hw_cache_event_ids)); | ||
2589 | |||
2590 | return 0; | ||
2591 | } | 1367 | } |
2592 | 1368 | ||
2593 | static void __init pmu_check_apic(void) | 1369 | static void __init pmu_check_apic(void) |
@@ -2602,6 +1378,7 @@ static void __init pmu_check_apic(void) | |||
2602 | 1378 | ||
2603 | void __init init_hw_perf_events(void) | 1379 | void __init init_hw_perf_events(void) |
2604 | { | 1380 | { |
1381 | struct event_constraint *c; | ||
2605 | int err; | 1382 | int err; |
2606 | 1383 | ||
2607 | pr_info("Performance Events: "); | 1384 | pr_info("Performance Events: "); |
@@ -2650,6 +1427,16 @@ void __init init_hw_perf_events(void) | |||
2650 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, | 1427 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, |
2651 | 0, x86_pmu.num_events); | 1428 | 0, x86_pmu.num_events); |
2652 | 1429 | ||
1430 | if (x86_pmu.event_constraints) { | ||
1431 | for_each_event_constraint(c, x86_pmu.event_constraints) { | ||
1432 | if (c->cmask != INTEL_ARCH_FIXED_MASK) | ||
1433 | continue; | ||
1434 | |||
1435 | c->idxmsk64 |= (1ULL << x86_pmu.num_events) - 1; | ||
1436 | c->weight += x86_pmu.num_events; | ||
1437 | } | ||
1438 | } | ||
1439 | |||
2653 | pr_info("... version: %d\n", x86_pmu.version); | 1440 | pr_info("... version: %d\n", x86_pmu.version); |
2654 | pr_info("... bit width: %d\n", x86_pmu.event_bits); | 1441 | pr_info("... bit width: %d\n", x86_pmu.event_bits); |
2655 | pr_info("... generic registers: %d\n", x86_pmu.num_events); | 1442 | pr_info("... generic registers: %d\n", x86_pmu.num_events); |
@@ -2657,16 +1444,20 @@ void __init init_hw_perf_events(void) | |||
2657 | pr_info("... max period: %016Lx\n", x86_pmu.max_period); | 1444 | pr_info("... max period: %016Lx\n", x86_pmu.max_period); |
2658 | pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); | 1445 | pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); |
2659 | pr_info("... event mask: %016Lx\n", perf_event_mask); | 1446 | pr_info("... event mask: %016Lx\n", perf_event_mask); |
1447 | |||
1448 | perf_cpu_notifier(x86_pmu_notifier); | ||
2660 | } | 1449 | } |
2661 | 1450 | ||
2662 | static inline void x86_pmu_read(struct perf_event *event) | 1451 | static inline void x86_pmu_read(struct perf_event *event) |
2663 | { | 1452 | { |
2664 | x86_perf_event_update(event, &event->hw, event->hw.idx); | 1453 | x86_perf_event_update(event); |
2665 | } | 1454 | } |
2666 | 1455 | ||
2667 | static const struct pmu pmu = { | 1456 | static const struct pmu pmu = { |
2668 | .enable = x86_pmu_enable, | 1457 | .enable = x86_pmu_enable, |
2669 | .disable = x86_pmu_disable, | 1458 | .disable = x86_pmu_disable, |
1459 | .start = x86_pmu_start, | ||
1460 | .stop = x86_pmu_stop, | ||
2670 | .read = x86_pmu_read, | 1461 | .read = x86_pmu_read, |
2671 | .unthrottle = x86_pmu_unthrottle, | 1462 | .unthrottle = x86_pmu_unthrottle, |
2672 | }; | 1463 | }; |
@@ -2841,14 +1632,42 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | |||
2841 | return len; | 1632 | return len; |
2842 | } | 1633 | } |
2843 | 1634 | ||
2844 | static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) | 1635 | #ifdef CONFIG_COMPAT |
1636 | static inline int | ||
1637 | perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | ||
2845 | { | 1638 | { |
2846 | unsigned long bytes; | 1639 | /* 32-bit process in 64-bit kernel. */ |
1640 | struct stack_frame_ia32 frame; | ||
1641 | const void __user *fp; | ||
2847 | 1642 | ||
2848 | bytes = copy_from_user_nmi(frame, fp, sizeof(*frame)); | 1643 | if (!test_thread_flag(TIF_IA32)) |
1644 | return 0; | ||
2849 | 1645 | ||
2850 | return bytes == sizeof(*frame); | 1646 | fp = compat_ptr(regs->bp); |
1647 | while (entry->nr < PERF_MAX_STACK_DEPTH) { | ||
1648 | unsigned long bytes; | ||
1649 | frame.next_frame = 0; | ||
1650 | frame.return_address = 0; | ||
1651 | |||
1652 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); | ||
1653 | if (bytes != sizeof(frame)) | ||
1654 | break; | ||
1655 | |||
1656 | if (fp < compat_ptr(regs->sp)) | ||
1657 | break; | ||
1658 | |||
1659 | callchain_store(entry, frame.return_address); | ||
1660 | fp = compat_ptr(frame.next_frame); | ||
1661 | } | ||
1662 | return 1; | ||
1663 | } | ||
1664 | #else | ||
1665 | static inline int | ||
1666 | perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | ||
1667 | { | ||
1668 | return 0; | ||
2851 | } | 1669 | } |
1670 | #endif | ||
2852 | 1671 | ||
2853 | static void | 1672 | static void |
2854 | perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry) | 1673 | perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry) |
@@ -2864,11 +1683,16 @@ perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
2864 | callchain_store(entry, PERF_CONTEXT_USER); | 1683 | callchain_store(entry, PERF_CONTEXT_USER); |
2865 | callchain_store(entry, regs->ip); | 1684 | callchain_store(entry, regs->ip); |
2866 | 1685 | ||
1686 | if (perf_callchain_user32(regs, entry)) | ||
1687 | return; | ||
1688 | |||
2867 | while (entry->nr < PERF_MAX_STACK_DEPTH) { | 1689 | while (entry->nr < PERF_MAX_STACK_DEPTH) { |
1690 | unsigned long bytes; | ||
2868 | frame.next_frame = NULL; | 1691 | frame.next_frame = NULL; |
2869 | frame.return_address = 0; | 1692 | frame.return_address = 0; |
2870 | 1693 | ||
2871 | if (!copy_stack_frame(fp, &frame)) | 1694 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); |
1695 | if (bytes != sizeof(frame)) | ||
2872 | break; | 1696 | break; |
2873 | 1697 | ||
2874 | if ((unsigned long)fp < regs->sp) | 1698 | if ((unsigned long)fp < regs->sp) |
@@ -2915,7 +1739,14 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
2915 | return entry; | 1739 | return entry; |
2916 | } | 1740 | } |
2917 | 1741 | ||
2918 | void hw_perf_event_setup_online(int cpu) | 1742 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) |
2919 | { | 1743 | { |
2920 | init_debug_store_on_cpu(cpu); | 1744 | regs->ip = ip; |
1745 | /* | ||
1746 | * perf_arch_fetch_caller_regs adds another call, we need to increment | ||
1747 | * the skip level | ||
1748 | */ | ||
1749 | regs->bp = rewind_frame_pointer(skip + 1); | ||
1750 | regs->cs = __KERNEL_CS; | ||
1751 | local_save_flags(regs->flags); | ||
2921 | } | 1752 | } |
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c new file mode 100644 index 000000000000..db6f7d4056e1 --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_amd.c | |||
@@ -0,0 +1,422 @@ | |||
1 | #ifdef CONFIG_CPU_SUP_AMD | ||
2 | |||
3 | static DEFINE_RAW_SPINLOCK(amd_nb_lock); | ||
4 | |||
5 | static __initconst u64 amd_hw_cache_event_ids | ||
6 | [PERF_COUNT_HW_CACHE_MAX] | ||
7 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
8 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
9 | { | ||
10 | [ C(L1D) ] = { | ||
11 | [ C(OP_READ) ] = { | ||
12 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
13 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ | ||
14 | }, | ||
15 | [ C(OP_WRITE) ] = { | ||
16 | [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ | ||
17 | [ C(RESULT_MISS) ] = 0, | ||
18 | }, | ||
19 | [ C(OP_PREFETCH) ] = { | ||
20 | [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts */ | ||
21 | [ C(RESULT_MISS) ] = 0x0167, /* Data Prefetcher :cancelled */ | ||
22 | }, | ||
23 | }, | ||
24 | [ C(L1I ) ] = { | ||
25 | [ C(OP_READ) ] = { | ||
26 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches */ | ||
27 | [ C(RESULT_MISS) ] = 0x0081, /* Instruction cache misses */ | ||
28 | }, | ||
29 | [ C(OP_WRITE) ] = { | ||
30 | [ C(RESULT_ACCESS) ] = -1, | ||
31 | [ C(RESULT_MISS) ] = -1, | ||
32 | }, | ||
33 | [ C(OP_PREFETCH) ] = { | ||
34 | [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */ | ||
35 | [ C(RESULT_MISS) ] = 0, | ||
36 | }, | ||
37 | }, | ||
38 | [ C(LL ) ] = { | ||
39 | [ C(OP_READ) ] = { | ||
40 | [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */ | ||
41 | [ C(RESULT_MISS) ] = 0x037E, /* L2 Cache Misses : IC+DC */ | ||
42 | }, | ||
43 | [ C(OP_WRITE) ] = { | ||
44 | [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback */ | ||
45 | [ C(RESULT_MISS) ] = 0, | ||
46 | }, | ||
47 | [ C(OP_PREFETCH) ] = { | ||
48 | [ C(RESULT_ACCESS) ] = 0, | ||
49 | [ C(RESULT_MISS) ] = 0, | ||
50 | }, | ||
51 | }, | ||
52 | [ C(DTLB) ] = { | ||
53 | [ C(OP_READ) ] = { | ||
54 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
55 | [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ | ||
56 | }, | ||
57 | [ C(OP_WRITE) ] = { | ||
58 | [ C(RESULT_ACCESS) ] = 0, | ||
59 | [ C(RESULT_MISS) ] = 0, | ||
60 | }, | ||
61 | [ C(OP_PREFETCH) ] = { | ||
62 | [ C(RESULT_ACCESS) ] = 0, | ||
63 | [ C(RESULT_MISS) ] = 0, | ||
64 | }, | ||
65 | }, | ||
66 | [ C(ITLB) ] = { | ||
67 | [ C(OP_READ) ] = { | ||
68 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */ | ||
69 | [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */ | ||
70 | }, | ||
71 | [ C(OP_WRITE) ] = { | ||
72 | [ C(RESULT_ACCESS) ] = -1, | ||
73 | [ C(RESULT_MISS) ] = -1, | ||
74 | }, | ||
75 | [ C(OP_PREFETCH) ] = { | ||
76 | [ C(RESULT_ACCESS) ] = -1, | ||
77 | [ C(RESULT_MISS) ] = -1, | ||
78 | }, | ||
79 | }, | ||
80 | [ C(BPU ) ] = { | ||
81 | [ C(OP_READ) ] = { | ||
82 | [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr. */ | ||
83 | [ C(RESULT_MISS) ] = 0x00c3, /* Retired Mispredicted BI */ | ||
84 | }, | ||
85 | [ C(OP_WRITE) ] = { | ||
86 | [ C(RESULT_ACCESS) ] = -1, | ||
87 | [ C(RESULT_MISS) ] = -1, | ||
88 | }, | ||
89 | [ C(OP_PREFETCH) ] = { | ||
90 | [ C(RESULT_ACCESS) ] = -1, | ||
91 | [ C(RESULT_MISS) ] = -1, | ||
92 | }, | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | /* | ||
97 | * AMD Performance Monitor K7 and later. | ||
98 | */ | ||
99 | static const u64 amd_perfmon_event_map[] = | ||
100 | { | ||
101 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | ||
102 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
103 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, | ||
104 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, | ||
105 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
106 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
107 | }; | ||
108 | |||
109 | static u64 amd_pmu_event_map(int hw_event) | ||
110 | { | ||
111 | return amd_perfmon_event_map[hw_event]; | ||
112 | } | ||
113 | |||
114 | static u64 amd_pmu_raw_event(u64 hw_event) | ||
115 | { | ||
116 | #define K7_EVNTSEL_EVENT_MASK 0xF000000FFULL | ||
117 | #define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL | ||
118 | #define K7_EVNTSEL_EDGE_MASK 0x000040000ULL | ||
119 | #define K7_EVNTSEL_INV_MASK 0x000800000ULL | ||
120 | #define K7_EVNTSEL_REG_MASK 0x0FF000000ULL | ||
121 | |||
122 | #define K7_EVNTSEL_MASK \ | ||
123 | (K7_EVNTSEL_EVENT_MASK | \ | ||
124 | K7_EVNTSEL_UNIT_MASK | \ | ||
125 | K7_EVNTSEL_EDGE_MASK | \ | ||
126 | K7_EVNTSEL_INV_MASK | \ | ||
127 | K7_EVNTSEL_REG_MASK) | ||
128 | |||
129 | return hw_event & K7_EVNTSEL_MASK; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * AMD64 events are detected based on their event codes. | ||
134 | */ | ||
135 | static inline int amd_is_nb_event(struct hw_perf_event *hwc) | ||
136 | { | ||
137 | return (hwc->config & 0xe0) == 0xe0; | ||
138 | } | ||
139 | |||
140 | static inline int amd_has_nb(struct cpu_hw_events *cpuc) | ||
141 | { | ||
142 | struct amd_nb *nb = cpuc->amd_nb; | ||
143 | |||
144 | return nb && nb->nb_id != -1; | ||
145 | } | ||
146 | |||
147 | static void amd_put_event_constraints(struct cpu_hw_events *cpuc, | ||
148 | struct perf_event *event) | ||
149 | { | ||
150 | struct hw_perf_event *hwc = &event->hw; | ||
151 | struct amd_nb *nb = cpuc->amd_nb; | ||
152 | int i; | ||
153 | |||
154 | /* | ||
155 | * only care about NB events | ||
156 | */ | ||
157 | if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc))) | ||
158 | return; | ||
159 | |||
160 | /* | ||
161 | * need to scan whole list because event may not have | ||
162 | * been assigned during scheduling | ||
163 | * | ||
164 | * no race condition possible because event can only | ||
165 | * be removed on one CPU at a time AND PMU is disabled | ||
166 | * when we come here | ||
167 | */ | ||
168 | for (i = 0; i < x86_pmu.num_events; i++) { | ||
169 | if (nb->owners[i] == event) { | ||
170 | cmpxchg(nb->owners+i, event, NULL); | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * AMD64 NorthBridge events need special treatment because | ||
178 | * counter access needs to be synchronized across all cores | ||
179 | * of a package. Refer to BKDG section 3.12 | ||
180 | * | ||
181 | * NB events are events measuring L3 cache, Hypertransport | ||
182 | * traffic. They are identified by an event code >= 0xe00. | ||
183 | * They measure events on the NorthBride which is shared | ||
184 | * by all cores on a package. NB events are counted on a | ||
185 | * shared set of counters. When a NB event is programmed | ||
186 | * in a counter, the data actually comes from a shared | ||
187 | * counter. Thus, access to those counters needs to be | ||
188 | * synchronized. | ||
189 | * | ||
190 | * We implement the synchronization such that no two cores | ||
191 | * can be measuring NB events using the same counters. Thus, | ||
192 | * we maintain a per-NB allocation table. The available slot | ||
193 | * is propagated using the event_constraint structure. | ||
194 | * | ||
195 | * We provide only one choice for each NB event based on | ||
196 | * the fact that only NB events have restrictions. Consequently, | ||
197 | * if a counter is available, there is a guarantee the NB event | ||
198 | * will be assigned to it. If no slot is available, an empty | ||
199 | * constraint is returned and scheduling will eventually fail | ||
200 | * for this event. | ||
201 | * | ||
202 | * Note that all cores attached the same NB compete for the same | ||
203 | * counters to host NB events, this is why we use atomic ops. Some | ||
204 | * multi-chip CPUs may have more than one NB. | ||
205 | * | ||
206 | * Given that resources are allocated (cmpxchg), they must be | ||
207 | * eventually freed for others to use. This is accomplished by | ||
208 | * calling amd_put_event_constraints(). | ||
209 | * | ||
210 | * Non NB events are not impacted by this restriction. | ||
211 | */ | ||
212 | static struct event_constraint * | ||
213 | amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | ||
214 | { | ||
215 | struct hw_perf_event *hwc = &event->hw; | ||
216 | struct amd_nb *nb = cpuc->amd_nb; | ||
217 | struct perf_event *old = NULL; | ||
218 | int max = x86_pmu.num_events; | ||
219 | int i, j, k = -1; | ||
220 | |||
221 | /* | ||
222 | * if not NB event or no NB, then no constraints | ||
223 | */ | ||
224 | if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc))) | ||
225 | return &unconstrained; | ||
226 | |||
227 | /* | ||
228 | * detect if already present, if so reuse | ||
229 | * | ||
230 | * cannot merge with actual allocation | ||
231 | * because of possible holes | ||
232 | * | ||
233 | * event can already be present yet not assigned (in hwc->idx) | ||
234 | * because of successive calls to x86_schedule_events() from | ||
235 | * hw_perf_group_sched_in() without hw_perf_enable() | ||
236 | */ | ||
237 | for (i = 0; i < max; i++) { | ||
238 | /* | ||
239 | * keep track of first free slot | ||
240 | */ | ||
241 | if (k == -1 && !nb->owners[i]) | ||
242 | k = i; | ||
243 | |||
244 | /* already present, reuse */ | ||
245 | if (nb->owners[i] == event) | ||
246 | goto done; | ||
247 | } | ||
248 | /* | ||
249 | * not present, so grab a new slot | ||
250 | * starting either at: | ||
251 | */ | ||
252 | if (hwc->idx != -1) { | ||
253 | /* previous assignment */ | ||
254 | i = hwc->idx; | ||
255 | } else if (k != -1) { | ||
256 | /* start from free slot found */ | ||
257 | i = k; | ||
258 | } else { | ||
259 | /* | ||
260 | * event not found, no slot found in | ||
261 | * first pass, try again from the | ||
262 | * beginning | ||
263 | */ | ||
264 | i = 0; | ||
265 | } | ||
266 | j = i; | ||
267 | do { | ||
268 | old = cmpxchg(nb->owners+i, NULL, event); | ||
269 | if (!old) | ||
270 | break; | ||
271 | if (++i == max) | ||
272 | i = 0; | ||
273 | } while (i != j); | ||
274 | done: | ||
275 | if (!old) | ||
276 | return &nb->event_constraints[i]; | ||
277 | |||
278 | return &emptyconstraint; | ||
279 | } | ||
280 | |||
281 | static struct amd_nb *amd_alloc_nb(int cpu, int nb_id) | ||
282 | { | ||
283 | struct amd_nb *nb; | ||
284 | int i; | ||
285 | |||
286 | nb = kmalloc(sizeof(struct amd_nb), GFP_KERNEL); | ||
287 | if (!nb) | ||
288 | return NULL; | ||
289 | |||
290 | memset(nb, 0, sizeof(*nb)); | ||
291 | nb->nb_id = nb_id; | ||
292 | |||
293 | /* | ||
294 | * initialize all possible NB constraints | ||
295 | */ | ||
296 | for (i = 0; i < x86_pmu.num_events; i++) { | ||
297 | __set_bit(i, nb->event_constraints[i].idxmsk); | ||
298 | nb->event_constraints[i].weight = 1; | ||
299 | } | ||
300 | return nb; | ||
301 | } | ||
302 | |||
303 | static int amd_pmu_cpu_prepare(int cpu) | ||
304 | { | ||
305 | struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); | ||
306 | |||
307 | WARN_ON_ONCE(cpuc->amd_nb); | ||
308 | |||
309 | if (boot_cpu_data.x86_max_cores < 2) | ||
310 | return NOTIFY_OK; | ||
311 | |||
312 | cpuc->amd_nb = amd_alloc_nb(cpu, -1); | ||
313 | if (!cpuc->amd_nb) | ||
314 | return NOTIFY_BAD; | ||
315 | |||
316 | return NOTIFY_OK; | ||
317 | } | ||
318 | |||
319 | static void amd_pmu_cpu_starting(int cpu) | ||
320 | { | ||
321 | struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); | ||
322 | struct amd_nb *nb; | ||
323 | int i, nb_id; | ||
324 | |||
325 | if (boot_cpu_data.x86_max_cores < 2) | ||
326 | return; | ||
327 | |||
328 | nb_id = amd_get_nb_id(cpu); | ||
329 | WARN_ON_ONCE(nb_id == BAD_APICID); | ||
330 | |||
331 | raw_spin_lock(&amd_nb_lock); | ||
332 | |||
333 | for_each_online_cpu(i) { | ||
334 | nb = per_cpu(cpu_hw_events, i).amd_nb; | ||
335 | if (WARN_ON_ONCE(!nb)) | ||
336 | continue; | ||
337 | |||
338 | if (nb->nb_id == nb_id) { | ||
339 | kfree(cpuc->amd_nb); | ||
340 | cpuc->amd_nb = nb; | ||
341 | break; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | cpuc->amd_nb->nb_id = nb_id; | ||
346 | cpuc->amd_nb->refcnt++; | ||
347 | |||
348 | raw_spin_unlock(&amd_nb_lock); | ||
349 | } | ||
350 | |||
351 | static void amd_pmu_cpu_dead(int cpu) | ||
352 | { | ||
353 | struct cpu_hw_events *cpuhw; | ||
354 | |||
355 | if (boot_cpu_data.x86_max_cores < 2) | ||
356 | return; | ||
357 | |||
358 | cpuhw = &per_cpu(cpu_hw_events, cpu); | ||
359 | |||
360 | raw_spin_lock(&amd_nb_lock); | ||
361 | |||
362 | if (cpuhw->amd_nb) { | ||
363 | struct amd_nb *nb = cpuhw->amd_nb; | ||
364 | |||
365 | if (nb->nb_id == -1 || --nb->refcnt == 0) | ||
366 | kfree(nb); | ||
367 | |||
368 | cpuhw->amd_nb = NULL; | ||
369 | } | ||
370 | |||
371 | raw_spin_unlock(&amd_nb_lock); | ||
372 | } | ||
373 | |||
374 | static __initconst struct x86_pmu amd_pmu = { | ||
375 | .name = "AMD", | ||
376 | .handle_irq = x86_pmu_handle_irq, | ||
377 | .disable_all = x86_pmu_disable_all, | ||
378 | .enable_all = x86_pmu_enable_all, | ||
379 | .enable = x86_pmu_enable_event, | ||
380 | .disable = x86_pmu_disable_event, | ||
381 | .eventsel = MSR_K7_EVNTSEL0, | ||
382 | .perfctr = MSR_K7_PERFCTR0, | ||
383 | .event_map = amd_pmu_event_map, | ||
384 | .raw_event = amd_pmu_raw_event, | ||
385 | .max_events = ARRAY_SIZE(amd_perfmon_event_map), | ||
386 | .num_events = 4, | ||
387 | .event_bits = 48, | ||
388 | .event_mask = (1ULL << 48) - 1, | ||
389 | .apic = 1, | ||
390 | /* use highest bit to detect overflow */ | ||
391 | .max_period = (1ULL << 47) - 1, | ||
392 | .get_event_constraints = amd_get_event_constraints, | ||
393 | .put_event_constraints = amd_put_event_constraints, | ||
394 | |||
395 | .cpu_prepare = amd_pmu_cpu_prepare, | ||
396 | .cpu_starting = amd_pmu_cpu_starting, | ||
397 | .cpu_dead = amd_pmu_cpu_dead, | ||
398 | }; | ||
399 | |||
400 | static __init int amd_pmu_init(void) | ||
401 | { | ||
402 | /* Performance-monitoring supported from K7 and later: */ | ||
403 | if (boot_cpu_data.x86 < 6) | ||
404 | return -ENODEV; | ||
405 | |||
406 | x86_pmu = amd_pmu; | ||
407 | |||
408 | /* Events are common for all AMDs */ | ||
409 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, | ||
410 | sizeof(hw_cache_event_ids)); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | #else /* CONFIG_CPU_SUP_AMD */ | ||
416 | |||
417 | static int amd_pmu_init(void) | ||
418 | { | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | #endif | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c new file mode 100644 index 000000000000..9c794ac87837 --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -0,0 +1,980 @@ | |||
1 | #ifdef CONFIG_CPU_SUP_INTEL | ||
2 | |||
3 | /* | ||
4 | * Intel PerfMon, used on Core and later. | ||
5 | */ | ||
6 | static const u64 intel_perfmon_event_map[] = | ||
7 | { | ||
8 | [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, | ||
9 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
10 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e, | ||
11 | [PERF_COUNT_HW_CACHE_MISSES] = 0x412e, | ||
12 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
13 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
14 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, | ||
15 | }; | ||
16 | |||
17 | static struct event_constraint intel_core_event_constraints[] = | ||
18 | { | ||
19 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
20 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
21 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
22 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
23 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
24 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */ | ||
25 | EVENT_CONSTRAINT_END | ||
26 | }; | ||
27 | |||
28 | static struct event_constraint intel_core2_event_constraints[] = | ||
29 | { | ||
30 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | ||
31 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | ||
32 | /* | ||
33 | * Core2 has Fixed Counter 2 listed as CPU_CLK_UNHALTED.REF and event | ||
34 | * 0x013c as CPU_CLK_UNHALTED.BUS and specifies there is a fixed | ||
35 | * ratio between these counters. | ||
36 | */ | ||
37 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
38 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
39 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
40 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
41 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
42 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
43 | INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ | ||
44 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
45 | INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ | ||
46 | INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */ | ||
47 | INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ | ||
48 | EVENT_CONSTRAINT_END | ||
49 | }; | ||
50 | |||
51 | static struct event_constraint intel_nehalem_event_constraints[] = | ||
52 | { | ||
53 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | ||
54 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | ||
55 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
56 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | ||
57 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | ||
58 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | ||
59 | INTEL_EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */ | ||
60 | INTEL_EVENT_CONSTRAINT(0x48, 0x3), /* L1D_PEND_MISS */ | ||
61 | INTEL_EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */ | ||
62 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
63 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
64 | EVENT_CONSTRAINT_END | ||
65 | }; | ||
66 | |||
67 | static struct event_constraint intel_westmere_event_constraints[] = | ||
68 | { | ||
69 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | ||
70 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | ||
71 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
72 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
73 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ | ||
74 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
75 | EVENT_CONSTRAINT_END | ||
76 | }; | ||
77 | |||
78 | static struct event_constraint intel_gen_event_constraints[] = | ||
79 | { | ||
80 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | ||
81 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | ||
82 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
83 | EVENT_CONSTRAINT_END | ||
84 | }; | ||
85 | |||
86 | static u64 intel_pmu_event_map(int hw_event) | ||
87 | { | ||
88 | return intel_perfmon_event_map[hw_event]; | ||
89 | } | ||
90 | |||
91 | static __initconst u64 westmere_hw_cache_event_ids | ||
92 | [PERF_COUNT_HW_CACHE_MAX] | ||
93 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
94 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
95 | { | ||
96 | [ C(L1D) ] = { | ||
97 | [ C(OP_READ) ] = { | ||
98 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
99 | [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */ | ||
100 | }, | ||
101 | [ C(OP_WRITE) ] = { | ||
102 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
103 | [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */ | ||
104 | }, | ||
105 | [ C(OP_PREFETCH) ] = { | ||
106 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
107 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
108 | }, | ||
109 | }, | ||
110 | [ C(L1I ) ] = { | ||
111 | [ C(OP_READ) ] = { | ||
112 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
113 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
114 | }, | ||
115 | [ C(OP_WRITE) ] = { | ||
116 | [ C(RESULT_ACCESS) ] = -1, | ||
117 | [ C(RESULT_MISS) ] = -1, | ||
118 | }, | ||
119 | [ C(OP_PREFETCH) ] = { | ||
120 | [ C(RESULT_ACCESS) ] = 0x0, | ||
121 | [ C(RESULT_MISS) ] = 0x0, | ||
122 | }, | ||
123 | }, | ||
124 | [ C(LL ) ] = { | ||
125 | [ C(OP_READ) ] = { | ||
126 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
127 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
128 | }, | ||
129 | [ C(OP_WRITE) ] = { | ||
130 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
131 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
132 | }, | ||
133 | [ C(OP_PREFETCH) ] = { | ||
134 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
135 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
136 | }, | ||
137 | }, | ||
138 | [ C(DTLB) ] = { | ||
139 | [ C(OP_READ) ] = { | ||
140 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
141 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
142 | }, | ||
143 | [ C(OP_WRITE) ] = { | ||
144 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
145 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
146 | }, | ||
147 | [ C(OP_PREFETCH) ] = { | ||
148 | [ C(RESULT_ACCESS) ] = 0x0, | ||
149 | [ C(RESULT_MISS) ] = 0x0, | ||
150 | }, | ||
151 | }, | ||
152 | [ C(ITLB) ] = { | ||
153 | [ C(OP_READ) ] = { | ||
154 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
155 | [ C(RESULT_MISS) ] = 0x0185, /* ITLB_MISSES.ANY */ | ||
156 | }, | ||
157 | [ C(OP_WRITE) ] = { | ||
158 | [ C(RESULT_ACCESS) ] = -1, | ||
159 | [ C(RESULT_MISS) ] = -1, | ||
160 | }, | ||
161 | [ C(OP_PREFETCH) ] = { | ||
162 | [ C(RESULT_ACCESS) ] = -1, | ||
163 | [ C(RESULT_MISS) ] = -1, | ||
164 | }, | ||
165 | }, | ||
166 | [ C(BPU ) ] = { | ||
167 | [ C(OP_READ) ] = { | ||
168 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
169 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
170 | }, | ||
171 | [ C(OP_WRITE) ] = { | ||
172 | [ C(RESULT_ACCESS) ] = -1, | ||
173 | [ C(RESULT_MISS) ] = -1, | ||
174 | }, | ||
175 | [ C(OP_PREFETCH) ] = { | ||
176 | [ C(RESULT_ACCESS) ] = -1, | ||
177 | [ C(RESULT_MISS) ] = -1, | ||
178 | }, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static __initconst u64 nehalem_hw_cache_event_ids | ||
183 | [PERF_COUNT_HW_CACHE_MAX] | ||
184 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
185 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
186 | { | ||
187 | [ C(L1D) ] = { | ||
188 | [ C(OP_READ) ] = { | ||
189 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
190 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
191 | }, | ||
192 | [ C(OP_WRITE) ] = { | ||
193 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
194 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
195 | }, | ||
196 | [ C(OP_PREFETCH) ] = { | ||
197 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
198 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
199 | }, | ||
200 | }, | ||
201 | [ C(L1I ) ] = { | ||
202 | [ C(OP_READ) ] = { | ||
203 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
204 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
205 | }, | ||
206 | [ C(OP_WRITE) ] = { | ||
207 | [ C(RESULT_ACCESS) ] = -1, | ||
208 | [ C(RESULT_MISS) ] = -1, | ||
209 | }, | ||
210 | [ C(OP_PREFETCH) ] = { | ||
211 | [ C(RESULT_ACCESS) ] = 0x0, | ||
212 | [ C(RESULT_MISS) ] = 0x0, | ||
213 | }, | ||
214 | }, | ||
215 | [ C(LL ) ] = { | ||
216 | [ C(OP_READ) ] = { | ||
217 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
218 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
219 | }, | ||
220 | [ C(OP_WRITE) ] = { | ||
221 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
222 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
223 | }, | ||
224 | [ C(OP_PREFETCH) ] = { | ||
225 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
226 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
227 | }, | ||
228 | }, | ||
229 | [ C(DTLB) ] = { | ||
230 | [ C(OP_READ) ] = { | ||
231 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
232 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
233 | }, | ||
234 | [ C(OP_WRITE) ] = { | ||
235 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
236 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
237 | }, | ||
238 | [ C(OP_PREFETCH) ] = { | ||
239 | [ C(RESULT_ACCESS) ] = 0x0, | ||
240 | [ C(RESULT_MISS) ] = 0x0, | ||
241 | }, | ||
242 | }, | ||
243 | [ C(ITLB) ] = { | ||
244 | [ C(OP_READ) ] = { | ||
245 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
246 | [ C(RESULT_MISS) ] = 0x20c8, /* ITLB_MISS_RETIRED */ | ||
247 | }, | ||
248 | [ C(OP_WRITE) ] = { | ||
249 | [ C(RESULT_ACCESS) ] = -1, | ||
250 | [ C(RESULT_MISS) ] = -1, | ||
251 | }, | ||
252 | [ C(OP_PREFETCH) ] = { | ||
253 | [ C(RESULT_ACCESS) ] = -1, | ||
254 | [ C(RESULT_MISS) ] = -1, | ||
255 | }, | ||
256 | }, | ||
257 | [ C(BPU ) ] = { | ||
258 | [ C(OP_READ) ] = { | ||
259 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
260 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
261 | }, | ||
262 | [ C(OP_WRITE) ] = { | ||
263 | [ C(RESULT_ACCESS) ] = -1, | ||
264 | [ C(RESULT_MISS) ] = -1, | ||
265 | }, | ||
266 | [ C(OP_PREFETCH) ] = { | ||
267 | [ C(RESULT_ACCESS) ] = -1, | ||
268 | [ C(RESULT_MISS) ] = -1, | ||
269 | }, | ||
270 | }, | ||
271 | }; | ||
272 | |||
273 | static __initconst u64 core2_hw_cache_event_ids | ||
274 | [PERF_COUNT_HW_CACHE_MAX] | ||
275 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
276 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
277 | { | ||
278 | [ C(L1D) ] = { | ||
279 | [ C(OP_READ) ] = { | ||
280 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
281 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
282 | }, | ||
283 | [ C(OP_WRITE) ] = { | ||
284 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
285 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
286 | }, | ||
287 | [ C(OP_PREFETCH) ] = { | ||
288 | [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS */ | ||
289 | [ C(RESULT_MISS) ] = 0, | ||
290 | }, | ||
291 | }, | ||
292 | [ C(L1I ) ] = { | ||
293 | [ C(OP_READ) ] = { | ||
294 | [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS */ | ||
295 | [ C(RESULT_MISS) ] = 0x0081, /* L1I.MISSES */ | ||
296 | }, | ||
297 | [ C(OP_WRITE) ] = { | ||
298 | [ C(RESULT_ACCESS) ] = -1, | ||
299 | [ C(RESULT_MISS) ] = -1, | ||
300 | }, | ||
301 | [ C(OP_PREFETCH) ] = { | ||
302 | [ C(RESULT_ACCESS) ] = 0, | ||
303 | [ C(RESULT_MISS) ] = 0, | ||
304 | }, | ||
305 | }, | ||
306 | [ C(LL ) ] = { | ||
307 | [ C(OP_READ) ] = { | ||
308 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
309 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
310 | }, | ||
311 | [ C(OP_WRITE) ] = { | ||
312 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
313 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
314 | }, | ||
315 | [ C(OP_PREFETCH) ] = { | ||
316 | [ C(RESULT_ACCESS) ] = 0, | ||
317 | [ C(RESULT_MISS) ] = 0, | ||
318 | }, | ||
319 | }, | ||
320 | [ C(DTLB) ] = { | ||
321 | [ C(OP_READ) ] = { | ||
322 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
323 | [ C(RESULT_MISS) ] = 0x0208, /* DTLB_MISSES.MISS_LD */ | ||
324 | }, | ||
325 | [ C(OP_WRITE) ] = { | ||
326 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
327 | [ C(RESULT_MISS) ] = 0x0808, /* DTLB_MISSES.MISS_ST */ | ||
328 | }, | ||
329 | [ C(OP_PREFETCH) ] = { | ||
330 | [ C(RESULT_ACCESS) ] = 0, | ||
331 | [ C(RESULT_MISS) ] = 0, | ||
332 | }, | ||
333 | }, | ||
334 | [ C(ITLB) ] = { | ||
335 | [ C(OP_READ) ] = { | ||
336 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
337 | [ C(RESULT_MISS) ] = 0x1282, /* ITLBMISSES */ | ||
338 | }, | ||
339 | [ C(OP_WRITE) ] = { | ||
340 | [ C(RESULT_ACCESS) ] = -1, | ||
341 | [ C(RESULT_MISS) ] = -1, | ||
342 | }, | ||
343 | [ C(OP_PREFETCH) ] = { | ||
344 | [ C(RESULT_ACCESS) ] = -1, | ||
345 | [ C(RESULT_MISS) ] = -1, | ||
346 | }, | ||
347 | }, | ||
348 | [ C(BPU ) ] = { | ||
349 | [ C(OP_READ) ] = { | ||
350 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
351 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
352 | }, | ||
353 | [ C(OP_WRITE) ] = { | ||
354 | [ C(RESULT_ACCESS) ] = -1, | ||
355 | [ C(RESULT_MISS) ] = -1, | ||
356 | }, | ||
357 | [ C(OP_PREFETCH) ] = { | ||
358 | [ C(RESULT_ACCESS) ] = -1, | ||
359 | [ C(RESULT_MISS) ] = -1, | ||
360 | }, | ||
361 | }, | ||
362 | }; | ||
363 | |||
364 | static __initconst u64 atom_hw_cache_event_ids | ||
365 | [PERF_COUNT_HW_CACHE_MAX] | ||
366 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
367 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
368 | { | ||
369 | [ C(L1D) ] = { | ||
370 | [ C(OP_READ) ] = { | ||
371 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE.LD */ | ||
372 | [ C(RESULT_MISS) ] = 0, | ||
373 | }, | ||
374 | [ C(OP_WRITE) ] = { | ||
375 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST */ | ||
376 | [ C(RESULT_MISS) ] = 0, | ||
377 | }, | ||
378 | [ C(OP_PREFETCH) ] = { | ||
379 | [ C(RESULT_ACCESS) ] = 0x0, | ||
380 | [ C(RESULT_MISS) ] = 0, | ||
381 | }, | ||
382 | }, | ||
383 | [ C(L1I ) ] = { | ||
384 | [ C(OP_READ) ] = { | ||
385 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
386 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
387 | }, | ||
388 | [ C(OP_WRITE) ] = { | ||
389 | [ C(RESULT_ACCESS) ] = -1, | ||
390 | [ C(RESULT_MISS) ] = -1, | ||
391 | }, | ||
392 | [ C(OP_PREFETCH) ] = { | ||
393 | [ C(RESULT_ACCESS) ] = 0, | ||
394 | [ C(RESULT_MISS) ] = 0, | ||
395 | }, | ||
396 | }, | ||
397 | [ C(LL ) ] = { | ||
398 | [ C(OP_READ) ] = { | ||
399 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
400 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
401 | }, | ||
402 | [ C(OP_WRITE) ] = { | ||
403 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
404 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
405 | }, | ||
406 | [ C(OP_PREFETCH) ] = { | ||
407 | [ C(RESULT_ACCESS) ] = 0, | ||
408 | [ C(RESULT_MISS) ] = 0, | ||
409 | }, | ||
410 | }, | ||
411 | [ C(DTLB) ] = { | ||
412 | [ C(OP_READ) ] = { | ||
413 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI (alias) */ | ||
414 | [ C(RESULT_MISS) ] = 0x0508, /* DTLB_MISSES.MISS_LD */ | ||
415 | }, | ||
416 | [ C(OP_WRITE) ] = { | ||
417 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI (alias) */ | ||
418 | [ C(RESULT_MISS) ] = 0x0608, /* DTLB_MISSES.MISS_ST */ | ||
419 | }, | ||
420 | [ C(OP_PREFETCH) ] = { | ||
421 | [ C(RESULT_ACCESS) ] = 0, | ||
422 | [ C(RESULT_MISS) ] = 0, | ||
423 | }, | ||
424 | }, | ||
425 | [ C(ITLB) ] = { | ||
426 | [ C(OP_READ) ] = { | ||
427 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
428 | [ C(RESULT_MISS) ] = 0x0282, /* ITLB.MISSES */ | ||
429 | }, | ||
430 | [ C(OP_WRITE) ] = { | ||
431 | [ C(RESULT_ACCESS) ] = -1, | ||
432 | [ C(RESULT_MISS) ] = -1, | ||
433 | }, | ||
434 | [ C(OP_PREFETCH) ] = { | ||
435 | [ C(RESULT_ACCESS) ] = -1, | ||
436 | [ C(RESULT_MISS) ] = -1, | ||
437 | }, | ||
438 | }, | ||
439 | [ C(BPU ) ] = { | ||
440 | [ C(OP_READ) ] = { | ||
441 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
442 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
443 | }, | ||
444 | [ C(OP_WRITE) ] = { | ||
445 | [ C(RESULT_ACCESS) ] = -1, | ||
446 | [ C(RESULT_MISS) ] = -1, | ||
447 | }, | ||
448 | [ C(OP_PREFETCH) ] = { | ||
449 | [ C(RESULT_ACCESS) ] = -1, | ||
450 | [ C(RESULT_MISS) ] = -1, | ||
451 | }, | ||
452 | }, | ||
453 | }; | ||
454 | |||
455 | static u64 intel_pmu_raw_event(u64 hw_event) | ||
456 | { | ||
457 | #define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
458 | #define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
459 | #define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
460 | #define CORE_EVNTSEL_INV_MASK 0x00800000ULL | ||
461 | #define CORE_EVNTSEL_REG_MASK 0xFF000000ULL | ||
462 | |||
463 | #define CORE_EVNTSEL_MASK \ | ||
464 | (INTEL_ARCH_EVTSEL_MASK | \ | ||
465 | INTEL_ARCH_UNIT_MASK | \ | ||
466 | INTEL_ARCH_EDGE_MASK | \ | ||
467 | INTEL_ARCH_INV_MASK | \ | ||
468 | INTEL_ARCH_CNT_MASK) | ||
469 | |||
470 | return hw_event & CORE_EVNTSEL_MASK; | ||
471 | } | ||
472 | |||
473 | static void intel_pmu_enable_bts(u64 config) | ||
474 | { | ||
475 | unsigned long debugctlmsr; | ||
476 | |||
477 | debugctlmsr = get_debugctlmsr(); | ||
478 | |||
479 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
480 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
481 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
482 | |||
483 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
484 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
485 | |||
486 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
487 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
488 | |||
489 | update_debugctlmsr(debugctlmsr); | ||
490 | } | ||
491 | |||
492 | static void intel_pmu_disable_bts(void) | ||
493 | { | ||
494 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
495 | unsigned long debugctlmsr; | ||
496 | |||
497 | if (!cpuc->ds) | ||
498 | return; | ||
499 | |||
500 | debugctlmsr = get_debugctlmsr(); | ||
501 | |||
502 | debugctlmsr &= | ||
503 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
504 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
505 | |||
506 | update_debugctlmsr(debugctlmsr); | ||
507 | } | ||
508 | |||
509 | static void intel_pmu_disable_all(void) | ||
510 | { | ||
511 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
512 | |||
513 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | ||
514 | |||
515 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
516 | intel_pmu_disable_bts(); | ||
517 | } | ||
518 | |||
519 | static void intel_pmu_enable_all(void) | ||
520 | { | ||
521 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
522 | |||
523 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | ||
524 | |||
525 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | ||
526 | struct perf_event *event = | ||
527 | cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
528 | |||
529 | if (WARN_ON_ONCE(!event)) | ||
530 | return; | ||
531 | |||
532 | intel_pmu_enable_bts(event->hw.config); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | static inline u64 intel_pmu_get_status(void) | ||
537 | { | ||
538 | u64 status; | ||
539 | |||
540 | rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); | ||
541 | |||
542 | return status; | ||
543 | } | ||
544 | |||
545 | static inline void intel_pmu_ack_status(u64 ack) | ||
546 | { | ||
547 | wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); | ||
548 | } | ||
549 | |||
550 | static inline void | ||
551 | intel_pmu_disable_fixed(struct hw_perf_event *hwc) | ||
552 | { | ||
553 | int idx = hwc->idx - X86_PMC_IDX_FIXED; | ||
554 | u64 ctrl_val, mask; | ||
555 | |||
556 | mask = 0xfULL << (idx * 4); | ||
557 | |||
558 | rdmsrl(hwc->config_base, ctrl_val); | ||
559 | ctrl_val &= ~mask; | ||
560 | (void)checking_wrmsrl(hwc->config_base, ctrl_val); | ||
561 | } | ||
562 | |||
563 | static void intel_pmu_drain_bts_buffer(void) | ||
564 | { | ||
565 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
566 | struct debug_store *ds = cpuc->ds; | ||
567 | struct bts_record { | ||
568 | u64 from; | ||
569 | u64 to; | ||
570 | u64 flags; | ||
571 | }; | ||
572 | struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
573 | struct bts_record *at, *top; | ||
574 | struct perf_output_handle handle; | ||
575 | struct perf_event_header header; | ||
576 | struct perf_sample_data data; | ||
577 | struct pt_regs regs; | ||
578 | |||
579 | if (!event) | ||
580 | return; | ||
581 | |||
582 | if (!ds) | ||
583 | return; | ||
584 | |||
585 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; | ||
586 | top = (struct bts_record *)(unsigned long)ds->bts_index; | ||
587 | |||
588 | if (top <= at) | ||
589 | return; | ||
590 | |||
591 | ds->bts_index = ds->bts_buffer_base; | ||
592 | |||
593 | perf_sample_data_init(&data, 0); | ||
594 | |||
595 | data.period = event->hw.last_period; | ||
596 | regs.ip = 0; | ||
597 | |||
598 | /* | ||
599 | * Prepare a generic sample, i.e. fill in the invariant fields. | ||
600 | * We will overwrite the from and to address before we output | ||
601 | * the sample. | ||
602 | */ | ||
603 | perf_prepare_sample(&header, &data, event, ®s); | ||
604 | |||
605 | if (perf_output_begin(&handle, event, | ||
606 | header.size * (top - at), 1, 1)) | ||
607 | return; | ||
608 | |||
609 | for (; at < top; at++) { | ||
610 | data.ip = at->from; | ||
611 | data.addr = at->to; | ||
612 | |||
613 | perf_output_sample(&handle, &header, &data, event); | ||
614 | } | ||
615 | |||
616 | perf_output_end(&handle); | ||
617 | |||
618 | /* There's new data available. */ | ||
619 | event->hw.interrupts++; | ||
620 | event->pending_kill = POLL_IN; | ||
621 | } | ||
622 | |||
623 | static inline void | ||
624 | intel_pmu_disable_event(struct perf_event *event) | ||
625 | { | ||
626 | struct hw_perf_event *hwc = &event->hw; | ||
627 | |||
628 | if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { | ||
629 | intel_pmu_disable_bts(); | ||
630 | intel_pmu_drain_bts_buffer(); | ||
631 | return; | ||
632 | } | ||
633 | |||
634 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
635 | intel_pmu_disable_fixed(hwc); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | x86_pmu_disable_event(event); | ||
640 | } | ||
641 | |||
642 | static inline void | ||
643 | intel_pmu_enable_fixed(struct hw_perf_event *hwc) | ||
644 | { | ||
645 | int idx = hwc->idx - X86_PMC_IDX_FIXED; | ||
646 | u64 ctrl_val, bits, mask; | ||
647 | int err; | ||
648 | |||
649 | /* | ||
650 | * Enable IRQ generation (0x8), | ||
651 | * and enable ring-3 counting (0x2) and ring-0 counting (0x1) | ||
652 | * if requested: | ||
653 | */ | ||
654 | bits = 0x8ULL; | ||
655 | if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) | ||
656 | bits |= 0x2; | ||
657 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | ||
658 | bits |= 0x1; | ||
659 | |||
660 | /* | ||
661 | * ANY bit is supported in v3 and up | ||
662 | */ | ||
663 | if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) | ||
664 | bits |= 0x4; | ||
665 | |||
666 | bits <<= (idx * 4); | ||
667 | mask = 0xfULL << (idx * 4); | ||
668 | |||
669 | rdmsrl(hwc->config_base, ctrl_val); | ||
670 | ctrl_val &= ~mask; | ||
671 | ctrl_val |= bits; | ||
672 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | ||
673 | } | ||
674 | |||
675 | static void intel_pmu_enable_event(struct perf_event *event) | ||
676 | { | ||
677 | struct hw_perf_event *hwc = &event->hw; | ||
678 | |||
679 | if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { | ||
680 | if (!__get_cpu_var(cpu_hw_events).enabled) | ||
681 | return; | ||
682 | |||
683 | intel_pmu_enable_bts(hwc->config); | ||
684 | return; | ||
685 | } | ||
686 | |||
687 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
688 | intel_pmu_enable_fixed(hwc); | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | __x86_pmu_enable_event(hwc); | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * Save and restart an expired event. Called by NMI contexts, | ||
697 | * so it has to be careful about preempting normal event ops: | ||
698 | */ | ||
699 | static int intel_pmu_save_and_restart(struct perf_event *event) | ||
700 | { | ||
701 | x86_perf_event_update(event); | ||
702 | return x86_perf_event_set_period(event); | ||
703 | } | ||
704 | |||
705 | static void intel_pmu_reset(void) | ||
706 | { | ||
707 | struct debug_store *ds = __get_cpu_var(cpu_hw_events).ds; | ||
708 | unsigned long flags; | ||
709 | int idx; | ||
710 | |||
711 | if (!x86_pmu.num_events) | ||
712 | return; | ||
713 | |||
714 | local_irq_save(flags); | ||
715 | |||
716 | printk("clearing PMU state on CPU#%d\n", smp_processor_id()); | ||
717 | |||
718 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | ||
719 | checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); | ||
720 | checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); | ||
721 | } | ||
722 | for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { | ||
723 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | ||
724 | } | ||
725 | if (ds) | ||
726 | ds->bts_index = ds->bts_buffer_base; | ||
727 | |||
728 | local_irq_restore(flags); | ||
729 | } | ||
730 | |||
731 | /* | ||
732 | * This handler is triggered by the local APIC, so the APIC IRQ handling | ||
733 | * rules apply: | ||
734 | */ | ||
735 | static int intel_pmu_handle_irq(struct pt_regs *regs) | ||
736 | { | ||
737 | struct perf_sample_data data; | ||
738 | struct cpu_hw_events *cpuc; | ||
739 | int bit, loops; | ||
740 | u64 ack, status; | ||
741 | |||
742 | perf_sample_data_init(&data, 0); | ||
743 | |||
744 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
745 | |||
746 | intel_pmu_disable_all(); | ||
747 | intel_pmu_drain_bts_buffer(); | ||
748 | status = intel_pmu_get_status(); | ||
749 | if (!status) { | ||
750 | intel_pmu_enable_all(); | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | loops = 0; | ||
755 | again: | ||
756 | if (++loops > 100) { | ||
757 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); | ||
758 | perf_event_print_debug(); | ||
759 | intel_pmu_reset(); | ||
760 | goto done; | ||
761 | } | ||
762 | |||
763 | inc_irq_stat(apic_perf_irqs); | ||
764 | ack = status; | ||
765 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | ||
766 | struct perf_event *event = cpuc->events[bit]; | ||
767 | |||
768 | if (!test_bit(bit, cpuc->active_mask)) | ||
769 | continue; | ||
770 | |||
771 | if (!intel_pmu_save_and_restart(event)) | ||
772 | continue; | ||
773 | |||
774 | data.period = event->hw.last_period; | ||
775 | |||
776 | if (perf_event_overflow(event, 1, &data, regs)) | ||
777 | x86_pmu_stop(event); | ||
778 | } | ||
779 | |||
780 | intel_pmu_ack_status(ack); | ||
781 | |||
782 | /* | ||
783 | * Repeat if there is more work to be done: | ||
784 | */ | ||
785 | status = intel_pmu_get_status(); | ||
786 | if (status) | ||
787 | goto again; | ||
788 | |||
789 | done: | ||
790 | intel_pmu_enable_all(); | ||
791 | return 1; | ||
792 | } | ||
793 | |||
794 | static struct event_constraint bts_constraint = | ||
795 | EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); | ||
796 | |||
797 | static struct event_constraint * | ||
798 | intel_special_constraints(struct perf_event *event) | ||
799 | { | ||
800 | unsigned int hw_event; | ||
801 | |||
802 | hw_event = event->hw.config & INTEL_ARCH_EVENT_MASK; | ||
803 | |||
804 | if (unlikely((hw_event == | ||
805 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
806 | (event->hw.sample_period == 1))) { | ||
807 | |||
808 | return &bts_constraint; | ||
809 | } | ||
810 | return NULL; | ||
811 | } | ||
812 | |||
813 | static struct event_constraint * | ||
814 | intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | ||
815 | { | ||
816 | struct event_constraint *c; | ||
817 | |||
818 | c = intel_special_constraints(event); | ||
819 | if (c) | ||
820 | return c; | ||
821 | |||
822 | return x86_get_event_constraints(cpuc, event); | ||
823 | } | ||
824 | |||
825 | static __initconst struct x86_pmu core_pmu = { | ||
826 | .name = "core", | ||
827 | .handle_irq = x86_pmu_handle_irq, | ||
828 | .disable_all = x86_pmu_disable_all, | ||
829 | .enable_all = x86_pmu_enable_all, | ||
830 | .enable = x86_pmu_enable_event, | ||
831 | .disable = x86_pmu_disable_event, | ||
832 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
833 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
834 | .event_map = intel_pmu_event_map, | ||
835 | .raw_event = intel_pmu_raw_event, | ||
836 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
837 | .apic = 1, | ||
838 | /* | ||
839 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
840 | * so we install an artificial 1<<31 period regardless of | ||
841 | * the generic event period: | ||
842 | */ | ||
843 | .max_period = (1ULL << 31) - 1, | ||
844 | .get_event_constraints = intel_get_event_constraints, | ||
845 | .event_constraints = intel_core_event_constraints, | ||
846 | }; | ||
847 | |||
848 | static __initconst struct x86_pmu intel_pmu = { | ||
849 | .name = "Intel", | ||
850 | .handle_irq = intel_pmu_handle_irq, | ||
851 | .disable_all = intel_pmu_disable_all, | ||
852 | .enable_all = intel_pmu_enable_all, | ||
853 | .enable = intel_pmu_enable_event, | ||
854 | .disable = intel_pmu_disable_event, | ||
855 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
856 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
857 | .event_map = intel_pmu_event_map, | ||
858 | .raw_event = intel_pmu_raw_event, | ||
859 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
860 | .apic = 1, | ||
861 | /* | ||
862 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
863 | * so we install an artificial 1<<31 period regardless of | ||
864 | * the generic event period: | ||
865 | */ | ||
866 | .max_period = (1ULL << 31) - 1, | ||
867 | .enable_bts = intel_pmu_enable_bts, | ||
868 | .disable_bts = intel_pmu_disable_bts, | ||
869 | .get_event_constraints = intel_get_event_constraints, | ||
870 | |||
871 | .cpu_starting = init_debug_store_on_cpu, | ||
872 | .cpu_dying = fini_debug_store_on_cpu, | ||
873 | }; | ||
874 | |||
875 | static __init int intel_pmu_init(void) | ||
876 | { | ||
877 | union cpuid10_edx edx; | ||
878 | union cpuid10_eax eax; | ||
879 | unsigned int unused; | ||
880 | unsigned int ebx; | ||
881 | int version; | ||
882 | |||
883 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | ||
884 | /* check for P6 processor family */ | ||
885 | if (boot_cpu_data.x86 == 6) { | ||
886 | return p6_pmu_init(); | ||
887 | } else { | ||
888 | return -ENODEV; | ||
889 | } | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * Check whether the Architectural PerfMon supports | ||
894 | * Branch Misses Retired hw_event or not. | ||
895 | */ | ||
896 | cpuid(10, &eax.full, &ebx, &unused, &edx.full); | ||
897 | if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED) | ||
898 | return -ENODEV; | ||
899 | |||
900 | version = eax.split.version_id; | ||
901 | if (version < 2) | ||
902 | x86_pmu = core_pmu; | ||
903 | else | ||
904 | x86_pmu = intel_pmu; | ||
905 | |||
906 | x86_pmu.version = version; | ||
907 | x86_pmu.num_events = eax.split.num_events; | ||
908 | x86_pmu.event_bits = eax.split.bit_width; | ||
909 | x86_pmu.event_mask = (1ULL << eax.split.bit_width) - 1; | ||
910 | |||
911 | /* | ||
912 | * Quirk: v2 perfmon does not report fixed-purpose events, so | ||
913 | * assume at least 3 events: | ||
914 | */ | ||
915 | if (version > 1) | ||
916 | x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); | ||
917 | |||
918 | /* | ||
919 | * Install the hw-cache-events table: | ||
920 | */ | ||
921 | switch (boot_cpu_data.x86_model) { | ||
922 | case 14: /* 65 nm core solo/duo, "Yonah" */ | ||
923 | pr_cont("Core events, "); | ||
924 | break; | ||
925 | |||
926 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ | ||
927 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ | ||
928 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ | ||
929 | case 29: /* six-core 45 nm xeon "Dunnington" */ | ||
930 | memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, | ||
931 | sizeof(hw_cache_event_ids)); | ||
932 | |||
933 | x86_pmu.event_constraints = intel_core2_event_constraints; | ||
934 | pr_cont("Core2 events, "); | ||
935 | break; | ||
936 | |||
937 | case 26: /* 45 nm nehalem, "Bloomfield" */ | ||
938 | case 30: /* 45 nm nehalem, "Lynnfield" */ | ||
939 | case 46: /* 45 nm nehalem-ex, "Beckton" */ | ||
940 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, | ||
941 | sizeof(hw_cache_event_ids)); | ||
942 | |||
943 | x86_pmu.event_constraints = intel_nehalem_event_constraints; | ||
944 | pr_cont("Nehalem/Corei7 events, "); | ||
945 | break; | ||
946 | case 28: /* Atom */ | ||
947 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | ||
948 | sizeof(hw_cache_event_ids)); | ||
949 | |||
950 | x86_pmu.event_constraints = intel_gen_event_constraints; | ||
951 | pr_cont("Atom events, "); | ||
952 | break; | ||
953 | |||
954 | case 37: /* 32 nm nehalem, "Clarkdale" */ | ||
955 | case 44: /* 32 nm nehalem, "Gulftown" */ | ||
956 | memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, | ||
957 | sizeof(hw_cache_event_ids)); | ||
958 | |||
959 | x86_pmu.event_constraints = intel_westmere_event_constraints; | ||
960 | pr_cont("Westmere events, "); | ||
961 | break; | ||
962 | |||
963 | default: | ||
964 | /* | ||
965 | * default constraints for v2 and up | ||
966 | */ | ||
967 | x86_pmu.event_constraints = intel_gen_event_constraints; | ||
968 | pr_cont("generic architected perfmon, "); | ||
969 | } | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | #else /* CONFIG_CPU_SUP_INTEL */ | ||
974 | |||
975 | static int intel_pmu_init(void) | ||
976 | { | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | #endif /* CONFIG_CPU_SUP_INTEL */ | ||
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c new file mode 100644 index 000000000000..a330485d14da --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_p6.c | |||
@@ -0,0 +1,159 @@ | |||
1 | #ifdef CONFIG_CPU_SUP_INTEL | ||
2 | |||
3 | /* | ||
4 | * Not sure about some of these | ||
5 | */ | ||
6 | static const u64 p6_perfmon_event_map[] = | ||
7 | { | ||
8 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
9 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
10 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, | ||
11 | [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, | ||
12 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
13 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
14 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
15 | }; | ||
16 | |||
17 | static u64 p6_pmu_event_map(int hw_event) | ||
18 | { | ||
19 | return p6_perfmon_event_map[hw_event]; | ||
20 | } | ||
21 | |||
22 | /* | ||
23 | * Event setting that is specified not to count anything. | ||
24 | * We use this to effectively disable a counter. | ||
25 | * | ||
26 | * L2_RQSTS with 0 MESI unit mask. | ||
27 | */ | ||
28 | #define P6_NOP_EVENT 0x0000002EULL | ||
29 | |||
30 | static u64 p6_pmu_raw_event(u64 hw_event) | ||
31 | { | ||
32 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
33 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
34 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
35 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
36 | #define P6_EVNTSEL_REG_MASK 0xFF000000ULL | ||
37 | |||
38 | #define P6_EVNTSEL_MASK \ | ||
39 | (P6_EVNTSEL_EVENT_MASK | \ | ||
40 | P6_EVNTSEL_UNIT_MASK | \ | ||
41 | P6_EVNTSEL_EDGE_MASK | \ | ||
42 | P6_EVNTSEL_INV_MASK | \ | ||
43 | P6_EVNTSEL_REG_MASK) | ||
44 | |||
45 | return hw_event & P6_EVNTSEL_MASK; | ||
46 | } | ||
47 | |||
48 | static struct event_constraint p6_event_constraints[] = | ||
49 | { | ||
50 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ | ||
51 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
52 | INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ | ||
53 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
54 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
55 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
56 | EVENT_CONSTRAINT_END | ||
57 | }; | ||
58 | |||
59 | static void p6_pmu_disable_all(void) | ||
60 | { | ||
61 | u64 val; | ||
62 | |||
63 | /* p6 only has one enable register */ | ||
64 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
65 | val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; | ||
66 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
67 | } | ||
68 | |||
69 | static void p6_pmu_enable_all(void) | ||
70 | { | ||
71 | unsigned long val; | ||
72 | |||
73 | /* p6 only has one enable register */ | ||
74 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
75 | val |= ARCH_PERFMON_EVENTSEL_ENABLE; | ||
76 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
77 | } | ||
78 | |||
79 | static inline void | ||
80 | p6_pmu_disable_event(struct perf_event *event) | ||
81 | { | ||
82 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
83 | struct hw_perf_event *hwc = &event->hw; | ||
84 | u64 val = P6_NOP_EVENT; | ||
85 | |||
86 | if (cpuc->enabled) | ||
87 | val |= ARCH_PERFMON_EVENTSEL_ENABLE; | ||
88 | |||
89 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); | ||
90 | } | ||
91 | |||
92 | static void p6_pmu_enable_event(struct perf_event *event) | ||
93 | { | ||
94 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
95 | struct hw_perf_event *hwc = &event->hw; | ||
96 | u64 val; | ||
97 | |||
98 | val = hwc->config; | ||
99 | if (cpuc->enabled) | ||
100 | val |= ARCH_PERFMON_EVENTSEL_ENABLE; | ||
101 | |||
102 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); | ||
103 | } | ||
104 | |||
105 | static __initconst struct x86_pmu p6_pmu = { | ||
106 | .name = "p6", | ||
107 | .handle_irq = x86_pmu_handle_irq, | ||
108 | .disable_all = p6_pmu_disable_all, | ||
109 | .enable_all = p6_pmu_enable_all, | ||
110 | .enable = p6_pmu_enable_event, | ||
111 | .disable = p6_pmu_disable_event, | ||
112 | .eventsel = MSR_P6_EVNTSEL0, | ||
113 | .perfctr = MSR_P6_PERFCTR0, | ||
114 | .event_map = p6_pmu_event_map, | ||
115 | .raw_event = p6_pmu_raw_event, | ||
116 | .max_events = ARRAY_SIZE(p6_perfmon_event_map), | ||
117 | .apic = 1, | ||
118 | .max_period = (1ULL << 31) - 1, | ||
119 | .version = 0, | ||
120 | .num_events = 2, | ||
121 | /* | ||
122 | * Events have 40 bits implemented. However they are designed such | ||
123 | * that bits [32-39] are sign extensions of bit 31. As such the | ||
124 | * effective width of a event for P6-like PMU is 32 bits only. | ||
125 | * | ||
126 | * See IA-32 Intel Architecture Software developer manual Vol 3B | ||
127 | */ | ||
128 | .event_bits = 32, | ||
129 | .event_mask = (1ULL << 32) - 1, | ||
130 | .get_event_constraints = x86_get_event_constraints, | ||
131 | .event_constraints = p6_event_constraints, | ||
132 | }; | ||
133 | |||
134 | static __init int p6_pmu_init(void) | ||
135 | { | ||
136 | switch (boot_cpu_data.x86_model) { | ||
137 | case 1: | ||
138 | case 3: /* Pentium Pro */ | ||
139 | case 5: | ||
140 | case 6: /* Pentium II */ | ||
141 | case 7: | ||
142 | case 8: | ||
143 | case 11: /* Pentium III */ | ||
144 | case 9: | ||
145 | case 13: | ||
146 | /* Pentium M */ | ||
147 | break; | ||
148 | default: | ||
149 | pr_cont("unsupported p6 CPU model %d ", | ||
150 | boot_cpu_data.x86_model); | ||
151 | return -ENODEV; | ||
152 | } | ||
153 | |||
154 | x86_pmu = p6_pmu; | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | #endif /* CONFIG_CPU_SUP_INTEL */ | ||
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 74f4e85a5727..fb329e9f8494 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c | |||
@@ -680,7 +680,7 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz) | |||
680 | cpu_nmi_set_wd_enabled(); | 680 | cpu_nmi_set_wd_enabled(); |
681 | 681 | ||
682 | apic_write(APIC_LVTPC, APIC_DM_NMI); | 682 | apic_write(APIC_LVTPC, APIC_DM_NMI); |
683 | evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 683 | evntsel |= ARCH_PERFMON_EVENTSEL_ENABLE; |
684 | wrmsr(evntsel_msr, evntsel, 0); | 684 | wrmsr(evntsel_msr, evntsel, 0); |
685 | intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); | 685 | intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); |
686 | return 1; | 686 | return 1; |
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 1cbed97b59cf..dfdb4dba2320 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/dmi.h> | 24 | #include <linux/dmi.h> |
25 | #include <linux/module.h> | ||
25 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
26 | #include <asm/vmware.h> | 27 | #include <asm/vmware.h> |
27 | #include <asm/x86_init.h> | 28 | #include <asm/x86_init.h> |
@@ -101,6 +102,7 @@ int vmware_platform(void) | |||
101 | 102 | ||
102 | return 0; | 103 | return 0; |
103 | } | 104 | } |
105 | EXPORT_SYMBOL(vmware_platform); | ||
104 | 106 | ||
105 | /* | 107 | /* |
106 | * VMware hypervisor takes care of exporting a reliable TSC to the guest. | 108 | * VMware hypervisor takes care of exporting a reliable TSC to the guest. |