2 * linux/arch/ia64/kernel/time.c
4 * Copyright (C) 1998-2000 Hewlett-Packard Co
5 * Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
6 * Copyright (C) 1999-2000 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>
11 #include <linux/config.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/time.h>
17 #include <linux/interrupt.h>
19 #include <asm/delay.h>
21 #include <asm/hw_irq.h>
22 #include <asm/ptrace.h>
24 #include <asm/system.h>
26 extern rwlock_t xtime_lock;
27 extern unsigned long wall_jiffies;
29 #ifdef CONFIG_IA64_DEBUG_IRQ
31 unsigned long last_cli_ip;
39 unsigned char pad[SMP_CACHE_BYTES];
44 do_profile (unsigned long ip)
46 extern unsigned long prof_cpu_mask;
49 if (!((1UL << smp_processor_id()) & prof_cpu_mask))
52 if (prof_buffer && current->pid) {
53 ip -= (unsigned long) &_stext;
56 * Don't ignore out-of-bounds IP values silently,
57 * put them into the last histogram slot, so if
58 * present, they will show up as a sharp peak.
60 if (ip > prof_len - 1)
63 atomic_inc((atomic_t *) &prof_buffer[ip]);
68 * Return the number of micro-seconds that elapsed since the last
69 * update to jiffy. The xtime_lock must be at least read-locked when
70 * calling this routine.
72 static inline unsigned long
77 * The code below doesn't work for SMP because only CPU 0
78 * keeps track of the time.
82 unsigned long now = ia64_get_itc(), last_tick;
83 unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
85 last_tick = (itm.next[smp_processor_id()].count - (lost+1)*itm.delta);
87 if ((long) (now - last_tick) < 0) {
88 printk("Yikes: now < last_tick (now=0x%lx,last_tick=%lx)! No can do.\n",
93 elapsed_cycles = now - last_tick;
94 return (elapsed_cycles*my_cpu_data.usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
99 do_settimeofday (struct timeval *tv)
101 write_lock_irq(&xtime_lock);
104 * This is revolting. We need to set "xtime"
105 * correctly. However, the value in this location is
106 * the value at the most recent update of wall time.
107 * Discover what correction gettimeofday would have
108 * done, and then undo it!
110 tv->tv_usec -= gettimeoffset();
111 tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
113 while (tv->tv_usec < 0) {
114 tv->tv_usec += 1000000;
119 time_adjust = 0; /* stop active adjtime() */
120 time_status |= STA_UNSYNC;
121 time_maxerror = NTP_PHASE_LIMIT;
122 time_esterror = NTP_PHASE_LIMIT;
124 write_unlock_irq(&xtime_lock);
128 do_gettimeofday (struct timeval *tv)
130 unsigned long flags, usec, sec;
132 read_lock_irqsave(&xtime_lock, flags);
134 usec = gettimeoffset();
137 usec += xtime.tv_usec;
139 read_unlock_irqrestore(&xtime_lock, flags);
141 while (usec >= 1000000) {
151 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
153 int cpu = smp_processor_id();
154 unsigned long new_itm;
156 new_itm = itm.next[cpu].count;
158 if (!time_after(ia64_get_itc(), new_itm))
159 printk("Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
160 ia64_get_itc(), new_itm);
164 * Do kernel PC profiling here. We multiply the instruction number by
165 * four so that we can use a prof_shift of 2 to get instruction-level
166 * instead of just bundle-level accuracy.
168 if (!user_mode(regs))
169 do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri);
174 if (smp_processor_id() == 0) {
176 * Here we are in the timer irq handler. We have irqs locally
177 * disabled, but we don't know if the timer_bh is running on
178 * another CPU. We need to avoid to SMP race by acquiring the
181 write_lock(&xtime_lock);
183 write_unlock(&xtime_lock);
186 new_itm += itm.delta;
187 itm.next[cpu].count = new_itm;
188 if (time_after(new_itm, ia64_get_itc()))
193 * If we're too close to the next clock tick for comfort, we
194 * increase the saftey margin by intentionally dropping the
195 * next tick(s). We do NOT update itm.next accordingly
196 * because that would force us to call do_timer() which in
197 * turn would let our clock run too fast (with the potentially
198 * devastating effect of losing monotony of time).
200 while (!time_after(new_itm, ia64_get_itc() + itm.delta/2))
201 new_itm += itm.delta;
202 ia64_set_itm(new_itm);
205 #ifdef CONFIG_IA64_SOFTSDV_HACKS
208 * Interrupts must be disabled before calling this routine.
211 ia64_reset_itm (void)
213 timer_interrupt(0, 0, ia64_task_regs(current));
219 * Encapsulate access to the itm structure for SMP.
222 ia64_cpu_local_tick(void)
224 #ifdef CONFIG_IA64_SOFTSDV_HACKS
228 /* arrange for the cycle counter to generate a timer interrupt: */
229 ia64_set_itv(TIMER_IRQ, 0);
230 itm.next[smp_processor_id()].count = ia64_get_itc() + itm.delta;
231 ia64_set_itm(itm.next[smp_processor_id()].count);
237 unsigned long platform_base_freq, itc_freq, drift;
238 struct pal_freq_ratio itc_ratio, proc_ratio;
242 * According to SAL v2.6, we need to use a SAL call to determine the
243 * platform base frequency and then a PAL call to determine the
244 * frequency ratio between the ITC and the base frequency.
246 status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &drift);
248 printk("SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status));
250 status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio);
252 printk("PAL_FREQ_RATIOS failed with status=%ld\n", status);
255 /* invent "random" values */
256 printk("SAL/PAL failed to obtain frequency info---inventing reasonably values\n");
257 platform_base_freq = 100000000;
261 #ifdef CONFIG_IA64_SOFTSDV_HACKS
262 platform_base_freq = 10000000;
263 proc_ratio.num = 4; proc_ratio.den = 1;
264 itc_ratio.num = 4; itc_ratio.den = 1;
266 if (platform_base_freq < 40000000) {
267 printk("Platform base frequency %lu bogus---resetting to 75MHz!\n",
269 platform_base_freq = 75000000;
273 proc_ratio.num = 1; /* avoid division by zero */
275 itc_ratio.num = 1; /* avoid division by zero */
277 itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
278 itm.delta = itc_freq / HZ;
279 printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
281 platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
282 itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
284 my_cpu_data.proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
285 my_cpu_data.itc_freq = itc_freq;
286 my_cpu_data.cyc_per_usec = itc_freq / 1000000;
287 my_cpu_data.usec_per_cyc = (1000000UL << IA64_USEC_PER_CYC_SHIFT) / itc_freq;
289 /* Setup the CPU local timer tick */
290 ia64_cpu_local_tick();
293 static struct irqaction timer_irqaction = {
294 handler: timer_interrupt,
302 /* we can't do request_irq() here because the kmalloc() would fail... */
303 irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
304 irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic;
305 setup_irq(TIMER_IRQ, &timer_irqaction);
307 efi_gettimeofday(&xtime);