Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
H. Peter Anvin | 1965aae | 2008-10-22 22:26:29 -0700 | [diff] [blame] | 2 | #ifndef _ASM_X86_VGTOD_H |
| 3 | #define _ASM_X86_VGTOD_H |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 4 | |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 5 | #include <linux/compiler.h> |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 6 | #include <linux/clocksource.h> |
| 7 | |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 8 | #include <uapi/linux/time.h> |
| 9 | |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 10 | #ifdef BUILD_VDSO32_64 |
| 11 | typedef u64 gtod_long_t; |
| 12 | #else |
| 13 | typedef unsigned long gtod_long_t; |
| 14 | #endif |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 15 | |
Andy Lutomirski | bcc4a62 | 2018-10-04 14:44:45 -0700 | [diff] [blame] | 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 | */ |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 25 | struct vgtod_ts { |
| 26 | u64 sec; |
| 27 | u64 nsec; |
| 28 | }; |
| 29 | |
Thomas Gleixner | 315f28f | 2018-09-17 14:45:44 +0200 | [diff] [blame] | 30 | #define VGTOD_BASES (CLOCK_TAI + 1) |
| 31 | #define VGTOD_HRES (BIT(CLOCK_REALTIME) | BIT(CLOCK_MONOTONIC) | BIT(CLOCK_TAI)) |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 32 | #define VGTOD_COARSE (BIT(CLOCK_REALTIME_COARSE) | BIT(CLOCK_MONOTONIC_COARSE)) |
| 33 | |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 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 | */ |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 38 | struct vsyscall_gtod_data { |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 39 | unsigned int seq; |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 40 | |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 41 | int vclock_mode; |
| 42 | u64 cycle_last; |
| 43 | u64 mask; |
| 44 | u32 mult; |
| 45 | u32 shift; |
Andy Lutomirski | 91ec87d | 2012-03-22 21:15:51 -0700 | [diff] [blame] | 46 | |
Thomas Gleixner | 49116f2 | 2018-09-17 14:45:38 +0200 | [diff] [blame] | 47 | struct vgtod_ts basetime[VGTOD_BASES]; |
Andy Lutomirski | 91ec87d | 2012-03-22 21:15:51 -0700 | [diff] [blame] | 48 | |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 49 | int tz_minuteswest; |
| 50 | int tz_dsttime; |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 51 | }; |
Andi Kleen | 2aae950 | 2007-07-21 17:10:01 +0200 | [diff] [blame] | 52 | extern struct vsyscall_gtod_data vsyscall_gtod_data; |
| 53 | |
Andy Lutomirski | bd902c5 | 2015-12-29 20:12:24 -0800 | [diff] [blame] | 54 | extern int vclocks_used; |
| 55 | static inline bool vclock_was_used(int vclock) |
| 56 | { |
| 57 | return READ_ONCE(vclocks_used) & (1 << vclock); |
| 58 | } |
| 59 | |
Thomas Gleixner | 77e9c67 | 2018-09-17 14:45:37 +0200 | [diff] [blame] | 60 | static inline unsigned int gtod_read_begin(const struct vsyscall_gtod_data *s) |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 61 | { |
Thomas Gleixner | 77e9c67 | 2018-09-17 14:45:37 +0200 | [diff] [blame] | 62 | unsigned int ret; |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 63 | |
| 64 | repeat: |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame] | 65 | ret = READ_ONCE(s->seq); |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 66 | if (unlikely(ret & 1)) { |
| 67 | cpu_relax(); |
| 68 | goto repeat; |
| 69 | } |
| 70 | smp_rmb(); |
| 71 | return ret; |
| 72 | } |
| 73 | |
| 74 | static inline int gtod_read_retry(const struct vsyscall_gtod_data *s, |
Thomas Gleixner | 77e9c67 | 2018-09-17 14:45:37 +0200 | [diff] [blame] | 75 | unsigned int start) |
Stefani Seibold | 7c03156 | 2014-03-17 23:22:10 +0100 | [diff] [blame] | 76 | { |
| 77 | smp_rmb(); |
| 78 | return unlikely(s->seq != start); |
| 79 | } |
| 80 | |
| 81 | static inline void gtod_write_begin(struct vsyscall_gtod_data *s) |
| 82 | { |
| 83 | ++s->seq; |
| 84 | smp_wmb(); |
| 85 | } |
| 86 | |
| 87 | static inline void gtod_write_end(struct vsyscall_gtod_data *s) |
| 88 | { |
| 89 | smp_wmb(); |
| 90 | ++s->seq; |
| 91 | } |
| 92 | |
H. Peter Anvin | 1965aae | 2008-10-22 22:26:29 -0700 | [diff] [blame] | 93 | #endif /* _ASM_X86_VGTOD_H */ |