time.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/ia64/kernel/time.c
  3.  *
  4.  * Copyright (C) 1998-2001 Hewlett-Packard Co
  5.  * Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
  6.  * Copyright (C) 1999-2001 David Mosberger <davidm@hpl.hp.com>
  7.  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  8.  * Copyright (C) 1999-2000 VA Linux Systems
  9.  * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/time.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/efi.h>
  18. #include <asm/delay.h>
  19. #include <asm/hw_irq.h>
  20. #include <asm/ptrace.h>
  21. #include <asm/sal.h>
  22. #include <asm/system.h>
  23. extern rwlock_t xtime_lock;
  24. extern unsigned long wall_jiffies;
  25. extern unsigned long last_time_offset;
  26. #ifdef CONFIG_IA64_DEBUG_IRQ
  27. unsigned long last_cli_ip;
  28. #endif
  29. static void
  30. do_profile (unsigned long ip)
  31. {
  32. extern unsigned long prof_cpu_mask;
  33. extern char _stext;
  34. if (!prof_buffer)
  35. return;
  36. if (!((1UL << smp_processor_id()) & prof_cpu_mask))
  37. return;
  38. ip -= (unsigned long) &_stext;
  39. ip >>= prof_shift;
  40. /*
  41.  * Don't ignore out-of-bounds IP values silently, put them into the last
  42.  * histogram slot, so if present, they will show up as a sharp peak.
  43.  */
  44. if (ip > prof_len - 1)
  45. ip = prof_len - 1;
  46. atomic_inc((atomic_t *) &prof_buffer[ip]);
  47. }
  48. /*
  49.  * Return the number of micro-seconds that elapsed since the last update to jiffy.  The
  50.  * xtime_lock must be at least read-locked when calling this routine.
  51.  */
  52. static inline unsigned long
  53. gettimeoffset (void)
  54. {
  55. unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
  56. unsigned long now, last_tick;
  57. # define time_keeper_id 0 /* smp_processor_id() of time-keeper */
  58. last_tick = (cpu_data(time_keeper_id)->itm_next
  59.      - (lost + 1)*cpu_data(time_keeper_id)->itm_delta);
  60. now = ia64_get_itc();
  61. if ((long) (now - last_tick) < 0) {
  62. # if 1
  63. printk("CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!n",
  64.        smp_processor_id(), now, last_tick);
  65. # endif
  66. return last_time_offset;
  67. }
  68. elapsed_cycles = now - last_tick;
  69. return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
  70. }
  71. void
  72. do_settimeofday (struct timeval *tv)
  73. {
  74. write_lock_irq(&xtime_lock);
  75. {
  76. /*
  77.  * This is revolting. We need to set "xtime" correctly. However, the value
  78.  * in this location is the value at the most recent update of wall time.
  79.  * Discover what correction gettimeofday would have done, and then undo
  80.  * it!
  81.  */
  82. tv->tv_usec -= gettimeoffset();
  83. tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
  84. while (tv->tv_usec < 0) {
  85. tv->tv_usec += 1000000;
  86. tv->tv_sec--;
  87. }
  88. xtime = *tv;
  89. time_adjust = 0; /* stop active adjtime() */
  90. time_status |= STA_UNSYNC;
  91. time_maxerror = NTP_PHASE_LIMIT;
  92. time_esterror = NTP_PHASE_LIMIT;
  93. }
  94. write_unlock_irq(&xtime_lock);
  95. }
  96. void
  97. do_gettimeofday (struct timeval *tv)
  98. {
  99. unsigned long flags, usec, sec, old;
  100. read_lock_irqsave(&xtime_lock, flags);
  101. {
  102. usec = gettimeoffset();
  103. /*
  104.  * Ensure time never goes backwards, even when ITC on different CPUs are
  105.  * not perfectly synchronized.
  106.  */
  107. do {
  108. old = last_time_offset;
  109. if (usec <= old) {
  110. usec = old;
  111. break;
  112. }
  113. } while (cmpxchg(&last_time_offset, old, usec) != old);
  114. sec = xtime.tv_sec;
  115. usec += xtime.tv_usec;
  116. }
  117. read_unlock_irqrestore(&xtime_lock, flags);
  118. while (usec >= 1000000) {
  119. usec -= 1000000;
  120. ++sec;
  121. }
  122. tv->tv_sec = sec;
  123. tv->tv_usec = usec;
  124. }
  125. static void
  126. timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  127. {
  128. unsigned long new_itm;
  129. new_itm = local_cpu_data->itm_next;
  130. if (!time_after(ia64_get_itc(), new_itm))
  131. printk("Oops: timer tick before it's due (itc=%lx,itm=%lx)n",
  132.        ia64_get_itc(), new_itm);
  133. while (1) {
  134. /*
  135.  * Do kernel PC profiling here.  We multiply the instruction number by
  136.  * four so that we can use a prof_shift of 2 to get instruction-level
  137.  * instead of just bundle-level accuracy.
  138.  */
  139. if (!user_mode(regs))
  140. do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri);
  141. #ifdef CONFIG_SMP
  142. smp_do_timer(regs);
  143. #endif
  144. new_itm += local_cpu_data->itm_delta;
  145. if (smp_processor_id() == 0) {
  146. /*
  147.  * Here we are in the timer irq handler. We have irqs locally
  148.  * disabled, but we don't know if the timer_bh is running on
  149.  * another CPU. We need to avoid to SMP race by acquiring the
  150.  * xtime_lock.
  151.  */
  152. write_lock(&xtime_lock);
  153. do_timer(regs);
  154. local_cpu_data->itm_next = new_itm;
  155. write_unlock(&xtime_lock);
  156. } else
  157. local_cpu_data->itm_next = new_itm;
  158. if (time_after(new_itm, ia64_get_itc()))
  159. break;
  160. }
  161. do {
  162.     /*
  163.      * If we're too close to the next clock tick for comfort, we increase the
  164.      * saftey margin by intentionally dropping the next tick(s).  We do NOT update
  165.      * itm.next because that would force us to call do_timer() which in turn would
  166.      * let our clock run too fast (with the potentially devastating effect of
  167.      * losing monotony of time).
  168.      */
  169.     while (!time_after(new_itm, ia64_get_itc() + local_cpu_data->itm_delta/2))
  170.       new_itm += local_cpu_data->itm_delta;
  171.     ia64_set_itm(new_itm);
  172.     /* double check, in case we got hit by a (slow) PMI: */
  173. } while (time_after_eq(ia64_get_itc(), new_itm));
  174. }
  175. /*
  176.  * Encapsulate access to the itm structure for SMP.
  177.  */
  178. void __init
  179. ia64_cpu_local_tick (void)
  180. {
  181. int cpu = smp_processor_id();
  182. unsigned long shift = 0, delta;
  183. /* arrange for the cycle counter to generate a timer interrupt: */
  184. ia64_set_itv(IA64_TIMER_VECTOR);
  185. delta = local_cpu_data->itm_delta;
  186. /*
  187.  * Stagger the timer tick for each CPU so they don't occur all at (almost) the
  188.  * same time:
  189.  */
  190. if (cpu) {
  191. unsigned long hi = 1UL << ia64_fls(cpu);
  192. shift = (2*(cpu - hi) + 1) * delta/hi/2;
  193. }
  194. local_cpu_data->itm_next = ia64_get_itc() + delta + shift;
  195. ia64_set_itm(local_cpu_data->itm_next);
  196. }
  197. void __init
  198. ia64_init_itm (void)
  199. {
  200. unsigned long platform_base_freq, itc_freq, drift;
  201. struct pal_freq_ratio itc_ratio, proc_ratio;
  202. long status;
  203. /*
  204.  * According to SAL v2.6, we need to use a SAL call to determine the platform base
  205.  * frequency and then a PAL call to determine the frequency ratio between the ITC
  206.  * and the base frequency.
  207.  */
  208. status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &drift);
  209. if (status != 0) {
  210. printk("SAL_FREQ_BASE_PLATFORM failed: %sn", ia64_sal_strerror(status));
  211. } else {
  212. status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio);
  213. if (status != 0)
  214. printk("PAL_FREQ_RATIOS failed with status=%ldn", status);
  215. }
  216. if (status != 0) {
  217. /* invent "random" values */
  218. printk("SAL/PAL failed to obtain frequency info---inventing reasonably valuesn");
  219. platform_base_freq = 100000000;
  220. itc_ratio.num = 3;
  221. itc_ratio.den = 1;
  222. }
  223. if (platform_base_freq < 40000000) {
  224. printk("Platform base frequency %lu bogus---resetting to 75MHz!n",
  225.        platform_base_freq);
  226. platform_base_freq = 75000000;
  227. }
  228. if (!proc_ratio.den)
  229. proc_ratio.den = 1; /* avoid division by zero */
  230. if (!itc_ratio.den)
  231. itc_ratio.den = 1; /* avoid division by zero */
  232. itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
  233. local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
  234. printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHzn",
  235.        smp_processor_id(),
  236.        platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
  237.        itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
  238. local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
  239. local_cpu_data->itc_freq = itc_freq;
  240. local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
  241. local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
  242. + itc_freq/2)/itc_freq;
  243. /* Setup the CPU local timer tick */
  244. ia64_cpu_local_tick();
  245. }
  246. static struct irqaction timer_irqaction = {
  247. handler: timer_interrupt,
  248. flags: SA_INTERRUPT,
  249. name: "timer"
  250. };
  251. void __init
  252. time_init (void)
  253. {
  254. register_percpu_irq(IA64_TIMER_VECTOR, &timer_irqaction);
  255. efi_gettimeofday((struct timeval *) &xtime);
  256. ia64_init_itm();
  257. }