File: /usr/src/linux/arch/ia64/kernel/time.c

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