1 /* 2 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. 3 */ 4 5 #ifndef _ASM_SPARC_VVAR_DATA_H 6 #define _ASM_SPARC_VVAR_DATA_H 7 8 #include <asm/clocksource.h> 9 #include <linux/seqlock.h> 10 #include <linux/time.h> 11 #include <linux/types.h> 12 13 struct vvar_data { 14 unsigned int seq; 15 16 int vclock_mode; 17 struct { /* extract of a clocksource struct */ 18 u64 cycle_last; 19 u64 mask; 20 int mult; 21 int shift; 22 } clock; 23 /* open coded 'struct timespec' */ 24 u64 wall_time_sec; 25 u64 wall_time_snsec; 26 u64 monotonic_time_snsec; 27 u64 monotonic_time_sec; 28 u64 monotonic_time_coarse_sec; 29 u64 monotonic_time_coarse_nsec; 30 u64 wall_time_coarse_sec; 31 u64 wall_time_coarse_nsec; 32 33 int tz_minuteswest; 34 int tz_dsttime; 35 }; 36 37 extern struct vvar_data *vvar_data; 38 extern int vdso_fix_stick; 39 40 static inline unsigned int vvar_read_begin(const struct vvar_data *s) 41 { 42 unsigned int ret; 43 44 repeat: 45 ret = READ_ONCE(s->seq); 46 if (unlikely(ret & 1)) { 47 cpu_relax(); 48 goto repeat; 49 } 50 smp_rmb(); /* Finish all reads before we return seq */ 51 return ret; 52 } 53 54 static inline int vvar_read_retry(const struct vvar_data *s, 55 unsigned int start) 56 { 57 smp_rmb(); /* Finish all reads before checking the value of seq */ 58 return unlikely(s->seq != start); 59 } 60 61 static inline void vvar_write_begin(struct vvar_data *s) 62 { 63 ++s->seq; 64 smp_wmb(); /* Makes sure that increment of seq is reflected */ 65 } 66 67 static inline void vvar_write_end(struct vvar_data *s) 68 { 69 smp_wmb(); /* Makes the value of seq current before we increment */ 70 ++s->seq; 71 } 72 73 74 #endif /* _ASM_SPARC_VVAR_DATA_H */ 75