Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Robert Richter and committed by
Ingo Molnar
c75841a3 ad8537cd

+14 -13
+14 -13
arch/x86/kernel/cpu/perf_event_amd_ibs.c
··· 386 386 if (!(*buf++ & perf_ibs->valid_mask)) 387 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 401 perf_sample_data_init(&data, 0); 402 + data.period = event->hw.last_period; 403 + 390 404 if (event->attr.sample_type & PERF_SAMPLE_RAW) { 391 405 ibs_data.caps = ibs_caps; 392 406 size = 1; ··· 418 404 } 419 405 420 406 regs = *iregs; /* XXX: update ip from ibs sample */ 421 - 422 - /* 423 - * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not 424 - * supported in all cpus. As this triggered an interrupt, we 425 - * set the current count to the max count. 426 - */ 427 - config = ibs_data.regs[0]; 428 - if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) { 429 - config &= ~IBS_OP_CUR_CNT; 430 - config |= (config & IBS_OP_MAX_CNT) << 36; 431 - } 432 - 433 - perf_ibs_event_update(perf_ibs, event, config); 434 407 435 408 overflow = perf_ibs_set_period(perf_ibs, hwc, &config); 436 409 reenable = !(overflow && perf_event_overflow(event, &data, &regs));