xref: /openbmc/linux/kernel/time/posix-stubs.c (revision 35728b8209ee7d25b6241a56304ee926469bd154)
1*35728b82SThomas 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  * This program is free software; you can redistribute it and/or modify
9baa73d9eSNicolas Pitre  * it under the terms of the GNU General Public License version 2 as
10baa73d9eSNicolas Pitre  * published by the Free Software Foundation.
11baa73d9eSNicolas Pitre  */
12baa73d9eSNicolas Pitre 
13baa73d9eSNicolas Pitre #include <linux/linkage.h>
14baa73d9eSNicolas Pitre #include <linux/kernel.h>
15baa73d9eSNicolas Pitre #include <linux/sched.h>
16baa73d9eSNicolas Pitre #include <linux/errno.h>
17baa73d9eSNicolas Pitre #include <linux/syscalls.h>
18baa73d9eSNicolas Pitre #include <linux/ktime.h>
19baa73d9eSNicolas Pitre #include <linux/timekeeping.h>
20baa73d9eSNicolas Pitre #include <linux/posix-timers.h>
21edbeda46SAl Viro #include <linux/compat.h>
22baa73d9eSNicolas Pitre 
237303e30eSDominik Brodowski #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
247303e30eSDominik Brodowski /* Architectures may override SYS_NI and COMPAT_SYS_NI */
257303e30eSDominik Brodowski #include <asm/syscall_wrapper.h>
267303e30eSDominik Brodowski #endif
277303e30eSDominik Brodowski 
28baa73d9eSNicolas Pitre asmlinkage long sys_ni_posix_timers(void)
29baa73d9eSNicolas Pitre {
30baa73d9eSNicolas Pitre 	pr_err_once("process %d (%s) attempted a POSIX timer syscall "
31baa73d9eSNicolas Pitre 		    "while CONFIG_POSIX_TIMERS is not set\n",
32baa73d9eSNicolas Pitre 		    current->pid, current->comm);
33baa73d9eSNicolas Pitre 	return -ENOSYS;
34baa73d9eSNicolas Pitre }
35baa73d9eSNicolas Pitre 
367303e30eSDominik Brodowski #ifndef SYS_NI
37baa73d9eSNicolas Pitre #define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
387303e30eSDominik Brodowski #endif
397303e30eSDominik Brodowski 
407303e30eSDominik Brodowski #ifndef COMPAT_SYS_NI
413a4d44b6SAl Viro #define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
427303e30eSDominik Brodowski #endif
43baa73d9eSNicolas Pitre 
44baa73d9eSNicolas Pitre SYS_NI(timer_create);
45baa73d9eSNicolas Pitre SYS_NI(timer_gettime);
46baa73d9eSNicolas Pitre SYS_NI(timer_getoverrun);
47baa73d9eSNicolas Pitre SYS_NI(timer_settime);
48baa73d9eSNicolas Pitre SYS_NI(timer_delete);
49baa73d9eSNicolas Pitre SYS_NI(clock_adjtime);
50baa73d9eSNicolas Pitre SYS_NI(getitimer);
51baa73d9eSNicolas Pitre SYS_NI(setitimer);
52baa73d9eSNicolas Pitre #ifdef __ARCH_WANT_SYS_ALARM
53baa73d9eSNicolas Pitre SYS_NI(alarm);
54baa73d9eSNicolas Pitre #endif
55baa73d9eSNicolas Pitre 
56baa73d9eSNicolas Pitre /*
57baa73d9eSNicolas Pitre  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
58baa73d9eSNicolas Pitre  * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
59baa73d9eSNicolas Pitre  * is also included for convenience as at least systemd uses it.
60baa73d9eSNicolas Pitre  */
61baa73d9eSNicolas Pitre 
62baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
636d5b8413SDeepa Dinamani 		const struct __kernel_timespec __user *, tp)
64baa73d9eSNicolas Pitre {
655c499410SDeepa Dinamani 	struct timespec64 new_tp;
66baa73d9eSNicolas Pitre 
67baa73d9eSNicolas Pitre 	if (which_clock != CLOCK_REALTIME)
68baa73d9eSNicolas Pitre 		return -EINVAL;
695c499410SDeepa Dinamani 	if (get_timespec64(&new_tp, tp))
70baa73d9eSNicolas Pitre 		return -EFAULT;
712ac00f17SDeepa Dinamani 
725c499410SDeepa Dinamani 	return do_sys_settimeofday64(&new_tp, NULL);
73baa73d9eSNicolas Pitre }
74baa73d9eSNicolas Pitre 
755c499410SDeepa Dinamani int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
765c499410SDeepa Dinamani {
775c499410SDeepa Dinamani 	switch (which_clock) {
785c499410SDeepa Dinamani 	case CLOCK_REALTIME:
795c499410SDeepa Dinamani 		ktime_get_real_ts64(tp);
805c499410SDeepa Dinamani 		break;
815c499410SDeepa Dinamani 	case CLOCK_MONOTONIC:
825c499410SDeepa Dinamani 		ktime_get_ts64(tp);
835c499410SDeepa Dinamani 		break;
845c499410SDeepa Dinamani 	case CLOCK_BOOTTIME:
8558a10456SArnd Bergmann 		ktime_get_boottime_ts64(tp);
865c499410SDeepa Dinamani 		break;
875c499410SDeepa Dinamani 	default:
885c499410SDeepa Dinamani 		return -EINVAL;
895c499410SDeepa Dinamani 	}
905c499410SDeepa Dinamani 
915c499410SDeepa Dinamani 	return 0;
925c499410SDeepa Dinamani }
93baa73d9eSNicolas Pitre SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
946d5b8413SDeepa Dinamani 		struct __kernel_timespec __user *, tp)
95baa73d9eSNicolas Pitre {
965c499410SDeepa Dinamani 	int ret;
975c499410SDeepa Dinamani 	struct timespec64 kernel_tp;
98baa73d9eSNicolas Pitre 
995c499410SDeepa Dinamani 	ret = do_clock_gettime(which_clock, &kernel_tp);
1005c499410SDeepa Dinamani 	if (ret)
1015c499410SDeepa Dinamani 		return ret;
1023c9c12f4SDeepa Dinamani 
1035c499410SDeepa Dinamani 	if (put_timespec64(&kernel_tp, tp))
104baa73d9eSNicolas Pitre 		return -EFAULT;
105baa73d9eSNicolas Pitre 	return 0;
106baa73d9eSNicolas Pitre }
107baa73d9eSNicolas Pitre 
1086d5b8413SDeepa Dinamani SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp)
109baa73d9eSNicolas Pitre {
1105c499410SDeepa Dinamani 	struct timespec64 rtn_tp = {
111baa73d9eSNicolas Pitre 		.tv_sec = 0,
112baa73d9eSNicolas Pitre 		.tv_nsec = hrtimer_resolution,
113baa73d9eSNicolas Pitre 	};
114baa73d9eSNicolas Pitre 
115baa73d9eSNicolas Pitre 	switch (which_clock) {
116baa73d9eSNicolas Pitre 	case CLOCK_REALTIME:
117baa73d9eSNicolas Pitre 	case CLOCK_MONOTONIC:
118baa73d9eSNicolas Pitre 	case CLOCK_BOOTTIME:
1195c499410SDeepa Dinamani 		if (put_timespec64(&rtn_tp, tp))
120baa73d9eSNicolas Pitre 			return -EFAULT;
121baa73d9eSNicolas Pitre 		return 0;
122baa73d9eSNicolas Pitre 	default:
123baa73d9eSNicolas Pitre 		return -EINVAL;
124baa73d9eSNicolas Pitre 	}
125baa73d9eSNicolas Pitre }
126baa73d9eSNicolas Pitre 
127baa73d9eSNicolas Pitre SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
12801909974SDeepa Dinamani 		const struct __kernel_timespec __user *, rqtp,
12901909974SDeepa Dinamani 		struct __kernel_timespec __user *, rmtp)
130baa73d9eSNicolas Pitre {
131fe460423SArnd Bergmann 	struct timespec64 t;
132baa73d9eSNicolas Pitre 
133baa73d9eSNicolas Pitre 	switch (which_clock) {
134baa73d9eSNicolas Pitre 	case CLOCK_REALTIME:
135baa73d9eSNicolas Pitre 	case CLOCK_MONOTONIC:
136baa73d9eSNicolas Pitre 	case CLOCK_BOOTTIME:
137edbeda46SAl Viro 		break;
138edbeda46SAl Viro 	default:
139edbeda46SAl Viro 		return -EINVAL;
140edbeda46SAl Viro 	}
141edbeda46SAl Viro 
142fe460423SArnd Bergmann 	if (get_timespec64(&t, rqtp))
143baa73d9eSNicolas Pitre 		return -EFAULT;
144fe460423SArnd Bergmann 	if (!timespec64_valid(&t))
145baa73d9eSNicolas Pitre 		return -EINVAL;
146192a82f9SAl Viro 	if (flags & TIMER_ABSTIME)
147192a82f9SAl Viro 		rmtp = NULL;
148edbeda46SAl Viro 	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
149192a82f9SAl Viro 	current->restart_block.nanosleep.rmtp = rmtp;
150fe460423SArnd Bergmann 	return hrtimer_nanosleep(&t, flags & TIMER_ABSTIME ?
151baa73d9eSNicolas Pitre 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
152baa73d9eSNicolas Pitre 				 which_clock);
153baa73d9eSNicolas Pitre }
154baa73d9eSNicolas Pitre 
155baa73d9eSNicolas Pitre #ifdef CONFIG_COMPAT
15663a766a1SDeepa Dinamani COMPAT_SYS_NI(timer_create);
15763a766a1SDeepa Dinamani COMPAT_SYS_NI(clock_adjtime);
15863a766a1SDeepa Dinamani COMPAT_SYS_NI(timer_settime);
15963a766a1SDeepa Dinamani COMPAT_SYS_NI(timer_gettime);
16063a766a1SDeepa Dinamani COMPAT_SYS_NI(getitimer);
16163a766a1SDeepa Dinamani COMPAT_SYS_NI(setitimer);
162b5793b0dSDeepa Dinamani #endif
16363a766a1SDeepa Dinamani 
164b5793b0dSDeepa Dinamani #ifdef CONFIG_COMPAT_32BIT_TIME
165d822cdccSAl Viro COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
1669afc5eeeSArnd Bergmann 		       struct old_timespec32 __user *, tp)
167d822cdccSAl Viro {
1685c499410SDeepa Dinamani 	struct timespec64 new_tp;
169d822cdccSAl Viro 
170d822cdccSAl Viro 	if (which_clock != CLOCK_REALTIME)
171d822cdccSAl Viro 		return -EINVAL;
1729afc5eeeSArnd Bergmann 	if (get_old_timespec32(&new_tp, tp))
173d822cdccSAl Viro 		return -EFAULT;
174d822cdccSAl Viro 
1755c499410SDeepa Dinamani 	return do_sys_settimeofday64(&new_tp, NULL);
176d822cdccSAl Viro }
177d822cdccSAl Viro 
1785c499410SDeepa Dinamani COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
1799afc5eeeSArnd Bergmann 		       struct old_timespec32 __user *, tp)
180d822cdccSAl Viro {
1815c499410SDeepa Dinamani 	int ret;
1825c499410SDeepa Dinamani 	struct timespec64 kernel_tp;
183d822cdccSAl Viro 
1845c499410SDeepa Dinamani 	ret = do_clock_gettime(which_clock, &kernel_tp);
1855c499410SDeepa Dinamani 	if (ret)
1865c499410SDeepa Dinamani 		return ret;
187d822cdccSAl Viro 
1889afc5eeeSArnd Bergmann 	if (put_old_timespec32(&kernel_tp, tp))
189d822cdccSAl Viro 		return -EFAULT;
190d822cdccSAl Viro 	return 0;
191d822cdccSAl Viro }
192d822cdccSAl Viro 
1935c499410SDeepa Dinamani COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
1949afc5eeeSArnd Bergmann 		       struct old_timespec32 __user *, tp)
195d822cdccSAl Viro {
1965c499410SDeepa Dinamani 	struct timespec64 rtn_tp = {
197d822cdccSAl Viro 		.tv_sec = 0,
198d822cdccSAl Viro 		.tv_nsec = hrtimer_resolution,
199d822cdccSAl Viro 	};
200d822cdccSAl Viro 
201d822cdccSAl Viro 	switch (which_clock) {
202d822cdccSAl Viro 	case CLOCK_REALTIME:
203d822cdccSAl Viro 	case CLOCK_MONOTONIC:
204d822cdccSAl Viro 	case CLOCK_BOOTTIME:
2059afc5eeeSArnd Bergmann 		if (put_old_timespec32(&rtn_tp, tp))
206d822cdccSAl Viro 			return -EFAULT;
207d822cdccSAl Viro 		return 0;
208d822cdccSAl Viro 	default:
209d822cdccSAl Viro 		return -EINVAL;
210d822cdccSAl Viro 	}
211d822cdccSAl Viro }
2125c499410SDeepa Dinamani 
213edbeda46SAl Viro COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
2149afc5eeeSArnd Bergmann 		       struct old_timespec32 __user *, rqtp,
2159afc5eeeSArnd Bergmann 		       struct old_timespec32 __user *, rmtp)
216baa73d9eSNicolas Pitre {
217fe460423SArnd Bergmann 	struct timespec64 t;
218edbeda46SAl Viro 
219edbeda46SAl Viro 	switch (which_clock) {
220edbeda46SAl Viro 	case CLOCK_REALTIME:
221edbeda46SAl Viro 	case CLOCK_MONOTONIC:
222edbeda46SAl Viro 	case CLOCK_BOOTTIME:
223edbeda46SAl Viro 		break;
224edbeda46SAl Viro 	default:
225edbeda46SAl Viro 		return -EINVAL;
226edbeda46SAl Viro 	}
227edbeda46SAl Viro 
2289afc5eeeSArnd Bergmann 	if (get_old_timespec32(&t, rqtp))
229edbeda46SAl Viro 		return -EFAULT;
230fe460423SArnd Bergmann 	if (!timespec64_valid(&t))
231edbeda46SAl Viro 		return -EINVAL;
232edbeda46SAl Viro 	if (flags & TIMER_ABSTIME)
233edbeda46SAl Viro 		rmtp = NULL;
234edbeda46SAl Viro 	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
235edbeda46SAl Viro 	current->restart_block.nanosleep.compat_rmtp = rmtp;
236fe460423SArnd Bergmann 	return hrtimer_nanosleep(&t, flags & TIMER_ABSTIME ?
237edbeda46SAl Viro 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
238edbeda46SAl Viro 				 which_clock);
239baa73d9eSNicolas Pitre }
240baa73d9eSNicolas Pitre #endif
241