vsyscall.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 ARM Ltd.
  4. *
  5. * Generic implementation of update_vsyscall and update_vsyscall_tz.
  6. *
  7. * Based on the x86 specific implementation.
  8. */
  9. #include <linux/hrtimer.h>
  10. #include <linux/timekeeper_internal.h>
  11. #include <vdso/datapage.h>
  12. #include <vdso/helpers.h>
  13. #include <vdso/vsyscall.h>
  14. #include "timekeeping_internal.h"
  15. static inline void update_vdso_data(struct vdso_data *vdata,
  16. struct timekeeper *tk)
  17. {
  18. struct vdso_timestamp *vdso_ts;
  19. u64 nsec, sec;
  20. vdata[CS_HRES_COARSE].cycle_last = tk->tkr_mono.cycle_last;
  21. #ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
  22. vdata[CS_HRES_COARSE].max_cycles = tk->tkr_mono.clock->max_cycles;
  23. #endif
  24. vdata[CS_HRES_COARSE].mask = tk->tkr_mono.mask;
  25. vdata[CS_HRES_COARSE].mult = tk->tkr_mono.mult;
  26. vdata[CS_HRES_COARSE].shift = tk->tkr_mono.shift;
  27. vdata[CS_RAW].cycle_last = tk->tkr_raw.cycle_last;
  28. #ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
  29. vdata[CS_RAW].max_cycles = tk->tkr_raw.clock->max_cycles;
  30. #endif
  31. vdata[CS_RAW].mask = tk->tkr_raw.mask;
  32. vdata[CS_RAW].mult = tk->tkr_raw.mult;
  33. vdata[CS_RAW].shift = tk->tkr_raw.shift;
  34. /* CLOCK_MONOTONIC */
  35. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
  36. vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
  37. nsec = tk->tkr_mono.xtime_nsec;
  38. nsec += ((u64)tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift);
  39. while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
  40. nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
  41. vdso_ts->sec++;
  42. }
  43. vdso_ts->nsec = nsec;
  44. /* Copy MONOTONIC time for BOOTTIME */
  45. sec = vdso_ts->sec;
  46. /* Add the boot offset */
  47. sec += tk->monotonic_to_boot.tv_sec;
  48. nsec += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
  49. /* CLOCK_BOOTTIME */
  50. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
  51. vdso_ts->sec = sec;
  52. while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
  53. nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
  54. vdso_ts->sec++;
  55. }
  56. vdso_ts->nsec = nsec;
  57. /* CLOCK_MONOTONIC_RAW */
  58. vdso_ts = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
  59. vdso_ts->sec = tk->raw_sec;
  60. vdso_ts->nsec = tk->tkr_raw.xtime_nsec;
  61. /* CLOCK_TAI */
  62. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
  63. vdso_ts->sec = tk->xtime_sec + (s64)tk->tai_offset;
  64. vdso_ts->nsec = tk->tkr_mono.xtime_nsec;
  65. }
  66. void update_vsyscall(struct timekeeper *tk)
  67. {
  68. struct vdso_data *vdata = __arch_get_k_vdso_data();
  69. struct vdso_timestamp *vdso_ts;
  70. s32 clock_mode;
  71. u64 nsec;
  72. /* copy vsyscall data */
  73. vdso_write_begin(vdata);
  74. clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
  75. vdata[CS_HRES_COARSE].clock_mode = clock_mode;
  76. vdata[CS_RAW].clock_mode = clock_mode;
  77. /* CLOCK_REALTIME also required for time() */
  78. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
  79. vdso_ts->sec = tk->xtime_sec;
  80. vdso_ts->nsec = tk->tkr_mono.xtime_nsec;
  81. /* CLOCK_REALTIME_COARSE */
  82. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE];
  83. vdso_ts->sec = tk->xtime_sec;
  84. vdso_ts->nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
  85. /* CLOCK_MONOTONIC_COARSE */
  86. vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE];
  87. vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
  88. nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
  89. nsec = nsec + tk->wall_to_monotonic.tv_nsec;
  90. vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &vdso_ts->nsec);
  91. /*
  92. * Read without the seqlock held by clock_getres().
  93. * Note: No need to have a second copy.
  94. */
  95. WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution);
  96. /*
  97. * If the current clocksource is not VDSO capable, then spare the
  98. * update of the high resolution parts.
  99. */
  100. if (clock_mode != VDSO_CLOCKMODE_NONE)
  101. update_vdso_data(vdata, tk);
  102. __arch_update_vsyscall(vdata, tk);
  103. vdso_write_end(vdata);
  104. __arch_sync_vdso_data(vdata);
  105. }
  106. void update_vsyscall_tz(void)
  107. {
  108. struct vdso_data *vdata = __arch_get_k_vdso_data();
  109. vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
  110. vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
  111. __arch_sync_vdso_data(vdata);
  112. }
  113. /**
  114. * vdso_update_begin - Start of a VDSO update section
  115. *
  116. * Allows architecture code to safely update the architecture specific VDSO
  117. * data. Disables interrupts, acquires timekeeper lock to serialize against
  118. * concurrent updates from timekeeping and invalidates the VDSO data
  119. * sequence counter to prevent concurrent readers from accessing
  120. * inconsistent data.
  121. *
  122. * Returns: Saved interrupt flags which need to be handed in to
  123. * vdso_update_end().
  124. */
  125. unsigned long vdso_update_begin(void)
  126. {
  127. struct vdso_data *vdata = __arch_get_k_vdso_data();
  128. unsigned long flags;
  129. raw_spin_lock_irqsave(&timekeeper_lock, flags);
  130. vdso_write_begin(vdata);
  131. return flags;
  132. }
  133. /**
  134. * vdso_update_end - End of a VDSO update section
  135. * @flags: Interrupt flags as returned from vdso_update_begin()
  136. *
  137. * Pairs with vdso_update_begin(). Marks vdso data consistent, invokes data
  138. * synchronization if the architecture requires it, drops timekeeper lock
  139. * and restores interrupt flags.
  140. */
  141. void vdso_update_end(unsigned long flags)
  142. {
  143. struct vdso_data *vdata = __arch_get_k_vdso_data();
  144. vdso_write_end(vdata);
  145. __arch_sync_vdso_data(vdata);
  146. raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
  147. }