0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef __ASM_VDSO_GETTIMEOFDAY_H
0011 #define __ASM_VDSO_GETTIMEOFDAY_H
0012
0013 #ifndef __ASSEMBLY__
0014
0015 #include <uapi/linux/time.h>
0016 #include <asm/vgtod.h>
0017 #include <asm/vvar.h>
0018 #include <asm/unistd.h>
0019 #include <asm/msr.h>
0020 #include <asm/pvclock.h>
0021 #include <clocksource/hyperv_timer.h>
0022
0023 #define __vdso_data (VVAR(_vdso_data))
0024 #define __timens_vdso_data (TIMENS(_vdso_data))
0025
0026 #define VDSO_HAS_TIME 1
0027
0028 #define VDSO_HAS_CLOCK_GETRES 1
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #ifdef CONFIG_PARAVIRT_CLOCK
0046
0047
0048
0049
0050
0051 extern struct pvclock_vsyscall_time_info pvclock_page
0052 __attribute__((visibility("hidden")));
0053 #endif
0054
0055 #ifdef CONFIG_HYPERV_TIMER
0056 extern struct ms_hyperv_tsc_page hvclock_page
0057 __attribute__((visibility("hidden")));
0058 #endif
0059
0060 #ifdef CONFIG_TIME_NS
0061 static __always_inline
0062 const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
0063 {
0064 return __timens_vdso_data;
0065 }
0066 #endif
0067
0068 #ifndef BUILD_VDSO32
0069
0070 static __always_inline
0071 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0072 {
0073 long ret;
0074
0075 asm ("syscall" : "=a" (ret), "=m" (*_ts) :
0076 "0" (__NR_clock_gettime), "D" (_clkid), "S" (_ts) :
0077 "rcx", "r11");
0078
0079 return ret;
0080 }
0081
0082 static __always_inline
0083 long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
0084 struct timezone *_tz)
0085 {
0086 long ret;
0087
0088 asm("syscall" : "=a" (ret) :
0089 "0" (__NR_gettimeofday), "D" (_tv), "S" (_tz) : "memory");
0090
0091 return ret;
0092 }
0093
0094 static __always_inline
0095 long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0096 {
0097 long ret;
0098
0099 asm ("syscall" : "=a" (ret), "=m" (*_ts) :
0100 "0" (__NR_clock_getres), "D" (_clkid), "S" (_ts) :
0101 "rcx", "r11");
0102
0103 return ret;
0104 }
0105
0106 #else
0107
0108 static __always_inline
0109 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0110 {
0111 long ret;
0112
0113 asm (
0114 "mov %%ebx, %%edx \n"
0115 "mov %[clock], %%ebx \n"
0116 "call __kernel_vsyscall \n"
0117 "mov %%edx, %%ebx \n"
0118 : "=a" (ret), "=m" (*_ts)
0119 : "0" (__NR_clock_gettime64), [clock] "g" (_clkid), "c" (_ts)
0120 : "edx");
0121
0122 return ret;
0123 }
0124
0125 static __always_inline
0126 long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
0127 {
0128 long ret;
0129
0130 asm (
0131 "mov %%ebx, %%edx \n"
0132 "mov %[clock], %%ebx \n"
0133 "call __kernel_vsyscall \n"
0134 "mov %%edx, %%ebx \n"
0135 : "=a" (ret), "=m" (*_ts)
0136 : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
0137 : "edx");
0138
0139 return ret;
0140 }
0141
0142 static __always_inline
0143 long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
0144 struct timezone *_tz)
0145 {
0146 long ret;
0147
0148 asm(
0149 "mov %%ebx, %%edx \n"
0150 "mov %2, %%ebx \n"
0151 "call __kernel_vsyscall \n"
0152 "mov %%edx, %%ebx \n"
0153 : "=a" (ret)
0154 : "0" (__NR_gettimeofday), "g" (_tv), "c" (_tz)
0155 : "memory", "edx");
0156
0157 return ret;
0158 }
0159
0160 static __always_inline long
0161 clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0162 {
0163 long ret;
0164
0165 asm (
0166 "mov %%ebx, %%edx \n"
0167 "mov %[clock], %%ebx \n"
0168 "call __kernel_vsyscall \n"
0169 "mov %%edx, %%ebx \n"
0170 : "=a" (ret), "=m" (*_ts)
0171 : "0" (__NR_clock_getres_time64), [clock] "g" (_clkid), "c" (_ts)
0172 : "edx");
0173
0174 return ret;
0175 }
0176
0177 static __always_inline
0178 long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
0179 {
0180 long ret;
0181
0182 asm (
0183 "mov %%ebx, %%edx \n"
0184 "mov %[clock], %%ebx \n"
0185 "call __kernel_vsyscall \n"
0186 "mov %%edx, %%ebx \n"
0187 : "=a" (ret), "=m" (*_ts)
0188 : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
0189 : "edx");
0190
0191 return ret;
0192 }
0193
0194 #endif
0195
0196 #ifdef CONFIG_PARAVIRT_CLOCK
0197 static u64 vread_pvclock(void)
0198 {
0199 const struct pvclock_vcpu_time_info *pvti = &pvclock_page.pvti;
0200 u32 version;
0201 u64 ret;
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 do {
0226 version = pvclock_read_begin(pvti);
0227
0228 if (unlikely(!(pvti->flags & PVCLOCK_TSC_STABLE_BIT)))
0229 return U64_MAX;
0230
0231 ret = __pvclock_read_cycles(pvti, rdtsc_ordered());
0232 } while (pvclock_read_retry(pvti, version));
0233
0234 return ret;
0235 }
0236 #endif
0237
0238 #ifdef CONFIG_HYPERV_TIMER
0239 static u64 vread_hvclock(void)
0240 {
0241 return hv_read_tsc_page(&hvclock_page);
0242 }
0243 #endif
0244
0245 static inline u64 __arch_get_hw_counter(s32 clock_mode,
0246 const struct vdso_data *vd)
0247 {
0248 if (likely(clock_mode == VDSO_CLOCKMODE_TSC))
0249 return (u64)rdtsc_ordered();
0250
0251
0252
0253
0254
0255
0256 #ifdef CONFIG_PARAVIRT_CLOCK
0257 if (clock_mode == VDSO_CLOCKMODE_PVCLOCK) {
0258 barrier();
0259 return vread_pvclock();
0260 }
0261 #endif
0262 #ifdef CONFIG_HYPERV_TIMER
0263 if (clock_mode == VDSO_CLOCKMODE_HVCLOCK) {
0264 barrier();
0265 return vread_hvclock();
0266 }
0267 #endif
0268 return U64_MAX;
0269 }
0270
0271 static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
0272 {
0273 return __vdso_data;
0274 }
0275
0276 static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd)
0277 {
0278 return true;
0279 }
0280 #define vdso_clocksource_ok arch_vdso_clocksource_ok
0281
0282
0283
0284
0285
0286
0287
0288 static inline bool arch_vdso_cycles_ok(u64 cycles)
0289 {
0290 return (s64)cycles >= 0;
0291 }
0292 #define vdso_cycles_ok arch_vdso_cycles_ok
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 static __always_inline
0313 u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
0314 {
0315 if (cycles > last)
0316 return (cycles - last) * mult;
0317 return 0;
0318 }
0319 #define vdso_calc_delta vdso_calc_delta
0320
0321 #endif
0322
0323 #endif