1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_X86_VGTOD_H 3#define _ASM_X86_VGTOD_H 4 5#include <linux/compiler.h> 6#include <linux/clocksource.h> 7 8#include <uapi/linux/time.h> 9 10#ifdef BUILD_VDSO32_64 11typedef u64 gtod_long_t; 12#else 13typedef unsigned long gtod_long_t; 14#endif 15 16/* 17 * There is one of these objects in the vvar page for each 18 * vDSO-accelerated clockid. For high-resolution clocks, this encodes 19 * the time corresponding to vsyscall_gtod_data.cycle_last. For coarse 20 * clocks, this encodes the actual time. 21 * 22 * To confuse the reader, for high-resolution clocks, nsec is left-shifted 23 * by vsyscall_gtod_data.shift. 24 */ 25struct vgtod_ts { 26 u64 sec; 27 u64 nsec; 28}; 29 30#define VGTOD_BASES (CLOCK_TAI + 1) 31#define VGTOD_HRES (BIT(CLOCK_REALTIME) | BIT(CLOCK_MONOTONIC) | BIT(CLOCK_TAI)) 32#define VGTOD_COARSE (BIT(CLOCK_REALTIME_COARSE) | BIT(CLOCK_MONOTONIC_COARSE)) 33 34/* 35 * vsyscall_gtod_data will be accessed by 32 and 64 bit code at the same time 36 * so be carefull by modifying this structure. 37 */ 38struct vsyscall_gtod_data { 39 unsigned int seq; 40 41 int vclock_mode; 42 u64 cycle_last; 43 u64 mask; 44 u32 mult; 45 u32 shift; 46 47 struct vgtod_ts basetime[VGTOD_BASES]; 48 49 int tz_minuteswest; 50 int tz_dsttime; 51}; 52extern struct vsyscall_gtod_data vsyscall_gtod_data; 53 54extern int vclocks_used; 55static inline bool vclock_was_used(int vclock) 56{ 57 return READ_ONCE(vclocks_used) & (1 << vclock); 58} 59 60static inline unsigned int gtod_read_begin(const struct vsyscall_gtod_data *s) 61{ 62 unsigned int ret; 63 64repeat: 65 ret = READ_ONCE(s->seq); 66 if (unlikely(ret & 1)) { 67 cpu_relax(); 68 goto repeat; 69 } 70 smp_rmb(); 71 return ret; 72} 73 74static inline int gtod_read_retry(const struct vsyscall_gtod_data *s, 75 unsigned int start) 76{ 77 smp_rmb(); 78 return unlikely(s->seq != start); 79} 80 81static inline void gtod_write_begin(struct vsyscall_gtod_data *s) 82{ 83 ++s->seq; 84 smp_wmb(); 85} 86 87static inline void gtod_write_end(struct vsyscall_gtod_data *s) 88{ 89 smp_wmb(); 90 ++s->seq; 91} 92 93#endif /* _ASM_X86_VGTOD_H */ 94