From: Adrian Hunter <adrian.hun...@intel.com>

Commit:

  b20112edeadf ("perf/x86: Improve accuracy of perf/sched clock")

allowed the time_shift value in perf_event_mmap_page to be as much
as 32.  Unfortunately the documented algorithms for using time_shift
have it shifting an integer, whereas to work correctly with the value
32, the type must be u64.

In the case of perf tools, Intel PT decodes correctly but the timestamps
that are output (for example by perf script) have lost 32-bits of
granularity so they look like they are not changing at all.

Fix by limiting the shift to 31 and adjusting the multiplier accordingly.

Also update the documentation of perf_event_mmap_page so that new code
based on it will be more future-proof.

Signed-off-by: Adrian Hunter <adrian.hun...@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Cc: Andy Lutomirski <l...@amacapital.net>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: David Ahern <dsah...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <eran...@google.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Vince Weaver <vincent.wea...@maine.edu>
Fixes: b20112edeadf ("perf/x86: Improve accuracy of perf/sched clock")
Link: 
http://lkml.kernel.org/r/1445001845-13688-2-git-send-email-adrian.hun...@intel.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
(cherry picked from commit b9511cd761faafca7a1acc059e792c1399f9d7c6)
Signed-off-by: Yong, Jonathan <jonathan.y...@intel.com>
---
 arch/x86/kernel/tsc.c           | 11 +++++++++++
 include/uapi/linux/perf_event.h |  4 ++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index d927c74..8aba162 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -264,6 +264,17 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int 
cpu)
        clocks_calc_mult_shift(&data->cyc2ns_mul, &data->cyc2ns_shift, cpu_khz,
                               NSEC_PER_MSEC, 0);
 
+       /*
+        * cyc2ns_shift is exported via arch_perf_update_userpage() where it is
+        * not expected to be greater than 31 due to the original published
+        * conversion algorithm shifting a 32-bit value (now specifies a 64-bit
+        * value) - refer perf_event_mmap_page documentation in perf_event.h.
+        */
+       if (data->cyc2ns_shift == 32) {
+               data->cyc2ns_shift = 31;
+               data->cyc2ns_mul >>= 1;
+       }
+
        data->cyc2ns_offset = ns_now -
                mul_u64_u32_shr(tsc_now, data->cyc2ns_mul, data->cyc2ns_shift);
 
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 309211b..9107e36 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -473,7 +473,7 @@ struct perf_event_mmap_page {
         *   u64 delta;
         *
         *   quot = (cyc >> time_shift);
-        *   rem = cyc & ((1 << time_shift) - 1);
+        *   rem = cyc & (((u64)1 << time_shift) - 1);
         *   delta = time_offset + quot * time_mult +
         *              ((rem * time_mult) >> time_shift);
         *
@@ -504,7 +504,7 @@ struct perf_event_mmap_page {
         * And vice versa:
         *
         *   quot = cyc >> time_shift;
-        *   rem  = cyc & ((1 << time_shift) - 1);
+        *   rem  = cyc & (((u64)1 << time_shift) - 1);
         *   timestamp = time_zero + quot * time_mult +
         *               ((rem * time_mult) >> time_shift);
         */
-- 
2.7.3

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to