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