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