time_kern.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include "linux/kernel.h"
  6. #include "linux/module.h"
  7. #include "linux/unistd.h"
  8. #include "linux/stddef.h"
  9. #include "linux/spinlock.h"
  10. #include "linux/time.h"
  11. #include "linux/sched.h"
  12. #include "linux/interrupt.h"
  13. #include "linux/init.h"
  14. #include "linux/delay.h"
  15. #include "asm/irq.h"
  16. #include "asm/param.h"
  17. #include "asm/current.h"
  18. #include "kern_util.h"
  19. #include "user_util.h"
  20. #include "time_user.h"
  21. #include "mode.h"
  22. #include "os.h"
  23. u64 jiffies_64 = INITIAL_JIFFIES;
  24. EXPORT_SYMBOL(jiffies_64);
  25. int hz(void)
  26. {
  27. return(HZ);
  28. }
  29. /*
  30. * Scheduler clock - returns current time in nanosec units.
  31. */
  32. unsigned long long sched_clock(void)
  33. {
  34. return (unsigned long long)jiffies_64 * (1000000000 / HZ);
  35. }
  36. /* Changed at early boot */
  37. int timer_irq_inited = 0;
  38. static int first_tick;
  39. static unsigned long long prev_usecs;
  40. #ifdef CONFIG_UML_REAL_TIME_CLOCK
  41. static long long delta; /* Deviation per interval */
  42. #endif
  43. #define MILLION 1000000
  44. void timer_irq(union uml_pt_regs *regs)
  45. {
  46. unsigned long long ticks = 0;
  47. if(!timer_irq_inited){
  48. /* This is to ensure that ticks don't pile up when
  49. * the timer handler is suspended */
  50. first_tick = 0;
  51. return;
  52. }
  53. if(first_tick){
  54. #ifdef CONFIG_UML_REAL_TIME_CLOCK
  55. /* We've had 1 tick */
  56. unsigned long long usecs = os_usecs();
  57. delta += usecs - prev_usecs;
  58. prev_usecs = usecs;
  59. /* Protect against the host clock being set backwards */
  60. if(delta < 0)
  61. delta = 0;
  62. ticks += (delta * HZ) / MILLION;
  63. delta -= (ticks * MILLION) / HZ;
  64. #else
  65. ticks = 1;
  66. #endif
  67. }
  68. else {
  69. prev_usecs = os_usecs();
  70. first_tick = 1;
  71. }
  72. while(ticks > 0){
  73. do_IRQ(TIMER_IRQ, regs);
  74. ticks--;
  75. }
  76. }
  77. void boot_timer_handler(int sig)
  78. {
  79. struct pt_regs regs;
  80. CHOOSE_MODE((void)
  81. (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
  82. (void) (regs.regs.skas.is_user = 0));
  83. do_timer(&regs);
  84. }
  85. irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
  86. {
  87. unsigned long flags;
  88. do_timer(regs);
  89. write_seqlock_irqsave(&xtime_lock, flags);
  90. timer();
  91. write_sequnlock_irqrestore(&xtime_lock, flags);
  92. return(IRQ_HANDLED);
  93. }
  94. long um_time(int __user *tloc)
  95. {
  96. struct timeval now;
  97. do_gettimeofday(&now);
  98. if (tloc) {
  99. if (put_user(now.tv_sec, tloc))
  100. now.tv_sec = -EFAULT;
  101. }
  102. return now.tv_sec;
  103. }
  104. long um_stime(int __user *tptr)
  105. {
  106. int value;
  107. struct timespec new;
  108. if (get_user(value, tptr))
  109. return -EFAULT;
  110. new.tv_sec = value;
  111. new.tv_nsec = 0;
  112. do_settimeofday(&new);
  113. return 0;
  114. }
  115. void __udelay(unsigned long usecs)
  116. {
  117. int i, n;
  118. n = (loops_per_jiffy * HZ * usecs) / MILLION;
  119. for(i=0;i<n;i++) ;
  120. }
  121. void __const_udelay(unsigned long usecs)
  122. {
  123. int i, n;
  124. n = (loops_per_jiffy * HZ * usecs) / MILLION;
  125. for(i=0;i<n;i++) ;
  126. }
  127. void timer_handler(int sig, union uml_pt_regs *regs)
  128. {
  129. local_irq_disable();
  130. update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), (regs)->skas.is_user));
  131. local_irq_enable();
  132. if(current_thread->cpu == 0)
  133. timer_irq(regs);
  134. }
  135. static DEFINE_SPINLOCK(timer_spinlock);
  136. unsigned long time_lock(void)
  137. {
  138. unsigned long flags;
  139. spin_lock_irqsave(&timer_spinlock, flags);
  140. return(flags);
  141. }
  142. void time_unlock(unsigned long flags)
  143. {
  144. spin_unlock_irqrestore(&timer_spinlock, flags);
  145. }
  146. int __init timer_init(void)
  147. {
  148. int err;
  149. CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
  150. err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
  151. if(err != 0)
  152. printk(KERN_ERR "timer_init : request_irq failed - "
  153. "errno = %d\n", -err);
  154. timer_irq_inited = 1;
  155. return(0);
  156. }
  157. __initcall(timer_init);
  158. /*
  159. * Overrides for Emacs so that we follow Linus's tabbing style.
  160. * Emacs will notice this stuff at the end of the file and automatically
  161. * adjust the settings for this buffer only. This must remain at the end
  162. * of the file.
  163. * ---------------------------------------------------------------------------
  164. * Local variables:
  165. * c-file-style: "linux"
  166. * End:
  167. */