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