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