aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2009-01-08 08:27:34 -0500
committerRobert Richter <robert.richter@amd.com>2009-01-08 08:27:34 -0500
commitd2852b932f0bb5e89177aa27c7bcf07f4167e129 (patch)
tree96d975ae155ba307acd07968939fff22afedddf7 /arch/x86
parent4a6908a3a050aacc9c3a2f36b276b46c0629ad91 (diff)
parent14f0ca8eaea42a5b5a69cfcb699665dd2618db5f (diff)
Merge branch 'oprofile/ring_buffer' into oprofile/oprofile-for-tip
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/oprofile/op_model_amd.c224
1 files changed, 91 insertions, 133 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 509513760a6e..8fdf06e4edf9 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -2,7 +2,7 @@
2 * @file op_model_amd.c 2 * @file op_model_amd.c
3 * athlon / K7 / K8 / Family 10h model-specific MSR operations 3 * athlon / K7 / K8 / Family 10h model-specific MSR operations
4 * 4 *
5 * @remark Copyright 2002-2008 OProfile authors 5 * @remark Copyright 2002-2009 OProfile authors
6 * @remark Read the file COPYING 6 * @remark Read the file COPYING
7 * 7 *
8 * @author John Levon 8 * @author John Levon
@@ -10,7 +10,7 @@
10 * @author Graydon Hoare 10 * @author Graydon Hoare
11 * @author Robert Richter <robert.richter@amd.com> 11 * @author Robert Richter <robert.richter@amd.com>
12 * @author Barry Kasindorf 12 * @author Barry Kasindorf
13*/ 13 */
14 14
15#include <linux/oprofile.h> 15#include <linux/oprofile.h>
16#include <linux/device.h> 16#include <linux/device.h>
@@ -60,56 +60,10 @@ static unsigned long reset_value[NUM_COUNTERS];
60#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ 60#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */
61#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ 61#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */
62 62
63/* Codes used in cpu_buffer.c */ 63#define IBS_FETCH_SIZE 6
64/* This produces duplicate code, need to be fixed */ 64#define IBS_OP_SIZE 12
65#define IBS_FETCH_BEGIN 3
66#define IBS_OP_BEGIN 4
67
68/* The function interface needs to be fixed, something like add
69 data. Should then be added to linux/oprofile.h. */
70extern void
71oprofile_add_ibs_sample(struct pt_regs *const regs,
72 unsigned int *const ibs_sample, int ibs_code);
73
74struct ibs_fetch_sample {
75 /* MSRC001_1031 IBS Fetch Linear Address Register */
76 unsigned int ibs_fetch_lin_addr_low;
77 unsigned int ibs_fetch_lin_addr_high;
78 /* MSRC001_1030 IBS Fetch Control Register */
79 unsigned int ibs_fetch_ctl_low;
80 unsigned int ibs_fetch_ctl_high;
81 /* MSRC001_1032 IBS Fetch Physical Address Register */
82 unsigned int ibs_fetch_phys_addr_low;
83 unsigned int ibs_fetch_phys_addr_high;
84};
85
86struct ibs_op_sample {
87 /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */
88 unsigned int ibs_op_rip_low;
89 unsigned int ibs_op_rip_high;
90 /* MSRC001_1035 IBS Op Data Register */
91 unsigned int ibs_op_data1_low;
92 unsigned int ibs_op_data1_high;
93 /* MSRC001_1036 IBS Op Data 2 Register */
94 unsigned int ibs_op_data2_low;
95 unsigned int ibs_op_data2_high;
96 /* MSRC001_1037 IBS Op Data 3 Register */
97 unsigned int ibs_op_data3_low;
98 unsigned int ibs_op_data3_high;
99 /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */
100 unsigned int ibs_dc_linear_low;
101 unsigned int ibs_dc_linear_high;
102 /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */
103 unsigned int ibs_dc_phys_low;
104 unsigned int ibs_dc_phys_high;
105};
106
107/*
108 * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+
109*/
110static void clear_ibs_nmi(void);
111 65
112static int ibs_allowed; /* AMD Family10h and later */ 66static int has_ibs; /* AMD Family10h and later */
113 67
114struct op_ibs_config { 68struct op_ibs_config {
115 unsigned long op_enabled; 69 unsigned long op_enabled;
@@ -200,31 +154,29 @@ static inline int
200op_amd_handle_ibs(struct pt_regs * const regs, 154op_amd_handle_ibs(struct pt_regs * const regs,
201 struct op_msrs const * const msrs) 155 struct op_msrs const * const msrs)
202{ 156{
203 unsigned int low, high; 157 u32 low, high;
204 struct ibs_fetch_sample ibs_fetch; 158 u64 msr;
205 struct ibs_op_sample ibs_op; 159 struct op_entry entry;
206 160
207 if (!ibs_allowed) 161 if (!has_ibs)
208 return 1; 162 return 1;
209 163
210 if (ibs_config.fetch_enabled) { 164 if (ibs_config.fetch_enabled) {
211 rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); 165 rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
212 if (high & IBS_FETCH_HIGH_VALID_BIT) { 166 if (high & IBS_FETCH_HIGH_VALID_BIT) {
213 ibs_fetch.ibs_fetch_ctl_high = high; 167 rdmsrl(MSR_AMD64_IBSFETCHLINAD, msr);
214 ibs_fetch.ibs_fetch_ctl_low = low; 168 oprofile_write_reserve(&entry, regs, msr,
215 rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); 169 IBS_FETCH_CODE, IBS_FETCH_SIZE);
216 ibs_fetch.ibs_fetch_lin_addr_high = high; 170 oprofile_add_data(&entry, (u32)msr);
217 ibs_fetch.ibs_fetch_lin_addr_low = low; 171 oprofile_add_data(&entry, (u32)(msr >> 32));
218 rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); 172 oprofile_add_data(&entry, low);
219 ibs_fetch.ibs_fetch_phys_addr_high = high; 173 oprofile_add_data(&entry, high);
220 ibs_fetch.ibs_fetch_phys_addr_low = low; 174 rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, msr);
221 175 oprofile_add_data(&entry, (u32)msr);
222 oprofile_add_ibs_sample(regs, 176 oprofile_add_data(&entry, (u32)(msr >> 32));
223 (unsigned int *)&ibs_fetch, 177 oprofile_write_commit(&entry);
224 IBS_FETCH_BEGIN); 178
225 179 /* reenable the IRQ */
226 /*reenable the IRQ */
227 rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
228 high &= ~IBS_FETCH_HIGH_VALID_BIT; 180 high &= ~IBS_FETCH_HIGH_VALID_BIT;
229 high |= IBS_FETCH_HIGH_ENABLE; 181 high |= IBS_FETCH_HIGH_ENABLE;
230 low &= IBS_FETCH_LOW_MAX_CNT_MASK; 182 low &= IBS_FETCH_LOW_MAX_CNT_MASK;
@@ -235,30 +187,29 @@ op_amd_handle_ibs(struct pt_regs * const regs,
235 if (ibs_config.op_enabled) { 187 if (ibs_config.op_enabled) {
236 rdmsr(MSR_AMD64_IBSOPCTL, low, high); 188 rdmsr(MSR_AMD64_IBSOPCTL, low, high);
237 if (low & IBS_OP_LOW_VALID_BIT) { 189 if (low & IBS_OP_LOW_VALID_BIT) {
238 rdmsr(MSR_AMD64_IBSOPRIP, low, high); 190 rdmsrl(MSR_AMD64_IBSOPRIP, msr);
239 ibs_op.ibs_op_rip_low = low; 191 oprofile_write_reserve(&entry, regs, msr,
240 ibs_op.ibs_op_rip_high = high; 192 IBS_OP_CODE, IBS_OP_SIZE);
241 rdmsr(MSR_AMD64_IBSOPDATA, low, high); 193 oprofile_add_data(&entry, (u32)msr);
242 ibs_op.ibs_op_data1_low = low; 194 oprofile_add_data(&entry, (u32)(msr >> 32));
243 ibs_op.ibs_op_data1_high = high; 195 rdmsrl(MSR_AMD64_IBSOPDATA, msr);
244 rdmsr(MSR_AMD64_IBSOPDATA2, low, high); 196 oprofile_add_data(&entry, (u32)msr);
245 ibs_op.ibs_op_data2_low = low; 197 oprofile_add_data(&entry, (u32)(msr >> 32));
246 ibs_op.ibs_op_data2_high = high; 198 rdmsrl(MSR_AMD64_IBSOPDATA2, msr);
247 rdmsr(MSR_AMD64_IBSOPDATA3, low, high); 199 oprofile_add_data(&entry, (u32)msr);
248 ibs_op.ibs_op_data3_low = low; 200 oprofile_add_data(&entry, (u32)(msr >> 32));
249 ibs_op.ibs_op_data3_high = high; 201 rdmsrl(MSR_AMD64_IBSOPDATA3, msr);
250 rdmsr(MSR_AMD64_IBSDCLINAD, low, high); 202 oprofile_add_data(&entry, (u32)msr);
251 ibs_op.ibs_dc_linear_low = low; 203 oprofile_add_data(&entry, (u32)(msr >> 32));
252 ibs_op.ibs_dc_linear_high = high; 204 rdmsrl(MSR_AMD64_IBSDCLINAD, msr);
253 rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); 205 oprofile_add_data(&entry, (u32)msr);
254 ibs_op.ibs_dc_phys_low = low; 206 oprofile_add_data(&entry, (u32)(msr >> 32));
255 ibs_op.ibs_dc_phys_high = high; 207 rdmsrl(MSR_AMD64_IBSDCPHYSAD, msr);
208 oprofile_add_data(&entry, (u32)msr);
209 oprofile_add_data(&entry, (u32)(msr >> 32));
210 oprofile_write_commit(&entry);
256 211
257 /* reenable the IRQ */ 212 /* reenable the IRQ */
258 oprofile_add_ibs_sample(regs,
259 (unsigned int *)&ibs_op,
260 IBS_OP_BEGIN);
261 rdmsr(MSR_AMD64_IBSOPCTL, low, high);
262 high = 0; 213 high = 0;
263 low &= ~IBS_OP_LOW_VALID_BIT; 214 low &= ~IBS_OP_LOW_VALID_BIT;
264 low |= IBS_OP_LOW_ENABLE; 215 low |= IBS_OP_LOW_ENABLE;
@@ -308,14 +259,14 @@ static void op_amd_start(struct op_msrs const * const msrs)
308 } 259 }
309 260
310#ifdef CONFIG_OPROFILE_IBS 261#ifdef CONFIG_OPROFILE_IBS
311 if (ibs_allowed && ibs_config.fetch_enabled) { 262 if (has_ibs && ibs_config.fetch_enabled) {
312 low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; 263 low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
313 high = ((ibs_config.rand_en & 0x1) << 25) /* bit 57 */ 264 high = ((ibs_config.rand_en & 0x1) << 25) /* bit 57 */
314 + IBS_FETCH_HIGH_ENABLE; 265 + IBS_FETCH_HIGH_ENABLE;
315 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); 266 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
316 } 267 }
317 268
318 if (ibs_allowed && ibs_config.op_enabled) { 269 if (has_ibs && ibs_config.op_enabled) {
319 low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) 270 low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF)
320 + ((ibs_config.dispatched_ops & 0x1) << 19) /* bit 19 */ 271 + ((ibs_config.dispatched_ops & 0x1) << 19) /* bit 19 */
321 + IBS_OP_LOW_ENABLE; 272 + IBS_OP_LOW_ENABLE;
@@ -331,8 +282,10 @@ static void op_amd_stop(struct op_msrs const * const msrs)
331 unsigned int low, high; 282 unsigned int low, high;
332 int i; 283 int i;
333 284
334 /* Subtle: stop on all counters to avoid race with 285 /*
335 * setting our pm callback */ 286 * Subtle: stop on all counters to avoid race with setting our
287 * pm callback
288 */
336 for (i = 0 ; i < NUM_COUNTERS ; ++i) { 289 for (i = 0 ; i < NUM_COUNTERS ; ++i) {
337 if (!reset_value[i]) 290 if (!reset_value[i])
338 continue; 291 continue;
@@ -342,14 +295,16 @@ static void op_amd_stop(struct op_msrs const * const msrs)
342 } 295 }
343 296
344#ifdef CONFIG_OPROFILE_IBS 297#ifdef CONFIG_OPROFILE_IBS
345 if (ibs_allowed && ibs_config.fetch_enabled) { 298 if (has_ibs && ibs_config.fetch_enabled) {
346 low = 0; /* clear max count and enable */ 299 /* clear max count and enable */
300 low = 0;
347 high = 0; 301 high = 0;
348 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); 302 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
349 } 303 }
350 304
351 if (ibs_allowed && ibs_config.op_enabled) { 305 if (has_ibs && ibs_config.op_enabled) {
352 low = 0; /* clear max count and enable */ 306 /* clear max count and enable */
307 low = 0;
353 high = 0; 308 high = 0;
354 wrmsr(MSR_AMD64_IBSOPCTL, low, high); 309 wrmsr(MSR_AMD64_IBSOPCTL, low, high);
355 } 310 }
@@ -370,18 +325,7 @@ static void op_amd_shutdown(struct op_msrs const * const msrs)
370 } 325 }
371} 326}
372 327
373#ifndef CONFIG_OPROFILE_IBS 328#ifdef CONFIG_OPROFILE_IBS
374
375/* no IBS support */
376
377static int op_amd_init(struct oprofile_operations *ops)
378{
379 return 0;
380}
381
382static void op_amd_exit(void) {}
383
384#else
385 329
386static u8 ibs_eilvt_off; 330static u8 ibs_eilvt_off;
387 331
@@ -395,7 +339,7 @@ static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
395 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); 339 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
396} 340}
397 341
398static int pfm_amd64_setup_eilvt(void) 342static int init_ibs_nmi(void)
399{ 343{
400#define IBSCTL_LVTOFFSETVAL (1 << 8) 344#define IBSCTL_LVTOFFSETVAL (1 << 8)
401#define IBSCTL 0x1cc 345#define IBSCTL 0x1cc
@@ -419,6 +363,7 @@ static int pfm_amd64_setup_eilvt(void)
419 | IBSCTL_LVTOFFSETVAL); 363 | IBSCTL_LVTOFFSETVAL);
420 pci_read_config_dword(cpu_cfg, IBSCTL, &value); 364 pci_read_config_dword(cpu_cfg, IBSCTL, &value);
421 if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { 365 if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
366 pci_dev_put(cpu_cfg);
422 printk(KERN_DEBUG "Failed to setup IBS LVT offset, " 367 printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
423 "IBSCTL = 0x%08x", value); 368 "IBSCTL = 0x%08x", value);
424 return 1; 369 return 1;
@@ -443,33 +388,35 @@ static int pfm_amd64_setup_eilvt(void)
443 return 0; 388 return 0;
444} 389}
445 390
446/* 391/* uninitialize the APIC for the IBS interrupts if needed */
447 * initialize the APIC for the IBS interrupts 392static void clear_ibs_nmi(void)
448 * if available (AMD Family10h rev B0 and later)
449 */
450static void setup_ibs(void)
451{ 393{
452 ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); 394 if (has_ibs)
395 on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
396}
397
398/* initialize the APIC for the IBS interrupts if available */
399static void ibs_init(void)
400{
401 has_ibs = boot_cpu_has(X86_FEATURE_IBS);
453 402
454 if (!ibs_allowed) 403 if (!has_ibs)
455 return; 404 return;
456 405
457 if (pfm_amd64_setup_eilvt()) { 406 if (init_ibs_nmi()) {
458 ibs_allowed = 0; 407 has_ibs = 0;
459 return; 408 return;
460 } 409 }
461 410
462 printk(KERN_INFO "oprofile: AMD IBS detected\n"); 411 printk(KERN_INFO "oprofile: AMD IBS detected\n");
463} 412}
464 413
465 414static void ibs_exit(void)
466/*
467 * unitialize the APIC for the IBS interrupts if needed on AMD Family10h
468 * rev B0 and later */
469static void clear_ibs_nmi(void)
470{ 415{
471 if (ibs_allowed) 416 if (!has_ibs)
472 on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); 417 return;
418
419 clear_ibs_nmi();
473} 420}
474 421
475static int (*create_arch_files)(struct super_block *sb, struct dentry *root); 422static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
@@ -486,7 +433,7 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
486 if (ret) 433 if (ret)
487 return ret; 434 return ret;
488 435
489 if (!ibs_allowed) 436 if (!has_ibs)
490 return ret; 437 return ret;
491 438
492 /* model specific files */ 439 /* model specific files */
@@ -519,7 +466,7 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
519 466
520static int op_amd_init(struct oprofile_operations *ops) 467static int op_amd_init(struct oprofile_operations *ops)
521{ 468{
522 setup_ibs(); 469 ibs_init();
523 create_arch_files = ops->create_files; 470 create_arch_files = ops->create_files;
524 ops->create_files = setup_ibs_files; 471 ops->create_files = setup_ibs_files;
525 return 0; 472 return 0;
@@ -527,10 +474,21 @@ static int op_amd_init(struct oprofile_operations *ops)
527 474
528static void op_amd_exit(void) 475static void op_amd_exit(void)
529{ 476{
530 clear_ibs_nmi(); 477 ibs_exit();
531} 478}
532 479
533#endif 480#else
481
482/* no IBS support */
483
484static int op_amd_init(struct oprofile_operations *ops)
485{
486 return 0;
487}
488
489static void op_amd_exit(void) {}
490
491#endif /* CONFIG_OPROFILE_IBS */
534 492
535struct op_x86_model_spec const op_amd_spec = { 493struct op_x86_model_spec const op_amd_spec = {
536 .init = op_amd_init, 494 .init = op_amd_init,