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
26SYSCALL_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(&new_tp, tp))
34		return -EFAULT;
35
36	return do_sys_settimeofday64(&new_tp, NULL);
37}
38
39static 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(tp);
44		break;
45	case CLOCK_MONOTONIC:
46		ktime_get_ts64(tp);
47		timens_add_monotonic(tp);
48		break;
49	case CLOCK_BOOTTIME:
50		ktime_get_boottime_ts64(tp);
51		timens_add_boottime(tp);
52		break;
53	default:
54		return -EINVAL;
55	}
56
57	return 0;
58}
59
60SYSCALL_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, &kernel_tp);
67	if (ret)
68		return ret;
69
70	if (put_timespec64(&kernel_tp, tp))
71		return -EFAULT;
72	return 0;
73}
74
75SYSCALL_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(&rtn_tp, tp))
87			return -EFAULT;
88		return 0;
89	default:
90		return -EINVAL;
91	}
92}
93
94SYSCALL_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(&t, rqtp))
111		return -EFAULT;
112	if (!timespec64_valid(&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(t);
120	if (flags & TIMER_ABSTIME)
121		texp = timens_ktime_to_host(which_clock, texp);
122	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
123				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
124				 which_clock);
125}
126
127#ifdef CONFIG_COMPAT_32BIT_TIME
128
129SYSCALL_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(&new_tp, NULL);
140}
141
142SYSCALL_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, &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
157SYSCALL_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
177SYSCALL_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(&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(t);
203	if (flags & TIMER_ABSTIME)
204		texp = timens_ktime_to_host(which_clock, texp);
205	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
206				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
207				 which_clock);
208}
209#endif
210