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/time_namespace.h> |
18 | #include <linux/compat.h> |
19 | |
20 | /* |
21 | * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC |
22 | * as it is easy to remain compatible with little code. CLOCK_BOOTTIME |
23 | * is also included for convenience as at least systemd uses it. |
24 | */ |
25 | |
26 | SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, |
27 | const struct __kernel_timespec __user *, tp) |
28 | { |
29 | struct timespec64 new_tp; |
30 | |
31 | if (which_clock != CLOCK_REALTIME) |
32 | return -EINVAL; |
33 | if (get_timespec64(ts: &new_tp, uts: tp)) |
34 | return -EFAULT; |
35 | |
36 | return do_sys_settimeofday64(tv: &new_tp, NULL); |
37 | } |
38 | |
39 | static int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp) |
40 | { |
41 | switch (which_clock) { |
42 | case CLOCK_REALTIME: |
43 | ktime_get_real_ts64(tv: tp); |
44 | break; |
45 | case CLOCK_MONOTONIC: |
46 | ktime_get_ts64(ts: tp); |
47 | timens_add_monotonic(ts: tp); |
48 | break; |
49 | case CLOCK_BOOTTIME: |
50 | ktime_get_boottime_ts64(ts: tp); |
51 | timens_add_boottime(ts: tp); |
52 | break; |
53 | default: |
54 | return -EINVAL; |
55 | } |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, |
61 | struct __kernel_timespec __user *, tp) |
62 | { |
63 | int ret; |
64 | struct timespec64 kernel_tp; |
65 | |
66 | ret = do_clock_gettime(which_clock, tp: &kernel_tp); |
67 | if (ret) |
68 | return ret; |
69 | |
70 | if (put_timespec64(ts: &kernel_tp, uts: tp)) |
71 | return -EFAULT; |
72 | return 0; |
73 | } |
74 | |
75 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct __kernel_timespec __user *, tp) |
76 | { |
77 | struct timespec64 rtn_tp = { |
78 | .tv_sec = 0, |
79 | .tv_nsec = hrtimer_resolution, |
80 | }; |
81 | |
82 | switch (which_clock) { |
83 | case CLOCK_REALTIME: |
84 | case CLOCK_MONOTONIC: |
85 | case CLOCK_BOOTTIME: |
86 | if (put_timespec64(ts: &rtn_tp, uts: tp)) |
87 | return -EFAULT; |
88 | return 0; |
89 | default: |
90 | return -EINVAL; |
91 | } |
92 | } |
93 | |
94 | SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, |
95 | const struct __kernel_timespec __user *, rqtp, |
96 | struct __kernel_timespec __user *, rmtp) |
97 | { |
98 | struct timespec64 t; |
99 | ktime_t texp; |
100 | |
101 | switch (which_clock) { |
102 | case CLOCK_REALTIME: |
103 | case CLOCK_MONOTONIC: |
104 | case CLOCK_BOOTTIME: |
105 | break; |
106 | default: |
107 | return -EINVAL; |
108 | } |
109 | |
110 | if (get_timespec64(ts: &t, uts: rqtp)) |
111 | return -EFAULT; |
112 | if (!timespec64_valid(ts: &t)) |
113 | return -EINVAL; |
114 | if (flags & TIMER_ABSTIME) |
115 | rmtp = NULL; |
116 | current->restart_block.fn = do_no_restart_syscall; |
117 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; |
118 | current->restart_block.nanosleep.rmtp = rmtp; |
119 | texp = timespec64_to_ktime(ts: t); |
120 | if (flags & TIMER_ABSTIME) |
121 | texp = timens_ktime_to_host(clockid: which_clock, tim: texp); |
122 | return hrtimer_nanosleep(rqtp: texp, mode: flags & TIMER_ABSTIME ? |
123 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, |
124 | clockid: which_clock); |
125 | } |
126 | |
127 | #ifdef CONFIG_COMPAT_32BIT_TIME |
128 | |
129 | SYSCALL_DEFINE2(clock_settime32, const clockid_t, which_clock, |
130 | struct old_timespec32 __user *, tp) |
131 | { |
132 | struct timespec64 new_tp; |
133 | |
134 | if (which_clock != CLOCK_REALTIME) |
135 | return -EINVAL; |
136 | if (get_old_timespec32(&new_tp, tp)) |
137 | return -EFAULT; |
138 | |
139 | return do_sys_settimeofday64(tv: &new_tp, NULL); |
140 | } |
141 | |
142 | SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock, |
143 | struct old_timespec32 __user *, tp) |
144 | { |
145 | int ret; |
146 | struct timespec64 kernel_tp; |
147 | |
148 | ret = do_clock_gettime(which_clock, tp: &kernel_tp); |
149 | if (ret) |
150 | return ret; |
151 | |
152 | if (put_old_timespec32(&kernel_tp, tp)) |
153 | return -EFAULT; |
154 | return 0; |
155 | } |
156 | |
157 | SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock, |
158 | struct old_timespec32 __user *, tp) |
159 | { |
160 | struct timespec64 rtn_tp = { |
161 | .tv_sec = 0, |
162 | .tv_nsec = hrtimer_resolution, |
163 | }; |
164 | |
165 | switch (which_clock) { |
166 | case CLOCK_REALTIME: |
167 | case CLOCK_MONOTONIC: |
168 | case CLOCK_BOOTTIME: |
169 | if (put_old_timespec32(&rtn_tp, tp)) |
170 | return -EFAULT; |
171 | return 0; |
172 | default: |
173 | return -EINVAL; |
174 | } |
175 | } |
176 | |
177 | SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags, |
178 | struct old_timespec32 __user *, rqtp, |
179 | struct old_timespec32 __user *, rmtp) |
180 | { |
181 | struct timespec64 t; |
182 | ktime_t texp; |
183 | |
184 | switch (which_clock) { |
185 | case CLOCK_REALTIME: |
186 | case CLOCK_MONOTONIC: |
187 | case CLOCK_BOOTTIME: |
188 | break; |
189 | default: |
190 | return -EINVAL; |
191 | } |
192 | |
193 | if (get_old_timespec32(&t, rqtp)) |
194 | return -EFAULT; |
195 | if (!timespec64_valid(ts: &t)) |
196 | return -EINVAL; |
197 | if (flags & TIMER_ABSTIME) |
198 | rmtp = NULL; |
199 | current->restart_block.fn = do_no_restart_syscall; |
200 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; |
201 | current->restart_block.nanosleep.compat_rmtp = rmtp; |
202 | texp = timespec64_to_ktime(ts: t); |
203 | if (flags & TIMER_ABSTIME) |
204 | texp = timens_ktime_to_host(clockid: which_clock, tim: texp); |
205 | return hrtimer_nanosleep(rqtp: texp, mode: flags & TIMER_ABSTIME ? |
206 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, |
207 | clockid: which_clock); |
208 | } |
209 | #endif |
210 | |