gettimeofday.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
  3. #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
  4. #ifndef __ASSEMBLY__
  5. #include <asm/page.h>
  6. #include <asm/vdso/timebase.h>
  7. #include <asm/barrier.h>
  8. #include <asm/unistd.h>
  9. #include <uapi/linux/time.h>
  10. #define VDSO_HAS_CLOCK_GETRES 1
  11. #define VDSO_HAS_TIME 1
  12. static __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3,
  13. const unsigned long _r4)
  14. {
  15. register long r0 asm("r0") = _r0;
  16. register unsigned long r3 asm("r3") = _r3;
  17. register unsigned long r4 asm("r4") = _r4;
  18. register int ret asm ("r3");
  19. asm volatile(
  20. " sc\n"
  21. " bns+ 1f\n"
  22. " neg %0, %0\n"
  23. "1:\n"
  24. : "=r" (ret), "+r" (r4), "+r" (r0)
  25. : "r" (r3)
  26. : "memory", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr");
  27. return ret;
  28. }
  29. static __always_inline
  30. int gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz)
  31. {
  32. return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz);
  33. }
  34. #ifdef __powerpc64__
  35. static __always_inline
  36. int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  37. {
  38. return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
  39. }
  40. static __always_inline
  41. int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  42. {
  43. return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
  44. }
  45. #else
  46. #define BUILD_VDSO32 1
  47. static __always_inline
  48. int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  49. {
  50. return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
  51. }
  52. static __always_inline
  53. int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  54. {
  55. return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned long)_ts);
  56. }
  57. static __always_inline
  58. int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
  59. {
  60. return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
  61. }
  62. static __always_inline
  63. int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
  64. {
  65. return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
  66. }
  67. #endif
  68. static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
  69. const struct vdso_data *vd)
  70. {
  71. return get_tb();
  72. }
  73. const struct vdso_data *__arch_get_vdso_data(void);
  74. #ifdef CONFIG_TIME_NS
  75. static __always_inline
  76. const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
  77. {
  78. return (void *)vd + PAGE_SIZE;
  79. }
  80. #endif
  81. static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
  82. {
  83. return true;
  84. }
  85. #define vdso_clocksource_ok vdso_clocksource_ok
  86. /*
  87. * powerpc specific delta calculation.
  88. *
  89. * This variant removes the masking of the subtraction because the
  90. * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
  91. * which would result in a pointless operation. The compiler cannot
  92. * optimize it away as the mask comes from the vdso data and is not compile
  93. * time constant.
  94. */
  95. static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
  96. {
  97. return (cycles - last) * mult;
  98. }
  99. #define vdso_calc_delta vdso_calc_delta
  100. #ifndef __powerpc64__
  101. static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
  102. {
  103. u32 hi = ns >> 32;
  104. u32 lo = ns;
  105. lo >>= shift;
  106. lo |= hi << (32 - shift);
  107. hi >>= shift;
  108. if (likely(hi == 0))
  109. return lo;
  110. return ((u64)hi << 32) | lo;
  111. }
  112. #define vdso_shift_ns vdso_shift_ns
  113. #endif
  114. #ifdef __powerpc64__
  115. int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
  116. const struct vdso_data *vd);
  117. int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
  118. const struct vdso_data *vd);
  119. #else
  120. int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
  121. const struct vdso_data *vd);
  122. int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
  123. const struct vdso_data *vd);
  124. int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
  125. const struct vdso_data *vd);
  126. #endif
  127. int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
  128. const struct vdso_data *vd);
  129. __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
  130. const struct vdso_data *vd);
  131. #endif /* __ASSEMBLY__ */
  132. #endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */