perf/x86-ibs: Fix update of period
authorRobert Richter <robert.richter@amd.com>
Mon, 2 Apr 2012 18:19:07 +0000 (20:19 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 9 May 2012 13:23:11 +0000 (15:23 +0200)
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>
arch/x86/kernel/cpu/perf_event_amd_ibs.c

index 8ff74d43904128af47eb043bba8bf9d4ca537fd9..c8f69bea66245ab0ae82c770c2b774b1eaf96ead 100644 (file)
@@ -386,7 +386,21 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
        if (!(*buf++ & perf_ibs->valid_mask))
                return 0;
 
+       /*
+        * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not
+        * supported in all cpus. As this triggered an interrupt, we
+        * set the current count to the max count.
+        */
+       config = ibs_data.regs[0];
+       if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) {
+               config &= ~IBS_OP_CUR_CNT;
+               config |= (config & IBS_OP_MAX_CNT) << 36;
+       }
+
+       perf_ibs_event_update(perf_ibs, event, config);
        perf_sample_data_init(&data, 0);
+       data.period = event->hw.last_period;
+
        if (event->attr.sample_type & PERF_SAMPLE_RAW) {
                ibs_data.caps = ibs_caps;
                size = 1;
@@ -405,19 +419,6 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
 
        regs = *iregs; /* XXX: update ip from ibs sample */
 
-       /*
-        * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not
-        * supported in all cpus. As this triggered an interrupt, we
-        * set the current count to the max count.
-        */
-       config = ibs_data.regs[0];
-       if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) {
-               config &= ~IBS_OP_CUR_CNT;
-               config |= (config & IBS_OP_MAX_CNT) << 36;
-       }
-
-       perf_ibs_event_update(perf_ibs, event, config);
-
        overflow = perf_ibs_set_period(perf_ibs, hwc, &config);
        reenable = !(overflow && perf_event_overflow(event, &data, &regs));
        config = (config >> 4) | (reenable ? perf_ibs->enable_mask : 0);