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

Merge tag 'timers-urgent-2020-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timekeeping updates from Thomas Gleixner:
"A set of timekeeping/VDSO updates:

- Preparatory work to allow S390 to switch over to the generic VDSO
implementation.

S390 requires that the VDSO data pointer is handed in to the
counter read function when time namespace support is enabled.
Adding the pointer is a NOOP for all other architectures because
the compiler is supposed to optimize that out when it is unused in
the architecture specific inline. The change also solved a similar
problem for MIPS which fortunately has time namespaces not yet
enabled.

S390 needs to update clock related VDSO data independent of the
timekeeping updates. This was solved so far with yet another
sequence counter in the S390 implementation. A better solution is
to utilize the already existing VDSO sequence count for this. The
core code now exposes helper functions which allow to serialize
against the timekeeper code and against concurrent readers.

S390 needs extra data for their clock readout function. The initial
common VDSO data structure did not provide a way to add that. It
now has an embedded architecture specific struct embedded which
defaults to an empty struct.

Doing this now avoids tree dependencies and conflicts post rc1 and
allows all other architectures which work on generic VDSO support
to work from a common upstream base.

- A trivial comment fix"

* tag 'timers-urgent-2020-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
time: Delete repeated words in comments
lib/vdso: Allow to add architecture-specific vdso data
timekeeping/vsyscall: Provide vdso_update_begin/end()
vdso/treewide: Add vdso_data pointer argument to __arch_get_hw_counter()

+84 -16
+3
arch/Kconfig
··· 972 972 entries at 4000, 5000 and 6000 locations. This option turns on syscall 973 973 related optimizations for a given architecture. 974 974 975 + config ARCH_HAS_VDSO_DATA 976 + bool 977 + 975 978 source "kernel/gcov/Kconfig" 976 979 977 980 source "scripts/gcc-plugins/Kconfig"
+2 -1
arch/arm/include/asm/vdso/gettimeofday.h
··· 113 113 } 114 114 #define __arch_vdso_hres_capable arm_vdso_hres_capable 115 115 116 - static __always_inline u64 __arch_get_hw_counter(int clock_mode) 116 + static __always_inline u64 __arch_get_hw_counter(int clock_mode, 117 + const struct vdso_data *vd) 117 118 { 118 119 #ifdef CONFIG_ARM_ARCH_TIMER 119 120 u64 cycle_now;
+2 -1
arch/arm64/include/asm/vdso/compat_gettimeofday.h
··· 103 103 return ret; 104 104 } 105 105 106 - static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) 106 + static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 107 + const struct vdso_data *vd) 107 108 { 108 109 u64 res; 109 110
+2 -1
arch/arm64/include/asm/vdso/gettimeofday.h
··· 64 64 return ret; 65 65 } 66 66 67 - static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) 67 + static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 68 + const struct vdso_data *vd) 68 69 { 69 70 u64 res; 70 71
+3 -2
arch/mips/include/asm/vdso/gettimeofday.h
··· 167 167 168 168 #endif 169 169 170 - static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) 170 + static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 171 + const struct vdso_data *vd) 171 172 { 172 173 #ifdef CONFIG_CSRC_R4K 173 174 if (clock_mode == VDSO_CLOCKMODE_R4K) ··· 176 175 #endif 177 176 #ifdef CONFIG_CLKSRC_MIPS_GIC 178 177 if (clock_mode == VDSO_CLOCKMODE_GIC) 179 - return read_gic_count(get_vdso_data()); 178 + return read_gic_count(vd); 180 179 #endif 181 180 /* 182 181 * Core checks mode already. So this raced against a concurrent
+2 -1
arch/riscv/include/asm/vdso/gettimeofday.h
··· 60 60 return ret; 61 61 } 62 62 63 - static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) 63 + static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 64 + const struct vdso_data *vd) 64 65 { 65 66 /* 66 67 * The purpose of csr_read(CSR_TIME) is to trap the system into
+2 -1
arch/x86/include/asm/vdso/gettimeofday.h
··· 241 241 } 242 242 #endif 243 243 244 - static inline u64 __arch_get_hw_counter(s32 clock_mode) 244 + static inline u64 __arch_get_hw_counter(s32 clock_mode, 245 + const struct vdso_data *vd) 245 246 { 246 247 if (likely(clock_mode == VDSO_CLOCKMODE_TSC)) 247 248 return (u64)rdtsc_ordered();
+10
include/vdso/datapage.h
··· 19 19 #include <vdso/time32.h> 20 20 #include <vdso/time64.h> 21 21 22 + #ifdef CONFIG_ARCH_HAS_VDSO_DATA 23 + #include <asm/vdso/data.h> 24 + #else 25 + struct arch_vdso_data {}; 26 + #endif 27 + 22 28 #define VDSO_BASES (CLOCK_TAI + 1) 23 29 #define VDSO_HRES (BIT(CLOCK_REALTIME) | \ 24 30 BIT(CLOCK_MONOTONIC) | \ ··· 70 64 * @tz_dsttime: type of DST correction 71 65 * @hrtimer_res: hrtimer resolution 72 66 * @__unused: unused 67 + * @arch_data: architecture specific data (optional, defaults 68 + * to an empty struct) 73 69 * 74 70 * vdso_data will be accessed by 64 bit and compat code at the same time 75 71 * so we should be careful before modifying this structure. ··· 105 97 s32 tz_dsttime; 106 98 u32 hrtimer_res; 107 99 u32 __unused; 100 + 101 + struct arch_vdso_data arch_data; 108 102 }; 109 103 110 104 /*
+3
include/vdso/vsyscall.h
··· 6 6 7 7 #include <asm/vdso/vsyscall.h> 8 8 9 + unsigned long vdso_update_begin(void); 10 + void vdso_update_end(unsigned long flags); 11 + 9 12 #endif /* !__ASSEMBLY__ */ 10 13 11 14 #endif /* __VDSO_VSYSCALL_H */
+1 -1
kernel/time/alarmtimer.c
··· 192 192 * When a alarm timer fires, this runs through the timerqueue to 193 193 * see which alarms expired, and runs those. If there are more alarm 194 194 * timers queued for the future, we set the hrtimer to fire when 195 - * when the next future alarm timer expires. 195 + * the next future alarm timer expires. 196 196 */ 197 197 static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) 198 198 {
+1 -1
kernel/time/sched_clock.c
··· 229 229 { 230 230 /* 231 231 * If no sched_clock() function has been provided at that point, 232 - * make it the final one one. 232 + * make it the final one. 233 233 */ 234 234 if (cd.actual_read_sched_clock == jiffy_sched_clock_read) 235 235 sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
+2 -2
kernel/time/timekeeping.c
··· 39 39 TK_ADV_FREQ 40 40 }; 41 41 42 - static DEFINE_RAW_SPINLOCK(timekeeper_lock); 42 + DEFINE_RAW_SPINLOCK(timekeeper_lock); 43 43 44 44 /* 45 45 * The most important data for readout fits into a single 64 byte ··· 2004 2004 * logarithmic_accumulation - shifted accumulation of cycles 2005 2005 * 2006 2006 * This functions accumulates a shifted interval of cycles into 2007 - * into a shifted interval nanoseconds. Allows for O(log) accumulation 2007 + * a shifted interval nanoseconds. Allows for O(log) accumulation 2008 2008 * loop. 2009 2009 * 2010 2010 * Returns the unconsumed cycles.
+8 -3
kernel/time/timekeeping_internal.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 #ifndef _TIMEKEEPING_INTERNAL_H 3 3 #define _TIMEKEEPING_INTERNAL_H 4 + 5 + #include <linux/clocksource.h> 6 + #include <linux/spinlock.h> 7 + #include <linux/time.h> 8 + 4 9 /* 5 10 * timekeeping debug functions 6 11 */ 7 - #include <linux/clocksource.h> 8 - #include <linux/time.h> 9 - 10 12 #ifdef CONFIG_DEBUG_FS 11 13 extern void tk_debug_account_sleep_time(const struct timespec64 *t); 12 14 #else ··· 32 30 return (now - last) & mask; 33 31 } 34 32 #endif 33 + 34 + /* Semi public for serialization of non timekeeper VDSO updates. */ 35 + extern raw_spinlock_t timekeeper_lock; 35 36 36 37 #endif /* _TIMEKEEPING_INTERNAL_H */
+41
kernel/time/vsyscall.c
··· 13 13 #include <vdso/helpers.h> 14 14 #include <vdso/vsyscall.h> 15 15 16 + #include "timekeeping_internal.h" 17 + 16 18 static inline void update_vdso_data(struct vdso_data *vdata, 17 19 struct timekeeper *tk) 18 20 { ··· 128 126 vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime; 129 127 130 128 __arch_sync_vdso_data(vdata); 129 + } 130 + 131 + /** 132 + * vdso_update_begin - Start of a VDSO update section 133 + * 134 + * Allows architecture code to safely update the architecture specific VDSO 135 + * data. Disables interrupts, acquires timekeeper lock to serialize against 136 + * concurrent updates from timekeeping and invalidates the VDSO data 137 + * sequence counter to prevent concurrent readers from accessing 138 + * inconsistent data. 139 + * 140 + * Returns: Saved interrupt flags which need to be handed in to 141 + * vdso_update_end(). 142 + */ 143 + unsigned long vdso_update_begin(void) 144 + { 145 + struct vdso_data *vdata = __arch_get_k_vdso_data(); 146 + unsigned long flags; 147 + 148 + raw_spin_lock_irqsave(&timekeeper_lock, flags); 149 + vdso_write_begin(vdata); 150 + return flags; 151 + } 152 + 153 + /** 154 + * vdso_update_end - End of a VDSO update section 155 + * @flags: Interrupt flags as returned from vdso_update_begin() 156 + * 157 + * Pairs with vdso_update_begin(). Marks vdso data consistent, invokes data 158 + * synchronization if the architecture requires it, drops timekeeper lock 159 + * and restores interrupt flags. 160 + */ 161 + void vdso_update_end(unsigned long flags) 162 + { 163 + struct vdso_data *vdata = __arch_get_k_vdso_data(); 164 + 165 + vdso_write_end(vdata); 166 + __arch_sync_vdso_data(vdata); 167 + raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 131 168 }
+2 -2
lib/vdso/gettimeofday.c
··· 68 68 if (unlikely(!vdso_clocksource_ok(vd))) 69 69 return -1; 70 70 71 - cycles = __arch_get_hw_counter(vd->clock_mode); 71 + cycles = __arch_get_hw_counter(vd->clock_mode, vd); 72 72 if (unlikely(!vdso_cycles_ok(cycles))) 73 73 return -1; 74 74 ns = vdso_ts->nsec; ··· 138 138 if (unlikely(!vdso_clocksource_ok(vd))) 139 139 return -1; 140 140 141 - cycles = __arch_get_hw_counter(vd->clock_mode); 141 + cycles = __arch_get_hw_counter(vd->clock_mode, vd); 142 142 if (unlikely(!vdso_cycles_ok(cycles))) 143 143 return -1; 144 144 ns = vdso_ts->nsec;