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/errno.h> 16 #include <linux/module.h> 17 #include <linux/sched.h> 18 #include <linux/kernel.h> 19 #include <linux/param.h> 20 #include <linux/string.h> 21 #include <linux/mm.h> 22 #include <linux/interrupt.h> 23 #include <linux/time.h> 24 #include <linux/delay.h> 25 #include <linux/init.h> 26 #include <linux/smp.h> 27 #include <linux/types.h> 28 #include <linux/profile.h> 29 #include <linux/timex.h> 30 #include <linux/notifier.h> 31 32 #include <asm/uaccess.h> 33 #include <asm/delay.h> 34 #include <asm/s390_ext.h> 35 #include <asm/div64.h> 36 #include <asm/irq.h> 37 #include <asm/timer.h> 38 39 /* change this if you have some constant time drift */ 40 #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) 41 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) 42 43 /* 44 * Create a small time difference between the timer interrupts 45 * on the different cpus to avoid lock contention. 46 */ 47 #define CPU_DEVIATION (smp_processor_id() << 12) 48 49 #define TICK_SIZE tick 50 51 static ext_int_info_t ext_int_info_cc; 52 static u64 init_timer_cc; 53 static u64 jiffies_timer_cc; 54 static u64 xtime_cc; 55 56 extern unsigned long wall_jiffies; 57 58 /* 59 * Scheduler clock - returns current time in nanosec units. 60 */ 61 unsigned long long sched_clock(void) 62 { 63 return ((get_clock() - jiffies_timer_cc) * 125) >> 9; 64 } 65 66 /* 67 * Monotonic_clock - returns # of nanoseconds passed since time_init() 68 */ 69 unsigned long long monotonic_clock(void) 70 { 71 return sched_clock(); 72 } 73 EXPORT_SYMBOL(monotonic_clock); 74 75 void tod_to_timeval(__u64 todval, struct timespec *xtime) 76 { 77 unsigned long long sec; 78 79 sec = todval >> 12; 80 do_div(sec, 1000000); 81 xtime->tv_sec = sec; 82 todval -= (sec * 1000000) << 12; 83 xtime->tv_nsec = ((todval * 1000) >> 12); 84 } 85 86 static inline unsigned long do_gettimeoffset(void) 87 { 88 __u64 now; 89 90 now = (get_clock() - jiffies_timer_cc) >> 12; 91 /* We require the offset from the latest update of xtime */ 92 now -= (__u64) wall_jiffies*USECS_PER_JIFFY; 93 return (unsigned long) now; 94 } 95 96 /* 97 * This version of gettimeofday has microsecond resolution. 98 */ 99 void do_gettimeofday(struct timeval *tv) 100 { 101 unsigned long flags; 102 unsigned long seq; 103 unsigned long usec, sec; 104 105 do { 106 seq = read_seqbegin_irqsave(&xtime_lock, flags); 107 108 sec = xtime.tv_sec; 109 usec = xtime.tv_nsec / 1000 + do_gettimeoffset(); 110 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); 111 112 while (usec >= 1000000) { 113 usec -= 1000000; 114 sec++; 115 } 116 117 tv->tv_sec = sec; 118 tv->tv_usec = usec; 119 } 120 121 EXPORT_SYMBOL(do_gettimeofday); 122 123 int do_settimeofday(struct timespec *tv) 124 { 125 time_t wtm_sec, sec = tv->tv_sec; 126 long wtm_nsec, nsec = tv->tv_nsec; 127 128 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) 129 return -EINVAL; 130 131 write_seqlock_irq(&xtime_lock); 132 /* This is revolting. We need to set the xtime.tv_nsec 133 * correctly. However, the value in this location is 134 * is value at the last tick. 135 * Discover what correction gettimeofday 136 * would have done, and then undo it! 137 */ 138 nsec -= do_gettimeoffset() * 1000; 139 140 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 141 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 142 143 set_normalized_timespec(&xtime, sec, nsec); 144 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); 145 146 ntp_clear(); 147 write_sequnlock_irq(&xtime_lock); 148 clock_was_set(); 149 return 0; 150 } 151 152 EXPORT_SYMBOL(do_settimeofday); 153 154 155 #ifdef CONFIG_PROFILING 156 #define s390_do_profile(regs) profile_tick(CPU_PROFILING, regs) 157 #else 158 #define s390_do_profile(regs) do { ; } while(0) 159 #endif /* CONFIG_PROFILING */ 160 161 162 /* 163 * timer_interrupt() needs to keep up the real-time clock, 164 * as well as call the "do_timer()" routine every clocktick 165 */ 166 void account_ticks(struct pt_regs *regs) 167 { 168 __u64 tmp; 169 __u32 ticks, xticks; 170 171 /* Calculate how many ticks have passed. */ 172 if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) { 173 /* 174 * We have to program the clock comparator even if 175 * no tick has passed. That happens if e.g. an i/o 176 * interrupt wakes up an idle processor that has 177 * switched off its hz timer. 178 */ 179 tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; 180 asm volatile ("SCKC %0" : : "m" (tmp)); 181 return; 182 } 183 tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; 184 if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */ 185 ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1; 186 S390_lowcore.jiffy_timer += 187 CLK_TICKS_PER_JIFFY * (__u64) ticks; 188 } else if (tmp >= CLK_TICKS_PER_JIFFY) { 189 ticks = 2; 190 S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY; 191 } else { 192 ticks = 1; 193 S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; 194 } 195 196 /* set clock comparator for next tick */ 197 tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; 198 asm volatile ("SCKC %0" : : "m" (tmp)); 199 200 #ifdef CONFIG_SMP 201 /* 202 * Do not rely on the boot cpu to do the calls to do_timer. 203 * Spread it over all cpus instead. 204 */ 205 write_seqlock(&xtime_lock); 206 if (S390_lowcore.jiffy_timer > xtime_cc) { 207 tmp = S390_lowcore.jiffy_timer - xtime_cc; 208 if (tmp >= 2*CLK_TICKS_PER_JIFFY) { 209 xticks = __div(tmp, CLK_TICKS_PER_JIFFY); 210 xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY; 211 } else { 212 xticks = 1; 213 xtime_cc += CLK_TICKS_PER_JIFFY; 214 } 215 while (xticks--) 216 do_timer(regs); 217 } 218 write_sequnlock(&xtime_lock); 219 #else 220 for (xticks = ticks; xticks > 0; xticks--) 221 do_timer(regs); 222 #endif 223 224 #ifdef CONFIG_VIRT_CPU_ACCOUNTING 225 account_tick_vtime(current); 226 #else 227 while (ticks--) 228 update_process_times(user_mode(regs)); 229 #endif 230 231 s390_do_profile(regs); 232 } 233 234 #ifdef CONFIG_NO_IDLE_HZ 235 236 #ifdef CONFIG_NO_IDLE_HZ_INIT 237 int sysctl_hz_timer = 0; 238 #else 239 int sysctl_hz_timer = 1; 240 #endif 241 242 /* 243 * Stop the HZ tick on the current CPU. 244 * Only cpu_idle may call this function. 245 */ 246 static inline void stop_hz_timer(void) 247 { 248 unsigned long flags; 249 unsigned long seq, next; 250 __u64 timer, todval; 251 int cpu = smp_processor_id(); 252 253 if (sysctl_hz_timer != 0) 254 return; 255 256 cpu_set(cpu, nohz_cpu_mask); 257 258 /* 259 * Leave the clock comparator set up for the next timer 260 * tick if either rcu or a softirq is pending. 261 */ 262 if (rcu_needs_cpu(cpu) || local_softirq_pending()) { 263 cpu_clear(cpu, nohz_cpu_mask); 264 return; 265 } 266 267 /* 268 * This cpu is going really idle. Set up the clock comparator 269 * for the next event. 270 */ 271 next = next_timer_interrupt(); 272 do { 273 seq = read_seqbegin_irqsave(&xtime_lock, flags); 274 timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64; 275 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); 276 todval = -1ULL; 277 /* Be careful about overflows. */ 278 if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { 279 timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; 280 if (timer >= jiffies_timer_cc) 281 todval = timer; 282 } 283 asm volatile ("SCKC %0" : : "m" (todval)); 284 } 285 286 /* 287 * Start the HZ tick on the current CPU. 288 * Only cpu_idle may call this function. 289 */ 290 static inline void start_hz_timer(void) 291 { 292 if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) 293 return; 294 account_ticks(task_pt_regs(current)); 295 cpu_clear(smp_processor_id(), nohz_cpu_mask); 296 } 297 298 static int nohz_idle_notify(struct notifier_block *self, 299 unsigned long action, void *hcpu) 300 { 301 switch (action) { 302 case CPU_IDLE: 303 stop_hz_timer(); 304 break; 305 case CPU_NOT_IDLE: 306 start_hz_timer(); 307 break; 308 } 309 return NOTIFY_OK; 310 } 311 312 static struct notifier_block nohz_idle_nb = { 313 .notifier_call = nohz_idle_notify, 314 }; 315 316 void __init nohz_init(void) 317 { 318 if (register_idle_notifier(&nohz_idle_nb)) 319 panic("Couldn't register idle notifier"); 320 } 321 322 #endif 323 324 /* 325 * Start the clock comparator on the current CPU. 326 */ 327 void init_cpu_timer(void) 328 { 329 unsigned long cr0; 330 __u64 timer; 331 332 timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY; 333 S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY; 334 timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION; 335 asm volatile ("SCKC %0" : : "m" (timer)); 336 /* allow clock comparator timer interrupt */ 337 __ctl_store(cr0, 0, 0); 338 cr0 |= 0x800; 339 __ctl_load(cr0, 0, 0); 340 } 341 342 extern void vtime_init(void); 343 344 /* 345 * Initialize the TOD clock and the CPU timer of 346 * the boot cpu. 347 */ 348 void __init time_init(void) 349 { 350 __u64 set_time_cc; 351 int cc; 352 353 /* kick the TOD clock */ 354 asm volatile ("STCK 0(%1)\n\t" 355 "IPM %0\n\t" 356 "SRL %0,28" : "=r" (cc) : "a" (&init_timer_cc) 357 : "memory", "cc"); 358 switch (cc) { 359 case 0: /* clock in set state: all is fine */ 360 break; 361 case 1: /* clock in non-set state: FIXME */ 362 printk("time_init: TOD clock in non-set state\n"); 363 break; 364 case 2: /* clock in error state: FIXME */ 365 printk("time_init: TOD clock in error state\n"); 366 break; 367 case 3: /* clock in stopped or not-operational state: FIXME */ 368 printk("time_init: TOD clock stopped/non-operational\n"); 369 break; 370 } 371 jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY; 372 373 /* set xtime */ 374 xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY; 375 set_time_cc = init_timer_cc - 0x8126d60e46000000LL + 376 (0x3c26700LL*1000000*4096); 377 tod_to_timeval(set_time_cc, &xtime); 378 set_normalized_timespec(&wall_to_monotonic, 379 -xtime.tv_sec, -xtime.tv_nsec); 380 381 /* request the clock comparator external interrupt */ 382 if (register_early_external_interrupt(0x1004, NULL, 383 &ext_int_info_cc) != 0) 384 panic("Couldn't request external interrupt 0x1004"); 385 386 init_cpu_timer(); 387 388 #ifdef CONFIG_NO_IDLE_HZ 389 nohz_init(); 390 #endif 391 392 #ifdef CONFIG_VIRT_TIMER 393 vtime_init(); 394 #endif 395 } 396 397