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