1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/timex.h>
28#include <linux/errno.h>
29#include <linux/smp_lock.h>
30
31#include <asm/uaccess.h>
32
33
34
35
36
37struct timezone sys_tz;
38
39
40
41extern rwlock_t xtime_lock;
42extern unsigned long last_time_offset;
43
44#if !defined(__alpha__) && !defined(__ia64__)
45
46
47
48
49
50
51
52
53
54asmlinkage long sys_time(int * tloc)
55{
56 int i;
57
58
59
60 i = CURRENT_TIME;
61 if (tloc) {
62 if (put_user(i,tloc))
63 i = -EFAULT;
64 }
65 return i;
66}
67
68
69
70
71
72
73
74
75asmlinkage long sys_stime(int * tptr)
76{
77 int value;
78
79 if (!capable(CAP_SYS_TIME))
80 return -EPERM;
81 if (get_user(value, tptr))
82 return -EFAULT;
83 write_lock_irq(&xtime_lock);
84 xtime.tv_sec = value;
85 xtime.tv_nsec = 0;
86 last_time_offset = 0;
87 time_adjust = 0;
88 time_status |= STA_UNSYNC;
89 time_maxerror = NTP_PHASE_LIMIT;
90 time_esterror = NTP_PHASE_LIMIT;
91 write_unlock_irq(&xtime_lock);
92 return 0;
93}
94
95#endif
96
97asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz)
98{
99 if (tv) {
100 struct timeval ktv;
101 do_gettimeofday(&ktv);
102 if (copy_to_user(tv, &ktv, sizeof(ktv)))
103 return -EFAULT;
104 }
105 if (tz) {
106 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
107 return -EFAULT;
108 }
109 return 0;
110}
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128inline static void warp_clock(void)
129{
130 write_lock_irq(&xtime_lock);
131 xtime.tv_sec += sys_tz.tz_minuteswest * 60;
132 last_time_offset = 0;
133 write_unlock_irq(&xtime_lock);
134}
135
136
137
138
139
140
141
142
143
144
145
146
147int do_sys_settimeofday(struct timeval *tv, struct timezone *tz)
148{
149 static int firsttime = 1;
150
151 if (!capable(CAP_SYS_TIME))
152 return -EPERM;
153
154 if (tz) {
155
156 sys_tz = *tz;
157 if (firsttime) {
158 firsttime = 0;
159 if (!tv)
160 warp_clock();
161 }
162 }
163 if (tv)
164 {
165
166
167
168 do_settimeofday(tv);
169 }
170 return 0;
171}
172
173asmlinkage long sys_settimeofday(struct timeval *tv, struct timezone *tz)
174{
175 struct timeval new_tv;
176 struct timezone new_tz;
177
178 if (tv) {
179 if (copy_from_user(&new_tv, tv, sizeof(*tv)))
180 return -EFAULT;
181 }
182 if (tz) {
183 if (copy_from_user(&new_tz, tz, sizeof(*tz)))
184 return -EFAULT;
185 }
186
187 return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
188}
189
190long pps_offset;
191long pps_jitter = MAXTIME;
192
193long pps_freq;
194long pps_stabil = MAXFREQ;
195
196long pps_valid = PPS_VALID;
197
198int pps_shift = PPS_SHIFT;
199
200long pps_jitcnt;
201long pps_calcnt;
202long pps_errcnt;
203long pps_stbcnt;
204
205
206void (*hardpps_ptr)(struct timeval *);
207
208
209
210
211int do_adjtimex(struct timex *txc)
212{
213 long ltemp, mtemp, save_adjust;
214 int result;
215
216
217 if (txc->modes && !capable(CAP_SYS_TIME))
218 return -EPERM;
219
220
221
222 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
223
224 if (txc->modes != ADJ_OFFSET_SINGLESHOT)
225 return -EINVAL;
226
227 if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
228
229 if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
230 return -EINVAL;
231
232
233 if (txc->modes & ADJ_TICK)
234 if (txc->tick < 900000/USER_HZ ||
235 txc->tick > 1100000/USER_HZ)
236 return -EINVAL;
237
238 write_lock_irq(&xtime_lock);
239 result = time_state;
240
241
242 save_adjust = time_adjust;
243
244#if 0
245 time_status &= ~STA_CLOCKERR;
246#endif
247
248 if (txc->modes)
249 {
250 if (txc->modes & ADJ_STATUS)
251 time_status = (txc->status & ~STA_RONLY) |
252 (time_status & STA_RONLY);
253
254 if (txc->modes & ADJ_FREQUENCY) {
255 if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
256 result = -EINVAL;
257 goto leave;
258 }
259 time_freq = txc->freq - pps_freq;
260 }
261
262 if (txc->modes & ADJ_MAXERROR) {
263 if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
264 result = -EINVAL;
265 goto leave;
266 }
267 time_maxerror = txc->maxerror;
268 }
269
270 if (txc->modes & ADJ_ESTERROR) {
271 if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
272 result = -EINVAL;
273 goto leave;
274 }
275 time_esterror = txc->esterror;
276 }
277
278 if (txc->modes & ADJ_TIMECONST) {
279 if (txc->constant < 0) {
280 result = -EINVAL;
281 goto leave;
282 }
283 time_constant = txc->constant;
284 }
285
286 if (txc->modes & ADJ_OFFSET) {
287 if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
288
289 time_adjust = txc->offset;
290 }
291 else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
292 ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
293 (STA_PPSTIME | STA_PPSSIGNAL) ?
294 pps_offset : txc->offset;
295
296
297
298
299
300 if (ltemp > MAXPHASE)
301 time_offset = MAXPHASE << SHIFT_UPDATE;
302 else if (ltemp < -MAXPHASE)
303 time_offset = -(MAXPHASE << SHIFT_UPDATE);
304 else
305 time_offset = ltemp << SHIFT_UPDATE;
306
307
308
309
310
311
312
313 if (time_status & STA_FREQHOLD || time_reftime == 0)
314 time_reftime = xtime.tv_sec;
315 mtemp = xtime.tv_sec - time_reftime;
316 time_reftime = xtime.tv_sec;
317 if (time_status & STA_FLL) {
318 if (mtemp >= MINSEC) {
319 ltemp = (time_offset / mtemp) << (SHIFT_USEC -
320 SHIFT_UPDATE);
321 if (ltemp < 0)
322 time_freq -= -ltemp >> SHIFT_KH;
323 else
324 time_freq += ltemp >> SHIFT_KH;
325 } else
326 result = TIME_ERROR;
327 } else {
328 if (mtemp < MAXSEC) {
329 ltemp *= mtemp;
330 if (ltemp < 0)
331 time_freq -= -ltemp >> (time_constant +
332 time_constant +
333 SHIFT_KF - SHIFT_USEC);
334 else
335 time_freq += ltemp >> (time_constant +
336 time_constant +
337 SHIFT_KF - SHIFT_USEC);
338 } else
339 result = TIME_ERROR;
340 }
341 if (time_freq > time_tolerance)
342 time_freq = time_tolerance;
343 else if (time_freq < -time_tolerance)
344 time_freq = -time_tolerance;
345 }
346 }
347 if (txc->modes & ADJ_TICK) {
348 tick_usec = txc->tick;
349 tick_nsec = TICK_NSEC(tick_usec);
350 }
351 }
352leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
353 || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
354 && (time_status & STA_PPSSIGNAL) == 0)
355
356 || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
357 == (STA_PPSTIME|STA_PPSJITTER))
358
359 || ((time_status & STA_PPSFREQ) != 0
360 && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
361
362 result = TIME_ERROR;
363
364 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
365 txc->offset = save_adjust;
366 else {
367 if (time_offset < 0)
368 txc->offset = -(-time_offset >> SHIFT_UPDATE);
369 else
370 txc->offset = time_offset >> SHIFT_UPDATE;
371 }
372 txc->freq = time_freq + pps_freq;
373 txc->maxerror = time_maxerror;
374 txc->esterror = time_esterror;
375 txc->status = time_status;
376 txc->constant = time_constant;
377 txc->precision = time_precision;
378 txc->tolerance = time_tolerance;
379 txc->tick = tick_usec;
380 txc->ppsfreq = pps_freq;
381 txc->jitter = pps_jitter >> PPS_AVG;
382 txc->shift = pps_shift;
383 txc->stabil = pps_stabil;
384 txc->jitcnt = pps_jitcnt;
385 txc->calcnt = pps_calcnt;
386 txc->errcnt = pps_errcnt;
387 txc->stbcnt = pps_stbcnt;
388 last_time_offset = 0;
389 write_unlock_irq(&xtime_lock);
390 do_gettimeofday(&txc->time);
391 return(result);
392}
393
394asmlinkage long sys_adjtimex(struct timex *txc_p)
395{
396 struct timex txc;
397 int ret;
398
399
400
401
402
403 if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
404 return -EFAULT;
405 ret = do_adjtimex(&txc);
406 return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
407}
408