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/unistd.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES 1 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic __always_inline 168c2ecf20Sopenharmony_ciint gettimeofday_fallback(struct __kernel_old_timeval *_tv, 178c2ecf20Sopenharmony_ci struct timezone *_tz) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci register struct timezone *tz asm("x1") = _tz; 208c2ecf20Sopenharmony_ci register struct __kernel_old_timeval *tv asm("x0") = _tv; 218c2ecf20Sopenharmony_ci register long ret asm ("x0"); 228c2ecf20Sopenharmony_ci register long nr asm("x8") = __NR_gettimeofday; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci asm volatile( 258c2ecf20Sopenharmony_ci " svc #0\n" 268c2ecf20Sopenharmony_ci : "=r" (ret) 278c2ecf20Sopenharmony_ci : "r" (tv), "r" (tz), "r" (nr) 288c2ecf20Sopenharmony_ci : "memory"); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci return ret; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic __always_inline 348c2ecf20Sopenharmony_cilong clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci register struct __kernel_timespec *ts asm("x1") = _ts; 378c2ecf20Sopenharmony_ci register clockid_t clkid asm("x0") = _clkid; 388c2ecf20Sopenharmony_ci register long ret asm ("x0"); 398c2ecf20Sopenharmony_ci register long nr asm("x8") = __NR_clock_gettime; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci asm volatile( 428c2ecf20Sopenharmony_ci " svc #0\n" 438c2ecf20Sopenharmony_ci : "=r" (ret) 448c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 458c2ecf20Sopenharmony_ci : "memory"); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci return ret; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic __always_inline 518c2ecf20Sopenharmony_ciint clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci register struct __kernel_timespec *ts asm("x1") = _ts; 548c2ecf20Sopenharmony_ci register clockid_t clkid asm("x0") = _clkid; 558c2ecf20Sopenharmony_ci register long ret asm ("x0"); 568c2ecf20Sopenharmony_ci register long nr asm("x8") = __NR_clock_getres; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci asm volatile( 598c2ecf20Sopenharmony_ci " svc #0\n" 608c2ecf20Sopenharmony_ci : "=r" (ret) 618c2ecf20Sopenharmony_ci : "r" (clkid), "r" (ts), "r" (nr) 628c2ecf20Sopenharmony_ci : "memory"); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return ret; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 688c2ecf20Sopenharmony_ci const struct vdso_data *vd) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci u64 res; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Core checks for mode already, so this raced against a concurrent 748c2ecf20Sopenharmony_ci * update. Return something. Core will do another round and then 758c2ecf20Sopenharmony_ci * see the mode change and fallback to the syscall. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci if (clock_mode == VDSO_CLOCKMODE_NONE) 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* 818c2ecf20Sopenharmony_ci * This isb() is required to prevent that the counter value 828c2ecf20Sopenharmony_ci * is speculated. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci isb(); 858c2ecf20Sopenharmony_ci asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory"); 868c2ecf20Sopenharmony_ci arch_counter_enforce_ordering(res); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return res; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic __always_inline 928c2ecf20Sopenharmony_ciconst struct vdso_data *__arch_get_vdso_data(void) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci return _vdso_data; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#ifdef CONFIG_TIME_NS 988c2ecf20Sopenharmony_cistatic __always_inline 998c2ecf20Sopenharmony_ciconst struct vdso_data *__arch_get_timens_vdso_data(void) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci return _timens_data; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci#endif 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ 108