time.c 9.7 KB

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