gettimeofday.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Generic userspace implementations of gettimeofday() and similar.
  4. */
  5. #include <vdso/datapage.h>
  6. #include <vdso/helpers.h>
  7. #ifndef vdso_calc_delta
  8. /*
  9. * Default implementation which works for all sane clocksources. That
  10. * obviously excludes x86/TSC.
  11. */
  12. static __always_inline
  13. u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
  14. {
  15. return ((cycles - last) & mask) * mult;
  16. }
  17. #endif
  18. #ifndef vdso_shift_ns
  19. static __always_inline u64 vdso_shift_ns(u64 ns, u32 shift)
  20. {
  21. return ns >> shift;
  22. }
  23. #endif
  24. #ifndef __arch_vdso_hres_capable
  25. static inline bool __arch_vdso_hres_capable(void)
  26. {
  27. return true;
  28. }
  29. #endif
  30. #ifndef vdso_clocksource_ok
  31. static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
  32. {
  33. return vd->clock_mode != VDSO_CLOCKMODE_NONE;
  34. }
  35. #endif
  36. #ifndef vdso_cycles_ok
  37. static inline bool vdso_cycles_ok(u64 cycles)
  38. {
  39. return true;
  40. }
  41. #endif
  42. #ifdef CONFIG_TIME_NS
  43. static __always_inline int do_hres_timens(const struct vdso_data *vdns, clockid_t clk,
  44. struct __kernel_timespec *ts)
  45. {
  46. const struct vdso_data *vd;
  47. const struct timens_offset *offs = &vdns->offset[clk];
  48. const struct vdso_timestamp *vdso_ts;
  49. u64 cycles, last, ns;
  50. u32 seq;
  51. s64 sec;
  52. vd = vdns - (clk == CLOCK_MONOTONIC_RAW ? CS_RAW : CS_HRES_COARSE);
  53. vd = __arch_get_timens_vdso_data(vd);
  54. if (clk != CLOCK_MONOTONIC_RAW)
  55. vd = &vd[CS_HRES_COARSE];
  56. else
  57. vd = &vd[CS_RAW];
  58. vdso_ts = &vd->basetime[clk];
  59. do {
  60. seq = vdso_read_begin(vd);
  61. if (unlikely(!vdso_clocksource_ok(vd)))
  62. return -1;
  63. cycles = __arch_get_hw_counter(vd->clock_mode, vd);
  64. if (unlikely(!vdso_cycles_ok(cycles)))
  65. return -1;
  66. ns = vdso_ts->nsec;
  67. last = vd->cycle_last;
  68. ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
  69. ns = vdso_shift_ns(ns, vd->shift);
  70. sec = vdso_ts->sec;
  71. } while (unlikely(vdso_read_retry(vd, seq)));
  72. /* Add the namespace offset */
  73. sec += offs->sec;
  74. ns += offs->nsec;
  75. /*
  76. * Do this outside the loop: a race inside the loop could result
  77. * in __iter_div_u64_rem() being extremely slow.
  78. */
  79. ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
  80. ts->tv_nsec = ns;
  81. return 0;
  82. }
  83. #else
  84. static __always_inline
  85. const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
  86. {
  87. return NULL;
  88. }
  89. static __always_inline int do_hres_timens(const struct vdso_data *vdns, clockid_t clk,
  90. struct __kernel_timespec *ts)
  91. {
  92. return -EINVAL;
  93. }
  94. #endif
  95. static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk,
  96. struct __kernel_timespec *ts)
  97. {
  98. const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
  99. u64 cycles, last, sec, ns;
  100. u32 seq;
  101. /* Allows to compile the high resolution parts out */
  102. if (!__arch_vdso_hres_capable())
  103. return -1;
  104. do {
  105. /*
  106. * Open coded to handle VDSO_CLOCKMODE_TIMENS. Time namespace
  107. * enabled tasks have a special VVAR page installed which
  108. * has vd->seq set to 1 and vd->clock_mode set to
  109. * VDSO_CLOCKMODE_TIMENS. For non time namespace affected tasks
  110. * this does not affect performance because if vd->seq is
  111. * odd, i.e. a concurrent update is in progress the extra
  112. * check for vd->clock_mode is just a few extra
  113. * instructions while spin waiting for vd->seq to become
  114. * even again.
  115. */
  116. while (unlikely((seq = READ_ONCE(vd->seq)) & 1)) {
  117. if (IS_ENABLED(CONFIG_TIME_NS) &&
  118. vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
  119. return do_hres_timens(vd, clk, ts);
  120. cpu_relax();
  121. }
  122. smp_rmb();
  123. if (unlikely(!vdso_clocksource_ok(vd)))
  124. return -1;
  125. cycles = __arch_get_hw_counter(vd->clock_mode, vd);
  126. if (unlikely(!vdso_cycles_ok(cycles)))
  127. return -1;
  128. ns = vdso_ts->nsec;
  129. last = vd->cycle_last;
  130. ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
  131. ns = vdso_shift_ns(ns, vd->shift);
  132. sec = vdso_ts->sec;
  133. } while (unlikely(vdso_read_retry(vd, seq)));
  134. /*
  135. * Do this outside the loop: a race inside the loop could result
  136. * in __iter_div_u64_rem() being extremely slow.
  137. */
  138. ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
  139. ts->tv_nsec = ns;
  140. return 0;
  141. }
  142. #ifdef CONFIG_TIME_NS
  143. static __always_inline int do_coarse_timens(const struct vdso_data *vdns, clockid_t clk,
  144. struct __kernel_timespec *ts)
  145. {
  146. const struct vdso_data *vd = __arch_get_timens_vdso_data(vdns);
  147. const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
  148. const struct timens_offset *offs = &vdns->offset[clk];
  149. u64 nsec;
  150. s64 sec;
  151. s32 seq;
  152. do {
  153. seq = vdso_read_begin(vd);
  154. sec = vdso_ts->sec;
  155. nsec = vdso_ts->nsec;
  156. } while (unlikely(vdso_read_retry(vd, seq)));
  157. /* Add the namespace offset */
  158. sec += offs->sec;
  159. nsec += offs->nsec;
  160. /*
  161. * Do this outside the loop: a race inside the loop could result
  162. * in __iter_div_u64_rem() being extremely slow.
  163. */
  164. ts->tv_sec = sec + __iter_div_u64_rem(nsec, NSEC_PER_SEC, &nsec);
  165. ts->tv_nsec = nsec;
  166. return 0;
  167. }
  168. #else
  169. static __always_inline int do_coarse_timens(const struct vdso_data *vdns, clockid_t clk,
  170. struct __kernel_timespec *ts)
  171. {
  172. return -1;
  173. }
  174. #endif
  175. static __always_inline int do_coarse(const struct vdso_data *vd, clockid_t clk,
  176. struct __kernel_timespec *ts)
  177. {
  178. const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
  179. u32 seq;
  180. do {
  181. /*
  182. * Open coded to handle VDSO_CLOCK_TIMENS. See comment in
  183. * do_hres().
  184. */
  185. while ((seq = READ_ONCE(vd->seq)) & 1) {
  186. if (IS_ENABLED(CONFIG_TIME_NS) &&
  187. vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
  188. return do_coarse_timens(vd, clk, ts);
  189. cpu_relax();
  190. }
  191. smp_rmb();
  192. ts->tv_sec = vdso_ts->sec;
  193. ts->tv_nsec = vdso_ts->nsec;
  194. } while (unlikely(vdso_read_retry(vd, seq)));
  195. return 0;
  196. }
  197. static __always_inline int
  198. __cvdso_clock_gettime_common(const struct vdso_data *vd, clockid_t clock,
  199. struct __kernel_timespec *ts)
  200. {
  201. u32 msk;
  202. /* Check for negative values or invalid clocks */
  203. if (unlikely((u32) clock >= MAX_CLOCKS))
  204. return -1;
  205. /*
  206. * Convert the clockid to a bitmask and use it to check which
  207. * clocks are handled in the VDSO directly.
  208. */
  209. msk = 1U << clock;
  210. if (likely(msk & VDSO_HRES))
  211. vd = &vd[CS_HRES_COARSE];
  212. else if (msk & VDSO_COARSE)
  213. return do_coarse(&vd[CS_HRES_COARSE], clock, ts);
  214. else if (msk & VDSO_RAW)
  215. vd = &vd[CS_RAW];
  216. else
  217. return -1;
  218. return do_hres(vd, clock, ts);
  219. }
  220. static __maybe_unused int
  221. __cvdso_clock_gettime_data(const struct vdso_data *vd, clockid_t clock,
  222. struct __kernel_timespec *ts)
  223. {
  224. int ret = __cvdso_clock_gettime_common(vd, clock, ts);
  225. if (unlikely(ret))
  226. return clock_gettime_fallback(clock, ts);
  227. return 0;
  228. }
  229. static __maybe_unused int
  230. __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
  231. {
  232. return __cvdso_clock_gettime_data(__arch_get_vdso_data(), clock, ts);
  233. }
  234. #ifdef BUILD_VDSO32
  235. static __maybe_unused int
  236. __cvdso_clock_gettime32_data(const struct vdso_data *vd, clockid_t clock,
  237. struct old_timespec32 *res)
  238. {
  239. struct __kernel_timespec ts;
  240. int ret;
  241. ret = __cvdso_clock_gettime_common(vd, clock, &ts);
  242. if (unlikely(ret))
  243. return clock_gettime32_fallback(clock, res);
  244. /* For ret == 0 */
  245. res->tv_sec = ts.tv_sec;
  246. res->tv_nsec = ts.tv_nsec;
  247. return ret;
  248. }
  249. static __maybe_unused int
  250. __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
  251. {
  252. return __cvdso_clock_gettime32_data(__arch_get_vdso_data(), clock, res);
  253. }
  254. #endif /* BUILD_VDSO32 */
  255. static __maybe_unused int
  256. __cvdso_gettimeofday_data(const struct vdso_data *vd,
  257. struct __kernel_old_timeval *tv, struct timezone *tz)
  258. {
  259. if (likely(tv != NULL)) {
  260. struct __kernel_timespec ts;
  261. if (do_hres(&vd[CS_HRES_COARSE], CLOCK_REALTIME, &ts))
  262. return gettimeofday_fallback(tv, tz);
  263. tv->tv_sec = ts.tv_sec;
  264. tv->tv_usec = (u32)ts.tv_nsec / NSEC_PER_USEC;
  265. }
  266. if (unlikely(tz != NULL)) {
  267. if (IS_ENABLED(CONFIG_TIME_NS) &&
  268. vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
  269. vd = __arch_get_timens_vdso_data(vd);
  270. tz->tz_minuteswest = vd[CS_HRES_COARSE].tz_minuteswest;
  271. tz->tz_dsttime = vd[CS_HRES_COARSE].tz_dsttime;
  272. }
  273. return 0;
  274. }
  275. static __maybe_unused int
  276. __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
  277. {
  278. return __cvdso_gettimeofday_data(__arch_get_vdso_data(), tv, tz);
  279. }
  280. #ifdef VDSO_HAS_TIME
  281. static __maybe_unused __kernel_old_time_t
  282. __cvdso_time_data(const struct vdso_data *vd, __kernel_old_time_t *time)
  283. {
  284. __kernel_old_time_t t;
  285. if (IS_ENABLED(CONFIG_TIME_NS) &&
  286. vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
  287. vd = __arch_get_timens_vdso_data(vd);
  288. t = READ_ONCE(vd[CS_HRES_COARSE].basetime[CLOCK_REALTIME].sec);
  289. if (time)
  290. *time = t;
  291. return t;
  292. }
  293. static __maybe_unused __kernel_old_time_t __cvdso_time(__kernel_old_time_t *time)
  294. {
  295. return __cvdso_time_data(__arch_get_vdso_data(), time);
  296. }
  297. #endif /* VDSO_HAS_TIME */
  298. #ifdef VDSO_HAS_CLOCK_GETRES
  299. static __maybe_unused
  300. int __cvdso_clock_getres_common(const struct vdso_data *vd, clockid_t clock,
  301. struct __kernel_timespec *res)
  302. {
  303. u32 msk;
  304. u64 ns;
  305. /* Check for negative values or invalid clocks */
  306. if (unlikely((u32) clock >= MAX_CLOCKS))
  307. return -1;
  308. if (IS_ENABLED(CONFIG_TIME_NS) &&
  309. vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
  310. vd = __arch_get_timens_vdso_data(vd);
  311. /*
  312. * Convert the clockid to a bitmask and use it to check which
  313. * clocks are handled in the VDSO directly.
  314. */
  315. msk = 1U << clock;
  316. if (msk & (VDSO_HRES | VDSO_RAW)) {
  317. /*
  318. * Preserves the behaviour of posix_get_hrtimer_res().
  319. */
  320. ns = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
  321. } else if (msk & VDSO_COARSE) {
  322. /*
  323. * Preserves the behaviour of posix_get_coarse_res().
  324. */
  325. ns = LOW_RES_NSEC;
  326. } else {
  327. return -1;
  328. }
  329. if (likely(res)) {
  330. res->tv_sec = 0;
  331. res->tv_nsec = ns;
  332. }
  333. return 0;
  334. }
  335. static __maybe_unused
  336. int __cvdso_clock_getres_data(const struct vdso_data *vd, clockid_t clock,
  337. struct __kernel_timespec *res)
  338. {
  339. int ret = __cvdso_clock_getres_common(vd, clock, res);
  340. if (unlikely(ret))
  341. return clock_getres_fallback(clock, res);
  342. return 0;
  343. }
  344. static __maybe_unused
  345. int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
  346. {
  347. return __cvdso_clock_getres_data(__arch_get_vdso_data(), clock, res);
  348. }
  349. #ifdef BUILD_VDSO32
  350. static __maybe_unused int
  351. __cvdso_clock_getres_time32_data(const struct vdso_data *vd, clockid_t clock,
  352. struct old_timespec32 *res)
  353. {
  354. struct __kernel_timespec ts;
  355. int ret;
  356. ret = __cvdso_clock_getres_common(vd, clock, &ts);
  357. if (unlikely(ret))
  358. return clock_getres32_fallback(clock, res);
  359. if (likely(res)) {
  360. res->tv_sec = ts.tv_sec;
  361. res->tv_nsec = ts.tv_nsec;
  362. }
  363. return ret;
  364. }
  365. static __maybe_unused int
  366. __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
  367. {
  368. return __cvdso_clock_getres_time32_data(__arch_get_vdso_data(),
  369. clock, res);
  370. }
  371. #endif /* BUILD_VDSO32 */
  372. #endif /* VDSO_HAS_CLOCK_GETRES */