vsyscall.c 4.9 KB

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