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