1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2018 ARM Limited 4 */ 5 #ifndef __ASM_VDSO_GETTIMEOFDAY_H 6 #define __ASM_VDSO_GETTIMEOFDAY_H 7 8 #ifndef __ASSEMBLY__ 9 10 #include <asm/alternative.h> 11 #include <asm/arch_timer.h> 12 #include <asm/barrier.h> 13 #include <asm/unistd.h> 14 #include <asm/sysreg.h> 15 16 #define VDSO_HAS_CLOCK_GETRES 1 17 18 static __always_inline 19 int gettimeofday_fallback(struct __kernel_old_timeval *_tv, 20 struct timezone *_tz) 21 { 22 register struct timezone *tz asm("x1") = _tz; 23 register struct __kernel_old_timeval *tv asm("x0") = _tv; 24 register long ret asm ("x0"); 25 register long nr asm("x8") = __NR_gettimeofday; 26 27 asm volatile( 28 " svc #0\n" 29 : "=r" (ret) 30 : "r" (tv), "r" (tz), "r" (nr) 31 : "memory"); 32 33 return ret; 34 } 35 36 static __always_inline 37 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 38 { 39 register struct __kernel_timespec *ts asm("x1") = _ts; 40 register clockid_t clkid asm("x0") = _clkid; 41 register long ret asm ("x0"); 42 register long nr asm("x8") = __NR_clock_gettime; 43 44 asm volatile( 45 " svc #0\n" 46 : "=r" (ret) 47 : "r" (clkid), "r" (ts), "r" (nr) 48 : "memory"); 49 50 return ret; 51 } 52 53 static __always_inline 54 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 55 { 56 register struct __kernel_timespec *ts asm("x1") = _ts; 57 register clockid_t clkid asm("x0") = _clkid; 58 register long ret asm ("x0"); 59 register long nr asm("x8") = __NR_clock_getres; 60 61 asm volatile( 62 " svc #0\n" 63 : "=r" (ret) 64 : "r" (clkid), "r" (ts), "r" (nr) 65 : "memory"); 66 67 return ret; 68 } 69 70 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 71 const struct vdso_time_data *vd) 72 { 73 /* 74 * Core checks for mode already, so this raced against a concurrent 75 * update. Return something. Core will do another round and then 76 * see the mode change and fallback to the syscall. 77 */ 78 if (clock_mode == VDSO_CLOCKMODE_NONE) 79 return 0; 80 81 return __arch_counter_get_cntvct(); 82 } 83 84 #if IS_ENABLED(CONFIG_CC_IS_GCC) && IS_ENABLED(CONFIG_PAGE_SIZE_64KB) 85 static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void) 86 { 87 const struct vdso_time_data *ret = &vdso_u_time_data; 88 89 /* Work around invalid absolute relocations */ 90 OPTIMIZER_HIDE_VAR(ret); 91 92 return ret; 93 } 94 #define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data 95 #endif /* IS_ENABLED(CONFIG_CC_IS_GCC) && IS_ENABLED(CONFIG_PAGE_SIZE_64KB) */ 96 97 #endif /* !__ASSEMBLY__ */ 98 99 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ 100