Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
0003 #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
0004 
0005 #ifndef __ASSEMBLY__
0006 
0007 #include <asm/page.h>
0008 #include <asm/vdso/timebase.h>
0009 #include <asm/barrier.h>
0010 #include <asm/unistd.h>
0011 #include <uapi/linux/time.h>
0012 
0013 #define VDSO_HAS_CLOCK_GETRES       1
0014 
0015 #define VDSO_HAS_TIME           1
0016 
0017 static __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3,
0018                     const unsigned long _r4)
0019 {
0020     register long r0 asm("r0") = _r0;
0021     register unsigned long r3 asm("r3") = _r3;
0022     register unsigned long r4 asm("r4") = _r4;
0023     register int ret asm ("r3");
0024 
0025     asm volatile(
0026         "       sc\n"
0027         "   bns+    1f\n"
0028         "   neg %0, %0\n"
0029         "1:\n"
0030     : "=r" (ret), "+r" (r4), "+r" (r0)
0031     : "r" (r3)
0032     : "memory", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr");
0033 
0034     return ret;
0035 }
0036 
0037 static __always_inline
0038 int gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz)
0039 {
0040     return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz);
0041 }
0042 
0043 #ifdef __powerpc64__
0044 
0045 static __always_inline
0046 int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0047 {
0048     return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
0049 }
0050 
0051 static __always_inline
0052 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0053 {
0054     return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
0055 }
0056 
0057 #else
0058 
0059 #define BUILD_VDSO32        1
0060 
0061 static __always_inline
0062 int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0063 {
0064     return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
0065 }
0066 
0067 static __always_inline
0068 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
0069 {
0070     return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned long)_ts);
0071 }
0072 
0073 static __always_inline
0074 int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
0075 {
0076     return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
0077 }
0078 
0079 static __always_inline
0080 int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
0081 {
0082     return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
0083 }
0084 #endif
0085 
0086 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
0087                          const struct vdso_data *vd)
0088 {
0089     return get_tb();
0090 }
0091 
0092 const struct vdso_data *__arch_get_vdso_data(void);
0093 
0094 #ifdef CONFIG_TIME_NS
0095 static __always_inline
0096 const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
0097 {
0098     return (void *)vd + PAGE_SIZE;
0099 }
0100 #endif
0101 
0102 static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
0103 {
0104     return true;
0105 }
0106 #define vdso_clocksource_ok vdso_clocksource_ok
0107 
0108 /*
0109  * powerpc specific delta calculation.
0110  *
0111  * This variant removes the masking of the subtraction because the
0112  * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
0113  * which would result in a pointless operation. The compiler cannot
0114  * optimize it away as the mask comes from the vdso data and is not compile
0115  * time constant.
0116  */
0117 static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
0118 {
0119     return (cycles - last) * mult;
0120 }
0121 #define vdso_calc_delta vdso_calc_delta
0122 
0123 #ifndef __powerpc64__
0124 static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
0125 {
0126     u32 hi = ns >> 32;
0127     u32 lo = ns;
0128 
0129     lo >>= shift;
0130     lo |= hi << (32 - shift);
0131     hi >>= shift;
0132 
0133     if (likely(hi == 0))
0134         return lo;
0135 
0136     return ((u64)hi << 32) | lo;
0137 }
0138 #define vdso_shift_ns vdso_shift_ns
0139 #endif
0140 
0141 #ifdef __powerpc64__
0142 int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
0143                  const struct vdso_data *vd);
0144 int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
0145                 const struct vdso_data *vd);
0146 #else
0147 int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
0148                  const struct vdso_data *vd);
0149 int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
0150                    const struct vdso_data *vd);
0151 int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
0152                 const struct vdso_data *vd);
0153 #endif
0154 int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
0155                 const struct vdso_data *vd);
0156 __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
0157                     const struct vdso_data *vd);
0158 #endif /* __ASSEMBLY__ */
0159 
0160 #endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */