162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H 362306a36Sopenharmony_ci#define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <asm/page.h> 862306a36Sopenharmony_ci#include <asm/vdso/timebase.h> 962306a36Sopenharmony_ci#include <asm/barrier.h> 1062306a36Sopenharmony_ci#include <asm/unistd.h> 1162306a36Sopenharmony_ci#include <uapi/linux/time.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES 1 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define VDSO_HAS_TIME 1 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3, 1862306a36Sopenharmony_ci const unsigned long _r4) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci register long r0 asm("r0") = _r0; 2162306a36Sopenharmony_ci register unsigned long r3 asm("r3") = _r3; 2262306a36Sopenharmony_ci register unsigned long r4 asm("r4") = _r4; 2362306a36Sopenharmony_ci register int ret asm ("r3"); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci asm volatile( 2662306a36Sopenharmony_ci " sc\n" 2762306a36Sopenharmony_ci " bns+ 1f\n" 2862306a36Sopenharmony_ci " neg %0, %0\n" 2962306a36Sopenharmony_ci "1:\n" 3062306a36Sopenharmony_ci : "=r" (ret), "+r" (r4), "+r" (r0) 3162306a36Sopenharmony_ci : "r" (r3) 3262306a36Sopenharmony_ci : "memory", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr"); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return ret; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic __always_inline 3862306a36Sopenharmony_ciint gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifdef __powerpc64__ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic __always_inline 4662306a36Sopenharmony_ciint clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic __always_inline 5262306a36Sopenharmony_ciint clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#else 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define BUILD_VDSO32 1 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic __always_inline 6262306a36Sopenharmony_ciint clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic __always_inline 6862306a36Sopenharmony_ciint clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned long)_ts); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic __always_inline 7462306a36Sopenharmony_ciint clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic __always_inline 8062306a36Sopenharmony_ciint clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci#endif 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 8762306a36Sopenharmony_ci const struct vdso_data *vd) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci return get_tb(); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciconst struct vdso_data *__arch_get_vdso_data(void); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#ifdef CONFIG_TIME_NS 9562306a36Sopenharmony_cistatic __always_inline 9662306a36Sopenharmony_ciconst struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci return (void *)vd + PAGE_SIZE; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic inline bool vdso_clocksource_ok(const struct vdso_data *vd) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci return true; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci#define vdso_clocksource_ok vdso_clocksource_ok 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * powerpc specific delta calculation. 11062306a36Sopenharmony_ci * 11162306a36Sopenharmony_ci * This variant removes the masking of the subtraction because the 11262306a36Sopenharmony_ci * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX 11362306a36Sopenharmony_ci * which would result in a pointless operation. The compiler cannot 11462306a36Sopenharmony_ci * optimize it away as the mask comes from the vdso data and is not compile 11562306a36Sopenharmony_ci * time constant. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistatic __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci return (cycles - last) * mult; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci#define vdso_calc_delta vdso_calc_delta 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#ifndef __powerpc64__ 12462306a36Sopenharmony_cistatic __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci u32 hi = ns >> 32; 12762306a36Sopenharmony_ci u32 lo = ns; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci lo >>= shift; 13062306a36Sopenharmony_ci lo |= hi << (32 - shift); 13162306a36Sopenharmony_ci hi >>= shift; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (likely(hi == 0)) 13462306a36Sopenharmony_ci return lo; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci return ((u64)hi << 32) | lo; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci#define vdso_shift_ns vdso_shift_ns 13962306a36Sopenharmony_ci#endif 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#ifdef __powerpc64__ 14262306a36Sopenharmony_ciint __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts, 14362306a36Sopenharmony_ci const struct vdso_data *vd); 14462306a36Sopenharmony_ciint __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res, 14562306a36Sopenharmony_ci const struct vdso_data *vd); 14662306a36Sopenharmony_ci#else 14762306a36Sopenharmony_ciint __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts, 14862306a36Sopenharmony_ci const struct vdso_data *vd); 14962306a36Sopenharmony_ciint __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts, 15062306a36Sopenharmony_ci const struct vdso_data *vd); 15162306a36Sopenharmony_ciint __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res, 15262306a36Sopenharmony_ci const struct vdso_data *vd); 15362306a36Sopenharmony_ci#endif 15462306a36Sopenharmony_ciint __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz, 15562306a36Sopenharmony_ci const struct vdso_data *vd); 15662306a36Sopenharmony_ci__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, 15762306a36Sopenharmony_ci const struct vdso_data *vd); 15862306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */ 161