History

Merge tag 'timers-core-2024-05-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timers and timekeeping updates from Thomas Gleixner: "Core code: - Make timekeeping and VDSO time readouts resilent against math overflow: In guest context the kernel is prone to math overflow when the host defers the timer interrupt due to overload, malfunction or malice. This can be mitigated by checking the clocksource delta for the maximum deferrement which is readily available. If that value is exceeded then the code uses a slowpath function which can handle the multiplication overflow. This functionality is enabled unconditionally in the kernel, but made conditional in the VDSO code. The latter is conditional because it allows architectures to optimize the check so it is not causing performance regressions. On X86 this is achieved by reworking the existing check for negative TSC deltas as a negative delta obviously exceeds the maximum deferrement when it is evaluated as an unsigned value. That avoids two conditionals in the hotpath and allows to hide both the negative delta and the large delta handling in the same slow path. - Add an initial minimal ktime_t abstraction for Rust - The usual boring cleanups and enhancements Drivers: - Boring updates to device trees and trivial enhancements in various drivers" * tag 'timers-core-2024-05-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (33 commits) clocksource/drivers/arm_arch_timer: Mark hisi_161010101_oem_info const clocksource/drivers/timer-ti-dm: Remove an unused field in struct dmtimer clocksource/drivers/renesas-ostm: Avoid reprobe after successful early probe clocksource/drivers/renesas-ostm: Allow OSTM driver to reprobe for RZ/V2H(P) SoC dt-bindings: timer: renesas: ostm: Document Renesas RZ/V2H(P) SoC rust: time: doc: Add missing C header links clocksource: Make the int help prompt unit readable in ncurses hrtimer: Rename __hrtimer_hres_active() to hrtimer_hres_active() timerqueue: Remove never used function timerqueue_node_expires() rust: time: Add Ktime vdso: Fix powerpc build U64_MAX undeclared error clockevents: Convert s[n]printf() to sysfs_emit() clocksource: Convert s[n]printf() to sysfs_emit() clocksource: Make watchdog and suspend-timing multiplication overflow safe timekeeping: Let timekeeping_cycles_to_ns() handle both under and overflow timekeeping: Make delta calculation overflow safe timekeeping: Prepare timekeeping_cycles_to_ns() for overflow safety timekeeping: Fold in timekeeping_delta_to_ns() timekeeping: Consolidate timekeeping helpers timekeeping: Refactor timekeeping helpers ...

Linus Torvalds committed 2 years ago

Commit 2d9db772 parents 61deafa a3825a721 files · +284 −173Browse files

Unified · Split

21 files
  1. Documentation/devicetree/bindings/timer/renesas,ostm.yaml +2 −0
  2. arch/powerpc/include/asm/vdso/gettimeofday.h +11 −15
  3. arch/s390/include/asm/vdso/gettimeofday.h +2 −5
  4. arch/x86/Kconfig +1 −0
  5. arch/x86/include/asm/vdso/gettimeofday.h +28 −16
  6. drivers/clocksource/arm_arch_timer.c +1 −1
  7. drivers/clocksource/renesas-ostm.c +2 −1
  8. drivers/clocksource/timer-ti-dm.c +0 −1
  9. include/linux/math64.h +2 −6
  10. include/linux/timerqueue.h +0 −5
  11. include/vdso/datapage.h +4 −0
  12. include/vdso/math64.h +38 −0
  13. kernel/time/Kconfig +1 −1
  14. kernel/time/clockevents.c +1 −1
  15. kernel/time/clocksource.c +21 −23
  16. kernel/time/hrtimer.c +9 −32
  17. kernel/time/timekeeping.c +49 −47
  18. kernel/time/vsyscall.c +6 −0
  19. lib/vdso/Kconfig +7 −0
  20. lib/vdso/gettimeofday.c +36 −19
  21. rust/kernel/time.rs +63 −0
Documentation/devicetree/bindings/timer/renesas,ostm.yaml+2−0
@@ -26,6 +26,7 @@ properties: · 25 unmodified lines
2626 - renesas,r9a07g043-ostm # RZ/G2UL and RZ/Five
2727 - renesas,r9a07g044-ostm # RZ/G2{L,LC}
2828 - renesas,r9a07g054-ostm # RZ/V2L
29+ - renesas,r9a09g057-ostm # RZ/V2H(P)
2930 - const: renesas,ostm # Generic
3031
3132 reg:
@@ -58,6 +59,7 @@ if: · 26 unmodified lines
5859 - renesas,r9a07g043-ostm
5960 - renesas,r9a07g044-ostm
6061 - renesas,r9a07g054-ostm
62+ - renesas,r9a09g057-ostm
6163 then:
6264 required:
6365 - resets
arch/powerpc/include/asm/vdso/gettimeofday.h+11−15
@@ -13,6 +13,17 @@ · 12 unmodified lines
1313
1414 #define VDSO_HAS_TIME 1
1515
16+/*
17+ * powerpc specific delta calculation.
18+ *
19+ * This variant removes the masking of the subtraction because the
20+ * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
21+ * which would result in a pointless operation. The compiler cannot
22+ * optimize it away as the mask comes from the vdso data and is not compile
23+ * time constant.
24+ */
25+#define VDSO_DELTA_NOMASK 1
26+
1627 static __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3,
1728 const unsigned long _r4)
1829 {
@@ -104,21 +115,6 @@ static inline bool vdso_clocksource_ok(const struct vdso_data *vd) · 85 unmodified lines
104115 }
105116 #define vdso_clocksource_ok vdso_clocksource_ok
106117
107−/*
108− * powerpc specific delta calculation.
109− *
110− * This variant removes the masking of the subtraction because the
111− * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
112− * which would result in a pointless operation. The compiler cannot
113− * optimize it away as the mask comes from the vdso data and is not compile
114− * time constant.
115− */
116−static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
117−{
118− return (cycles - last) * mult;
119−}
120−#define vdso_calc_delta vdso_calc_delta
121−
122118 #ifndef __powerpc64__
123119 static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
124120 {
arch/s390/include/asm/vdso/gettimeofday.h+2−5
@@ -6,16 +6,13 @@ · 5 unmodified lines
66
77 #define VDSO_HAS_CLOCK_GETRES 1
88
9+#define VDSO_DELTA_NOMASK 1
10+
911 #include <asm/syscall.h>
1012 #include <asm/timex.h>
1113 #include <asm/unistd.h>
1214 #include <linux/compiler.h>
1315
14−#define vdso_calc_delta __arch_vdso_calc_delta
15−static __always_inline u64 __arch_vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
16−{
17− return (cycles - last) * mult;
18−}
1916
2017 static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
2118 {
arch/x86/Kconfig+1−0
@@ -169,6 +169,7 @@ config X86 · 168 unmodified lines
169169 select GENERIC_TIME_VSYSCALL
170170 select GENERIC_GETTIMEOFDAY
171171 select GENERIC_VDSO_TIME_NS
172+ select GENERIC_VDSO_OVERFLOW_PROTECT
172173 select GUP_GET_PXX_LOW_HIGH if X86_PAE
173174 select HARDIRQS_SW_RESEND
174175 select HARDLOCKUP_CHECK_TIMESTAMP if X86_64
arch/x86/include/asm/vdso/gettimeofday.h+28−16
@@ -300,7 +300,7 @@ static inline bool arch_vdso_cycles_ok(u64 cycles) · 299 unmodified lines
300300 #define vdso_cycles_ok arch_vdso_cycles_ok
301301
302302 /*
303− * x86 specific delta calculation.
303+ * x86 specific calculation of nanoseconds for the current cycle count
304304 *
305305 * The regular implementation assumes that clocksource reads are globally
306306 * monotonic. The TSC can be slightly off across sockets which can cause
@@ -308,8 +308,8 @@ static inline bool arch_vdso_cycles_ok(u64 cycles) · 1 unmodified line
308308 * jump.
309309 *
310310 * Therefore it needs to be verified that @cycles are greater than
311− * @last. If not then use @last, which is the base time of the current
312− * conversion period.
311+ * @vd->cycles_last. If not then use @vd->cycles_last, which is the base
312+ * time of the current conversion period.
313313 *
314314 * This variant also uses a custom mask because while the clocksource mask of
315315 * all the VDSO capable clocksources on x86 is U64_MAX, the above code uses
@@ -317,25 +317,37 @@ static inline bool arch_vdso_cycles_ok(u64 cycles) · 1 unmodified line
317317 * declares everything with the MSB/Sign-bit set as invalid. Therefore the
318318 * effective mask is S64_MAX.
319319 */
320−static __always_inline
321−u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
320+static __always_inline u64 vdso_calc_ns(const struct vdso_data *vd, u64 cycles, u64 base)
322321 {
323− /*
324− * Due to the MSB/Sign-bit being used as invalid marker (see
325− * arch_vdso_cycles_valid() above), the effective mask is S64_MAX.
326− */
327− u64 delta = (cycles - last) & S64_MAX;
322+ u64 delta = cycles - vd->cycle_last;
328323
329324 /*
330− * Due to the above mentioned TSC wobbles, filter out negative motion.
331− * Per the above masking, the effective sign bit is now bit 62.
325+ * Negative motion and deltas which can cause multiplication
326+ * overflow require special treatment. This check covers both as
327+ * negative motion is guaranteed to be greater than @vd::max_cycles
328+ * due to unsigned comparison.
329+ *
330+ * Due to the MSB/Sign-bit being used as invalid marker (see
331+ * arch_vdso_cycles_valid() above), the effective mask is S64_MAX,
332+ * but that case is also unlikely and will also take the unlikely path
333+ * here.
332334 */
333− if (unlikely(delta & (1ULL << 62)))
334− return 0;
335+ if (unlikely(delta > vd->max_cycles)) {
336+ /*
337+ * Due to the above mentioned TSC wobbles, filter out
338+ * negative motion. Per the above masking, the effective
339+ * sign bit is now bit 62.
340+ */
341+ if (delta & (1ULL << 62))
342+ return base >> vd->shift;
343+
344+ /* Handle multiplication overflow gracefully */
345+ return mul_u64_u32_add_u64_shr(delta & S64_MAX, vd->mult, base, vd->shift);
346+ }
335347
336− return delta * mult;
348+ return ((delta * vd->mult) + base) >> vd->shift;
337349 }
338−#define vdso_calc_delta vdso_calc_delta
350+#define vdso_calc_ns vdso_calc_ns
339351
340352 #endif /* !__ASSEMBLY__ */
341353
drivers/clocksource/arm_arch_timer.c+1−1
@@ -331,7 +331,7 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) · 330 unmodified lines
331331 return __hisi_161010101_read_reg(cntvct_el0);
332332 }
333333
334−static struct ate_acpi_oem_info hisi_161010101_oem_info[] = {
334+static const struct ate_acpi_oem_info hisi_161010101_oem_info[] = {
335335 /*
336336 * Note that trailing spaces are required to properly match
337337 * the OEM table information.
drivers/clocksource/renesas-ostm.c+2−1
@@ -210,6 +210,7 @@ static int __init ostm_init(struct device_node *np) · 209 unmodified lines
210210 pr_info("%pOF: used for clock events\n", np);
211211 }
212212
213+ of_node_set_flag(np, OF_POPULATED);
213214 return 0;
214215
215216 err_cleanup:
@@ -224,7 +225,7 @@ err_free: · 8 unmodified lines
224225
225226 TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init);
226227
227−#ifdef CONFIG_ARCH_RZG2L
228+#if defined(CONFIG_ARCH_RZG2L) || defined(CONFIG_ARCH_R9A09G057)
228229 static int __init ostm_probe(struct platform_device *pdev)
229230 {
230231 struct device *dev = &pdev->dev;
drivers/clocksource/timer-ti-dm.c+0−1
@@ -129,7 +129,6 @@ struct dmtimer { · 128 unmodified lines
129129 void __iomem *func_base; /* function register base */
130130
131131 atomic_t enabled;
132− unsigned long rate;
133132 unsigned reserved:1;
134133 unsigned posted:1;
135134 unsigned omap1:1;
include/linux/math64.h+2−6
@@ -4,8 +4,8 @@ · 3 unmodified lines
44
55 #include <linux/types.h>
66 #include <linux/math.h>
7−#include <vdso/math64.h>
87 #include <asm/div64.h>
8+#include <vdso/math64.h>
99
1010 #if BITS_PER_LONG == 64
1111
@@ -179,16 +179,12 @@ static __always_inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift) · 167 unmodified lines
179179 #ifndef mul_u64_u32_shr
180180 static __always_inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
181181 {
182− u32 ah, al;
182+ u32 ah = a >> 32, al = a;
183183 u64 ret;
184184
185− al = a;
186− ah = a >> 32;
187−
188185 ret = mul_u32_u32(al, mul) >> shift;
189186 if (ah)
190187 ret += mul_u32_u32(ah, mul) << (32 - shift);
191−
192188 return ret;
193189 }
194190 #endif /* mul_u64_u32_shr */
include/linux/timerqueue.h+0−5
@@ -37,11 +37,6 @@ static inline bool timerqueue_node_queued(struct timerqueue_node *node) · 36 unmodified lines
3737 return !RB_EMPTY_NODE(&node->node);
3838 }
3939
40−static inline bool timerqueue_node_expires(struct timerqueue_node *node)
41−{
42− return node->expires;
43−}
44−
4540 static inline void timerqueue_init_head(struct timerqueue_head *head)
4641 {
4742 head->rb_root = RB_ROOT_CACHED;
include/vdso/datapage.h+4−0
@@ -61,6 +61,7 @@ struct vdso_timestamp { · 60 unmodified lines
6161 * @seq: timebase sequence counter
6262 * @clock_mode: clock mode
6363 * @cycle_last: timebase at clocksource init
64+ * @max_cycles: maximum cycles which won't overflow 64bit multiplication
6465 * @mask: clocksource mask
6566 * @mult: clocksource multiplier
6667 * @shift: clocksource shift
@@ -92,6 +93,9 @@ struct vdso_data { · 25 unmodified lines
9293
9394 s32 clock_mode;
9495 u64 cycle_last;
96+#ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
97+ u64 max_cycles;
98+#endif
9599 u64 mask;
96100 u32 mult;
97101 u32 shift;
include/vdso/math64.h+38−0
@@ -21,4 +21,42 @@ __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) · 20 unmodified lines
2121 return ret;
2222 }
2323
24+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
25+
26+#ifndef mul_u64_u32_add_u64_shr
27+static __always_inline u64 mul_u64_u32_add_u64_shr(u64 a, u32 mul, u64 b, unsigned int shift)
28+{
29+ return (u64)((((unsigned __int128)a * mul) + b) >> shift);
30+}
31+#endif /* mul_u64_u32_add_u64_shr */
32+
33+#else
34+
35+#ifndef mul_u64_u32_add_u64_shr
36+#ifndef mul_u32_u32
37+static inline u64 mul_u32_u32(u32 a, u32 b)
38+{
39+ return (u64)a * b;
40+}
41+#define mul_u32_u32 mul_u32_u32
42+#endif
43+static __always_inline u64 mul_u64_u32_add_u64_shr(u64 a, u32 mul, u64 b, unsigned int shift)
44+{
45+ u32 ah = a >> 32, al = a;
46+ bool ovf;
47+ u64 ret;
48+
49+ ovf = __builtin_add_overflow(mul_u32_u32(al, mul), b, &ret);
50+ ret >>= shift;
51+ if (ovf && shift)
52+ ret += 1ULL << (64 - shift);
53+ if (ah)
54+ ret += mul_u32_u32(ah, mul) << (32 - shift);
55+
56+ return ret;
57+}
58+#endif /* mul_u64_u32_add_u64_shr */
59+
60+#endif
61+
2462 #endif /* __VDSO_MATH64_H */
kernel/time/Kconfig+1−1
@@ -202,7 +202,7 @@ config HIGH_RES_TIMERS · 201 unmodified lines
202202 the size of the kernel image.
203203
204204 config CLOCKSOURCE_WATCHDOG_MAX_SKEW_US
205− int "Clocksource watchdog maximum allowable skew (in μs)"
205+ int "Clocksource watchdog maximum allowable skew (in microseconds)"
206206 depends on CLOCKSOURCE_WATCHDOG
207207 range 50 1000
208208 default 125
kernel/time/clockevents.c+1−1
@@ -677,7 +677,7 @@ static ssize_t current_device_show(struct device *dev, · 676 unmodified lines
677677 raw_spin_lock_irq(&clockevents_lock);
678678 td = tick_get_tick_dev(dev);
679679 if (td && td->evtdev)
680− count = snprintf(buf, PAGE_SIZE, "%s\n", td->evtdev->name);
680+ count = sysfs_emit(buf, "%s\n", td->evtdev->name);
681681 raw_spin_unlock_irq(&clockevents_lock);
682682 return count;
683683 }
kernel/time/clocksource.c+21−23
@@ -20,6 +20,16 @@ · 19 unmodified lines
2020 #include "tick-internal.h"
2121 #include "timekeeping_internal.h"
2222
23+static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end)
24+{
25+ u64 delta = clocksource_delta(end, start, cs->mask);
26+
27+ if (likely(delta < cs->max_cycles))
28+ return clocksource_cyc2ns(delta, cs->mult, cs->shift);
29+
30+ return mul_u64_u32_shr(delta, cs->mult, cs->shift);
31+}
32+
2333 /**
2434 * clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks
2535 * @mult: pointer to mult variable
@@ -222,8 +232,8 @@ enum wd_read_status { · 196 unmodified lines
222232 static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)
223233 {
224234 unsigned int nretries, max_retries;
225− u64 wd_end, wd_end2, wd_delta;
226235 int64_t wd_delay, wd_seq_delay;
236+ u64 wd_end, wd_end2;
227237
228238 max_retries = clocksource_get_max_watchdog_retry();
229239 for (nretries = 0; nretries <= max_retries; nretries++) {
@@ -234,9 +244,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, · 4 unmodified lines
234244 wd_end2 = watchdog->read(watchdog);
235245 local_irq_enable();
236246
237− wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask);
238− wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult,
239− watchdog->shift);
247+ wd_delay = cycles_to_nsec_safe(watchdog, *wdnow, wd_end);
240248 if (wd_delay <= WATCHDOG_MAX_SKEW) {
241249 if (nretries > 1 || nretries >= max_retries) {
242250 pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",
@@ -254,8 +262,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, · 11 unmodified lines
254262 * report system busy, reinit the watchdog and skip the current
255263 * watchdog test.
256264 */
257− wd_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask);
258− wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift);
265+ wd_seq_delay = cycles_to_nsec_safe(watchdog, wd_end, wd_end2);
259266 if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)
260267 goto skip_test;
261268 }
@@ -366,8 +373,7 @@ void clocksource_verify_percpu(struct clocksource *cs) · 104 unmodified lines
366373 delta = (csnow_end - csnow_mid) & cs->mask;
367374 if (delta < 0)
368375 cpumask_set_cpu(cpu, &cpus_ahead);
369− delta = clocksource_delta(csnow_end, csnow_begin, cs->mask);
370− cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
376+ cs_nsec = cycles_to_nsec_safe(cs, csnow_begin, csnow_end);
371377 if (cs_nsec > cs_nsec_max)
372378 cs_nsec_max = cs_nsec;
373379 if (cs_nsec < cs_nsec_min)
@@ -398,8 +404,8 @@ static inline void clocksource_reset_watchdog(void) · 24 unmodified lines
398404
399405 static void clocksource_watchdog(struct timer_list *unused)
400406 {
401− u64 csnow, wdnow, cslast, wdlast, delta;
402407 int64_t wd_nsec, cs_nsec, interval;
408+ u64 csnow, wdnow, cslast, wdlast;
403409 int next_cpu, reset_pending;
404410 struct clocksource *cs;
405411 enum wd_read_status read_ret;
@@ -456,12 +462,8 @@ static void clocksource_watchdog(struct timer_list *unused) · 50 unmodified lines
456462 continue;
457463 }
458464
459− delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask);
460− wd_nsec = clocksource_cyc2ns(delta, watchdog->mult,
461− watchdog->shift);
462−
463− delta = clocksource_delta(csnow, cs->cs_last, cs->mask);
464− cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
465+ wd_nsec = cycles_to_nsec_safe(watchdog, cs->wd_last, wdnow);
466+ cs_nsec = cycles_to_nsec_safe(cs, cs->cs_last, csnow);
465467 wdlast = cs->wd_last; /* save these in case we print them */
466468 cslast = cs->cs_last;
467469 cs->cs_last = csnow;
@@ -832,7 +834,7 @@ void clocksource_start_suspend_timing(struct clocksource *cs, u64 start_cycles) · 364 unmodified lines
832834 */
833835 u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)
834836 {
835− u64 now, delta, nsec = 0;
837+ u64 now, nsec = 0;
836838
837839 if (!suspend_clocksource)
838840 return 0;
@@ -847,12 +849,8 @@ u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now) · 8 unmodified lines
847849 else
848850 now = suspend_clocksource->read(suspend_clocksource);
849851
850− if (now > suspend_start) {
851− delta = clocksource_delta(now, suspend_start,
852− suspend_clocksource->mask);
853− nsec = mul_u64_u32_shr(delta, suspend_clocksource->mult,
854− suspend_clocksource->shift);
855− }
852+ if (now > suspend_start)
853+ nsec = cycles_to_nsec_safe(suspend_clocksource, suspend_start, now);
856854
857855 /*
858856 * Disable the suspend timer to save power if current clocksource is
@@ -1336,7 +1334,7 @@ static ssize_t current_clocksource_show(struct device *dev, · 477 unmodified lines
13361334 ssize_t count = 0;
13371335
13381336 mutex_lock(&clocksource_mutex);
1339− count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name);
1337+ count = sysfs_emit(buf, "%s\n", curr_clocksource->name);
13401338 mutex_unlock(&clocksource_mutex);
13411339
13421340 return count;
kernel/time/hrtimer.c+9−32
@@ -644,17 +644,12 @@ static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) · 643 unmodified lines
644644 /*
645645 * Is the high resolution mode active ?
646646 */
647−static inline int __hrtimer_hres_active(struct hrtimer_cpu_base *cpu_base)
647+static inline int hrtimer_hres_active(struct hrtimer_cpu_base *cpu_base)
648648 {
649649 return IS_ENABLED(CONFIG_HIGH_RES_TIMERS) ?
650650 cpu_base->hres_active : 0;
651651 }
652652
653−static inline int hrtimer_hres_active(void)
654−{
655− return __hrtimer_hres_active(this_cpu_ptr(&hrtimer_bases));
656−}
657−
658653 static void __hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base,
659654 struct hrtimer *next_timer,
660655 ktime_t expires_next)
@@ -678,7 +673,7 @@ static void __hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base, · 17 unmodified lines
678673 * set. So we'd effectively block all timers until the T2 event
679674 * fires.
680675 */
681− if (!__hrtimer_hres_active(cpu_base) || cpu_base->hang_detected)
676+ if (!hrtimer_hres_active(cpu_base) || cpu_base->hang_detected)
682677 return;
683678
684679 tick_program_event(expires_next, 1);
@@ -789,12 +784,12 @@ static void retrigger_next_event(void *arg) · 104 unmodified lines
789784 * function call will take care of the reprogramming in case the
790785 * CPU was in a NOHZ idle sleep.
791786 */
792− if (!__hrtimer_hres_active(base) && !tick_nohz_active)
787+ if (!hrtimer_hres_active(base) && !tick_nohz_active)
793788 return;
794789
795790 raw_spin_lock(&base->lock);
796791 hrtimer_update_base(base);
797− if (__hrtimer_hres_active(base))
792+ if (hrtimer_hres_active(base))
798793 hrtimer_force_reprogram(base, 0);
799794 else
800795 hrtimer_update_next_event(base);
@@ -951,7 +946,7 @@ void clock_was_set(unsigned int bases) · 150 unmodified lines
951946 cpumask_var_t mask;
952947 int cpu;
953948
954− if (!__hrtimer_hres_active(cpu_base) && !tick_nohz_active)
949+ if (!hrtimer_hres_active(cpu_base) && !tick_nohz_active)
955950 goto out_timerfd;
956951
957952 if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
@@ -1491,7 +1486,7 @@ u64 hrtimer_get_next_event(void) · 533 unmodified lines
14911486
14921487 raw_spin_lock_irqsave(&cpu_base->lock, flags);
14931488
1494− if (!__hrtimer_hres_active(cpu_base))
1489+ if (!hrtimer_hres_active(cpu_base))
14951490 expires = __hrtimer_get_next_event(cpu_base, HRTIMER_ACTIVE_ALL);
14961491
14971492 raw_spin_unlock_irqrestore(&cpu_base->lock, flags);
@@ -1514,7 +1509,7 @@ u64 hrtimer_next_event_without(const struct hrtimer *exclude) · 16 unmodified lines
15141509
15151510 raw_spin_lock_irqsave(&cpu_base->lock, flags);
15161511
1517− if (__hrtimer_hres_active(cpu_base)) {
1512+ if (hrtimer_hres_active(cpu_base)) {
15181513 unsigned int active;
15191514
15201515 if (!cpu_base->softirq_activated) {
@@ -1875,25 +1870,7 @@ retry: · 354 unmodified lines
18751870 tick_program_event(expires_next, 1);
18761871 pr_warn_once("hrtimer: interrupt took %llu ns\n", ktime_to_ns(delta));
18771872 }
1878−
1879−/* called with interrupts disabled */
1880−static inline void __hrtimer_peek_ahead_timers(void)
1881−{
1882− struct tick_device *td;
1883−
1884− if (!hrtimer_hres_active())
1885− return;
1886−
1887− td = this_cpu_ptr(&tick_cpu_device);
1888− if (td && td->evtdev)
1889− hrtimer_interrupt(td->evtdev);
1890−}
1891−
1892−#else /* CONFIG_HIGH_RES_TIMERS */
1893−
1894−static inline void __hrtimer_peek_ahead_timers(void) { }
1895−
1896−#endif /* !CONFIG_HIGH_RES_TIMERS */
1873+#endif /* !CONFIG_HIGH_RES_TIMERS */
18971874
18981875 /*
18991876 * Called from run_local_timers in hardirq context every jiffy
@@ -1904,7 +1881,7 @@ void hrtimer_run_queues(void) · 4 unmodified lines
19041881 unsigned long flags;
19051882 ktime_t now;
19061883
1907− if (__hrtimer_hres_active(cpu_base))
1884+ if (hrtimer_hres_active(cpu_base))
19081885 return;
19091886
19101887 /*
kernel/time/timekeeping.c+49−47
@@ -237,7 +237,9 @@ static void timekeeping_check_update(struct timekeeper *tk, u64 offset) · 236 unmodified lines
237237 }
238238 }
239239
240−static inline u64 timekeeping_get_delta(const struct tk_read_base *tkr)
240+static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles);
241+
242+static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr)
241243 {
242244 struct timekeeper *tk = &tk_core.timekeeper;
243245 u64 now, last, mask, max, delta;
@@ -264,34 +266,23 @@ static inline u64 timekeeping_get_delta(const struct tk_read_base *tkr) · 20 unmodified lines
264266 * Try to catch underflows by checking if we are seeing small
265267 * mask-relative negative values.
266268 */
267− if (unlikely((~delta & mask) < (mask >> 3))) {
269+ if (unlikely((~delta & mask) < (mask >> 3)))
268270 tk->underflow_seen = 1;
269− delta = 0;
270− }
271271
272− /* Cap delta value to the max_cycles values to avoid mult overflows */
273− if (unlikely(delta > max)) {
272+ /* Check for multiplication overflows */
273+ if (unlikely(delta > max))
274274 tk->overflow_seen = 1;
275− delta = tkr->clock->max_cycles;
276− }
277275
278− return delta;
276+ /* timekeeping_cycles_to_ns() handles both under and overflow */
277+ return timekeeping_cycles_to_ns(tkr, now);
279278 }
280279 #else
281280 static inline void timekeeping_check_update(struct timekeeper *tk, u64 offset)
282281 {
283282 }
284−static inline u64 timekeeping_get_delta(const struct tk_read_base *tkr)
283+static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr)
285284 {
286− u64 cycle_now, delta;
287−
288− /* read clocksource */
289− cycle_now = tk_clock_read(tkr);
290−
291− /* calculate the delta since the last update_wall_time */
292− delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
293−
294− return delta;
285+ BUG();
295286 }
296287 #endif
297288
@@ -370,32 +361,46 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock) · 72 unmodified lines
370361 }
371362
372363 /* Timekeeper helper functions. */
364+static noinline u64 delta_to_ns_safe(const struct tk_read_base *tkr, u64 delta)
365+{
366+ return mul_u64_u32_add_u64_shr(delta, tkr->mult, tkr->xtime_nsec, tkr->shift);
367+}
373368
374−static inline u64 timekeeping_delta_to_ns(const struct tk_read_base *tkr, u64 delta)
369+static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles)
375370 {
376− u64 nsec;
371+ /* Calculate the delta since the last update_wall_time() */
372+ u64 mask = tkr->mask, delta = (cycles - tkr->cycle_last) & mask;
377373
378− nsec = delta * tkr->mult + tkr->xtime_nsec;
379− nsec >>= tkr->shift;
374+ /*
375+ * This detects both negative motion and the case where the delta
376+ * overflows the multiplication with tkr->mult.
377+ */
378+ if (unlikely(delta > tkr->clock->max_cycles)) {
379+ /*
380+ * Handle clocksource inconsistency between CPUs to prevent
381+ * time from going backwards by checking for the MSB of the
382+ * mask being set in the delta.
383+ */
384+ if (delta & ~(mask >> 1))
385+ return tkr->xtime_nsec >> tkr->shift;
386+
387+ return delta_to_ns_safe(tkr, delta);
388+ }
380389
381− return nsec;
390+ return ((delta * tkr->mult) + tkr->xtime_nsec) >> tkr->shift;
382391 }
383392
384−static inline u64 timekeeping_get_ns(const struct tk_read_base *tkr)
393+static __always_inline u64 __timekeeping_get_ns(const struct tk_read_base *tkr)
385394 {
386− u64 delta;
387−
388− delta = timekeeping_get_delta(tkr);
389− return timekeeping_delta_to_ns(tkr, delta);
395+ return timekeeping_cycles_to_ns(tkr, tk_clock_read(tkr));
390396 }
391397
392−static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles)
398+static inline u64 timekeeping_get_ns(const struct tk_read_base *tkr)
393399 {
394− u64 delta;
400+ if (IS_ENABLED(CONFIG_DEBUG_TIMEKEEPING))
401+ return timekeeping_debug_get_ns(tkr);
395402
396− /* calculate the delta since the last update_wall_time */
397− delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask);
398− return timekeeping_delta_to_ns(tkr, delta);
403+ return __timekeeping_get_ns(tkr);
399404 }
400405
401406 /**
@@ -431,14 +436,6 @@ static void update_fast_timekeeper(const struct tk_read_base *tkr, · 29 unmodified lines
431436 memcpy(base + 1, base, sizeof(*base));
432437 }
433438
434−static __always_inline u64 fast_tk_get_delta_ns(struct tk_read_base *tkr)
435−{
436− u64 delta, cycles = tk_clock_read(tkr);
437−
438− delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask);
439− return timekeeping_delta_to_ns(tkr, delta);
440−}
441−
442439 static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf)
443440 {
444441 struct tk_read_base *tkr;
@@ -449,7 +446,7 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf) · 4 unmodified lines
449446 seq = raw_read_seqcount_latch(&tkf->seq);
450447 tkr = tkf->base + (seq & 0x01);
451448 now = ktime_to_ns(tkr->base);
452− now += fast_tk_get_delta_ns(tkr);
449+ now += __timekeeping_get_ns(tkr);
453450 } while (raw_read_seqcount_latch_retry(&tkf->seq, seq));
454451
455452 return now;
@@ -565,7 +562,7 @@ static __always_inline u64 __ktime_get_real_fast(struct tk_fast *tkf, u64 *mono) · 109 unmodified lines
565562 tkr = tkf->base + (seq & 0x01);
566563 basem = ktime_to_ns(tkr->base);
567564 baser = ktime_to_ns(tkr->base_real);
568− delta = fast_tk_get_delta_ns(tkr);
565+ delta = __timekeeping_get_ns(tkr);
569566 } while (raw_read_seqcount_latch_retry(&tkf->seq, seq));
570567
571568 if (mono)
@@ -800,10 +797,15 @@ static void timekeeping_forward_now(struct timekeeper *tk) · 228 unmodified lines
800797 tk->tkr_mono.cycle_last = cycle_now;
801798 tk->tkr_raw.cycle_last = cycle_now;
802799
803− tk->tkr_mono.xtime_nsec += delta * tk->tkr_mono.mult;
804− tk->tkr_raw.xtime_nsec += delta * tk->tkr_raw.mult;
800+ while (delta > 0) {
801+ u64 max = tk->tkr_mono.clock->max_cycles;
802+ u64 incr = delta < max ? delta : max;
805803
806− tk_normalize_xtime(tk);
804+ tk->tkr_mono.xtime_nsec += incr * tk->tkr_mono.mult;
805+ tk->tkr_raw.xtime_nsec += incr * tk->tkr_raw.mult;
806+ tk_normalize_xtime(tk);
807+ delta -= incr;
808+ }
807809 }
808810
809811 /**
kernel/time/vsyscall.c+6−0
@@ -22,10 +22,16 @@ static inline void update_vdso_data(struct vdso_data *vdata, · 21 unmodified lines
2222 u64 nsec, sec;
2323
2424 vdata[CS_HRES_COARSE].cycle_last = tk->tkr_mono.cycle_last;
25+#ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
26+ vdata[CS_HRES_COARSE].max_cycles = tk->tkr_mono.clock->max_cycles;
27+#endif
2528 vdata[CS_HRES_COARSE].mask = tk->tkr_mono.mask;
2629 vdata[CS_HRES_COARSE].mult = tk->tkr_mono.mult;
2730 vdata[CS_HRES_COARSE].shift = tk->tkr_mono.shift;
2831 vdata[CS_RAW].cycle_last = tk->tkr_raw.cycle_last;
32+#ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
33+ vdata[CS_RAW].max_cycles = tk->tkr_raw.clock->max_cycles;
34+#endif
2935 vdata[CS_RAW].mask = tk->tkr_raw.mask;
3036 vdata[CS_RAW].mult = tk->tkr_raw.mult;
3137 vdata[CS_RAW].shift = tk->tkr_raw.shift;
lib/vdso/Kconfig+7−0
@@ -30,4 +30,11 @@ config GENERIC_VDSO_TIME_NS · 29 unmodified lines
3030 Selected by architectures which support time namespaces in the
3131 VDSO
3232
33+config GENERIC_VDSO_OVERFLOW_PROTECT
34+ bool
35+ help
36+ Select to add multiplication overflow protection to the VDSO
37+ time getter functions for the price of an extra conditional
38+ in the hotpath.
39+
3340 endif
lib/vdso/gettimeofday.c+36−19
@@ -5,15 +5,23 @@ · 4 unmodified lines
55 #include <vdso/datapage.h>
66 #include <vdso/helpers.h>
77
8−#ifndef vdso_calc_delta
9−/*
10− * Default implementation which works for all sane clocksources. That
11− * obviously excludes x86/TSC.
12− */
13−static __always_inline
14−u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
8+#ifndef vdso_calc_ns
9+
10+#ifdef VDSO_DELTA_NOMASK
11+# define VDSO_DELTA_MASK(vd) ULLONG_MAX
12+#else
13+# define VDSO_DELTA_MASK(vd) (vd->mask)
14+#endif
15+
16+#ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
17+static __always_inline bool vdso_delta_ok(const struct vdso_data *vd, u64 delta)
18+{
19+ return delta < vd->max_cycles;
20+}
21+#else
22+static __always_inline bool vdso_delta_ok(const struct vdso_data *vd, u64 delta)
1523 {
16− return ((cycles - last) & mask) * mult;
24+ return true;
1725 }
1826 #endif
1927
@@ -24,6 +32,21 @@ static __always_inline u64 vdso_shift_ns(u64 ns, u32 shift) · 4 unmodified lines
2432 }
2533 #endif
2634
35+/*
36+ * Default implementation which works for all sane clocksources. That
37+ * obviously excludes x86/TSC.
38+ */
39+static __always_inline u64 vdso_calc_ns(const struct vdso_data *vd, u64 cycles, u64 base)
40+{
41+ u64 delta = (cycles - vd->cycle_last) & VDSO_DELTA_MASK(vd);
42+
43+ if (likely(vdso_delta_ok(vd, delta)))
44+ return vdso_shift_ns((delta * vd->mult) + base, vd->shift);
45+
46+ return mul_u64_u32_add_u64_shr(delta, vd->mult, base, vd->shift);
47+}
48+#endif /* vdso_calc_ns */
49+
2750 #ifndef __arch_vdso_hres_capable
2851 static inline bool __arch_vdso_hres_capable(void)
2952 {
@@ -49,10 +72,10 @@ static inline bool vdso_cycles_ok(u64 cycles) · 19 unmodified lines
4972 static __always_inline int do_hres_timens(const struct vdso_data *vdns, clockid_t clk,
5073 struct __kernel_timespec *ts)
5174 {
52− const struct vdso_data *vd;
5375 const struct timens_offset *offs = &vdns->offset[clk];
5476 const struct vdso_timestamp *vdso_ts;
55− u64 cycles, last, ns;
77+ const struct vdso_data *vd;
78+ u64 cycles, ns;
5679 u32 seq;
5780 s64 sec;
5881
@@ -73,10 +96,7 @@ static __always_inline int do_hres_timens(const struct vdso_data *vdns, clockid_ · 14 unmodified lines
7396 cycles = __arch_get_hw_counter(vd->clock_mode, vd);
7497 if (unlikely(!vdso_cycles_ok(cycles)))
7598 return -1;
76− ns = vdso_ts->nsec;
77− last = vd->cycle_last;
78− ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
79− ns = vdso_shift_ns(ns, vd->shift);
99+ ns = vdso_calc_ns(vd, cycles, vdso_ts->nsec);
80100 sec = vdso_ts->sec;
81101 } while (unlikely(vdso_read_retry(vd, seq)));
82102
@@ -111,7 +131,7 @@ static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk, · 28 unmodified lines
111131 struct __kernel_timespec *ts)
112132 {
113133 const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
114− u64 cycles, last, sec, ns;
134+ u64 cycles, sec, ns;
115135 u32 seq;
116136
117137 /* Allows to compile the high resolution parts out */
@@ -144,10 +164,7 @@ static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk, · 26 unmodified lines
144164 cycles = __arch_get_hw_counter(vd->clock_mode, vd);
145165 if (unlikely(!vdso_cycles_ok(cycles)))
146166 return -1;
147− ns = vdso_ts->nsec;
148− last = vd->cycle_last;
149− ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
150− ns = vdso_shift_ns(ns, vd->shift);
167+ ns = vdso_calc_ns(vd, cycles, vdso_ts->nsec);
151168 sec = vdso_ts->sec;
152169 } while (unlikely(vdso_read_retry(vd, seq)));
153170
rust/kernel/time.rs+63−0
@@ -4,6 +4,12 @@ · 3 unmodified lines
44 //!
55 //! This module contains the kernel APIs related to time and timers that
66 //! have been ported or wrapped for usage by Rust code in the kernel.
7+//!
8+//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
9+//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
10+
11+/// The number of nanoseconds per millisecond.
12+pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
713
814 /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
915 pub type Jiffies = core::ffi::c_ulong;
@@ -18,3 +24,60 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies { · 8 unmodified lines
1824 // matter what the argument is.
1925 unsafe { bindings::__msecs_to_jiffies(msecs) }
2026 }
27+
28+/// A Rust wrapper around a `ktime_t`.
29+#[repr(transparent)]
30+#[derive(Copy, Clone)]
31+pub struct Ktime {
32+ inner: bindings::ktime_t,
33+}
34+
35+impl Ktime {
36+ /// Create a `Ktime` from a raw `ktime_t`.
37+ #[inline]
38+ pub fn from_raw(inner: bindings::ktime_t) -> Self {
39+ Self { inner }
40+ }
41+
42+ /// Get the current time using `CLOCK_MONOTONIC`.
43+ #[inline]
44+ pub fn ktime_get() -> Self {
45+ // SAFETY: It is always safe to call `ktime_get` outside of NMI context.
46+ Self::from_raw(unsafe { bindings::ktime_get() })
47+ }
48+
49+ /// Divide the number of nanoseconds by a compile-time constant.
50+ #[inline]
51+ fn divns_constant<const DIV: i64>(self) -> i64 {
52+ self.to_ns() / DIV
53+ }
54+
55+ /// Returns the number of nanoseconds.
56+ #[inline]
57+ pub fn to_ns(self) -> i64 {
58+ self.inner
59+ }
60+
61+ /// Returns the number of milliseconds.
62+ #[inline]
63+ pub fn to_ms(self) -> i64 {
64+ self.divns_constant::<NSEC_PER_MSEC>()
65+ }
66+}
67+
68+/// Returns the number of milliseconds between two ktimes.
69+#[inline]
70+pub fn ktime_ms_delta(later: Ktime, earlier: Ktime) -> i64 {
71+ (later - earlier).to_ms()
72+}
73+
74+impl core::ops::Sub for Ktime {
75+ type Output = Ktime;
76+
77+ #[inline]
78+ fn sub(self, other: Ktime) -> Ktime {
79+ Self {
80+ inner: self.inner - other.inner,
81+ }
82+ }
83+}