VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / s390 / kernel / time.c
1 /*
2  *  arch/s390/kernel/time.c
3  *    Time of day based timer functions.
4  *
5  *  S390 version
6  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *    Author(s): Hartmut Penner (hp@de.ibm.com),
8  *               Martin Schwidefsky (schwidefsky@de.ibm.com),
9  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
10  *
11  *  Derived from "arch/i386/kernel/time.c"
12  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
13  */
14
15 #include <linux/config.h>
16 #include <linux/errno.h>
17 #include <linux/module.h>
18 #include <linux/sched.h>
19 #include <linux/kernel.h>
20 #include <linux/param.h>
21 #include <linux/string.h>
22 #include <linux/mm.h>
23 #include <linux/interrupt.h>
24 #include <linux/time.h>
25 #include <linux/delay.h>
26 #include <linux/init.h>
27 #include <linux/smp.h>
28 #include <linux/types.h>
29 #include <linux/profile.h>
30 #include <linux/timex.h>
31 #include <linux/notifier.h>
32
33 #include <asm/uaccess.h>
34 #include <asm/delay.h>
35 #include <asm/s390_ext.h>
36 #include <asm/div64.h>
37 #include <asm/irq.h>
38 #include <asm/timer.h>
39
40 /* change this if you have some constant time drift */
41 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
42 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
43
44 /*
45  * Create a small time difference between the timer interrupts
46  * on the different cpus to avoid lock contention.
47  */
48 #define CPU_DEVIATION       (smp_processor_id() << 12)
49
50 #define TICK_SIZE tick
51
52 u64 jiffies_64 = INITIAL_JIFFIES;
53
54 EXPORT_SYMBOL(jiffies_64);
55
56 static ext_int_info_t ext_int_info_cc;
57 static u64 init_timer_cc;
58 static u64 jiffies_timer_cc;
59 static u64 xtime_cc;
60
61 extern unsigned long wall_jiffies;
62
63 /*
64  * Scheduler clock - returns current time in nanosec units.
65  */
66 unsigned long long sched_clock(void)
67 {
68         return ((get_clock() - jiffies_timer_cc) * 1000) >> 12;
69 }
70
71 void tod_to_timeval(__u64 todval, struct timespec *xtime)
72 {
73         unsigned long long sec;
74
75         sec = todval >> 12;
76         do_div(sec, 1000000);
77         xtime->tv_sec = sec;
78         todval -= (sec * 1000000) << 12;
79         xtime->tv_nsec = ((todval * 1000) >> 12);
80 }
81
82 static inline unsigned long do_gettimeoffset(void) 
83 {
84         __u64 now;
85
86         now = (get_clock() - jiffies_timer_cc) >> 12;
87         /* We require the offset from the latest update of xtime */
88         now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
89         return (unsigned long) now;
90 }
91
92 /*
93  * This version of gettimeofday has microsecond resolution.
94  */
95 void do_gettimeofday(struct timeval *tv)
96 {
97         unsigned long flags;
98         unsigned long seq;
99         unsigned long usec, sec;
100
101         do {
102                 seq = read_seqbegin_irqsave(&xtime_lock, flags);
103
104                 sec = xtime.tv_sec;
105                 usec = xtime.tv_nsec / 1000 + do_gettimeoffset();
106         } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
107
108         while (usec >= 1000000) {
109                 usec -= 1000000;
110                 sec++;
111         }
112
113         tv->tv_sec = sec;
114         tv->tv_usec = usec;
115 }
116
117 EXPORT_SYMBOL(do_gettimeofday);
118
119 int do_settimeofday(struct timespec *tv)
120 {
121         time_t wtm_sec, sec = tv->tv_sec;
122         long wtm_nsec, nsec = tv->tv_nsec;
123
124         if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
125                 return -EINVAL;
126
127         write_seqlock_irq(&xtime_lock);
128         /* This is revolting. We need to set the xtime.tv_nsec
129          * correctly. However, the value in this location is
130          * is value at the last tick.
131          * Discover what correction gettimeofday
132          * would have done, and then undo it!
133          */
134         nsec -= do_gettimeoffset() * 1000;
135
136         wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
137         wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
138
139         set_normalized_timespec(&xtime, sec, nsec);
140         set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
141
142         time_adjust = 0;                /* stop active adjtime() */
143         time_status |= STA_UNSYNC;
144         time_maxerror = NTP_PHASE_LIMIT;
145         time_esterror = NTP_PHASE_LIMIT;
146         write_sequnlock_irq(&xtime_lock);
147         clock_was_set();
148         return 0;
149 }
150
151 EXPORT_SYMBOL(do_settimeofday);
152
153 #ifndef CONFIG_ARCH_S390X
154
155 static inline __u32
156 __calculate_ticks(__u64 elapsed)
157 {
158         register_pair rp;
159
160         rp.pair = elapsed >> 1;
161         asm ("dr %0,%1" : "+d" (rp) : "d" (CLK_TICKS_PER_JIFFY >> 1));
162         return rp.subreg.odd;
163 }
164
165 #else /* CONFIG_ARCH_S390X */
166
167 static inline __u32
168 __calculate_ticks(__u64 elapsed)
169 {
170         return elapsed / CLK_TICKS_PER_JIFFY;
171 }
172
173 #endif /* CONFIG_ARCH_S390X */
174
175
176 #ifdef CONFIG_PROFILING
177 extern char _stext, _etext;
178
179 /*
180  * The profiling function is SMP safe. (nothing can mess
181  * around with "current", and the profiling counters are
182  * updated with atomic operations). This is especially
183  * useful with a profiling multiplier != 1
184  */
185 static inline void s390_do_profile(struct pt_regs * regs)
186 {
187         unsigned long eip;
188         extern cpumask_t prof_cpu_mask;
189
190         profile_hook(regs);
191
192         if (user_mode(regs))
193                 return;
194
195         if (!prof_buffer)
196                 return;
197
198         eip = instruction_pointer(regs);
199
200         /*
201          * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
202          * (default is all CPUs.)
203          */
204         if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
205                 return;
206
207         eip -= (unsigned long) &_stext;
208         eip >>= prof_shift;
209         /*
210          * Don't ignore out-of-bounds EIP values silently,
211          * put them into the last histogram slot, so if
212          * present, they will show up as a sharp peak.
213          */
214         if (eip > prof_len-1)
215                 eip = prof_len-1;
216         atomic_inc((atomic_t *)&prof_buffer[eip]);
217 }
218 #else
219 #define s390_do_profile(regs)  do { ; } while(0)
220 #endif /* CONFIG_PROFILING */
221
222
223 /*
224  * timer_interrupt() needs to keep up the real-time clock,
225  * as well as call the "do_timer()" routine every clocktick
226  */
227 void account_ticks(struct pt_regs *regs)
228 {
229         __u64 tmp;
230         __u32 ticks;
231
232         /* Calculate how many ticks have passed. */
233         if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer)
234                 return;
235         tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
236         if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than two ticks ? */
237                 ticks = __calculate_ticks(tmp) + 1;
238                 S390_lowcore.jiffy_timer +=
239                         CLK_TICKS_PER_JIFFY * (__u64) ticks;
240         } else if (tmp >= CLK_TICKS_PER_JIFFY) {
241                 ticks = 2;
242                 S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
243         } else {
244                 ticks = 1;
245                 S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
246         }
247
248         /* set clock comparator for next tick */
249         tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
250         asm volatile ("SCKC %0" : : "m" (tmp));
251
252 #ifdef CONFIG_SMP
253         /*
254          * Do not rely on the boot cpu to do the calls to do_timer.
255          * Spread it over all cpus instead.
256          */
257         write_seqlock(&xtime_lock);
258         if (S390_lowcore.jiffy_timer > xtime_cc) {
259                 __u32 xticks;
260
261                 tmp = S390_lowcore.jiffy_timer - xtime_cc;
262                 if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
263                         xticks = __calculate_ticks(tmp);
264                         xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
265                 } else {
266                         xticks = 1;
267                         xtime_cc += CLK_TICKS_PER_JIFFY;
268                 }
269                 while (xticks--)
270                         do_timer(regs);
271         }
272         write_sequnlock(&xtime_lock);
273         while (ticks--)
274                 update_process_times(user_mode(regs));
275 #else
276         while (ticks--)
277                 do_timer(regs);
278 #endif
279         s390_do_profile(regs);
280 }
281
282 #ifdef CONFIG_NO_IDLE_HZ
283
284 #ifdef CONFIG_NO_IDLE_HZ_INIT
285 int sysctl_hz_timer = 0;
286 #else
287 int sysctl_hz_timer = 1;
288 #endif
289
290 /*
291  * Stop the HZ tick on the current CPU.
292  * Only cpu_idle may call this function.
293  */
294 static inline void stop_hz_timer(void)
295 {
296         __u64 timer;
297
298         if (sysctl_hz_timer != 0)
299                 return;
300
301         /*
302          * Leave the clock comparator set up for the next timer
303          * tick if either rcu or a softirq is pending.
304          */
305         if (rcu_pending(smp_processor_id()) || local_softirq_pending())
306                 return;
307
308         /*
309          * This cpu is going really idle. Set up the clock comparator
310          * for the next event.
311          */
312         cpu_set(smp_processor_id(), nohz_cpu_mask);
313         timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
314         timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
315         asm volatile ("SCKC %0" : : "m" (timer));
316 }
317
318 /*
319  * Start the HZ tick on the current CPU.
320  * Only cpu_idle may call this function.
321  */
322 static inline void start_hz_timer(void)
323 {
324         if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
325                 return;
326         account_ticks(__KSTK_PTREGS(current));
327         cpu_clear(smp_processor_id(), nohz_cpu_mask);
328 }
329
330 static int nohz_idle_notify(struct notifier_block *self,
331                             unsigned long action, void *hcpu)
332 {
333         switch (action) {
334         case CPU_IDLE:
335                 stop_hz_timer();
336                 break;
337         case CPU_NOT_IDLE:
338                 start_hz_timer();
339                 break;
340         }
341         return NOTIFY_OK;
342 }
343
344 static struct notifier_block nohz_idle_nb = {
345         .notifier_call = nohz_idle_notify,
346 };
347
348 void __init nohz_init(void)
349 {
350         if (register_idle_notifier(&nohz_idle_nb))
351                 panic("Couldn't register idle notifier");
352 }
353
354 #endif
355
356 /*
357  * Start the clock comparator on the current CPU.
358  */
359 void init_cpu_timer(void)
360 {
361         unsigned long cr0;
362         __u64 timer;
363
364         timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY;
365         S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
366         timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION;
367         asm volatile ("SCKC %0" : : "m" (timer));
368         /* allow clock comparator timer interrupt */
369         __ctl_store(cr0, 0, 0);
370         cr0 |= 0x800;
371         __ctl_load(cr0, 0, 0);
372 }
373
374 extern void vtime_init(void);
375
376 /*
377  * Initialize the TOD clock and the CPU timer of
378  * the boot cpu.
379  */
380 void __init time_init(void)
381 {
382         __u64 set_time_cc;
383         int cc;
384
385         /* kick the TOD clock */
386         asm volatile ("STCK 0(%1)\n\t"
387                       "IPM  %0\n\t"
388                       "SRL  %0,28" : "=r" (cc) : "a" (&init_timer_cc) 
389                                    : "memory", "cc");
390         switch (cc) {
391         case 0: /* clock in set state: all is fine */
392                 break;
393         case 1: /* clock in non-set state: FIXME */
394                 printk("time_init: TOD clock in non-set state\n");
395                 break;
396         case 2: /* clock in error state: FIXME */
397                 printk("time_init: TOD clock in error state\n");
398                 break;
399         case 3: /* clock in stopped or not-operational state: FIXME */
400                 printk("time_init: TOD clock stopped/non-operational\n");
401                 break;
402         }
403         jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
404
405         /* set xtime */
406         xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
407         set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
408                 (0x3c26700LL*1000000*4096);
409         tod_to_timeval(set_time_cc, &xtime);
410         set_normalized_timespec(&wall_to_monotonic,
411                                 -xtime.tv_sec, -xtime.tv_nsec);
412
413         /* request the clock comparator external interrupt */
414         if (register_early_external_interrupt(0x1004, 0,
415                                               &ext_int_info_cc) != 0)
416                 panic("Couldn't request external interrupt 0x1004");
417
418         init_cpu_timer();
419
420 #ifdef CONFIG_NO_IDLE_HZ
421         nohz_init();
422 #endif
423
424 #ifdef CONFIG_VIRT_TIMER
425         vtime_init();
426 #endif
427 }
428