gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/vdso/vdso.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // This is the VDSO for sandboxed binaries. This file just contains the entry 16 // points to the VDSO. All of the real work is done in vdso_time.cc 17 18 #define _DEFAULT_SOURCE // ensure glibc provides struct timezone. 19 #include <sys/time.h> 20 #include <time.h> 21 22 #include "vdso/syscalls.h" 23 #include "vdso/vdso_time.h" 24 25 namespace vdso { 26 namespace { 27 28 int __common_clock_gettime(clockid_t clock, struct timespec* ts) { 29 int ret; 30 31 switch (clock) { 32 case CLOCK_REALTIME_COARSE: 33 // Fallthrough, CLOCK_REALTIME_COARSE is an alias for CLOCK_REALTIME 34 case CLOCK_REALTIME: 35 ret = ClockRealtime(ts); 36 break; 37 38 case CLOCK_BOOTTIME: 39 // Fallthrough, CLOCK_BOOTTIME is an alias for CLOCK_MONOTONIC 40 case CLOCK_MONOTONIC_RAW: 41 // Fallthrough, CLOCK_MONOTONIC_RAW is an alias for CLOCK_MONOTONIC 42 case CLOCK_MONOTONIC_COARSE: 43 // Fallthrough, CLOCK_MONOTONIC_COARSE is an alias for CLOCK_MONOTONIC 44 case CLOCK_MONOTONIC: 45 ret = ClockMonotonic(ts); 46 break; 47 48 default: 49 ret = sys_clock_gettime(clock, ts); 50 break; 51 } 52 53 return ret; 54 } 55 56 int __common_gettimeofday(struct timeval* tv, struct timezone* tz) { 57 if (tv) { 58 struct timespec ts; 59 int ret = ClockRealtime(&ts); 60 if (ret) { 61 return ret; 62 } 63 tv->tv_sec = ts.tv_sec; 64 tv->tv_usec = ts.tv_nsec / 1000; 65 } 66 67 // Nobody should be calling gettimeofday() with a non-NULL 68 // timezone pointer. If they do then they will get zeros. 69 if (tz) { 70 tz->tz_minuteswest = 0; 71 tz->tz_dsttime = 0; 72 } 73 74 return 0; 75 } 76 } // namespace 77 78 // __kernel_rt_sigreturn() implements rt_sigreturn() 79 extern "C" void __kernel_rt_sigreturn(unsigned long unused) { 80 // No optimizations yet, just make the real system call. 81 sys_rt_sigreturn(); 82 } 83 84 #if __x86_64__ 85 86 // __vdso_clock_gettime() implements clock_gettime() 87 extern "C" int __vdso_clock_gettime(clockid_t clock, struct timespec* ts) { 88 return __common_clock_gettime(clock, ts); 89 } 90 extern "C" int clock_gettime(clockid_t clock, struct timespec* ts) 91 __attribute__((weak, alias("__vdso_clock_gettime"))); 92 93 // __vdso_gettimeofday() implements gettimeofday() 94 extern "C" int __vdso_gettimeofday(struct timeval* tv, struct timezone* tz) { 95 return __common_gettimeofday(tv, tz); 96 } 97 extern "C" int gettimeofday(struct timeval* tv, struct timezone* tz) 98 __attribute__((weak, alias("__vdso_gettimeofday"))); 99 100 // __vdso_time() implements time() 101 extern "C" time_t __vdso_time(time_t* t) { 102 struct timespec ts; 103 ClockRealtime(&ts); 104 if (t) { 105 *t = ts.tv_sec; 106 } 107 return ts.tv_sec; 108 } 109 extern "C" time_t time(time_t* t) __attribute__((weak, alias("__vdso_time"))); 110 111 // __vdso_getcpu() implements getcpu() 112 extern "C" long __vdso_getcpu(unsigned* cpu, unsigned* node, 113 struct getcpu_cache* cache) { 114 // No optimizations yet, just make the real system call. 115 return sys_getcpu(cpu, node, cache); 116 } 117 extern "C" long getcpu(unsigned* cpu, unsigned* node, 118 struct getcpu_cache* cache) 119 __attribute__((weak, alias("__vdso_getcpu"))); 120 121 #elif __aarch64__ 122 123 // __kernel_clock_gettime() implements clock_gettime() 124 extern "C" int __kernel_clock_gettime(clockid_t clock, struct timespec* ts) { 125 return __common_clock_gettime(clock, ts); 126 } 127 128 // __kernel_gettimeofday() implements gettimeofday() 129 extern "C" int __kernel_gettimeofday(struct timeval* tv, struct timezone* tz) { 130 return __common_gettimeofday(tv, tz); 131 } 132 133 // __kernel_clock_getres() implements clock_getres() 134 extern "C" int __kernel_clock_getres(clockid_t clock, struct timespec* res) { 135 int ret = 0; 136 137 switch (clock) { 138 case CLOCK_REALTIME: 139 case CLOCK_MONOTONIC: 140 case CLOCK_BOOTTIME: { 141 if (res == nullptr) { 142 return 0; 143 } 144 145 res->tv_sec = 0; 146 res->tv_nsec = 1; 147 break; 148 } 149 150 default: 151 ret = sys_clock_getres(clock, res); 152 break; 153 } 154 155 return ret; 156 } 157 158 #else 159 #error "unsupported architecture" 160 #endif 161 } // namespace vdso