aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/oprofile/op_model_amd.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/oprofile/op_model_amd.c')
-rw-r--r--arch/x86/oprofile/op_model_amd.c356
1 files changed, 276 insertions, 80 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index b67a6b5aa8d4..9cbb710dc94b 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -29,11 +29,12 @@
29#include "op_x86_model.h" 29#include "op_x86_model.h"
30#include "op_counter.h" 30#include "op_counter.h"
31 31
32#define NUM_COUNTERS 4 32#define NUM_COUNTERS 4
33#define NUM_COUNTERS_F15H 6
33#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX 34#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
34#define NUM_VIRT_COUNTERS 32 35#define NUM_VIRT_COUNTERS 32
35#else 36#else
36#define NUM_VIRT_COUNTERS NUM_COUNTERS 37#define NUM_VIRT_COUNTERS 0
37#endif 38#endif
38 39
39#define OP_EVENT_MASK 0x0FFF 40#define OP_EVENT_MASK 0x0FFF
@@ -41,38 +42,61 @@
41 42
42#define MSR_AMD_EVENTSEL_RESERVED ((0xFFFFFCF0ULL<<32)|(1ULL<<21)) 43#define MSR_AMD_EVENTSEL_RESERVED ((0xFFFFFCF0ULL<<32)|(1ULL<<21))
43 44
44static unsigned long reset_value[NUM_VIRT_COUNTERS]; 45static int num_counters;
46static unsigned long reset_value[OP_MAX_COUNTER];
45 47
46#define IBS_FETCH_SIZE 6 48#define IBS_FETCH_SIZE 6
47#define IBS_OP_SIZE 12 49#define IBS_OP_SIZE 12
48 50
49static u32 ibs_caps; 51static u32 ibs_caps;
50 52
51struct op_ibs_config { 53struct ibs_config {
52 unsigned long op_enabled; 54 unsigned long op_enabled;
53 unsigned long fetch_enabled; 55 unsigned long fetch_enabled;
54 unsigned long max_cnt_fetch; 56 unsigned long max_cnt_fetch;
55 unsigned long max_cnt_op; 57 unsigned long max_cnt_op;
56 unsigned long rand_en; 58 unsigned long rand_en;
57 unsigned long dispatched_ops; 59 unsigned long dispatched_ops;
60 unsigned long branch_target;
58}; 61};
59 62
60static struct op_ibs_config ibs_config; 63struct ibs_state {
61static u64 ibs_op_ctl; 64 u64 ibs_op_ctl;
65 int branch_target;
66 unsigned long sample_size;
67};
68
69static struct ibs_config ibs_config;
70static struct ibs_state ibs_state;
62 71
63/* 72/*
64 * IBS cpuid feature detection 73 * IBS cpuid feature detection
65 */ 74 */
66 75
67#define IBS_CPUID_FEATURES 0x8000001b 76#define IBS_CPUID_FEATURES 0x8000001b
68 77
69/* 78/*
70 * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but 79 * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
71 * bit 0 is used to indicate the existence of IBS. 80 * bit 0 is used to indicate the existence of IBS.
72 */ 81 */
73#define IBS_CAPS_AVAIL (1LL<<0) 82#define IBS_CAPS_AVAIL (1U<<0)
74#define IBS_CAPS_RDWROPCNT (1LL<<3) 83#define IBS_CAPS_FETCHSAM (1U<<1)
75#define IBS_CAPS_OPCNT (1LL<<4) 84#define IBS_CAPS_OPSAM (1U<<2)
85#define IBS_CAPS_RDWROPCNT (1U<<3)
86#define IBS_CAPS_OPCNT (1U<<4)
87#define IBS_CAPS_BRNTRGT (1U<<5)
88#define IBS_CAPS_OPCNTEXT (1U<<6)
89
90#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \
91 | IBS_CAPS_FETCHSAM \
92 | IBS_CAPS_OPSAM)
93
94/*
95 * IBS APIC setup
96 */
97#define IBSCTL 0x1cc
98#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
99#define IBSCTL_LVT_OFFSET_MASK 0x0F
76 100
77/* 101/*
78 * IBS randomization macros 102 * IBS randomization macros
@@ -92,12 +116,12 @@ static u32 get_ibs_caps(void)
92 /* check IBS cpuid feature flags */ 116 /* check IBS cpuid feature flags */
93 max_level = cpuid_eax(0x80000000); 117 max_level = cpuid_eax(0x80000000);
94 if (max_level < IBS_CPUID_FEATURES) 118 if (max_level < IBS_CPUID_FEATURES)
95 return IBS_CAPS_AVAIL; 119 return IBS_CAPS_DEFAULT;
96 120
97 ibs_caps = cpuid_eax(IBS_CPUID_FEATURES); 121 ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
98 if (!(ibs_caps & IBS_CAPS_AVAIL)) 122 if (!(ibs_caps & IBS_CAPS_AVAIL))
99 /* cpuid flags not valid */ 123 /* cpuid flags not valid */
100 return IBS_CAPS_AVAIL; 124 return IBS_CAPS_DEFAULT;
101 125
102 return ibs_caps; 126 return ibs_caps;
103} 127}
@@ -190,8 +214,8 @@ op_amd_handle_ibs(struct pt_regs * const regs,
190 rdmsrl(MSR_AMD64_IBSOPCTL, ctl); 214 rdmsrl(MSR_AMD64_IBSOPCTL, ctl);
191 if (ctl & IBS_OP_VAL) { 215 if (ctl & IBS_OP_VAL) {
192 rdmsrl(MSR_AMD64_IBSOPRIP, val); 216 rdmsrl(MSR_AMD64_IBSOPRIP, val);
193 oprofile_write_reserve(&entry, regs, val, 217 oprofile_write_reserve(&entry, regs, val, IBS_OP_CODE,
194 IBS_OP_CODE, IBS_OP_SIZE); 218 ibs_state.sample_size);
195 oprofile_add_data64(&entry, val); 219 oprofile_add_data64(&entry, val);
196 rdmsrl(MSR_AMD64_IBSOPDATA, val); 220 rdmsrl(MSR_AMD64_IBSOPDATA, val);
197 oprofile_add_data64(&entry, val); 221 oprofile_add_data64(&entry, val);
@@ -203,10 +227,14 @@ op_amd_handle_ibs(struct pt_regs * const regs,
203 oprofile_add_data64(&entry, val); 227 oprofile_add_data64(&entry, val);
204 rdmsrl(MSR_AMD64_IBSDCPHYSAD, val); 228 rdmsrl(MSR_AMD64_IBSDCPHYSAD, val);
205 oprofile_add_data64(&entry, val); 229 oprofile_add_data64(&entry, val);
230 if (ibs_state.branch_target) {
231 rdmsrl(MSR_AMD64_IBSBRTARGET, val);
232 oprofile_add_data(&entry, (unsigned long)val);
233 }
206 oprofile_write_commit(&entry); 234 oprofile_write_commit(&entry);
207 235
208 /* reenable the IRQ */ 236 /* reenable the IRQ */
209 ctl = op_amd_randomize_ibs_op(ibs_op_ctl); 237 ctl = op_amd_randomize_ibs_op(ibs_state.ibs_op_ctl);
210 wrmsrl(MSR_AMD64_IBSOPCTL, ctl); 238 wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
211 } 239 }
212 } 240 }
@@ -219,21 +247,32 @@ static inline void op_amd_start_ibs(void)
219 if (!ibs_caps) 247 if (!ibs_caps)
220 return; 248 return;
221 249
250 memset(&ibs_state, 0, sizeof(ibs_state));
251
252 /*
253 * Note: Since the max count settings may out of range we
254 * write back the actual used values so that userland can read
255 * it.
256 */
257
222 if (ibs_config.fetch_enabled) { 258 if (ibs_config.fetch_enabled) {
223 val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT; 259 val = ibs_config.max_cnt_fetch >> 4;
260 val = min(val, IBS_FETCH_MAX_CNT);
261 ibs_config.max_cnt_fetch = val << 4;
224 val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0; 262 val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
225 val |= IBS_FETCH_ENABLE; 263 val |= IBS_FETCH_ENABLE;
226 wrmsrl(MSR_AMD64_IBSFETCHCTL, val); 264 wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
227 } 265 }
228 266
229 if (ibs_config.op_enabled) { 267 if (ibs_config.op_enabled) {
230 ibs_op_ctl = ibs_config.max_cnt_op >> 4; 268 val = ibs_config.max_cnt_op >> 4;
231 if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) { 269 if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) {
232 /* 270 /*
233 * IbsOpCurCnt not supported. See 271 * IbsOpCurCnt not supported. See
234 * op_amd_randomize_ibs_op() for details. 272 * op_amd_randomize_ibs_op() for details.
235 */ 273 */
236 ibs_op_ctl = clamp(ibs_op_ctl, 0x0081ULL, 0xFF80ULL); 274 val = clamp(val, 0x0081ULL, 0xFF80ULL);
275 ibs_config.max_cnt_op = val << 4;
237 } else { 276 } else {
238 /* 277 /*
239 * The start value is randomized with a 278 * The start value is randomized with a
@@ -241,13 +280,24 @@ static inline void op_amd_start_ibs(void)
241 * with the half of the randomized range. Also 280 * with the half of the randomized range. Also
242 * avoid underflows. 281 * avoid underflows.
243 */ 282 */
244 ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET, 283 val += IBS_RANDOM_MAXCNT_OFFSET;
245 IBS_OP_MAX_CNT); 284 if (ibs_caps & IBS_CAPS_OPCNTEXT)
285 val = min(val, IBS_OP_MAX_CNT_EXT);
286 else
287 val = min(val, IBS_OP_MAX_CNT);
288 ibs_config.max_cnt_op =
289 (val - IBS_RANDOM_MAXCNT_OFFSET) << 4;
246 } 290 }
247 if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops) 291 val = ((val & ~IBS_OP_MAX_CNT) << 4) | (val & IBS_OP_MAX_CNT);
248 ibs_op_ctl |= IBS_OP_CNT_CTL; 292 val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0;
249 ibs_op_ctl |= IBS_OP_ENABLE; 293 val |= IBS_OP_ENABLE;
250 val = op_amd_randomize_ibs_op(ibs_op_ctl); 294 ibs_state.ibs_op_ctl = val;
295 ibs_state.sample_size = IBS_OP_SIZE;
296 if (ibs_config.branch_target) {
297 ibs_state.branch_target = 1;
298 ibs_state.sample_size++;
299 }
300 val = op_amd_randomize_ibs_op(ibs_state.ibs_op_ctl);
251 wrmsrl(MSR_AMD64_IBSOPCTL, val); 301 wrmsrl(MSR_AMD64_IBSOPCTL, val);
252 } 302 }
253} 303}
@@ -266,6 +316,81 @@ static void op_amd_stop_ibs(void)
266 wrmsrl(MSR_AMD64_IBSOPCTL, 0); 316 wrmsrl(MSR_AMD64_IBSOPCTL, 0);
267} 317}
268 318
319static inline int get_eilvt(int offset)
320{
321 return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
322}
323
324static inline int put_eilvt(int offset)
325{
326 return !setup_APIC_eilvt(offset, 0, 0, 1);
327}
328
329static inline int ibs_eilvt_valid(void)
330{
331 int offset;
332 u64 val;
333 int valid = 0;
334
335 preempt_disable();
336
337 rdmsrl(MSR_AMD64_IBSCTL, val);
338 offset = val & IBSCTL_LVT_OFFSET_MASK;
339
340 if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
341 pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
342 smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
343 goto out;
344 }
345
346 if (!get_eilvt(offset)) {
347 pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
348 smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
349 goto out;
350 }
351
352 valid = 1;
353out:
354 preempt_enable();
355
356 return valid;
357}
358
359static inline int get_ibs_offset(void)
360{
361 u64 val;
362
363 rdmsrl(MSR_AMD64_IBSCTL, val);
364 if (!(val & IBSCTL_LVT_OFFSET_VALID))
365 return -EINVAL;
366
367 return val & IBSCTL_LVT_OFFSET_MASK;
368}
369
370static void setup_APIC_ibs(void)
371{
372 int offset;
373
374 offset = get_ibs_offset();
375 if (offset < 0)
376 goto failed;
377
378 if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
379 return;
380failed:
381 pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
382 smp_processor_id());
383}
384
385static void clear_APIC_ibs(void)
386{
387 int offset;
388
389 offset = get_ibs_offset();
390 if (offset >= 0)
391 setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
392}
393
269#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX 394#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
270 395
271static void op_mux_switch_ctrl(struct op_x86_model_spec const *model, 396static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -275,7 +400,7 @@ static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
275 int i; 400 int i;
276 401
277 /* enable active counters */ 402 /* enable active counters */
278 for (i = 0; i < NUM_COUNTERS; ++i) { 403 for (i = 0; i < num_counters; ++i) {
279 int virt = op_x86_phys_to_virt(i); 404 int virt = op_x86_phys_to_virt(i);
280 if (!reset_value[virt]) 405 if (!reset_value[virt])
281 continue; 406 continue;
@@ -294,7 +419,7 @@ static void op_amd_shutdown(struct op_msrs const * const msrs)
294{ 419{
295 int i; 420 int i;
296 421
297 for (i = 0; i < NUM_COUNTERS; ++i) { 422 for (i = 0; i < num_counters; ++i) {
298 if (!msrs->counters[i].addr) 423 if (!msrs->counters[i].addr)
299 continue; 424 continue;
300 release_perfctr_nmi(MSR_K7_PERFCTR0 + i); 425 release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
@@ -306,7 +431,7 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
306{ 431{
307 int i; 432 int i;
308 433
309 for (i = 0; i < NUM_COUNTERS; i++) { 434 for (i = 0; i < num_counters; i++) {
310 if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) 435 if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
311 goto fail; 436 goto fail;
312 if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { 437 if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) {
@@ -314,8 +439,13 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
314 goto fail; 439 goto fail;
315 } 440 }
316 /* both registers must be reserved */ 441 /* both registers must be reserved */
317 msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; 442 if (num_counters == NUM_COUNTERS_F15H) {
318 msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; 443 msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
444 msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
445 } else {
446 msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
447 msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
448 }
319 continue; 449 continue;
320 fail: 450 fail:
321 if (!counter_config[i].enabled) 451 if (!counter_config[i].enabled)
@@ -335,7 +465,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
335 int i; 465 int i;
336 466
337 /* setup reset_value */ 467 /* setup reset_value */
338 for (i = 0; i < NUM_VIRT_COUNTERS; ++i) { 468 for (i = 0; i < OP_MAX_COUNTER; ++i) {
339 if (counter_config[i].enabled 469 if (counter_config[i].enabled
340 && msrs->counters[op_x86_virt_to_phys(i)].addr) 470 && msrs->counters[op_x86_virt_to_phys(i)].addr)
341 reset_value[i] = counter_config[i].count; 471 reset_value[i] = counter_config[i].count;
@@ -344,7 +474,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
344 } 474 }
345 475
346 /* clear all counters */ 476 /* clear all counters */
347 for (i = 0; i < NUM_COUNTERS; ++i) { 477 for (i = 0; i < num_counters; ++i) {
348 if (!msrs->controls[i].addr) 478 if (!msrs->controls[i].addr)
349 continue; 479 continue;
350 rdmsrl(msrs->controls[i].addr, val); 480 rdmsrl(msrs->controls[i].addr, val);
@@ -360,7 +490,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
360 } 490 }
361 491
362 /* enable active counters */ 492 /* enable active counters */
363 for (i = 0; i < NUM_COUNTERS; ++i) { 493 for (i = 0; i < num_counters; ++i) {
364 int virt = op_x86_phys_to_virt(i); 494 int virt = op_x86_phys_to_virt(i);
365 if (!reset_value[virt]) 495 if (!reset_value[virt])
366 continue; 496 continue;
@@ -376,13 +506,13 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
376 } 506 }
377 507
378 if (ibs_caps) 508 if (ibs_caps)
379 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); 509 setup_APIC_ibs();
380} 510}
381 511
382static void op_amd_cpu_shutdown(void) 512static void op_amd_cpu_shutdown(void)
383{ 513{
384 if (ibs_caps) 514 if (ibs_caps)
385 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); 515 clear_APIC_ibs();
386} 516}
387 517
388static int op_amd_check_ctrs(struct pt_regs * const regs, 518static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -391,7 +521,7 @@ static int op_amd_check_ctrs(struct pt_regs * const regs,
391 u64 val; 521 u64 val;
392 int i; 522 int i;
393 523
394 for (i = 0; i < NUM_COUNTERS; ++i) { 524 for (i = 0; i < num_counters; ++i) {
395 int virt = op_x86_phys_to_virt(i); 525 int virt = op_x86_phys_to_virt(i);
396 if (!reset_value[virt]) 526 if (!reset_value[virt])
397 continue; 527 continue;
@@ -414,7 +544,7 @@ static void op_amd_start(struct op_msrs const * const msrs)
414 u64 val; 544 u64 val;
415 int i; 545 int i;
416 546
417 for (i = 0; i < NUM_COUNTERS; ++i) { 547 for (i = 0; i < num_counters; ++i) {
418 if (!reset_value[op_x86_phys_to_virt(i)]) 548 if (!reset_value[op_x86_phys_to_virt(i)])
419 continue; 549 continue;
420 rdmsrl(msrs->controls[i].addr, val); 550 rdmsrl(msrs->controls[i].addr, val);
@@ -434,7 +564,7 @@ static void op_amd_stop(struct op_msrs const * const msrs)
434 * Subtle: stop on all counters to avoid race with setting our 564 * Subtle: stop on all counters to avoid race with setting our
435 * pm callback 565 * pm callback
436 */ 566 */
437 for (i = 0; i < NUM_COUNTERS; ++i) { 567 for (i = 0; i < num_counters; ++i) {
438 if (!reset_value[op_x86_phys_to_virt(i)]) 568 if (!reset_value[op_x86_phys_to_virt(i)])
439 continue; 569 continue;
440 rdmsrl(msrs->controls[i].addr, val); 570 rdmsrl(msrs->controls[i].addr, val);
@@ -445,16 +575,11 @@ static void op_amd_stop(struct op_msrs const * const msrs)
445 op_amd_stop_ibs(); 575 op_amd_stop_ibs();
446} 576}
447 577
448static int __init_ibs_nmi(void) 578static int setup_ibs_ctl(int ibs_eilvt_off)
449{ 579{
450#define IBSCTL_LVTOFFSETVAL (1 << 8)
451#define IBSCTL 0x1cc
452 struct pci_dev *cpu_cfg; 580 struct pci_dev *cpu_cfg;
453 int nodes; 581 int nodes;
454 u32 value = 0; 582 u32 value = 0;
455 u8 ibs_eilvt_off;
456
457 ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
458 583
459 nodes = 0; 584 nodes = 0;
460 cpu_cfg = NULL; 585 cpu_cfg = NULL;
@@ -466,25 +591,75 @@ static int __init_ibs_nmi(void)
466 break; 591 break;
467 ++nodes; 592 ++nodes;
468 pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off 593 pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
469 | IBSCTL_LVTOFFSETVAL); 594 | IBSCTL_LVT_OFFSET_VALID);
470 pci_read_config_dword(cpu_cfg, IBSCTL, &value); 595 pci_read_config_dword(cpu_cfg, IBSCTL, &value);
471 if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { 596 if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
472 pci_dev_put(cpu_cfg); 597 pci_dev_put(cpu_cfg);
473 printk(KERN_DEBUG "Failed to setup IBS LVT offset, " 598 printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
474 "IBSCTL = 0x%08x", value); 599 "IBSCTL = 0x%08x\n", value);
475 return 1; 600 return -EINVAL;
476 } 601 }
477 } while (1); 602 } while (1);
478 603
479 if (!nodes) { 604 if (!nodes) {
480 printk(KERN_DEBUG "No CPU node configured for IBS"); 605 printk(KERN_DEBUG "No CPU node configured for IBS\n");
481 return 1; 606 return -ENODEV;
607 }
608
609 return 0;
610}
611
612/*
613 * This runs only on the current cpu. We try to find an LVT offset and
614 * setup the local APIC. For this we must disable preemption. On
615 * success we initialize all nodes with this offset. This updates then
616 * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
617 * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_-
618 * amd_cpu_shutdown() using the new offset.
619 */
620static int force_ibs_eilvt_setup(void)
621{
622 int offset;
623 int ret;
624
625 preempt_disable();
626 /* find the next free available EILVT entry, skip offset 0 */
627 for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
628 if (get_eilvt(offset))
629 break;
630 }
631 preempt_enable();
632
633 if (offset == APIC_EILVT_NR_MAX) {
634 printk(KERN_DEBUG "No EILVT entry available\n");
635 return -EBUSY;
482 } 636 }
483 637
638 ret = setup_ibs_ctl(offset);
639 if (ret)
640 goto out;
641
642 if (!ibs_eilvt_valid()) {
643 ret = -EFAULT;
644 goto out;
645 }
646
647 pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
648 pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
649
484 return 0; 650 return 0;
651out:
652 preempt_disable();
653 put_eilvt(offset);
654 preempt_enable();
655 return ret;
485} 656}
486 657
487/* initialize the APIC for the IBS interrupts if available */ 658/*
659 * check and reserve APIC extended interrupt LVT offset for IBS if
660 * available
661 */
662
488static void init_ibs(void) 663static void init_ibs(void)
489{ 664{
490 ibs_caps = get_ibs_caps(); 665 ibs_caps = get_ibs_caps();
@@ -492,13 +667,18 @@ static void init_ibs(void)
492 if (!ibs_caps) 667 if (!ibs_caps)
493 return; 668 return;
494 669
495 if (__init_ibs_nmi()) { 670 if (ibs_eilvt_valid())
496 ibs_caps = 0; 671 goto out;
497 return; 672
498 } 673 if (!force_ibs_eilvt_setup())
674 goto out;
499 675
500 printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", 676 /* Failed to setup ibs */
501 (unsigned)ibs_caps); 677 ibs_caps = 0;
678 return;
679
680out:
681 printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
502} 682}
503 683
504static int (*create_arch_files)(struct super_block *sb, struct dentry *root); 684static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
@@ -521,44 +701,60 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
521 /* model specific files */ 701 /* model specific files */
522 702
523 /* setup some reasonable defaults */ 703 /* setup some reasonable defaults */
704 memset(&ibs_config, 0, sizeof(ibs_config));
524 ibs_config.max_cnt_fetch = 250000; 705 ibs_config.max_cnt_fetch = 250000;
525 ibs_config.fetch_enabled = 0;
526 ibs_config.max_cnt_op = 250000; 706 ibs_config.max_cnt_op = 250000;
527 ibs_config.op_enabled = 0; 707
528 ibs_config.dispatched_ops = 0; 708 if (ibs_caps & IBS_CAPS_FETCHSAM) {
529 709 dir = oprofilefs_mkdir(sb, root, "ibs_fetch");
530 dir = oprofilefs_mkdir(sb, root, "ibs_fetch"); 710 oprofilefs_create_ulong(sb, dir, "enable",
531 oprofilefs_create_ulong(sb, dir, "enable", 711 &ibs_config.fetch_enabled);
532 &ibs_config.fetch_enabled); 712 oprofilefs_create_ulong(sb, dir, "max_count",
533 oprofilefs_create_ulong(sb, dir, "max_count", 713 &ibs_config.max_cnt_fetch);
534 &ibs_config.max_cnt_fetch); 714 oprofilefs_create_ulong(sb, dir, "rand_enable",
535 oprofilefs_create_ulong(sb, dir, "rand_enable", 715 &ibs_config.rand_en);
536 &ibs_config.rand_en); 716 }
537 717
538 dir = oprofilefs_mkdir(sb, root, "ibs_op"); 718 if (ibs_caps & IBS_CAPS_OPSAM) {
539 oprofilefs_create_ulong(sb, dir, "enable", 719 dir = oprofilefs_mkdir(sb, root, "ibs_op");
540 &ibs_config.op_enabled); 720 oprofilefs_create_ulong(sb, dir, "enable",
541 oprofilefs_create_ulong(sb, dir, "max_count", 721 &ibs_config.op_enabled);
542 &ibs_config.max_cnt_op); 722 oprofilefs_create_ulong(sb, dir, "max_count",
543 if (ibs_caps & IBS_CAPS_OPCNT) 723 &ibs_config.max_cnt_op);
544 oprofilefs_create_ulong(sb, dir, "dispatched_ops", 724 if (ibs_caps & IBS_CAPS_OPCNT)
545 &ibs_config.dispatched_ops); 725 oprofilefs_create_ulong(sb, dir, "dispatched_ops",
726 &ibs_config.dispatched_ops);
727 if (ibs_caps & IBS_CAPS_BRNTRGT)
728 oprofilefs_create_ulong(sb, dir, "branch_target",
729 &ibs_config.branch_target);
730 }
546 731
547 return 0; 732 return 0;
548} 733}
549 734
735struct op_x86_model_spec op_amd_spec;
736
550static int op_amd_init(struct oprofile_operations *ops) 737static int op_amd_init(struct oprofile_operations *ops)
551{ 738{
552 init_ibs(); 739 init_ibs();
553 create_arch_files = ops->create_files; 740 create_arch_files = ops->create_files;
554 ops->create_files = setup_ibs_files; 741 ops->create_files = setup_ibs_files;
742
743 if (boot_cpu_data.x86 == 0x15) {
744 num_counters = NUM_COUNTERS_F15H;
745 } else {
746 num_counters = NUM_COUNTERS;
747 }
748
749 op_amd_spec.num_counters = num_counters;
750 op_amd_spec.num_controls = num_counters;
751 op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS);
752
555 return 0; 753 return 0;
556} 754}
557 755
558struct op_x86_model_spec op_amd_spec = { 756struct op_x86_model_spec op_amd_spec = {
559 .num_counters = NUM_COUNTERS, 757 /* num_counters/num_controls filled in at runtime */
560 .num_controls = NUM_COUNTERS,
561 .num_virt_counters = NUM_VIRT_COUNTERS,
562 .reserved = MSR_AMD_EVENTSEL_RESERVED, 758 .reserved = MSR_AMD_EVENTSEL_RESERVED,
563 .event_mask = OP_EVENT_MASK, 759 .event_mask = OP_EVENT_MASK,
564 .init = op_amd_init, 760 .init = op_amd_init,