xref: /openbmc/linux/kernel/time/posix-stubs.c (revision 1b0b4c4238c0bdcf1a8ffa4c5431ec1d3fb9a345)
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