xref: /openbmc/linux/kernel/time/posix-stubs.c (revision ccb01374)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Dummy stubs used when CONFIG_POSIX_TIMERS=n
4  *
5  * Created by:  Nicolas Pitre, July 2016
6  * Copyright:   (C) 2016 Linaro Limited
7  */
8 
9 #include <linux/linkage.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/errno.h>
13 #include <linux/syscalls.h>
14 #include <linux/ktime.h>
15 #include <linux/timekeeping.h>
16 #include <linux/posix-timers.h>
17 #include <linux/compat.h>
18 
19 #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
20 /* Architectures may override SYS_NI and COMPAT_SYS_NI */
21 #include <asm/syscall_wrapper.h>
22 #endif
23 
24 asmlinkage long sys_ni_posix_timers(void)
25 {
26 	pr_err_once("process %d (%s) attempted a POSIX timer syscall "
27 		    "while CONFIG_POSIX_TIMERS is not set\n",
28 		    current->pid, current->comm);
29 	return -ENOSYS;
30 }
31 
32 #ifndef SYS_NI
33 #define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
34 #endif
35 
36 #ifndef COMPAT_SYS_NI
37 #define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
38 #endif
39 
40 SYS_NI(timer_create);
41 SYS_NI(timer_gettime);
42 SYS_NI(timer_getoverrun);
43 SYS_NI(timer_settime);
44 SYS_NI(timer_delete);
45 SYS_NI(clock_adjtime);
46 SYS_NI(getitimer);
47 SYS_NI(setitimer);
48 #ifdef __ARCH_WANT_SYS_ALARM
49 SYS_NI(alarm);
50 #endif
51 
52 /*
53  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
54  * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
55  * is also included for convenience as at least systemd uses it.
56  */
57 
58 SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
59 		const struct __kernel_timespec __user *, tp)
60 {
61 	struct timespec64 new_tp;
62 
63 	if (which_clock != CLOCK_REALTIME)
64 		return -EINVAL;
65 	if (get_timespec64(&new_tp, tp))
66 		return -EFAULT;
67 
68 	return do_sys_settimeofday64(&new_tp, NULL);
69 }
70 
71 int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
72 {
73 	switch (which_clock) {
74 	case CLOCK_REALTIME:
75 		ktime_get_real_ts64(tp);
76 		break;
77 	case CLOCK_MONOTONIC:
78 		ktime_get_ts64(tp);
79 		break;
80 	case CLOCK_BOOTTIME:
81 		ktime_get_boottime_ts64(tp);
82 		break;
83 	default:
84 		return -EINVAL;
85 	}
86 
87 	return 0;
88 }
89 SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
90 		struct __kernel_timespec __user *, tp)
91 {
92 	int ret;
93 	struct timespec64 kernel_tp;
94 
95 	ret = do_clock_gettime(which_clock, &kernel_tp);
96 	if (ret)
97 		return ret;
98 
99 	if (put_timespec64(&kernel_tp, tp))
100 		return -EFAULT;
101 	return 0;
102 }
103 
104 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp)
105 {
106 	struct timespec64 rtn_tp = {
107 		.tv_sec = 0,
108 		.tv_nsec = hrtimer_resolution,
109 	};
110 
111 	switch (which_clock) {
112 	case CLOCK_REALTIME:
113 	case CLOCK_MONOTONIC:
114 	case CLOCK_BOOTTIME:
115 		if (put_timespec64(&rtn_tp, tp))
116 			return -EFAULT;
117 		return 0;
118 	default:
119 		return -EINVAL;
120 	}
121 }
122 
123 SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
124 		const struct __kernel_timespec __user *, rqtp,
125 		struct __kernel_timespec __user *, rmtp)
126 {
127 	struct timespec64 t;
128 
129 	switch (which_clock) {
130 	case CLOCK_REALTIME:
131 	case CLOCK_MONOTONIC:
132 	case CLOCK_BOOTTIME:
133 		break;
134 	default:
135 		return -EINVAL;
136 	}
137 
138 	if (get_timespec64(&t, rqtp))
139 		return -EFAULT;
140 	if (!timespec64_valid(&t))
141 		return -EINVAL;
142 	if (flags & TIMER_ABSTIME)
143 		rmtp = NULL;
144 	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
145 	current->restart_block.nanosleep.rmtp = rmtp;
146 	return hrtimer_nanosleep(&t, flags & TIMER_ABSTIME ?
147 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
148 				 which_clock);
149 }
150 
151 #ifdef CONFIG_COMPAT
152 COMPAT_SYS_NI(timer_create);
153 COMPAT_SYS_NI(clock_adjtime);
154 COMPAT_SYS_NI(timer_settime);
155 COMPAT_SYS_NI(timer_gettime);
156 COMPAT_SYS_NI(getitimer);
157 COMPAT_SYS_NI(setitimer);
158 #endif
159 
160 #ifdef CONFIG_COMPAT_32BIT_TIME
161 COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
162 		       struct old_timespec32 __user *, tp)
163 {
164 	struct timespec64 new_tp;
165 
166 	if (which_clock != CLOCK_REALTIME)
167 		return -EINVAL;
168 	if (get_old_timespec32(&new_tp, tp))
169 		return -EFAULT;
170 
171 	return do_sys_settimeofday64(&new_tp, NULL);
172 }
173 
174 COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
175 		       struct old_timespec32 __user *, tp)
176 {
177 	int ret;
178 	struct timespec64 kernel_tp;
179 
180 	ret = do_clock_gettime(which_clock, &kernel_tp);
181 	if (ret)
182 		return ret;
183 
184 	if (put_old_timespec32(&kernel_tp, tp))
185 		return -EFAULT;
186 	return 0;
187 }
188 
189 COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
190 		       struct old_timespec32 __user *, tp)
191 {
192 	struct timespec64 rtn_tp = {
193 		.tv_sec = 0,
194 		.tv_nsec = hrtimer_resolution,
195 	};
196 
197 	switch (which_clock) {
198 	case CLOCK_REALTIME:
199 	case CLOCK_MONOTONIC:
200 	case CLOCK_BOOTTIME:
201 		if (put_old_timespec32(&rtn_tp, tp))
202 			return -EFAULT;
203 		return 0;
204 	default:
205 		return -EINVAL;
206 	}
207 }
208 
209 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
210 		       struct old_timespec32 __user *, rqtp,
211 		       struct old_timespec32 __user *, rmtp)
212 {
213 	struct timespec64 t;
214 
215 	switch (which_clock) {
216 	case CLOCK_REALTIME:
217 	case CLOCK_MONOTONIC:
218 	case CLOCK_BOOTTIME:
219 		break;
220 	default:
221 		return -EINVAL;
222 	}
223 
224 	if (get_old_timespec32(&t, rqtp))
225 		return -EFAULT;
226 	if (!timespec64_valid(&t))
227 		return -EINVAL;
228 	if (flags & TIMER_ABSTIME)
229 		rmtp = NULL;
230 	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
231 	current->restart_block.nanosleep.compat_rmtp = rmtp;
232 	return hrtimer_nanosleep(&t, flags & TIMER_ABSTIME ?
233 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
234 				 which_clock);
235 }
236 #endif
237