aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2008-07-22 15:09:06 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-26 05:48:13 -0400
commit852402cc27bfa1200164e9e8dc7f6e5f0a4fbd46 (patch)
tree0194e23373230888de9115f5ffaacb09e005b57a
parent6aa360e6c16c145edf1837690e0f7aaea6b86ef3 (diff)
x86/oprofile: add CONFIG_OPROFILE_IBS option
Signed-off-by: Robert Richter <robert.richter@amd.com> Cc: oprofile-list <oprofile-list@lists.sourceforge.net> Cc: Robert Richter <robert.richter@amd.com> Cc: Barry Kasindorf <barry.kasindorf@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/Kconfig14
-rw-r--r--arch/x86/oprofile/op_model_athlon.c33
-rw-r--r--drivers/oprofile/buffer_sync.c6
-rw-r--r--drivers/oprofile/cpu_buffer.c4
4 files changed, 47 insertions, 10 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index b0fabfa864ff..2651af48b2e5 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -13,6 +13,20 @@ config OPROFILE
13 13
14 If unsure, say N. 14 If unsure, say N.
15 15
16config OPROFILE_IBS
17 bool "OProfile AMD IBS support (EXPERIMENTAL)"
18 default n
19 depends on OPROFILE && SMP && X86
20 help
21 Instruction-Based Sampling (IBS) is a new profiling
22 technique that provides rich, precise program performance
23 information. IBS is introduced by AMD Family10h processors
24 (AMD Opteron Quad-Core processor “Barcelona”) to overcome
25 the limitations of conventional performance counter
26 sampling.
27
28 If unsure, say N.
29
16config HAVE_OPROFILE 30config HAVE_OPROFILE
17 def_bool n 31 def_bool n
18 32
diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c
index 9c8c8c583132..fb6015c1132b 100644
--- a/arch/x86/oprofile/op_model_athlon.c
+++ b/arch/x86/oprofile/op_model_athlon.c
@@ -47,6 +47,10 @@
47#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) 47#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9))
48#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) 48#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
49 49
50static unsigned long reset_value[NUM_COUNTERS];
51
52#ifdef CONFIG_OPROFILE_IBS
53
50/* IbsFetchCtl bits/masks */ 54/* IbsFetchCtl bits/masks */
51#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ 55#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */
52#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ 56#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */
@@ -104,7 +108,6 @@ struct ibs_op_sample {
104*/ 108*/
105static void clear_ibs_nmi(void); 109static void clear_ibs_nmi(void);
106 110
107static unsigned long reset_value[NUM_COUNTERS];
108static int ibs_allowed; /* AMD Family10h and later */ 111static int ibs_allowed; /* AMD Family10h and later */
109 112
110struct op_ibs_config { 113struct op_ibs_config {
@@ -118,6 +121,8 @@ struct op_ibs_config {
118 121
119static struct op_ibs_config ibs_config; 122static struct op_ibs_config ibs_config;
120 123
124#endif
125
121/* functions for op_amd_spec */ 126/* functions for op_amd_spec */
122 127
123static void op_amd_fill_in_addresses(struct op_msrs * const msrs) 128static void op_amd_fill_in_addresses(struct op_msrs * const msrs)
@@ -188,6 +193,8 @@ static void op_amd_setup_ctrs(struct op_msrs const * const msrs)
188 } 193 }
189} 194}
190 195
196#ifdef CONFIG_OPROFILE_IBS
197
191static inline int 198static inline int
192op_amd_handle_ibs(struct pt_regs * const regs, 199op_amd_handle_ibs(struct pt_regs * const regs,
193 struct op_msrs const * const msrs) 200 struct op_msrs const * const msrs)
@@ -261,6 +268,8 @@ op_amd_handle_ibs(struct pt_regs * const regs,
261 return 1; 268 return 1;
262} 269}
263 270
271#endif
272
264static int op_amd_check_ctrs(struct pt_regs * const regs, 273static int op_amd_check_ctrs(struct pt_regs * const regs,
265 struct op_msrs const * const msrs) 274 struct op_msrs const * const msrs)
266{ 275{
@@ -277,7 +286,9 @@ static int op_amd_check_ctrs(struct pt_regs * const regs,
277 } 286 }
278 } 287 }
279 288
289#ifdef CONFIG_OPROFILE_IBS
280 op_amd_handle_ibs(regs, msrs); 290 op_amd_handle_ibs(regs, msrs);
291#endif
281 292
282 /* See op_model_ppro.c */ 293 /* See op_model_ppro.c */
283 return 1; 294 return 1;
@@ -294,6 +305,8 @@ static void op_amd_start(struct op_msrs const * const msrs)
294 CTRL_WRITE(low, high, msrs, i); 305 CTRL_WRITE(low, high, msrs, i);
295 } 306 }
296 } 307 }
308
309#ifdef CONFIG_OPROFILE_IBS
297 if (ibs_allowed && ibs_config.fetch_enabled) { 310 if (ibs_allowed && ibs_config.fetch_enabled) {
298 low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; 311 low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
299 high = IBS_FETCH_HIGH_ENABLE; 312 high = IBS_FETCH_HIGH_ENABLE;
@@ -305,6 +318,7 @@ static void op_amd_start(struct op_msrs const * const msrs)
305 high = 0; 318 high = 0;
306 wrmsr(MSR_AMD64_IBSOPCTL, low, high); 319 wrmsr(MSR_AMD64_IBSOPCTL, low, high);
307 } 320 }
321#endif
308} 322}
309 323
310 324
@@ -323,6 +337,7 @@ static void op_amd_stop(struct op_msrs const * const msrs)
323 CTRL_WRITE(low, high, msrs, i); 337 CTRL_WRITE(low, high, msrs, i);
324 } 338 }
325 339
340#ifdef CONFIG_OPROFILE_IBS
326 if (ibs_allowed && ibs_config.fetch_enabled) { 341 if (ibs_allowed && ibs_config.fetch_enabled) {
327 low = 0; /* clear max count and enable */ 342 low = 0; /* clear max count and enable */
328 high = 0; 343 high = 0;
@@ -334,6 +349,7 @@ static void op_amd_stop(struct op_msrs const * const msrs)
334 high = 0; 349 high = 0;
335 wrmsr(MSR_AMD64_IBSOPCTL, low, high); 350 wrmsr(MSR_AMD64_IBSOPCTL, low, high);
336 } 351 }
352#endif
337} 353}
338 354
339static void op_amd_shutdown(struct op_msrs const * const msrs) 355static void op_amd_shutdown(struct op_msrs const * const msrs)
@@ -350,17 +366,10 @@ static void op_amd_shutdown(struct op_msrs const * const msrs)
350 } 366 }
351} 367}
352 368
353#ifndef CONFIG_SMP 369#ifndef CONFIG_OPROFILE_IBS
354 370
355/* no IBS support */ 371/* no IBS support */
356 372
357static void setup_ibs(void)
358{
359 ibs_allowed = 0;
360}
361
362static void clear_ibs_nmi(void) {}
363
364static int op_amd_init(struct oprofile_operations *ops) 373static int op_amd_init(struct oprofile_operations *ops)
365{ 374{
366 return 0; 375 return 0;
@@ -441,8 +450,12 @@ static void setup_ibs(void)
441 if (!ibs_allowed) 450 if (!ibs_allowed)
442 return; 451 return;
443 452
444 if (pfm_amd64_setup_eilvt()) 453 if (pfm_amd64_setup_eilvt()) {
445 ibs_allowed = 0; 454 ibs_allowed = 0;
455 return;
456 }
457
458 printk(KERN_INFO "oprofile: AMD IBS detected\n");
446} 459}
447 460
448 461
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index e1782d2df09f..ed982273fb8b 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -328,6 +328,8 @@ static void add_trace_begin(void)
328 add_event_entry(TRACE_BEGIN_CODE); 328 add_event_entry(TRACE_BEGIN_CODE);
329} 329}
330 330
331#ifdef CONFIG_OPROFILE_IBS
332
331#define IBS_FETCH_CODE_SIZE 2 333#define IBS_FETCH_CODE_SIZE 2
332#define IBS_OP_CODE_SIZE 5 334#define IBS_OP_CODE_SIZE 5
333#define IBS_EIP(offset) \ 335#define IBS_EIP(offset) \
@@ -390,6 +392,8 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
390 } 392 }
391} 393}
392 394
395#endif
396
393static void add_sample_entry(unsigned long offset, unsigned long event) 397static void add_sample_entry(unsigned long offset, unsigned long event)
394{ 398{
395 add_event_entry(offset); 399 add_event_entry(offset);
@@ -586,6 +590,7 @@ void sync_buffer(int cpu)
586 } else if (s->event == CPU_TRACE_BEGIN) { 590 } else if (s->event == CPU_TRACE_BEGIN) {
587 state = sb_bt_start; 591 state = sb_bt_start;
588 add_trace_begin(); 592 add_trace_begin();
593#ifdef CONFIG_OPROFILE_IBS
589 } else if (s->event == IBS_FETCH_BEGIN) { 594 } else if (s->event == IBS_FETCH_BEGIN) {
590 state = sb_bt_start; 595 state = sb_bt_start;
591 add_ibs_begin(cpu_buf, 596 add_ibs_begin(cpu_buf,
@@ -594,6 +599,7 @@ void sync_buffer(int cpu)
594 state = sb_bt_start; 599 state = sb_bt_start;
595 add_ibs_begin(cpu_buf, 600 add_ibs_begin(cpu_buf,
596 IBS_OP_CODE, in_kernel, mm); 601 IBS_OP_CODE, in_kernel, mm);
602#endif
597 } else { 603 } else {
598 struct mm_struct *oldmm = mm; 604 struct mm_struct *oldmm = mm;
599 605
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index c9ac4e156918..aba905b3afb8 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -253,6 +253,8 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
253 oprofile_add_ext_sample(pc, regs, event, is_kernel); 253 oprofile_add_ext_sample(pc, regs, event, is_kernel);
254} 254}
255 255
256#ifdef CONFIG_OPROFILE_IBS
257
256#define MAX_IBS_SAMPLE_SIZE 14 258#define MAX_IBS_SAMPLE_SIZE 14
257static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf, 259static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
258 unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code) 260 unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code)
@@ -318,6 +320,8 @@ void oprofile_add_ibs_sample(struct pt_regs *const regs,
318 oprofile_ops.backtrace(regs, backtrace_depth); 320 oprofile_ops.backtrace(regs, backtrace_depth);
319} 321}
320 322
323#endif
324
321void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) 325void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
322{ 326{
323 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); 327 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);