aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/oprofile
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2009-05-25 09:10:32 -0400
committerRobert Richter <robert.richter@amd.com>2009-06-11 13:42:14 -0400
commit3370d358569755625aba4d9a846a040ce691d9ed (patch)
tree97b712208843a33dd29d1bfd9f90bc8aec30a595 /arch/x86/oprofile
parentef8828ddf828174785421af67c281144d4b8e796 (diff)
x86/oprofile: replace macros to calculate control register
This patch introduces op_x86_get_ctrl() to calculate the value of the performance control register. This is generic code usable for all models. The event and reserved masks are model specific and stored in struct op_x86_model_spec. 64 bit MSR functions are used now. The patch removes many hard to read macros used for ctrl calculation. The function op_x86_get_ctrl() is common code and the first step to further merge performance counter implementations for x86 models. Signed-off-by: Robert Richter <robert.richter@amd.com>
Diffstat (limited to 'arch/x86/oprofile')
-rw-r--r--arch/x86/oprofile/nmi_int.c20
-rw-r--r--arch/x86/oprofile/op_model_amd.c41
-rw-r--r--arch/x86/oprofile/op_model_ppro.c29
-rw-r--r--arch/x86/oprofile/op_x86_model.h15
4 files changed, 60 insertions, 45 deletions
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index c31f87bbf436..388ee15e0e42 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -31,6 +31,26 @@ static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
31/* 0 == registered but off, 1 == registered and on */ 31/* 0 == registered but off, 1 == registered and on */
32static int nmi_enabled = 0; 32static int nmi_enabled = 0;
33 33
34/* common functions */
35
36u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
37 struct op_counter_config *counter_config)
38{
39 u64 val = 0;
40 u16 event = (u16)counter_config->event;
41
42 val |= ARCH_PERFMON_EVENTSEL_INT;
43 val |= counter_config->user ? ARCH_PERFMON_EVENTSEL_USR : 0;
44 val |= counter_config->kernel ? ARCH_PERFMON_EVENTSEL_OS : 0;
45 val |= (counter_config->unit_mask & 0xFF) << 8;
46 event &= model->event_mask ? model->event_mask : 0xFF;
47 val |= event & 0xFF;
48 val |= (event & 0x0F00) << 24;
49
50 return val;
51}
52
53
34static int profile_exceptions_notify(struct notifier_block *self, 54static int profile_exceptions_notify(struct notifier_block *self,
35 unsigned long val, void *data) 55 unsigned long val, void *data)
36{ 56{
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 86e0a01ba125..2406ab863605 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -25,12 +25,11 @@
25 25
26#define NUM_COUNTERS 4 26#define NUM_COUNTERS 4
27#define NUM_CONTROLS 4 27#define NUM_CONTROLS 4
28#define OP_EVENT_MASK 0x0FFF
29
30#define MSR_AMD_EVENTSEL_RESERVED ((0xFFFFFCF0ULL<<32)|(1ULL<<21))
28 31
29#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) 32#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
30#define CTRL_CLEAR_LO(x) (x &= (1<<21))
31#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
32#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
33#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
34 33
35static unsigned long reset_value[NUM_COUNTERS]; 34static unsigned long reset_value[NUM_COUNTERS];
36 35
@@ -84,21 +83,19 @@ static void op_amd_fill_in_addresses(struct op_msrs * const msrs)
84 } 83 }
85} 84}
86 85
87
88static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, 86static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
89 struct op_msrs const * const msrs) 87 struct op_msrs const * const msrs)
90{ 88{
91 unsigned int low, high; 89 u64 val;
92 int i; 90 int i;
93 91
94 /* clear all counters */ 92 /* clear all counters */
95 for (i = 0 ; i < NUM_CONTROLS; ++i) { 93 for (i = 0 ; i < NUM_CONTROLS; ++i) {
96 if (unlikely(!CTRL_IS_RESERVED(msrs, i))) 94 if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
97 continue; 95 continue;
98 rdmsr(msrs->controls[i].addr, low, high); 96 rdmsrl(msrs->controls[i].addr, val);
99 CTRL_CLEAR_LO(low); 97 val &= model->reserved;
100 CTRL_CLEAR_HI(high); 98 wrmsrl(msrs->controls[i].addr, val);
101 wrmsr(msrs->controls[i].addr, low, high);
102 } 99 }
103 100
104 /* avoid a false detection of ctr overflows in NMI handler */ 101 /* avoid a false detection of ctr overflows in NMI handler */
@@ -112,19 +109,11 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
112 for (i = 0; i < NUM_COUNTERS; ++i) { 109 for (i = 0; i < NUM_COUNTERS; ++i) {
113 if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { 110 if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
114 reset_value[i] = counter_config[i].count; 111 reset_value[i] = counter_config[i].count;
115
116 wrmsr(msrs->counters[i].addr, -(unsigned int)counter_config[i].count, -1); 112 wrmsr(msrs->counters[i].addr, -(unsigned int)counter_config[i].count, -1);
117 113 rdmsrl(msrs->controls[i].addr, val);
118 rdmsr(msrs->controls[i].addr, low, high); 114 val &= model->reserved;
119 CTRL_CLEAR_LO(low); 115 val |= op_x86_get_ctrl(model, &counter_config[i]);
120 CTRL_CLEAR_HI(high); 116 wrmsrl(msrs->controls[i].addr, val);
121 CTRL_SET_ENABLE(low);
122 CTRL_SET_USR(low, counter_config[i].user);
123 CTRL_SET_KERN(low, counter_config[i].kernel);
124 CTRL_SET_UM(low, counter_config[i].unit_mask);
125 CTRL_SET_EVENT_LOW(low, counter_config[i].event);
126 CTRL_SET_EVENT_HIGH(high, counter_config[i].event);
127 wrmsr(msrs->controls[i].addr, low, high);
128 } else { 117 } else {
129 reset_value[i] = 0; 118 reset_value[i] = 0;
130 } 119 }
@@ -486,14 +475,16 @@ static void op_amd_exit(void) {}
486#endif /* CONFIG_OPROFILE_IBS */ 475#endif /* CONFIG_OPROFILE_IBS */
487 476
488struct op_x86_model_spec const op_amd_spec = { 477struct op_x86_model_spec const op_amd_spec = {
489 .init = op_amd_init,
490 .exit = op_amd_exit,
491 .num_counters = NUM_COUNTERS, 478 .num_counters = NUM_COUNTERS,
492 .num_controls = NUM_CONTROLS, 479 .num_controls = NUM_CONTROLS,
480 .reserved = MSR_AMD_EVENTSEL_RESERVED,
481 .event_mask = OP_EVENT_MASK,
482 .init = op_amd_init,
483 .exit = op_amd_exit,
493 .fill_in_addresses = &op_amd_fill_in_addresses, 484 .fill_in_addresses = &op_amd_fill_in_addresses,
494 .setup_ctrs = &op_amd_setup_ctrs, 485 .setup_ctrs = &op_amd_setup_ctrs,
495 .check_ctrs = &op_amd_check_ctrs, 486 .check_ctrs = &op_amd_check_ctrs,
496 .start = &op_amd_start, 487 .start = &op_amd_start,
497 .stop = &op_amd_stop, 488 .stop = &op_amd_stop,
498 .shutdown = &op_amd_shutdown 489 .shutdown = &op_amd_shutdown,
499}; 490};
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index 40b44ee521d5..3092f998baf2 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -10,6 +10,7 @@
10 * @author Philippe Elie 10 * @author Philippe Elie
11 * @author Graydon Hoare 11 * @author Graydon Hoare
12 * @author Andi Kleen 12 * @author Andi Kleen
13 * @author Robert Richter <robert.richter@amd.com>
13 */ 14 */
14 15
15#include <linux/oprofile.h> 16#include <linux/oprofile.h>
@@ -26,8 +27,8 @@ static int num_counters = 2;
26static int counter_width = 32; 27static int counter_width = 32;
27 28
28#define CTR_OVERFLOWED(n) (!((n) & (1ULL<<(counter_width-1)))) 29#define CTR_OVERFLOWED(n) (!((n) & (1ULL<<(counter_width-1))))
29#define CTRL_CLEAR(x) (x &= (1<<21)) 30
30#define CTRL_SET_EVENT(val, e) (val |= e) 31#define MSR_PPRO_EVENTSEL_RESERVED ((0xFFFFFFFFULL<<32)|(1ULL<<21))
31 32
32static u64 *reset_value; 33static u64 *reset_value;
33 34
@@ -54,7 +55,7 @@ static void ppro_fill_in_addresses(struct op_msrs * const msrs)
54static void ppro_setup_ctrs(struct op_x86_model_spec const *model, 55static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
55 struct op_msrs const * const msrs) 56 struct op_msrs const * const msrs)
56{ 57{
57 unsigned int low, high; 58 u64 val;
58 int i; 59 int i;
59 60
60 if (!reset_value) { 61 if (!reset_value) {
@@ -85,9 +86,9 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
85 for (i = 0 ; i < num_counters; ++i) { 86 for (i = 0 ; i < num_counters; ++i) {
86 if (unlikely(!CTRL_IS_RESERVED(msrs, i))) 87 if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
87 continue; 88 continue;
88 rdmsr(msrs->controls[i].addr, low, high); 89 rdmsrl(msrs->controls[i].addr, val);
89 CTRL_CLEAR(low); 90 val &= model->reserved;
90 wrmsr(msrs->controls[i].addr, low, high); 91 wrmsrl(msrs->controls[i].addr, val);
91 } 92 }
92 93
93 /* avoid a false detection of ctr overflows in NMI handler */ 94 /* avoid a false detection of ctr overflows in NMI handler */
@@ -101,17 +102,11 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
101 for (i = 0; i < num_counters; ++i) { 102 for (i = 0; i < num_counters; ++i) {
102 if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { 103 if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
103 reset_value[i] = counter_config[i].count; 104 reset_value[i] = counter_config[i].count;
104
105 wrmsrl(msrs->counters[i].addr, -reset_value[i]); 105 wrmsrl(msrs->counters[i].addr, -reset_value[i]);
106 106 rdmsrl(msrs->controls[i].addr, val);
107 rdmsr(msrs->controls[i].addr, low, high); 107 val &= model->reserved;
108 CTRL_CLEAR(low); 108 val |= op_x86_get_ctrl(model, &counter_config[i]);
109 CTRL_SET_ENABLE(low); 109 wrmsrl(msrs->controls[i].addr, val);
110 CTRL_SET_USR(low, counter_config[i].user);
111 CTRL_SET_KERN(low, counter_config[i].kernel);
112 CTRL_SET_UM(low, counter_config[i].unit_mask);
113 CTRL_SET_EVENT(low, counter_config[i].event);
114 wrmsr(msrs->controls[i].addr, low, high);
115 } else { 110 } else {
116 reset_value[i] = 0; 111 reset_value[i] = 0;
117 } 112 }
@@ -205,6 +200,7 @@ static void ppro_shutdown(struct op_msrs const * const msrs)
205struct op_x86_model_spec const op_ppro_spec = { 200struct op_x86_model_spec const op_ppro_spec = {
206 .num_counters = 2, 201 .num_counters = 2,
207 .num_controls = 2, 202 .num_controls = 2,
203 .reserved = MSR_PPRO_EVENTSEL_RESERVED,
208 .fill_in_addresses = &ppro_fill_in_addresses, 204 .fill_in_addresses = &ppro_fill_in_addresses,
209 .setup_ctrs = &ppro_setup_ctrs, 205 .setup_ctrs = &ppro_setup_ctrs,
210 .check_ctrs = &ppro_check_ctrs, 206 .check_ctrs = &ppro_check_ctrs,
@@ -249,6 +245,7 @@ static int arch_perfmon_init(struct oprofile_operations *ignore)
249} 245}
250 246
251struct op_x86_model_spec op_arch_perfmon_spec = { 247struct op_x86_model_spec op_arch_perfmon_spec = {
248 .reserved = MSR_PPRO_EVENTSEL_RESERVED,
252 .init = &arch_perfmon_init, 249 .init = &arch_perfmon_init,
253 /* num_counters/num_controls filled in at runtime */ 250 /* num_counters/num_controls filled in at runtime */
254 .fill_in_addresses = &ppro_fill_in_addresses, 251 .fill_in_addresses = &ppro_fill_in_addresses,
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h
index 6161c7f0e7fb..3220d4ce6322 100644
--- a/arch/x86/oprofile/op_x86_model.h
+++ b/arch/x86/oprofile/op_x86_model.h
@@ -6,21 +6,19 @@
6 * @remark Read the file COPYING 6 * @remark Read the file COPYING
7 * 7 *
8 * @author Graydon Hoare 8 * @author Graydon Hoare
9 * @author Robert Richter <robert.richter@amd.com>
9 */ 10 */
10 11
11#ifndef OP_X86_MODEL_H 12#ifndef OP_X86_MODEL_H
12#define OP_X86_MODEL_H 13#define OP_X86_MODEL_H
13 14
15#include <asm/types.h>
14#include <asm/intel_arch_perfmon.h> 16#include <asm/intel_arch_perfmon.h>
15 17
16#define CTR_IS_RESERVED(msrs, c) ((msrs)->counters[(c)].addr ? 1 : 0) 18#define CTR_IS_RESERVED(msrs, c) ((msrs)->counters[(c)].addr ? 1 : 0)
17#define CTRL_IS_RESERVED(msrs, c) ((msrs)->controls[(c)].addr ? 1 : 0) 19#define CTRL_IS_RESERVED(msrs, c) ((msrs)->controls[(c)].addr ? 1 : 0)
18#define CTRL_SET_ACTIVE(val) ((val) |= ARCH_PERFMON_EVENTSEL0_ENABLE) 20#define CTRL_SET_ACTIVE(val) ((val) |= ARCH_PERFMON_EVENTSEL0_ENABLE)
19#define CTRL_SET_ENABLE(val) ((val) |= ARCH_PERFMON_EVENTSEL_INT)
20#define CTRL_SET_INACTIVE(val) ((val) &= ~ARCH_PERFMON_EVENTSEL0_ENABLE) 21#define CTRL_SET_INACTIVE(val) ((val) &= ~ARCH_PERFMON_EVENTSEL0_ENABLE)
21#define CTRL_SET_KERN(val, k) ((val) |= ((k) ? ARCH_PERFMON_EVENTSEL_OS : 0))
22#define CTRL_SET_USR(val, u) ((val) |= ((u) ? ARCH_PERFMON_EVENTSEL_USR : 0))
23#define CTRL_SET_UM(val, m) ((val) |= ((m) << 8))
24 22
25struct op_saved_msr { 23struct op_saved_msr {
26 unsigned int high; 24 unsigned int high;
@@ -39,12 +37,16 @@ struct op_msrs {
39 37
40struct pt_regs; 38struct pt_regs;
41 39
40struct oprofile_operations;
41
42/* The model vtable abstracts the differences between 42/* The model vtable abstracts the differences between
43 * various x86 CPU models' perfctr support. 43 * various x86 CPU models' perfctr support.
44 */ 44 */
45struct op_x86_model_spec { 45struct op_x86_model_spec {
46 unsigned int num_counters; 46 unsigned int num_counters;
47 unsigned int num_controls; 47 unsigned int num_controls;
48 u64 reserved;
49 u16 event_mask;
48 int (*init)(struct oprofile_operations *ops); 50 int (*init)(struct oprofile_operations *ops);
49 void (*exit)(void); 51 void (*exit)(void);
50 void (*fill_in_addresses)(struct op_msrs * const msrs); 52 void (*fill_in_addresses)(struct op_msrs * const msrs);
@@ -57,6 +59,11 @@ struct op_x86_model_spec {
57 void (*shutdown)(struct op_msrs const * const msrs); 59 void (*shutdown)(struct op_msrs const * const msrs);
58}; 60};
59 61
62struct op_counter_config;
63
64extern u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
65 struct op_counter_config *counter_config);
66
60extern struct op_x86_model_spec const op_ppro_spec; 67extern struct op_x86_model_spec const op_ppro_spec;
61extern struct op_x86_model_spec const op_p4_spec; 68extern struct op_x86_model_spec const op_p4_spec;
62extern struct op_x86_model_spec const op_p4_ht2_spec; 69extern struct op_x86_model_spec const op_p4_ht2_spec;