]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.15/0052-sched-x86-Fix-overflow-in-cyc2ns_offset.patch
linux-ti335x-psp 3.2: update to 3.2.16
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.15 / 0052-sched-x86-Fix-overflow-in-cyc2ns_offset.patch
1 From 844d37ab7b6069d15d096a879225ac1e71b51974 Mon Sep 17 00:00:00 2001
2 From: Salman Qazi <sqazi@google.com>
3 Date: Fri, 9 Mar 2012 16:41:01 -0800
4 Subject: [PATCH 52/60] sched/x86: Fix overflow in cyc2ns_offset
6 commit 9993bc635d01a6ee7f6b833b4ee65ce7c06350b1 upstream.
8 When a machine boots up, the TSC generally gets reset.  However,
9 when kexec is used to boot into a kernel, the TSC value would be
10 carried over from the previous kernel.  The computation of
11 cycns_offset in set_cyc2ns_scale is prone to an overflow, if the
12 machine has been up more than 208 days prior to the kexec.  The
13 overflow happens when we multiply *scale, even though there is
14 enough room to store the final answer.
16 We fix this issue by decomposing tsc_now into the quotient and
17 remainder of division by CYC2NS_SCALE_FACTOR and then performing
18 the multiplication separately on the two components.
20 Refactor code to share the calculation with the previous
21 fix in __cycles_2_ns().
23 Signed-off-by: Salman Qazi <sqazi@google.com>
24 Acked-by: John Stultz <john.stultz@linaro.org>
25 Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
26 Cc: Paul Turner <pjt@google.com>
27 Cc: john stultz <johnstul@us.ibm.com>
28 Link: http://lkml.kernel.org/r/20120310004027.19291.88460.stgit@dungbeetle.mtv.corp.google.com
29 Signed-off-by: Ingo Molnar <mingo@elte.hu>
30 Cc: Mike Galbraith <efault@gmx.de>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32 ---
33  arch/x86/include/asm/timer.h |    8 ++------
34  arch/x86/kernel/tsc.c        |    3 ++-
35  include/linux/kernel.h       |   13 +++++++++++++
36  3 files changed, 17 insertions(+), 7 deletions(-)
38 diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
39 index 431793e..34baa0e 100644
40 --- a/arch/x86/include/asm/timer.h
41 +++ b/arch/x86/include/asm/timer.h
42 @@ -57,14 +57,10 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset);
43  
44  static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
45  {
46 -       unsigned long long quot;
47 -       unsigned long long rem;
48         int cpu = smp_processor_id();
49         unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
50 -       quot = (cyc >> CYC2NS_SCALE_FACTOR);
51 -       rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
52 -       ns += quot * per_cpu(cyc2ns, cpu) +
53 -               ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
54 +       ns += mult_frac(cyc, per_cpu(cyc2ns, cpu),
55 +                       (1UL << CYC2NS_SCALE_FACTOR));
56         return ns;
57  }
58  
59 diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
60 index 3fe298a..1ec515b 100644
61 --- a/arch/x86/kernel/tsc.c
62 +++ b/arch/x86/kernel/tsc.c
63 @@ -622,7 +622,8 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
64  
65         if (cpu_khz) {
66                 *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
67 -               *offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
68 +               *offset = ns_now - mult_frac(tsc_now, *scale,
69 +                                            (1UL << CYC2NS_SCALE_FACTOR));
70         }
71  
72         sched_clock_idle_wakeup_event(0);
73 diff --git a/include/linux/kernel.h b/include/linux/kernel.h
74 index e8b1597..a70783d 100644
75 --- a/include/linux/kernel.h
76 +++ b/include/linux/kernel.h
77 @@ -85,6 +85,19 @@
78  }                                                      \
79  )
80  
81 +/*
82 + * Multiplies an integer by a fraction, while avoiding unnecessary
83 + * overflow or loss of precision.
84 + */
85 +#define mult_frac(x, numer, denom)(                    \
86 +{                                                      \
87 +       typeof(x) quot = (x) / (denom);                 \
88 +       typeof(x) rem  = (x) % (denom);                 \
89 +       (quot * (numer)) + ((rem * (numer)) / (denom)); \
90 +}                                                      \
91 +)
92 +
93 +
94  #define _RET_IP_               (unsigned long)__builtin_return_address(0)
95  #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
96  
97 -- 
98 1.7.9.5