]>
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 | ||
5c499410 | 73 | 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 | } | |
93 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | |
6d5b8413 | 94 | struct __kernel_timespec __user *, tp) |
5c499410 DD |
95 | { |
96 | int ret; | |
97 | struct timespec64 kernel_tp; | |
98 | ||
99 | ret = do_clock_gettime(which_clock, &kernel_tp); | |
100 | if (ret) | |
101 | return ret; | |
102 | ||
103 | if (put_timespec64(&kernel_tp, tp)) | |
baa73d9e NP |
104 | return -EFAULT; |
105 | return 0; | |
106 | } | |
107 | ||
6d5b8413 | 108 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp) |
baa73d9e | 109 | { |
5c499410 | 110 | struct timespec64 rtn_tp = { |
baa73d9e NP |
111 | .tv_sec = 0, |
112 | .tv_nsec = hrtimer_resolution, | |
113 | }; | |
114 | ||
115 | switch (which_clock) { | |
116 | case CLOCK_REALTIME: | |
117 | case CLOCK_MONOTONIC: | |
118 | case CLOCK_BOOTTIME: | |
5c499410 | 119 | if (put_timespec64(&rtn_tp, tp)) |
baa73d9e NP |
120 | return -EFAULT; |
121 | return 0; | |
122 | default: | |
123 | return -EINVAL; | |
124 | } | |
125 | } | |
126 | ||
127 | SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, | |
01909974 DD |
128 | const struct __kernel_timespec __user *, rqtp, |
129 | struct __kernel_timespec __user *, rmtp) | |
baa73d9e | 130 | { |
fe460423 | 131 | struct timespec64 t; |
1f9b37bf | 132 | ktime_t texp; |
baa73d9e NP |
133 | |
134 | switch (which_clock) { | |
135 | case CLOCK_REALTIME: | |
136 | case CLOCK_MONOTONIC: | |
137 | case CLOCK_BOOTTIME: | |
edbeda46 | 138 | break; |
baa73d9e NP |
139 | default: |
140 | return -EINVAL; | |
141 | } | |
edbeda46 | 142 | |
fe460423 | 143 | if (get_timespec64(&t, rqtp)) |
edbeda46 | 144 | return -EFAULT; |
fe460423 | 145 | if (!timespec64_valid(&t)) |
edbeda46 AV |
146 | return -EINVAL; |
147 | if (flags & TIMER_ABSTIME) | |
148 | rmtp = NULL; | |
149 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; | |
150 | current->restart_block.nanosleep.rmtp = rmtp; | |
1f9b37bf AV |
151 | texp = timespec64_to_ktime(t); |
152 | if (flags & TIMER_ABSTIME) | |
153 | texp = timens_ktime_to_host(which_clock, texp); | |
154 | return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ? | |
edbeda46 AV |
155 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, |
156 | which_clock); | |
baa73d9e NP |
157 | } |
158 | ||
159 | #ifdef CONFIG_COMPAT | |
63a766a1 | 160 | COMPAT_SYS_NI(timer_create); |
f35deaff AB |
161 | #endif |
162 | ||
163 | #if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA) | |
63a766a1 DD |
164 | COMPAT_SYS_NI(getitimer); |
165 | COMPAT_SYS_NI(setitimer); | |
b5793b0d | 166 | #endif |
63a766a1 | 167 | |
b5793b0d | 168 | #ifdef CONFIG_COMPAT_32BIT_TIME |
8dabe724 AB |
169 | SYS_NI(timer_settime32); |
170 | SYS_NI(timer_gettime32); | |
171 | ||
172 | SYSCALL_DEFINE2(clock_settime32, const clockid_t, which_clock, | |
173 | struct old_timespec32 __user *, tp) | |
d822cdcc | 174 | { |
5c499410 | 175 | struct timespec64 new_tp; |
d822cdcc AV |
176 | |
177 | if (which_clock != CLOCK_REALTIME) | |
178 | return -EINVAL; | |
9afc5eee | 179 | if (get_old_timespec32(&new_tp, tp)) |
d822cdcc AV |
180 | return -EFAULT; |
181 | ||
5c499410 | 182 | return do_sys_settimeofday64(&new_tp, NULL); |
d822cdcc AV |
183 | } |
184 | ||
8dabe724 AB |
185 | SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock, |
186 | struct old_timespec32 __user *, tp) | |
d822cdcc | 187 | { |
5c499410 DD |
188 | int ret; |
189 | struct timespec64 kernel_tp; | |
d822cdcc | 190 | |
5c499410 DD |
191 | ret = do_clock_gettime(which_clock, &kernel_tp); |
192 | if (ret) | |
193 | return ret; | |
d822cdcc | 194 | |
9afc5eee | 195 | if (put_old_timespec32(&kernel_tp, tp)) |
d822cdcc AV |
196 | return -EFAULT; |
197 | return 0; | |
198 | } | |
199 | ||
8dabe724 AB |
200 | SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock, |
201 | struct old_timespec32 __user *, tp) | |
d822cdcc | 202 | { |
5c499410 | 203 | struct timespec64 rtn_tp = { |
d822cdcc AV |
204 | .tv_sec = 0, |
205 | .tv_nsec = hrtimer_resolution, | |
206 | }; | |
207 | ||
208 | switch (which_clock) { | |
209 | case CLOCK_REALTIME: | |
210 | case CLOCK_MONOTONIC: | |
211 | case CLOCK_BOOTTIME: | |
9afc5eee | 212 | if (put_old_timespec32(&rtn_tp, tp)) |
d822cdcc AV |
213 | return -EFAULT; |
214 | return 0; | |
215 | default: | |
216 | return -EINVAL; | |
217 | } | |
218 | } | |
5c499410 | 219 | |
8dabe724 AB |
220 | SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags, |
221 | struct old_timespec32 __user *, rqtp, | |
222 | struct old_timespec32 __user *, rmtp) | |
baa73d9e | 223 | { |
fe460423 | 224 | struct timespec64 t; |
1f9b37bf | 225 | ktime_t texp; |
edbeda46 AV |
226 | |
227 | switch (which_clock) { | |
228 | case CLOCK_REALTIME: | |
229 | case CLOCK_MONOTONIC: | |
230 | case CLOCK_BOOTTIME: | |
231 | break; | |
232 | default: | |
233 | return -EINVAL; | |
234 | } | |
235 | ||
9afc5eee | 236 | if (get_old_timespec32(&t, rqtp)) |
edbeda46 | 237 | return -EFAULT; |
fe460423 | 238 | if (!timespec64_valid(&t)) |
edbeda46 AV |
239 | return -EINVAL; |
240 | if (flags & TIMER_ABSTIME) | |
241 | rmtp = NULL; | |
242 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; | |
243 | current->restart_block.nanosleep.compat_rmtp = rmtp; | |
1f9b37bf AV |
244 | texp = timespec64_to_ktime(t); |
245 | if (flags & TIMER_ABSTIME) | |
246 | texp = timens_ktime_to_host(which_clock, texp); | |
247 | return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ? | |
edbeda46 AV |
248 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, |
249 | which_clock); | |
baa73d9e NP |
250 | } |
251 | #endif |