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