diff options
author | Robert Richter <robert.richter@amd.com> | 2010-09-22 11:45:39 -0400 |
---|---|---|
committer | Robert Richter <robert.richter@amd.com> | 2010-10-15 06:50:43 -0400 |
commit | b47fad3bfb5940cc3e28a1c69716f6dc44e4b7e6 (patch) | |
tree | ac665594dee589c38608f2c24ddb2d2f7a39d201 | |
parent | 25da6950475becb35d7a3bb3b5fbdc715a76887e (diff) |
oprofile, x86: Add support for IBS periodic op counter extension
The count value for IBS op sampling has been extended by 7 bits. The
feature is reflected in bit 6 (OpCntExt) of the IBS capability
register (CPUID Fn8000_001B_EAX).
Signed-off-by: Robert Richter <robert.richter@amd.com>
-rw-r--r-- | arch/x86/include/asm/perf_event.h | 19 | ||||
-rw-r--r-- | arch/x86/oprofile/op_model_amd.c | 22 |
2 files changed, 29 insertions, 12 deletions
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 6e742cc4251b..550e26b1dbb3 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h | |||
@@ -111,17 +111,18 @@ union cpuid10_edx { | |||
111 | #define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) | 111 | #define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) |
112 | 112 | ||
113 | /* IbsFetchCtl bits/masks */ | 113 | /* IbsFetchCtl bits/masks */ |
114 | #define IBS_FETCH_RAND_EN (1ULL<<57) | 114 | #define IBS_FETCH_RAND_EN (1ULL<<57) |
115 | #define IBS_FETCH_VAL (1ULL<<49) | 115 | #define IBS_FETCH_VAL (1ULL<<49) |
116 | #define IBS_FETCH_ENABLE (1ULL<<48) | 116 | #define IBS_FETCH_ENABLE (1ULL<<48) |
117 | #define IBS_FETCH_CNT 0xFFFF0000ULL | 117 | #define IBS_FETCH_CNT 0xFFFF0000ULL |
118 | #define IBS_FETCH_MAX_CNT 0x0000FFFFULL | 118 | #define IBS_FETCH_MAX_CNT 0x0000FFFFULL |
119 | 119 | ||
120 | /* IbsOpCtl bits */ | 120 | /* IbsOpCtl bits */ |
121 | #define IBS_OP_CNT_CTL (1ULL<<19) | 121 | #define IBS_OP_CNT_CTL (1ULL<<19) |
122 | #define IBS_OP_VAL (1ULL<<18) | 122 | #define IBS_OP_VAL (1ULL<<18) |
123 | #define IBS_OP_ENABLE (1ULL<<17) | 123 | #define IBS_OP_ENABLE (1ULL<<17) |
124 | #define IBS_OP_MAX_CNT 0x0000FFFFULL | 124 | #define IBS_OP_MAX_CNT 0x0000FFFFULL |
125 | #define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */ | ||
125 | 126 | ||
126 | #ifdef CONFIG_PERF_EVENTS | 127 | #ifdef CONFIG_PERF_EVENTS |
127 | extern void init_hw_perf_events(void); | 128 | extern void init_hw_perf_events(void); |
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9de33fa9531a..65f0a1eb6b86 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -83,6 +83,7 @@ static struct ibs_state ibs_state; | |||
83 | #define IBS_CAPS_RDWROPCNT (1U<<3) | 83 | #define IBS_CAPS_RDWROPCNT (1U<<3) |
84 | #define IBS_CAPS_OPCNT (1U<<4) | 84 | #define IBS_CAPS_OPCNT (1U<<4) |
85 | #define IBS_CAPS_BRNTRGT (1U<<5) | 85 | #define IBS_CAPS_BRNTRGT (1U<<5) |
86 | #define IBS_CAPS_OPCNTEXT (1U<<6) | ||
86 | 87 | ||
87 | #define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ | 88 | #define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ |
88 | | IBS_CAPS_FETCHSAM \ | 89 | | IBS_CAPS_FETCHSAM \ |
@@ -246,8 +247,16 @@ static inline void op_amd_start_ibs(void) | |||
246 | 247 | ||
247 | memset(&ibs_state, 0, sizeof(ibs_state)); | 248 | memset(&ibs_state, 0, sizeof(ibs_state)); |
248 | 249 | ||
250 | /* | ||
251 | * Note: Since the max count settings may out of range we | ||
252 | * write back the actual used values so that userland can read | ||
253 | * it. | ||
254 | */ | ||
255 | |||
249 | if (ibs_config.fetch_enabled) { | 256 | if (ibs_config.fetch_enabled) { |
250 | val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT; | 257 | val = ibs_config.max_cnt_fetch >> 4; |
258 | val = min(val, IBS_FETCH_MAX_CNT); | ||
259 | ibs_config.max_cnt_fetch = val << 4; | ||
251 | val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0; | 260 | val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0; |
252 | val |= IBS_FETCH_ENABLE; | 261 | val |= IBS_FETCH_ENABLE; |
253 | wrmsrl(MSR_AMD64_IBSFETCHCTL, val); | 262 | wrmsrl(MSR_AMD64_IBSFETCHCTL, val); |
@@ -261,6 +270,7 @@ static inline void op_amd_start_ibs(void) | |||
261 | * op_amd_randomize_ibs_op() for details. | 270 | * op_amd_randomize_ibs_op() for details. |
262 | */ | 271 | */ |
263 | val = clamp(val, 0x0081ULL, 0xFF80ULL); | 272 | val = clamp(val, 0x0081ULL, 0xFF80ULL); |
273 | ibs_config.max_cnt_op = val << 4; | ||
264 | } else { | 274 | } else { |
265 | /* | 275 | /* |
266 | * The start value is randomized with a | 276 | * The start value is randomized with a |
@@ -268,9 +278,15 @@ static inline void op_amd_start_ibs(void) | |||
268 | * with the half of the randomized range. Also | 278 | * with the half of the randomized range. Also |
269 | * avoid underflows. | 279 | * avoid underflows. |
270 | */ | 280 | */ |
271 | val = min(val + IBS_RANDOM_MAXCNT_OFFSET, | 281 | val += IBS_RANDOM_MAXCNT_OFFSET; |
272 | IBS_OP_MAX_CNT); | 282 | if (ibs_caps & IBS_CAPS_OPCNTEXT) |
283 | val = min(val, IBS_OP_MAX_CNT_EXT); | ||
284 | else | ||
285 | val = min(val, IBS_OP_MAX_CNT); | ||
286 | ibs_config.max_cnt_op = | ||
287 | (val - IBS_RANDOM_MAXCNT_OFFSET) << 4; | ||
273 | } | 288 | } |
289 | val = ((val & ~IBS_OP_MAX_CNT) << 4) | (val & IBS_OP_MAX_CNT); | ||
274 | val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0; | 290 | val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0; |
275 | val |= IBS_OP_ENABLE; | 291 | val |= IBS_OP_ENABLE; |
276 | ibs_state.ibs_op_ctl = val; | 292 | ibs_state.ibs_op_ctl = val; |