summaryrefslogtreecommitdiffstats
path: root/kernel/time/posix-stubs.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/posix-stubs.c')
-rw-r--r--kernel/time/posix-stubs.c112
1 files changed, 102 insertions, 10 deletions
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c0cd53eb018a..38f3b20efa29 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -17,6 +17,7 @@
17#include <linux/ktime.h> 17#include <linux/ktime.h>
18#include <linux/timekeeping.h> 18#include <linux/timekeeping.h>
19#include <linux/posix-timers.h> 19#include <linux/posix-timers.h>
20#include <linux/compat.h>
20 21
21asmlinkage long sys_ni_posix_timers(void) 22asmlinkage long sys_ni_posix_timers(void)
22{ 23{
@@ -27,6 +28,7 @@ asmlinkage long sys_ni_posix_timers(void)
27} 28}
28 29
29#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) 30#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
31#define COMPAT_SYS_NI(name) SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
30 32
31SYS_NI(timer_create); 33SYS_NI(timer_create);
32SYS_NI(timer_gettime); 34SYS_NI(timer_gettime);
@@ -39,6 +41,12 @@ SYS_NI(setitimer);
39#ifdef __ARCH_WANT_SYS_ALARM 41#ifdef __ARCH_WANT_SYS_ALARM
40SYS_NI(alarm); 42SYS_NI(alarm);
41#endif 43#endif
44COMPAT_SYS_NI(timer_create);
45COMPAT_SYS_NI(clock_adjtime);
46COMPAT_SYS_NI(timer_settime);
47COMPAT_SYS_NI(timer_gettime);
48COMPAT_SYS_NI(getitimer);
49COMPAT_SYS_NI(setitimer);
42 50
43/* 51/*
44 * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC 52 * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
@@ -110,22 +118,106 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
110 case CLOCK_REALTIME: 118 case CLOCK_REALTIME:
111 case CLOCK_MONOTONIC: 119 case CLOCK_MONOTONIC:
112 case CLOCK_BOOTTIME: 120 case CLOCK_BOOTTIME:
113 if (copy_from_user(&t, rqtp, sizeof (struct timespec))) 121 break;
114 return -EFAULT;
115 t64 = timespec_to_timespec64(t);
116 if (!timespec64_valid(&t64))
117 return -EINVAL;
118 return hrtimer_nanosleep(&t64, rmtp, flags & TIMER_ABSTIME ?
119 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
120 which_clock);
121 default: 122 default:
122 return -EINVAL; 123 return -EINVAL;
123 } 124 }
125
126 if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
127 return -EFAULT;
128 t64 = timespec_to_timespec64(t);
129 if (!timespec64_valid(&t64))
130 return -EINVAL;
131 if (flags & TIMER_ABSTIME)
132 rmtp = NULL;
133 current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
134 current->restart_block.nanosleep.rmtp = rmtp;
135 return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
136 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
137 which_clock);
124} 138}
125 139
126#ifdef CONFIG_COMPAT 140#ifdef CONFIG_COMPAT
127long clock_nanosleep_restart(struct restart_block *restart_block) 141COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
142 struct compat_timespec __user *, tp)
143{
144 struct timespec64 new_tp64;
145 struct timespec new_tp;
146
147 if (which_clock != CLOCK_REALTIME)
148 return -EINVAL;
149 if (compat_get_timespec(&new_tp, tp))
150 return -EFAULT;
151
152 new_tp64 = timespec_to_timespec64(new_tp);
153 return do_sys_settimeofday64(&new_tp64, NULL);
154}
155
156COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
157 struct compat_timespec __user *,tp)
128{ 158{
129 return hrtimer_nanosleep_restart(restart_block); 159 struct timespec64 kernel_tp64;
160 struct timespec kernel_tp;
161
162 switch (which_clock) {
163 case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break;
164 case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break;
165 case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break;
166 default: return -EINVAL;
167 }
168
169 kernel_tp = timespec64_to_timespec(kernel_tp64);
170 if (compat_put_timespec(&kernel_tp, tp))
171 return -EFAULT;
172 return 0;
173}
174
175COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
176 struct compat_timespec __user *, tp)
177{
178 struct timespec rtn_tp = {
179 .tv_sec = 0,
180 .tv_nsec = hrtimer_resolution,
181 };
182
183 switch (which_clock) {
184 case CLOCK_REALTIME:
185 case CLOCK_MONOTONIC:
186 case CLOCK_BOOTTIME:
187 if (compat_put_timespec(&rtn_tp, tp))
188 return -EFAULT;
189 return 0;
190 default:
191 return -EINVAL;
192 }
193}
194COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
195 struct compat_timespec __user *, rqtp,
196 struct compat_timespec __user *, rmtp)
197{
198 struct timespec64 t64;
199 struct timespec t;
200
201 switch (which_clock) {
202 case CLOCK_REALTIME:
203 case CLOCK_MONOTONIC:
204 case CLOCK_BOOTTIME:
205 break;
206 default:
207 return -EINVAL;
208 }
209
210 if (compat_get_timespec(&t, rqtp))
211 return -EFAULT;
212 t64 = timespec_to_timespec64(t);
213 if (!timespec64_valid(&t64))
214 return -EINVAL;
215 if (flags & TIMER_ABSTIME)
216 rmtp = NULL;
217 current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
218 current->restart_block.nanosleep.compat_rmtp = rmtp;
219 return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
220 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
221 which_clock);
130} 222}
131#endif 223#endif