x86/oprofile: use 64 bit values in IBS functions
[pandora-kernel.git] / arch / x86 / oprofile / op_model_amd.c
1 /*
2  * @file op_model_amd.c
3  * athlon / K7 / K8 / Family 10h model-specific MSR operations
4  *
5  * @remark Copyright 2002-2009 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author John Levon
9  * @author Philippe Elie
10  * @author Graydon Hoare
11  * @author Robert Richter <robert.richter@amd.com>
12  * @author Barry Kasindorf
13  */
14
15 #include <linux/oprofile.h>
16 #include <linux/device.h>
17 #include <linux/pci.h>
18
19 #include <asm/ptrace.h>
20 #include <asm/msr.h>
21 #include <asm/nmi.h>
22
23 #include "op_x86_model.h"
24 #include "op_counter.h"
25
26 #define NUM_COUNTERS 4
27 #define NUM_CONTROLS 4
28 #define OP_EVENT_MASK                   0x0FFF
29 #define OP_CTR_OVERFLOW                 (1ULL<<31)
30
31 #define MSR_AMD_EVENTSEL_RESERVED       ((0xFFFFFCF0ULL<<32)|(1ULL<<21))
32
33 static unsigned long reset_value[NUM_COUNTERS];
34
35 #ifdef CONFIG_OPROFILE_IBS
36
37 /* IbsFetchCtl bits/masks */
38 #define IBS_FETCH_RAND_EN               (1ULL<<57)
39 #define IBS_FETCH_VAL                   (1ULL<<49)
40 #define IBS_FETCH_ENABLE                (1ULL<<48)
41 #define IBS_FETCH_CNT_MASK              0xFFFF0000ULL
42
43 /*IbsOpCtl bits */
44 #define IBS_OP_CNT_CTL                  (1ULL<<19)
45 #define IBS_OP_VAL                      (1ULL<<18)
46 #define IBS_OP_ENABLE                   (1ULL<<17)
47
48 #define IBS_FETCH_SIZE                  6
49 #define IBS_OP_SIZE                     12
50
51 static int has_ibs;     /* AMD Family10h and later */
52
53 struct op_ibs_config {
54         unsigned long op_enabled;
55         unsigned long fetch_enabled;
56         unsigned long max_cnt_fetch;
57         unsigned long max_cnt_op;
58         unsigned long rand_en;
59         unsigned long dispatched_ops;
60 };
61
62 static struct op_ibs_config ibs_config;
63
64 #endif
65
66 /* functions for op_amd_spec */
67
68 static void op_amd_fill_in_addresses(struct op_msrs * const msrs)
69 {
70         int i;
71
72         for (i = 0; i < NUM_COUNTERS; i++) {
73                 if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
74                         msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
75                 else
76                         msrs->counters[i].addr = 0;
77         }
78
79         for (i = 0; i < NUM_CONTROLS; i++) {
80                 if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
81                         msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
82                 else
83                         msrs->controls[i].addr = 0;
84         }
85 }
86
87 static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
88                               struct op_msrs const * const msrs)
89 {
90         u64 val;
91         int i;
92
93         /* clear all counters */
94         for (i = 0 ; i < NUM_CONTROLS; ++i) {
95                 if (unlikely(!msrs->controls[i].addr))
96                         continue;
97                 rdmsrl(msrs->controls[i].addr, val);
98                 val &= model->reserved;
99                 wrmsrl(msrs->controls[i].addr, val);
100         }
101
102         /* avoid a false detection of ctr overflows in NMI handler */
103         for (i = 0; i < NUM_COUNTERS; ++i) {
104                 if (unlikely(!msrs->counters[i].addr))
105                         continue;
106                 wrmsrl(msrs->counters[i].addr, -1LL);
107         }
108
109         /* enable active counters */
110         for (i = 0; i < NUM_COUNTERS; ++i) {
111                 if (counter_config[i].enabled && msrs->counters[i].addr) {
112                         reset_value[i] = counter_config[i].count;
113                         wrmsrl(msrs->counters[i].addr,
114                                -(s64)counter_config[i].count);
115                         rdmsrl(msrs->controls[i].addr, val);
116                         val &= model->reserved;
117                         val |= op_x86_get_ctrl(model, &counter_config[i]);
118                         wrmsrl(msrs->controls[i].addr, val);
119                 } else {
120                         reset_value[i] = 0;
121                 }
122         }
123 }
124
125 #ifdef CONFIG_OPROFILE_IBS
126
127 static inline int
128 op_amd_handle_ibs(struct pt_regs * const regs,
129                   struct op_msrs const * const msrs)
130 {
131         u64 val, ctl;
132         struct op_entry entry;
133
134         if (!has_ibs)
135                 return 1;
136
137         if (ibs_config.fetch_enabled) {
138                 rdmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
139                 if (ctl & IBS_FETCH_VAL) {
140                         rdmsrl(MSR_AMD64_IBSFETCHLINAD, val);
141                         oprofile_write_reserve(&entry, regs, val,
142                                                IBS_FETCH_CODE, IBS_FETCH_SIZE);
143                         oprofile_add_data(&entry, (u32)val);
144                         oprofile_add_data(&entry, (u32)(val >> 32));
145                         oprofile_add_data(&entry, (u32)ctl);
146                         oprofile_add_data(&entry, (u32)(ctl >> 32));
147                         rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, val);
148                         oprofile_add_data(&entry, (u32)val);
149                         oprofile_add_data(&entry, (u32)(val >> 32));
150                         oprofile_write_commit(&entry);
151
152                         /* reenable the IRQ */
153                         ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT_MASK);
154                         ctl |= IBS_FETCH_ENABLE;
155                         wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
156                 }
157         }
158
159         if (ibs_config.op_enabled) {
160                 rdmsrl(MSR_AMD64_IBSOPCTL, ctl);
161                 if (ctl & IBS_OP_VAL) {
162                         rdmsrl(MSR_AMD64_IBSOPRIP, val);
163                         oprofile_write_reserve(&entry, regs, val,
164                                                IBS_OP_CODE, IBS_OP_SIZE);
165                         oprofile_add_data(&entry, (u32)val);
166                         oprofile_add_data(&entry, (u32)(val >> 32));
167                         rdmsrl(MSR_AMD64_IBSOPDATA, val);
168                         oprofile_add_data(&entry, (u32)val);
169                         oprofile_add_data(&entry, (u32)(val >> 32));
170                         rdmsrl(MSR_AMD64_IBSOPDATA2, val);
171                         oprofile_add_data(&entry, (u32)val);
172                         oprofile_add_data(&entry, (u32)(val >> 32));
173                         rdmsrl(MSR_AMD64_IBSOPDATA3, val);
174                         oprofile_add_data(&entry, (u32)val);
175                         oprofile_add_data(&entry, (u32)(val >> 32));
176                         rdmsrl(MSR_AMD64_IBSDCLINAD, val);
177                         oprofile_add_data(&entry, (u32)val);
178                         oprofile_add_data(&entry, (u32)(val >> 32));
179                         rdmsrl(MSR_AMD64_IBSDCPHYSAD, val);
180                         oprofile_add_data(&entry, (u32)val);
181                         oprofile_add_data(&entry, (u32)(val >> 32));
182                         oprofile_write_commit(&entry);
183
184                         /* reenable the IRQ */
185                         ctl &= ~IBS_OP_VAL & 0xFFFFFFFF;
186                         ctl |= IBS_OP_ENABLE;
187                         wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
188                 }
189         }
190
191         return 1;
192 }
193
194 static inline void op_amd_start_ibs(void)
195 {
196         u64 val;
197         if (has_ibs && ibs_config.fetch_enabled) {
198                 val = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
199                 val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
200                 val |= IBS_FETCH_ENABLE;
201                 wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
202         }
203
204         if (has_ibs && ibs_config.op_enabled) {
205                 val = (ibs_config.max_cnt_op >> 4) & 0xFFFF;
206                 val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0;
207                 val |= IBS_OP_ENABLE;
208                 wrmsrl(MSR_AMD64_IBSOPCTL, val);
209         }
210 }
211
212 static void op_amd_stop_ibs(void)
213 {
214         if (has_ibs && ibs_config.fetch_enabled)
215                 /* clear max count and enable */
216                 wrmsrl(MSR_AMD64_IBSFETCHCTL, 0);
217
218         if (has_ibs && ibs_config.op_enabled)
219                 /* clear max count and enable */
220                 wrmsrl(MSR_AMD64_IBSOPCTL, 0);
221 }
222
223 #else
224
225 static inline int op_amd_handle_ibs(struct pt_regs * const regs,
226                                     struct op_msrs const * const msrs) { }
227 static inline void op_amd_start_ibs(void) { }
228 static inline void op_amd_stop_ibs(void) { }
229
230 #endif
231
232 static int op_amd_check_ctrs(struct pt_regs * const regs,
233                              struct op_msrs const * const msrs)
234 {
235         u64 val;
236         int i;
237
238         for (i = 0 ; i < NUM_COUNTERS; ++i) {
239                 if (!reset_value[i])
240                         continue;
241                 rdmsrl(msrs->counters[i].addr, val);
242                 /* bit is clear if overflowed: */
243                 if (val & OP_CTR_OVERFLOW)
244                         continue;
245                 oprofile_add_sample(regs, i);
246                 wrmsrl(msrs->counters[i].addr, -(s64)reset_value[i]);
247         }
248
249         op_amd_handle_ibs(regs, msrs);
250
251         /* See op_model_ppro.c */
252         return 1;
253 }
254
255 static void op_amd_start(struct op_msrs const * const msrs)
256 {
257         u64 val;
258         int i;
259         for (i = 0 ; i < NUM_COUNTERS ; ++i) {
260                 if (reset_value[i]) {
261                         rdmsrl(msrs->controls[i].addr, val);
262                         val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
263                         wrmsrl(msrs->controls[i].addr, val);
264                 }
265         }
266
267         op_amd_start_ibs();
268 }
269
270 static void op_amd_stop(struct op_msrs const * const msrs)
271 {
272         u64 val;
273         int i;
274
275         /*
276          * Subtle: stop on all counters to avoid race with setting our
277          * pm callback
278          */
279         for (i = 0 ; i < NUM_COUNTERS ; ++i) {
280                 if (!reset_value[i])
281                         continue;
282                 rdmsrl(msrs->controls[i].addr, val);
283                 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
284                 wrmsrl(msrs->controls[i].addr, val);
285         }
286
287         op_amd_stop_ibs();
288 }
289
290 static void op_amd_shutdown(struct op_msrs const * const msrs)
291 {
292         int i;
293
294         for (i = 0 ; i < NUM_COUNTERS ; ++i) {
295                 if (msrs->counters[i].addr)
296                         release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
297         }
298         for (i = 0 ; i < NUM_CONTROLS ; ++i) {
299                 if (msrs->controls[i].addr)
300                         release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
301         }
302 }
303
304 #ifdef CONFIG_OPROFILE_IBS
305
306 static u8 ibs_eilvt_off;
307
308 static inline void apic_init_ibs_nmi_per_cpu(void *arg)
309 {
310         ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
311 }
312
313 static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
314 {
315         setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
316 }
317
318 static int init_ibs_nmi(void)
319 {
320 #define IBSCTL_LVTOFFSETVAL             (1 << 8)
321 #define IBSCTL                          0x1cc
322         struct pci_dev *cpu_cfg;
323         int nodes;
324         u32 value = 0;
325
326         /* per CPU setup */
327         on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1);
328
329         nodes = 0;
330         cpu_cfg = NULL;
331         do {
332                 cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
333                                          PCI_DEVICE_ID_AMD_10H_NB_MISC,
334                                          cpu_cfg);
335                 if (!cpu_cfg)
336                         break;
337                 ++nodes;
338                 pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
339                                        | IBSCTL_LVTOFFSETVAL);
340                 pci_read_config_dword(cpu_cfg, IBSCTL, &value);
341                 if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
342                         pci_dev_put(cpu_cfg);
343                         printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
344                                 "IBSCTL = 0x%08x", value);
345                         return 1;
346                 }
347         } while (1);
348
349         if (!nodes) {
350                 printk(KERN_DEBUG "No CPU node configured for IBS");
351                 return 1;
352         }
353
354 #ifdef CONFIG_NUMA
355         /* Sanity check */
356         /* Works only for 64bit with proper numa implementation. */
357         if (nodes != num_possible_nodes()) {
358                 printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, "
359                         "found: %d, expected %d",
360                         nodes, num_possible_nodes());
361                 return 1;
362         }
363 #endif
364         return 0;
365 }
366
367 /* uninitialize the APIC for the IBS interrupts if needed */
368 static void clear_ibs_nmi(void)
369 {
370         if (has_ibs)
371                 on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
372 }
373
374 /* initialize the APIC for the IBS interrupts if available */
375 static void ibs_init(void)
376 {
377         has_ibs = boot_cpu_has(X86_FEATURE_IBS);
378
379         if (!has_ibs)
380                 return;
381
382         if (init_ibs_nmi()) {
383                 has_ibs = 0;
384                 return;
385         }
386
387         printk(KERN_INFO "oprofile: AMD IBS detected\n");
388 }
389
390 static void ibs_exit(void)
391 {
392         if (!has_ibs)
393                 return;
394
395         clear_ibs_nmi();
396 }
397
398 static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
399
400 static int setup_ibs_files(struct super_block *sb, struct dentry *root)
401 {
402         struct dentry *dir;
403         int ret = 0;
404
405         /* architecture specific files */
406         if (create_arch_files)
407                 ret = create_arch_files(sb, root);
408
409         if (ret)
410                 return ret;
411
412         if (!has_ibs)
413                 return ret;
414
415         /* model specific files */
416
417         /* setup some reasonable defaults */
418         ibs_config.max_cnt_fetch = 250000;
419         ibs_config.fetch_enabled = 0;
420         ibs_config.max_cnt_op = 250000;
421         ibs_config.op_enabled = 0;
422         ibs_config.dispatched_ops = 1;
423
424         dir = oprofilefs_mkdir(sb, root, "ibs_fetch");
425         oprofilefs_create_ulong(sb, dir, "enable",
426                                 &ibs_config.fetch_enabled);
427         oprofilefs_create_ulong(sb, dir, "max_count",
428                                 &ibs_config.max_cnt_fetch);
429         oprofilefs_create_ulong(sb, dir, "rand_enable",
430                                 &ibs_config.rand_en);
431
432         dir = oprofilefs_mkdir(sb, root, "ibs_op");
433         oprofilefs_create_ulong(sb, dir, "enable",
434                                 &ibs_config.op_enabled);
435         oprofilefs_create_ulong(sb, dir, "max_count",
436                                 &ibs_config.max_cnt_op);
437         oprofilefs_create_ulong(sb, dir, "dispatched_ops",
438                                 &ibs_config.dispatched_ops);
439
440         return 0;
441 }
442
443 static int op_amd_init(struct oprofile_operations *ops)
444 {
445         ibs_init();
446         create_arch_files = ops->create_files;
447         ops->create_files = setup_ibs_files;
448         return 0;
449 }
450
451 static void op_amd_exit(void)
452 {
453         ibs_exit();
454 }
455
456 #else
457
458 /* no IBS support */
459
460 static int op_amd_init(struct oprofile_operations *ops)
461 {
462         return 0;
463 }
464
465 static void op_amd_exit(void) {}
466
467 #endif /* CONFIG_OPROFILE_IBS */
468
469 struct op_x86_model_spec const op_amd_spec = {
470         .num_counters           = NUM_COUNTERS,
471         .num_controls           = NUM_CONTROLS,
472         .reserved               = MSR_AMD_EVENTSEL_RESERVED,
473         .event_mask             = OP_EVENT_MASK,
474         .init                   = op_amd_init,
475         .exit                   = op_amd_exit,
476         .fill_in_addresses      = &op_amd_fill_in_addresses,
477         .setup_ctrs             = &op_amd_setup_ctrs,
478         .check_ctrs             = &op_amd_check_ctrs,
479         .start                  = &op_amd_start,
480         .stop                   = &op_amd_stop,
481         .shutdown               = &op_amd_shutdown,
482 };