1ce7d8056SChristophe Leroy /* SPDX-License-Identifier: GPL-2.0 */
2ce7d8056SChristophe Leroy #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
3ce7d8056SChristophe Leroy #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
4ce7d8056SChristophe Leroy 
5*692b21d7SChristophe Leroy #ifndef __ASSEMBLY__
6*692b21d7SChristophe Leroy 
774205b3fSChristophe Leroy #include <asm/page.h>
8ce7d8056SChristophe Leroy #include <asm/vdso/timebase.h>
9ce7d8056SChristophe Leroy #include <asm/barrier.h>
10ce7d8056SChristophe Leroy #include <asm/unistd.h>
11ce7d8056SChristophe Leroy #include <uapi/linux/time.h>
12ce7d8056SChristophe Leroy 
13ce7d8056SChristophe Leroy #define VDSO_HAS_CLOCK_GETRES		1
14ce7d8056SChristophe Leroy 
15ce7d8056SChristophe Leroy #define VDSO_HAS_TIME			1
16ce7d8056SChristophe Leroy 
do_syscall_2(const unsigned long _r0,const unsigned long _r3,const unsigned long _r4)17ce7d8056SChristophe Leroy static __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3,
18ce7d8056SChristophe Leroy 					const unsigned long _r4)
19ce7d8056SChristophe Leroy {
20ce7d8056SChristophe Leroy 	register long r0 asm("r0") = _r0;
21ce7d8056SChristophe Leroy 	register unsigned long r3 asm("r3") = _r3;
22ce7d8056SChristophe Leroy 	register unsigned long r4 asm("r4") = _r4;
23ce7d8056SChristophe Leroy 	register int ret asm ("r3");
24ce7d8056SChristophe Leroy 
25ce7d8056SChristophe Leroy 	asm volatile(
26ce7d8056SChristophe Leroy 		"       sc\n"
27ce7d8056SChristophe Leroy 		"	bns+	1f\n"
28ce7d8056SChristophe Leroy 		"	neg	%0, %0\n"
29ce7d8056SChristophe Leroy 		"1:\n"
30ce7d8056SChristophe Leroy 	: "=r" (ret), "+r" (r4), "+r" (r0)
31ce7d8056SChristophe Leroy 	: "r" (r3)
32ce7d8056SChristophe Leroy 	: "memory", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr");
33ce7d8056SChristophe Leroy 
34ce7d8056SChristophe Leroy 	return ret;
35ce7d8056SChristophe Leroy }
36ce7d8056SChristophe Leroy 
37ce7d8056SChristophe Leroy static __always_inline
gettimeofday_fallback(struct __kernel_old_timeval * _tv,struct timezone * _tz)38ce7d8056SChristophe Leroy int gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz)
39ce7d8056SChristophe Leroy {
40ce7d8056SChristophe Leroy 	return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz);
41ce7d8056SChristophe Leroy }
42ce7d8056SChristophe Leroy 
4341131a5eSAndreas Schwab #ifdef __powerpc64__
4441131a5eSAndreas Schwab 
45ce7d8056SChristophe Leroy static __always_inline
clock_gettime_fallback(clockid_t _clkid,struct __kernel_timespec * _ts)46ce7d8056SChristophe Leroy int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
47ce7d8056SChristophe Leroy {
48ce7d8056SChristophe Leroy 	return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
49ce7d8056SChristophe Leroy }
50ce7d8056SChristophe Leroy 
51ce7d8056SChristophe Leroy static __always_inline
clock_getres_fallback(clockid_t _clkid,struct __kernel_timespec * _ts)52ce7d8056SChristophe Leroy int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
53ce7d8056SChristophe Leroy {
54ce7d8056SChristophe Leroy 	return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
55ce7d8056SChristophe Leroy }
56ce7d8056SChristophe Leroy 
5741131a5eSAndreas Schwab #else
58ce7d8056SChristophe Leroy 
59ce7d8056SChristophe Leroy #define BUILD_VDSO32		1
60ce7d8056SChristophe Leroy 
61ce7d8056SChristophe Leroy static __always_inline
clock_gettime_fallback(clockid_t _clkid,struct __kernel_timespec * _ts)6241131a5eSAndreas Schwab int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
6341131a5eSAndreas Schwab {
6441131a5eSAndreas Schwab 	return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
6541131a5eSAndreas Schwab }
6641131a5eSAndreas Schwab 
6741131a5eSAndreas Schwab static __always_inline
clock_getres_fallback(clockid_t _clkid,struct __kernel_timespec * _ts)6841131a5eSAndreas Schwab int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
6941131a5eSAndreas Schwab {
7041131a5eSAndreas Schwab 	return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned long)_ts);
7141131a5eSAndreas Schwab }
7241131a5eSAndreas Schwab 
7341131a5eSAndreas Schwab static __always_inline
clock_gettime32_fallback(clockid_t _clkid,struct old_timespec32 * _ts)74ce7d8056SChristophe Leroy int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
75ce7d8056SChristophe Leroy {
76ce7d8056SChristophe Leroy 	return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
77ce7d8056SChristophe Leroy }
78ce7d8056SChristophe Leroy 
79ce7d8056SChristophe Leroy static __always_inline
clock_getres32_fallback(clockid_t _clkid,struct old_timespec32 * _ts)80ce7d8056SChristophe Leroy int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
81ce7d8056SChristophe Leroy {
82ce7d8056SChristophe Leroy 	return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
83ce7d8056SChristophe Leroy }
84ce7d8056SChristophe Leroy #endif
85ce7d8056SChristophe Leroy 
__arch_get_hw_counter(s32 clock_mode,const struct vdso_data * vd)86ce7d8056SChristophe Leroy static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
87ce7d8056SChristophe Leroy 						 const struct vdso_data *vd)
88ce7d8056SChristophe Leroy {
89ce7d8056SChristophe Leroy 	return get_tb();
90ce7d8056SChristophe Leroy }
91ce7d8056SChristophe Leroy 
92ce7d8056SChristophe Leroy const struct vdso_data *__arch_get_vdso_data(void);
93ce7d8056SChristophe Leroy 
9474205b3fSChristophe Leroy #ifdef CONFIG_TIME_NS
9574205b3fSChristophe Leroy static __always_inline
__arch_get_timens_vdso_data(const struct vdso_data * vd)9674205b3fSChristophe Leroy const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
9774205b3fSChristophe Leroy {
9874205b3fSChristophe Leroy 	return (void *)vd + PAGE_SIZE;
9974205b3fSChristophe Leroy }
10074205b3fSChristophe Leroy #endif
10174205b3fSChristophe Leroy 
vdso_clocksource_ok(const struct vdso_data * vd)102ce7d8056SChristophe Leroy static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
103ce7d8056SChristophe Leroy {
104ce7d8056SChristophe Leroy 	return true;
105ce7d8056SChristophe Leroy }
106ce7d8056SChristophe Leroy #define vdso_clocksource_ok vdso_clocksource_ok
107ce7d8056SChristophe Leroy 
108ce7d8056SChristophe Leroy /*
109ce7d8056SChristophe Leroy  * powerpc specific delta calculation.
110ce7d8056SChristophe Leroy  *
111ce7d8056SChristophe Leroy  * This variant removes the masking of the subtraction because the
112ce7d8056SChristophe Leroy  * clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
113ce7d8056SChristophe Leroy  * which would result in a pointless operation. The compiler cannot
114ce7d8056SChristophe Leroy  * optimize it away as the mask comes from the vdso data and is not compile
115ce7d8056SChristophe Leroy  * time constant.
116ce7d8056SChristophe Leroy  */
vdso_calc_delta(u64 cycles,u64 last,u64 mask,u32 mult)117ce7d8056SChristophe Leroy static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
118ce7d8056SChristophe Leroy {
119ce7d8056SChristophe Leroy 	return (cycles - last) * mult;
120ce7d8056SChristophe Leroy }
121ce7d8056SChristophe Leroy #define vdso_calc_delta vdso_calc_delta
122ce7d8056SChristophe Leroy 
123ce7d8056SChristophe Leroy #ifndef __powerpc64__
vdso_shift_ns(u64 ns,unsigned long shift)124ce7d8056SChristophe Leroy static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
125ce7d8056SChristophe Leroy {
126ce7d8056SChristophe Leroy 	u32 hi = ns >> 32;
127ce7d8056SChristophe Leroy 	u32 lo = ns;
128ce7d8056SChristophe Leroy 
129ce7d8056SChristophe Leroy 	lo >>= shift;
130ce7d8056SChristophe Leroy 	lo |= hi << (32 - shift);
131ce7d8056SChristophe Leroy 	hi >>= shift;
132ce7d8056SChristophe Leroy 
133ce7d8056SChristophe Leroy 	if (likely(hi == 0))
134ce7d8056SChristophe Leroy 		return lo;
135ce7d8056SChristophe Leroy 
136ce7d8056SChristophe Leroy 	return ((u64)hi << 32) | lo;
137ce7d8056SChristophe Leroy }
138ce7d8056SChristophe Leroy #define vdso_shift_ns vdso_shift_ns
139ce7d8056SChristophe Leroy #endif
140ce7d8056SChristophe Leroy 
141ce7d8056SChristophe Leroy #ifdef __powerpc64__
142ce7d8056SChristophe Leroy int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
143ce7d8056SChristophe Leroy 			     const struct vdso_data *vd);
144ce7d8056SChristophe Leroy int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
145ce7d8056SChristophe Leroy 			    const struct vdso_data *vd);
146ce7d8056SChristophe Leroy #else
147ce7d8056SChristophe Leroy int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
148ce7d8056SChristophe Leroy 			     const struct vdso_data *vd);
149d0e3fc69SChristophe Leroy int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
150d0e3fc69SChristophe Leroy 			       const struct vdso_data *vd);
151ce7d8056SChristophe Leroy int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
152ce7d8056SChristophe Leroy 			    const struct vdso_data *vd);
153ce7d8056SChristophe Leroy #endif
154ce7d8056SChristophe Leroy int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
155ce7d8056SChristophe Leroy 			    const struct vdso_data *vd);
156ce7d8056SChristophe Leroy __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
157ce7d8056SChristophe Leroy 				    const struct vdso_data *vd);
158ce7d8056SChristophe Leroy #endif /* __ASSEMBLY__ */
159ce7d8056SChristophe Leroy 
160ce7d8056SChristophe Leroy #endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */
161