18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2018 ARM Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef __ASM_VDSO_GETTIMEOFDAY_H 68c2ecf20Sopenharmony_ci#define __ASM_VDSO_GETTIMEOFDAY_H 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <asm/barrier.h> 118c2ecf20Sopenharmony_ci#include <asm/errno.h> 128c2ecf20Sopenharmony_ci#include <asm/unistd.h> 138c2ecf20Sopenharmony_ci#include <asm/vdso/cp15.h> 148c2ecf20Sopenharmony_ci#include <uapi/linux/time.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES 1 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciextern struct vdso_data *__get_datapage(void); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic __always_inline int gettimeofday_fallback( 218c2ecf20Sopenharmony_ci struct __kernel_old_timeval *_tv, 228c2ecf20Sopenharmony_ci struct timezone *_tz) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci register struct timezone *tz asm("r1") = _tz; 258c2ecf20Sopenharmony_ci register struct __kernel_old_timeval *tv asm("r0") = _tv; 268c2ecf20Sopenharmony_ci register long ret asm ("r0"); 278c2ecf20Sopenharmony_ci register long nr asm("r7") = __NR_gettimeofday; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci asm volatile( 308c2ecf20Sopenharmony_ci " swi #0\n" 318c2ecf20Sopenharmony_ci : "=r" (ret) 328c2ecf20Sopenharmony_ci : "r" (tv), "r" (tz), "r" (nr) 338c2ecf20Sopenharmony_ci : "memory"); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return ret; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic __always_inline long clock_gettime_fallback( 398c2ecf20Sopenharmony_ci clockid_t _clkid, 408c2ecf20Sopenharmony_ci struct __kernel_timespec *_ts) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci register struct __kernel_timespec *ts asm("r1") = _ts; 438c2ecf20Sopenharmony_ci register clockid_t clkid asm("r0") = _clkid; 448c2ecf20Sopenharmony_ci register long ret asm ("r0"); 458c2ecf20Sopenharmony_ci register long nr asm("r7") = __NR_clock_gettime64; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci asm volatile( 488c2ecf20Sopenharmony_ci " swi #0\n" 498c2ecf20Sopenharmony_ci : "=r" (ret) 508c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 518c2ecf20Sopenharmony_ci : "memory"); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return ret; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic __always_inline long clock_gettime32_fallback( 578c2ecf20Sopenharmony_ci clockid_t _clkid, 588c2ecf20Sopenharmony_ci struct old_timespec32 *_ts) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci register struct old_timespec32 *ts asm("r1") = _ts; 618c2ecf20Sopenharmony_ci register clockid_t clkid asm("r0") = _clkid; 628c2ecf20Sopenharmony_ci register long ret asm ("r0"); 638c2ecf20Sopenharmony_ci register long nr asm("r7") = __NR_clock_gettime; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci asm volatile( 668c2ecf20Sopenharmony_ci " swi #0\n" 678c2ecf20Sopenharmony_ci : "=r" (ret) 688c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 698c2ecf20Sopenharmony_ci : "memory"); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return ret; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic __always_inline int clock_getres_fallback( 758c2ecf20Sopenharmony_ci clockid_t _clkid, 768c2ecf20Sopenharmony_ci struct __kernel_timespec *_ts) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci register struct __kernel_timespec *ts asm("r1") = _ts; 798c2ecf20Sopenharmony_ci register clockid_t clkid asm("r0") = _clkid; 808c2ecf20Sopenharmony_ci register long ret asm ("r0"); 818c2ecf20Sopenharmony_ci register long nr asm("r7") = __NR_clock_getres_time64; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci asm volatile( 848c2ecf20Sopenharmony_ci " swi #0\n" 858c2ecf20Sopenharmony_ci : "=r" (ret) 868c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 878c2ecf20Sopenharmony_ci : "memory"); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return ret; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic __always_inline int clock_getres32_fallback( 938c2ecf20Sopenharmony_ci clockid_t _clkid, 948c2ecf20Sopenharmony_ci struct old_timespec32 *_ts) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci register struct old_timespec32 *ts asm("r1") = _ts; 978c2ecf20Sopenharmony_ci register clockid_t clkid asm("r0") = _clkid; 988c2ecf20Sopenharmony_ci register long ret asm ("r0"); 998c2ecf20Sopenharmony_ci register long nr asm("r7") = __NR_clock_getres; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci asm volatile( 1028c2ecf20Sopenharmony_ci " swi #0\n" 1038c2ecf20Sopenharmony_ci : "=r" (ret) 1048c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 1058c2ecf20Sopenharmony_ci : "memory"); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return ret; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline bool arm_vdso_hres_capable(void) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci return IS_ENABLED(CONFIG_ARM_ARCH_TIMER); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci#define __arch_vdso_hres_capable arm_vdso_hres_capable 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic __always_inline u64 __arch_get_hw_counter(int clock_mode, 1178c2ecf20Sopenharmony_ci const struct vdso_data *vd) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_ARCH_TIMER 1208c2ecf20Sopenharmony_ci u64 cycle_now; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* 1238c2ecf20Sopenharmony_ci * Core checks for mode already, so this raced against a concurrent 1248c2ecf20Sopenharmony_ci * update. Return something. Core will do another round and then 1258c2ecf20Sopenharmony_ci * see the mode change and fallback to the syscall. 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci if (clock_mode == VDSO_CLOCKMODE_NONE) 1288c2ecf20Sopenharmony_ci return 0; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci isb(); 1318c2ecf20Sopenharmony_ci cycle_now = read_sysreg(CNTVCT); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci return cycle_now; 1348c2ecf20Sopenharmony_ci#else 1358c2ecf20Sopenharmony_ci /* Make GCC happy. This is compiled out anyway */ 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci#endif 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic __always_inline const struct vdso_data *__arch_get_vdso_data(void) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci return __get_datapage(); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ 148