135728b82SThomas Gleixner // SPDX-License-Identifier: GPL-2.0 2baa73d9eSNicolas Pitre /* 3baa73d9eSNicolas Pitre * Dummy stubs used when CONFIG_POSIX_TIMERS=n 4baa73d9eSNicolas Pitre * 5baa73d9eSNicolas Pitre * Created by: Nicolas Pitre, July 2016 6baa73d9eSNicolas Pitre * Copyright: (C) 2016 Linaro Limited 7baa73d9eSNicolas Pitre */ 8baa73d9eSNicolas Pitre 9baa73d9eSNicolas Pitre #include <linux/linkage.h> 10baa73d9eSNicolas Pitre #include <linux/kernel.h> 11baa73d9eSNicolas Pitre #include <linux/sched.h> 12baa73d9eSNicolas Pitre #include <linux/errno.h> 13baa73d9eSNicolas Pitre #include <linux/syscalls.h> 14baa73d9eSNicolas Pitre #include <linux/ktime.h> 15baa73d9eSNicolas Pitre #include <linux/timekeeping.h> 16baa73d9eSNicolas Pitre #include <linux/posix-timers.h> 175a590f35SAndrei Vagin #include <linux/time_namespace.h> 18edbeda46SAl Viro #include <linux/compat.h> 19baa73d9eSNicolas Pitre 207303e30eSDominik Brodowski #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER 217303e30eSDominik Brodowski /* Architectures may override SYS_NI and COMPAT_SYS_NI */ 227303e30eSDominik Brodowski #include <asm/syscall_wrapper.h> 237303e30eSDominik Brodowski #endif 247303e30eSDominik Brodowski 25baa73d9eSNicolas Pitre asmlinkage long sys_ni_posix_timers(void) 26baa73d9eSNicolas Pitre { 27baa73d9eSNicolas Pitre pr_err_once("process %d (%s) attempted a POSIX timer syscall " 28baa73d9eSNicolas Pitre "while CONFIG_POSIX_TIMERS is not set\n", 29baa73d9eSNicolas Pitre current->pid, current->comm); 30baa73d9eSNicolas Pitre return -ENOSYS; 31baa73d9eSNicolas Pitre } 32baa73d9eSNicolas Pitre 337303e30eSDominik Brodowski #ifndef SYS_NI 34baa73d9eSNicolas Pitre #define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) 357303e30eSDominik Brodowski #endif 367303e30eSDominik Brodowski 377303e30eSDominik Brodowski #ifndef COMPAT_SYS_NI 383a4d44b6SAl Viro #define COMPAT_SYS_NI(name) SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers) 397303e30eSDominik Brodowski #endif 40baa73d9eSNicolas Pitre 41baa73d9eSNicolas Pitre SYS_NI(timer_create); 42baa73d9eSNicolas Pitre SYS_NI(timer_gettime); 43baa73d9eSNicolas Pitre SYS_NI(timer_getoverrun); 44baa73d9eSNicolas Pitre SYS_NI(timer_settime); 45baa73d9eSNicolas Pitre SYS_NI(timer_delete); 46baa73d9eSNicolas Pitre SYS_NI(clock_adjtime); 47baa73d9eSNicolas Pitre SYS_NI(getitimer); 48baa73d9eSNicolas Pitre SYS_NI(setitimer); 498dabe724SArnd Bergmann SYS_NI(clock_adjtime32); 50baa73d9eSNicolas Pitre #ifdef __ARCH_WANT_SYS_ALARM 51baa73d9eSNicolas Pitre SYS_NI(alarm); 52baa73d9eSNicolas Pitre #endif 53baa73d9eSNicolas Pitre 54baa73d9eSNicolas Pitre /* 55baa73d9eSNicolas Pitre * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC 56baa73d9eSNicolas Pitre * as it is easy to remain compatible with little code. CLOCK_BOOTTIME 57baa73d9eSNicolas Pitre * is also included for convenience as at least systemd uses it. 58baa73d9eSNicolas Pitre */ 59baa73d9eSNicolas Pitre 60baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, 616d5b8413SDeepa Dinamani const struct __kernel_timespec __user *, tp) 62baa73d9eSNicolas Pitre { 635c499410SDeepa Dinamani struct timespec64 new_tp; 64baa73d9eSNicolas Pitre 65baa73d9eSNicolas Pitre if (which_clock != CLOCK_REALTIME) 66baa73d9eSNicolas Pitre return -EINVAL; 675c499410SDeepa Dinamani if (get_timespec64(&new_tp, tp)) 68baa73d9eSNicolas Pitre return -EFAULT; 692ac00f17SDeepa Dinamani 705c499410SDeepa Dinamani return do_sys_settimeofday64(&new_tp, NULL); 71baa73d9eSNicolas Pitre } 72baa73d9eSNicolas Pitre 73221f9d9cSJiri Slaby static int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp) 745c499410SDeepa Dinamani { 755c499410SDeepa Dinamani switch (which_clock) { 765c499410SDeepa Dinamani case CLOCK_REALTIME: 775c499410SDeepa Dinamani ktime_get_real_ts64(tp); 785c499410SDeepa Dinamani break; 795c499410SDeepa Dinamani case CLOCK_MONOTONIC: 805c499410SDeepa Dinamani ktime_get_ts64(tp); 815a590f35SAndrei Vagin timens_add_monotonic(tp); 825c499410SDeepa Dinamani break; 835c499410SDeepa Dinamani case CLOCK_BOOTTIME: 8458a10456SArnd Bergmann ktime_get_boottime_ts64(tp); 855a590f35SAndrei Vagin timens_add_boottime(tp); 865c499410SDeepa Dinamani break; 875c499410SDeepa Dinamani default: 885c499410SDeepa Dinamani return -EINVAL; 895c499410SDeepa Dinamani } 905c499410SDeepa Dinamani 915c499410SDeepa Dinamani return 0; 925c499410SDeepa Dinamani } 93221f9d9cSJiri Slaby 94baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, 956d5b8413SDeepa Dinamani struct __kernel_timespec __user *, tp) 96baa73d9eSNicolas Pitre { 975c499410SDeepa Dinamani int ret; 985c499410SDeepa Dinamani struct timespec64 kernel_tp; 99baa73d9eSNicolas Pitre 1005c499410SDeepa Dinamani ret = do_clock_gettime(which_clock, &kernel_tp); 1015c499410SDeepa Dinamani if (ret) 1025c499410SDeepa Dinamani return ret; 1033c9c12f4SDeepa Dinamani 1045c499410SDeepa Dinamani if (put_timespec64(&kernel_tp, tp)) 105baa73d9eSNicolas Pitre return -EFAULT; 106baa73d9eSNicolas Pitre return 0; 107baa73d9eSNicolas Pitre } 108baa73d9eSNicolas Pitre 1096d5b8413SDeepa Dinamani SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp) 110baa73d9eSNicolas Pitre { 1115c499410SDeepa Dinamani struct timespec64 rtn_tp = { 112baa73d9eSNicolas Pitre .tv_sec = 0, 113baa73d9eSNicolas Pitre .tv_nsec = hrtimer_resolution, 114baa73d9eSNicolas Pitre }; 115baa73d9eSNicolas Pitre 116baa73d9eSNicolas Pitre switch (which_clock) { 117baa73d9eSNicolas Pitre case CLOCK_REALTIME: 118baa73d9eSNicolas Pitre case CLOCK_MONOTONIC: 119baa73d9eSNicolas Pitre case CLOCK_BOOTTIME: 1205c499410SDeepa Dinamani if (put_timespec64(&rtn_tp, tp)) 121baa73d9eSNicolas Pitre return -EFAULT; 122baa73d9eSNicolas Pitre return 0; 123baa73d9eSNicolas Pitre default: 124baa73d9eSNicolas Pitre return -EINVAL; 125baa73d9eSNicolas Pitre } 126baa73d9eSNicolas Pitre } 127baa73d9eSNicolas Pitre 128baa73d9eSNicolas Pitre SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, 12901909974SDeepa Dinamani const struct __kernel_timespec __user *, rqtp, 13001909974SDeepa Dinamani struct __kernel_timespec __user *, rmtp) 131baa73d9eSNicolas Pitre { 132fe460423SArnd Bergmann struct timespec64 t; 1331f9b37bfSAndrei Vagin ktime_t texp; 134baa73d9eSNicolas Pitre 135baa73d9eSNicolas Pitre switch (which_clock) { 136baa73d9eSNicolas Pitre case CLOCK_REALTIME: 137baa73d9eSNicolas Pitre case CLOCK_MONOTONIC: 138baa73d9eSNicolas Pitre case CLOCK_BOOTTIME: 139edbeda46SAl Viro break; 140edbeda46SAl Viro default: 141edbeda46SAl Viro return -EINVAL; 142edbeda46SAl Viro } 143edbeda46SAl Viro 144fe460423SArnd Bergmann if (get_timespec64(&t, rqtp)) 145baa73d9eSNicolas Pitre return -EFAULT; 146fe460423SArnd Bergmann if (!timespec64_valid(&t)) 147baa73d9eSNicolas Pitre return -EINVAL; 148192a82f9SAl Viro if (flags & TIMER_ABSTIME) 149192a82f9SAl Viro rmtp = NULL; 150*9f76d591SJann Horn current->restart_block.fn = do_no_restart_syscall; 151edbeda46SAl Viro current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; 152192a82f9SAl Viro current->restart_block.nanosleep.rmtp = rmtp; 1531f9b37bfSAndrei Vagin texp = timespec64_to_ktime(t); 1541f9b37bfSAndrei Vagin if (flags & TIMER_ABSTIME) 1551f9b37bfSAndrei Vagin texp = timens_ktime_to_host(which_clock, texp); 1561f9b37bfSAndrei Vagin return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ? 157baa73d9eSNicolas Pitre HRTIMER_MODE_ABS : HRTIMER_MODE_REL, 158baa73d9eSNicolas Pitre which_clock); 159baa73d9eSNicolas Pitre } 160baa73d9eSNicolas Pitre 161baa73d9eSNicolas Pitre #ifdef CONFIG_COMPAT 16263a766a1SDeepa Dinamani COMPAT_SYS_NI(timer_create); 163f35deaffSArnd Bergmann #endif 164f35deaffSArnd Bergmann 165f35deaffSArnd Bergmann #if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA) 16663a766a1SDeepa Dinamani COMPAT_SYS_NI(getitimer); 16763a766a1SDeepa Dinamani COMPAT_SYS_NI(setitimer); 168b5793b0dSDeepa Dinamani #endif 16963a766a1SDeepa Dinamani 170b5793b0dSDeepa Dinamani #ifdef CONFIG_COMPAT_32BIT_TIME 1718dabe724SArnd Bergmann SYS_NI(timer_settime32); 1728dabe724SArnd Bergmann SYS_NI(timer_gettime32); 1738dabe724SArnd Bergmann 1748dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_settime32, const clockid_t, which_clock, 1759afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp) 176d822cdccSAl Viro { 1775c499410SDeepa Dinamani struct timespec64 new_tp; 178d822cdccSAl Viro 179d822cdccSAl Viro if (which_clock != CLOCK_REALTIME) 180d822cdccSAl Viro return -EINVAL; 1819afc5eeeSArnd Bergmann if (get_old_timespec32(&new_tp, tp)) 182d822cdccSAl Viro return -EFAULT; 183d822cdccSAl Viro 1845c499410SDeepa Dinamani return do_sys_settimeofday64(&new_tp, NULL); 185d822cdccSAl Viro } 186d822cdccSAl Viro 1878dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock, 1889afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp) 189d822cdccSAl Viro { 1905c499410SDeepa Dinamani int ret; 1915c499410SDeepa Dinamani struct timespec64 kernel_tp; 192d822cdccSAl Viro 1935c499410SDeepa Dinamani ret = do_clock_gettime(which_clock, &kernel_tp); 1945c499410SDeepa Dinamani if (ret) 1955c499410SDeepa Dinamani return ret; 196d822cdccSAl Viro 1979afc5eeeSArnd Bergmann if (put_old_timespec32(&kernel_tp, tp)) 198d822cdccSAl Viro return -EFAULT; 199d822cdccSAl Viro return 0; 200d822cdccSAl Viro } 201d822cdccSAl Viro 2028dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock, 2039afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp) 204d822cdccSAl Viro { 2055c499410SDeepa Dinamani struct timespec64 rtn_tp = { 206d822cdccSAl Viro .tv_sec = 0, 207d822cdccSAl Viro .tv_nsec = hrtimer_resolution, 208d822cdccSAl Viro }; 209d822cdccSAl Viro 210d822cdccSAl Viro switch (which_clock) { 211d822cdccSAl Viro case CLOCK_REALTIME: 212d822cdccSAl Viro case CLOCK_MONOTONIC: 213d822cdccSAl Viro case CLOCK_BOOTTIME: 2149afc5eeeSArnd Bergmann if (put_old_timespec32(&rtn_tp, tp)) 215d822cdccSAl Viro return -EFAULT; 216d822cdccSAl Viro return 0; 217d822cdccSAl Viro default: 218d822cdccSAl Viro return -EINVAL; 219d822cdccSAl Viro } 220d822cdccSAl Viro } 2215c499410SDeepa Dinamani 2228dabe724SArnd Bergmann SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags, 2239afc5eeeSArnd Bergmann struct old_timespec32 __user *, rqtp, 2249afc5eeeSArnd Bergmann struct old_timespec32 __user *, rmtp) 225baa73d9eSNicolas Pitre { 226fe460423SArnd Bergmann struct timespec64 t; 2271f9b37bfSAndrei Vagin ktime_t texp; 228edbeda46SAl Viro 229edbeda46SAl Viro switch (which_clock) { 230edbeda46SAl Viro case CLOCK_REALTIME: 231edbeda46SAl Viro case CLOCK_MONOTONIC: 232edbeda46SAl Viro case CLOCK_BOOTTIME: 233edbeda46SAl Viro break; 234edbeda46SAl Viro default: 235edbeda46SAl Viro return -EINVAL; 236edbeda46SAl Viro } 237edbeda46SAl Viro 2389afc5eeeSArnd Bergmann if (get_old_timespec32(&t, rqtp)) 239edbeda46SAl Viro return -EFAULT; 240fe460423SArnd Bergmann if (!timespec64_valid(&t)) 241edbeda46SAl Viro return -EINVAL; 242edbeda46SAl Viro if (flags & TIMER_ABSTIME) 243edbeda46SAl Viro rmtp = NULL; 244*9f76d591SJann Horn current->restart_block.fn = do_no_restart_syscall; 245edbeda46SAl Viro current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; 246edbeda46SAl Viro current->restart_block.nanosleep.compat_rmtp = rmtp; 2471f9b37bfSAndrei Vagin texp = timespec64_to_ktime(t); 2481f9b37bfSAndrei Vagin if (flags & TIMER_ABSTIME) 2491f9b37bfSAndrei Vagin texp = timens_ktime_to_host(which_clock, texp); 2501f9b37bfSAndrei Vagin return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ? 251edbeda46SAl Viro HRTIMER_MODE_ABS : HRTIMER_MODE_REL, 252edbeda46SAl Viro which_clock); 253baa73d9eSNicolas Pitre } 254baa73d9eSNicolas Pitre #endif 255