aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/oprofile/op_model_amd.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 97c84ebe3f24..a9d194734a8e 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -52,7 +52,7 @@ static unsigned long reset_value[NUM_VIRT_COUNTERS];
52#define IBS_FETCH_ENABLE (1ULL<<48) 52#define IBS_FETCH_ENABLE (1ULL<<48)
53#define IBS_FETCH_CNT_MASK 0xFFFF0000ULL 53#define IBS_FETCH_CNT_MASK 0xFFFF0000ULL
54 54
55/*IbsOpCtl bits */ 55/* IbsOpCtl bits */
56#define IBS_OP_CNT_CTL (1ULL<<19) 56#define IBS_OP_CNT_CTL (1ULL<<19)
57#define IBS_OP_VAL (1ULL<<18) 57#define IBS_OP_VAL (1ULL<<18)
58#define IBS_OP_ENABLE (1ULL<<17) 58#define IBS_OP_ENABLE (1ULL<<17)
@@ -72,6 +72,7 @@ struct op_ibs_config {
72}; 72};
73 73
74static struct op_ibs_config ibs_config; 74static struct op_ibs_config ibs_config;
75static u64 ibs_op_ctl;
75 76
76/* 77/*
77 * IBS cpuid feature detection 78 * IBS cpuid feature detection
@@ -84,8 +85,16 @@ static struct op_ibs_config ibs_config;
84 * bit 0 is used to indicate the existence of IBS. 85 * bit 0 is used to indicate the existence of IBS.
85 */ 86 */
86#define IBS_CAPS_AVAIL (1LL<<0) 87#define IBS_CAPS_AVAIL (1LL<<0)
88#define IBS_CAPS_RDWROPCNT (1LL<<3)
87#define IBS_CAPS_OPCNT (1LL<<4) 89#define IBS_CAPS_OPCNT (1LL<<4)
88 90
91/*
92 * IBS randomization macros
93 */
94#define IBS_RANDOM_BITS 12
95#define IBS_RANDOM_MASK ((1ULL << IBS_RANDOM_BITS) - 1)
96#define IBS_RANDOM_MAXCNT_OFFSET (1ULL << (IBS_RANDOM_BITS - 5))
97
89static u32 get_ibs_caps(void) 98static u32 get_ibs_caps(void)
90{ 99{
91 u32 ibs_caps; 100 u32 ibs_caps;
@@ -241,6 +250,38 @@ static unsigned int lfsr_random(void)
241 return lfsr_value; 250 return lfsr_value;
242} 251}
243 252
253/*
254 * IBS software randomization
255 *
256 * The IBS periodic op counter is randomized in software. The lower 12
257 * bits of the 20 bit counter are randomized. IbsOpCurCnt is
258 * initialized with a 12 bit random value.
259 */
260static inline u64 op_amd_randomize_ibs_op(u64 val)
261{
262 unsigned int random = lfsr_random();
263
264 if (!(ibs_caps & IBS_CAPS_RDWROPCNT))
265 /*
266 * Work around if the hw can not write to IbsOpCurCnt
267 *
268 * Randomize the lower 8 bits of the 16 bit
269 * IbsOpMaxCnt [15:0] value in the range of -128 to
270 * +127 by adding/subtracting an offset to the
271 * maximum count (IbsOpMaxCnt).
272 *
273 * To avoid over or underflows and protect upper bits
274 * starting at bit 16, the initial value for
275 * IbsOpMaxCnt must fit in the range from 0x0081 to
276 * 0xff80.
277 */
278 val += (s8)(random >> 4);
279 else
280 val |= (u64)(random & IBS_RANDOM_MASK) << 32;
281
282 return val;
283}
284
244static inline void 285static inline void
245op_amd_handle_ibs(struct pt_regs * const regs, 286op_amd_handle_ibs(struct pt_regs * const regs,
246 struct op_msrs const * const msrs) 287 struct op_msrs const * const msrs)
@@ -290,8 +331,7 @@ op_amd_handle_ibs(struct pt_regs * const regs,
290 oprofile_write_commit(&entry); 331 oprofile_write_commit(&entry);
291 332
292 /* reenable the IRQ */ 333 /* reenable the IRQ */
293 ctl &= ~IBS_OP_VAL & 0xFFFFFFFF; 334 ctl = op_amd_randomize_ibs_op(ibs_op_ctl);
294 ctl |= IBS_OP_ENABLE;
295 wrmsrl(MSR_AMD64_IBSOPCTL, ctl); 335 wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
296 } 336 }
297 } 337 }
@@ -312,10 +352,27 @@ static inline void op_amd_start_ibs(void)
312 } 352 }
313 353
314 if (ibs_config.op_enabled) { 354 if (ibs_config.op_enabled) {
315 val = (ibs_config.max_cnt_op >> 4) & 0xFFFF; 355 ibs_op_ctl = ibs_config.max_cnt_op >> 4;
356 if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) {
357 /*
358 * IbsOpCurCnt not supported. See
359 * op_amd_randomize_ibs_op() for details.
360 */
361 ibs_op_ctl = clamp(ibs_op_ctl, 0x0081ULL, 0xFF80ULL);
362 } else {
363 /*
364 * The start value is randomized with a
365 * positive offset, we need to compensate it
366 * with the half of the randomized range. Also
367 * avoid underflows.
368 */
369 ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
370 0xFFFFULL);
371 }
316 if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops) 372 if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
317 val |= IBS_OP_CNT_CTL; 373 ibs_op_ctl |= IBS_OP_CNT_CTL;
318 val |= IBS_OP_ENABLE; 374 ibs_op_ctl |= IBS_OP_ENABLE;
375 val = op_amd_randomize_ibs_op(ibs_op_ctl);
319 wrmsrl(MSR_AMD64_IBSOPCTL, val); 376 wrmsrl(MSR_AMD64_IBSOPCTL, val);
320 } 377 }
321} 378}