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
20baa73d9eSNicolas Pitre /*
21baa73d9eSNicolas Pitre * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
22baa73d9eSNicolas Pitre * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
23baa73d9eSNicolas Pitre * is also included for convenience as at least systemd uses it.
24baa73d9eSNicolas Pitre */
25baa73d9eSNicolas Pitre
SYSCALL_DEFINE2(clock_settime,const clockid_t,which_clock,const struct __kernel_timespec __user *,tp)26baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
276d5b8413SDeepa Dinamani const struct __kernel_timespec __user *, tp)
28baa73d9eSNicolas Pitre {
295c499410SDeepa Dinamani struct timespec64 new_tp;
30baa73d9eSNicolas Pitre
31baa73d9eSNicolas Pitre if (which_clock != CLOCK_REALTIME)
32baa73d9eSNicolas Pitre return -EINVAL;
335c499410SDeepa Dinamani if (get_timespec64(&new_tp, tp))
34baa73d9eSNicolas Pitre return -EFAULT;
352ac00f17SDeepa Dinamani
365c499410SDeepa Dinamani return do_sys_settimeofday64(&new_tp, NULL);
37baa73d9eSNicolas Pitre }
38baa73d9eSNicolas Pitre
do_clock_gettime(clockid_t which_clock,struct timespec64 * tp)39221f9d9cSJiri Slaby static int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
405c499410SDeepa Dinamani {
415c499410SDeepa Dinamani switch (which_clock) {
425c499410SDeepa Dinamani case CLOCK_REALTIME:
435c499410SDeepa Dinamani ktime_get_real_ts64(tp);
445c499410SDeepa Dinamani break;
455c499410SDeepa Dinamani case CLOCK_MONOTONIC:
465c499410SDeepa Dinamani ktime_get_ts64(tp);
475a590f35SAndrei Vagin timens_add_monotonic(tp);
485c499410SDeepa Dinamani break;
495c499410SDeepa Dinamani case CLOCK_BOOTTIME:
5058a10456SArnd Bergmann ktime_get_boottime_ts64(tp);
515a590f35SAndrei Vagin timens_add_boottime(tp);
525c499410SDeepa Dinamani break;
535c499410SDeepa Dinamani default:
545c499410SDeepa Dinamani return -EINVAL;
555c499410SDeepa Dinamani }
565c499410SDeepa Dinamani
575c499410SDeepa Dinamani return 0;
585c499410SDeepa Dinamani }
59221f9d9cSJiri Slaby
SYSCALL_DEFINE2(clock_gettime,const clockid_t,which_clock,struct __kernel_timespec __user *,tp)60baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
616d5b8413SDeepa Dinamani struct __kernel_timespec __user *, tp)
62baa73d9eSNicolas Pitre {
635c499410SDeepa Dinamani int ret;
645c499410SDeepa Dinamani struct timespec64 kernel_tp;
65baa73d9eSNicolas Pitre
665c499410SDeepa Dinamani ret = do_clock_gettime(which_clock, &kernel_tp);
675c499410SDeepa Dinamani if (ret)
685c499410SDeepa Dinamani return ret;
693c9c12f4SDeepa Dinamani
705c499410SDeepa Dinamani if (put_timespec64(&kernel_tp, tp))
71baa73d9eSNicolas Pitre return -EFAULT;
72baa73d9eSNicolas Pitre return 0;
73baa73d9eSNicolas Pitre }
74baa73d9eSNicolas Pitre
SYSCALL_DEFINE2(clock_getres,const clockid_t,which_clock,struct __kernel_timespec __user *,tp)756d5b8413SDeepa Dinamani SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp)
76baa73d9eSNicolas Pitre {
775c499410SDeepa Dinamani struct timespec64 rtn_tp = {
78baa73d9eSNicolas Pitre .tv_sec = 0,
79baa73d9eSNicolas Pitre .tv_nsec = hrtimer_resolution,
80baa73d9eSNicolas Pitre };
81baa73d9eSNicolas Pitre
82baa73d9eSNicolas Pitre switch (which_clock) {
83baa73d9eSNicolas Pitre case CLOCK_REALTIME:
84baa73d9eSNicolas Pitre case CLOCK_MONOTONIC:
85baa73d9eSNicolas Pitre case CLOCK_BOOTTIME:
865c499410SDeepa Dinamani if (put_timespec64(&rtn_tp, tp))
87baa73d9eSNicolas Pitre return -EFAULT;
88baa73d9eSNicolas Pitre return 0;
89baa73d9eSNicolas Pitre default:
90baa73d9eSNicolas Pitre return -EINVAL;
91baa73d9eSNicolas Pitre }
92baa73d9eSNicolas Pitre }
93baa73d9eSNicolas Pitre
SYSCALL_DEFINE4(clock_nanosleep,const clockid_t,which_clock,int,flags,const struct __kernel_timespec __user *,rqtp,struct __kernel_timespec __user *,rmtp)94baa73d9eSNicolas Pitre SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
9501909974SDeepa Dinamani const struct __kernel_timespec __user *, rqtp,
9601909974SDeepa Dinamani struct __kernel_timespec __user *, rmtp)
97baa73d9eSNicolas Pitre {
98fe460423SArnd Bergmann struct timespec64 t;
991f9b37bfSAndrei Vagin ktime_t texp;
100baa73d9eSNicolas Pitre
101baa73d9eSNicolas Pitre switch (which_clock) {
102baa73d9eSNicolas Pitre case CLOCK_REALTIME:
103baa73d9eSNicolas Pitre case CLOCK_MONOTONIC:
104baa73d9eSNicolas Pitre case CLOCK_BOOTTIME:
105edbeda46SAl Viro break;
106edbeda46SAl Viro default:
107edbeda46SAl Viro return -EINVAL;
108edbeda46SAl Viro }
109edbeda46SAl Viro
110fe460423SArnd Bergmann if (get_timespec64(&t, rqtp))
111baa73d9eSNicolas Pitre return -EFAULT;
112fe460423SArnd Bergmann if (!timespec64_valid(&t))
113baa73d9eSNicolas Pitre return -EINVAL;
114192a82f9SAl Viro if (flags & TIMER_ABSTIME)
115192a82f9SAl Viro rmtp = NULL;
116*9f76d591SJann Horn current->restart_block.fn = do_no_restart_syscall;
117edbeda46SAl Viro current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
118192a82f9SAl Viro current->restart_block.nanosleep.rmtp = rmtp;
1191f9b37bfSAndrei Vagin texp = timespec64_to_ktime(t);
1201f9b37bfSAndrei Vagin if (flags & TIMER_ABSTIME)
1211f9b37bfSAndrei Vagin texp = timens_ktime_to_host(which_clock, texp);
1221f9b37bfSAndrei Vagin return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
123baa73d9eSNicolas Pitre HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
124baa73d9eSNicolas Pitre which_clock);
125baa73d9eSNicolas Pitre }
126baa73d9eSNicolas Pitre
127b5793b0dSDeepa Dinamani #ifdef CONFIG_COMPAT_32BIT_TIME
1288dabe724SArnd Bergmann
SYSCALL_DEFINE2(clock_settime32,const clockid_t,which_clock,struct old_timespec32 __user *,tp)1298dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_settime32, const clockid_t, which_clock,
1309afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp)
131d822cdccSAl Viro {
1325c499410SDeepa Dinamani struct timespec64 new_tp;
133d822cdccSAl Viro
134d822cdccSAl Viro if (which_clock != CLOCK_REALTIME)
135d822cdccSAl Viro return -EINVAL;
1369afc5eeeSArnd Bergmann if (get_old_timespec32(&new_tp, tp))
137d822cdccSAl Viro return -EFAULT;
138d822cdccSAl Viro
1395c499410SDeepa Dinamani return do_sys_settimeofday64(&new_tp, NULL);
140d822cdccSAl Viro }
141d822cdccSAl Viro
SYSCALL_DEFINE2(clock_gettime32,clockid_t,which_clock,struct old_timespec32 __user *,tp)1428dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock,
1439afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp)
144d822cdccSAl Viro {
1455c499410SDeepa Dinamani int ret;
1465c499410SDeepa Dinamani struct timespec64 kernel_tp;
147d822cdccSAl Viro
1485c499410SDeepa Dinamani ret = do_clock_gettime(which_clock, &kernel_tp);
1495c499410SDeepa Dinamani if (ret)
1505c499410SDeepa Dinamani return ret;
151d822cdccSAl Viro
1529afc5eeeSArnd Bergmann if (put_old_timespec32(&kernel_tp, tp))
153d822cdccSAl Viro return -EFAULT;
154d822cdccSAl Viro return 0;
155d822cdccSAl Viro }
156d822cdccSAl Viro
SYSCALL_DEFINE2(clock_getres_time32,clockid_t,which_clock,struct old_timespec32 __user *,tp)1578dabe724SArnd Bergmann SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock,
1589afc5eeeSArnd Bergmann struct old_timespec32 __user *, tp)
159d822cdccSAl Viro {
1605c499410SDeepa Dinamani struct timespec64 rtn_tp = {
161d822cdccSAl Viro .tv_sec = 0,
162d822cdccSAl Viro .tv_nsec = hrtimer_resolution,
163d822cdccSAl Viro };
164d822cdccSAl Viro
165d822cdccSAl Viro switch (which_clock) {
166d822cdccSAl Viro case CLOCK_REALTIME:
167d822cdccSAl Viro case CLOCK_MONOTONIC:
168d822cdccSAl Viro case CLOCK_BOOTTIME:
1699afc5eeeSArnd Bergmann if (put_old_timespec32(&rtn_tp, tp))
170d822cdccSAl Viro return -EFAULT;
171d822cdccSAl Viro return 0;
172d822cdccSAl Viro default:
173d822cdccSAl Viro return -EINVAL;
174d822cdccSAl Viro }
175d822cdccSAl Viro }
1765c499410SDeepa Dinamani
SYSCALL_DEFINE4(clock_nanosleep_time32,clockid_t,which_clock,int,flags,struct old_timespec32 __user *,rqtp,struct old_timespec32 __user *,rmtp)1778dabe724SArnd Bergmann SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,
1789afc5eeeSArnd Bergmann struct old_timespec32 __user *, rqtp,
1799afc5eeeSArnd Bergmann struct old_timespec32 __user *, rmtp)
180baa73d9eSNicolas Pitre {
181fe460423SArnd Bergmann struct timespec64 t;
1821f9b37bfSAndrei Vagin ktime_t texp;
183edbeda46SAl Viro
184edbeda46SAl Viro switch (which_clock) {
185edbeda46SAl Viro case CLOCK_REALTIME:
186edbeda46SAl Viro case CLOCK_MONOTONIC:
187edbeda46SAl Viro case CLOCK_BOOTTIME:
188edbeda46SAl Viro break;
189edbeda46SAl Viro default:
190edbeda46SAl Viro return -EINVAL;
191edbeda46SAl Viro }
192edbeda46SAl Viro
1939afc5eeeSArnd Bergmann if (get_old_timespec32(&t, rqtp))
194edbeda46SAl Viro return -EFAULT;
195fe460423SArnd Bergmann if (!timespec64_valid(&t))
196edbeda46SAl Viro return -EINVAL;
197edbeda46SAl Viro if (flags & TIMER_ABSTIME)
198edbeda46SAl Viro rmtp = NULL;
199*9f76d591SJann Horn current->restart_block.fn = do_no_restart_syscall;
200edbeda46SAl Viro current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
201edbeda46SAl Viro current->restart_block.nanosleep.compat_rmtp = rmtp;
2021f9b37bfSAndrei Vagin texp = timespec64_to_ktime(t);
2031f9b37bfSAndrei Vagin if (flags & TIMER_ABSTIME)
2041f9b37bfSAndrei Vagin texp = timens_ktime_to_host(which_clock, texp);
2051f9b37bfSAndrei Vagin return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
206edbeda46SAl Viro HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
207edbeda46SAl Viro which_clock);
208baa73d9eSNicolas Pitre }
209baa73d9eSNicolas Pitre #endif
210