aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/perf_event_amd_ibs.c
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2012-04-02 14:19:07 -0400
committerIngo Molnar <mingo@kernel.org>2012-05-09 09:23:11 -0400
commitc75841a398d667d9968245b9519d93cedbfb4780 (patch)
tree41d89325e579c8962cdac056c887db6eb5acce6c /arch/x86/kernel/cpu/perf_event_amd_ibs.c
parentad8537cda68a8fe81776cceca6c22d54dd652ea5 (diff)
perf/x86-ibs: Fix update of period
The last sw period was not correctly updated on overflow and thus led to wrong distribution of events. We always need to properly initialize data.period in struct perf_sample_data. Signed-off-by: Robert Richter <robert.richter@amd.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1333390758-10893-2-git-send-email-robert.richter@amd.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_amd_ibs.c')
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_ibs.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 8ff74d439041..c8f69bea6624 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -386,7 +386,21 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
386 if (!(*buf++ & perf_ibs->valid_mask)) 386 if (!(*buf++ & perf_ibs->valid_mask))
387 return 0; 387 return 0;
388 388
389 /*
390 * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not
391 * supported in all cpus. As this triggered an interrupt, we
392 * set the current count to the max count.
393 */
394 config = ibs_data.regs[0];
395 if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) {
396 config &= ~IBS_OP_CUR_CNT;
397 config |= (config & IBS_OP_MAX_CNT) << 36;
398 }
399
400 perf_ibs_event_update(perf_ibs, event, config);
389 perf_sample_data_init(&data, 0); 401 perf_sample_data_init(&data, 0);
402 data.period = event->hw.last_period;
403
390 if (event->attr.sample_type & PERF_SAMPLE_RAW) { 404 if (event->attr.sample_type & PERF_SAMPLE_RAW) {
391 ibs_data.caps = ibs_caps; 405 ibs_data.caps = ibs_caps;
392 size = 1; 406 size = 1;
@@ -405,19 +419,6 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
405 419
406 regs = *iregs; /* XXX: update ip from ibs sample */ 420 regs = *iregs; /* XXX: update ip from ibs sample */
407 421
408 /*
409 * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not
410 * supported in all cpus. As this triggered an interrupt, we
411 * set the current count to the max count.
412 */
413 config = ibs_data.regs[0];
414 if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) {
415 config &= ~IBS_OP_CUR_CNT;
416 config |= (config & IBS_OP_MAX_CNT) << 36;
417 }
418
419 perf_ibs_event_update(perf_ibs, event, config);
420
421 overflow = perf_ibs_set_period(perf_ibs, hwc, &config); 422 overflow = perf_ibs_set_period(perf_ibs, hwc, &config);
422 reenable = !(overflow && perf_event_overflow(event, &data, &regs)); 423 reenable = !(overflow && perf_event_overflow(event, &data, &regs));
423 config = (config >> 4) | (reenable ? perf_ibs->enable_mask : 0); 424 config = (config >> 4) | (reenable ? perf_ibs->enable_mask : 0);