blob: 7d606e3364aec30d667c9b21c6c5368671c40ca0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* defines for inline arch setup functions */
2
3#include <asm/apic.h>
Ingo Molnar306e4402005-06-30 02:58:55 -07004#include <asm/i8259.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005
6/**
7 * do_timer_interrupt_hook - hook into timer tick
8 * @regs: standard registers from interrupt
9 *
10 * Description:
11 * This hook is called immediately after the timer interrupt is ack'd.
12 * It's primary purpose is to allow architectures that don't possess
13 * individual per CPU clocks (like the CPU APICs supply) to broadcast the
14 * timer interrupt as a means of triggering reschedules etc.
15 **/
16
David Howells7d12e782006-10-05 14:55:46 +010017static inline void do_timer_interrupt_hook(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070018{
Atsushi Nemoto3171a032006-09-29 02:00:32 -070019 do_timer(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#ifndef CONFIG_SMP
David Howells7d12e782006-10-05 14:55:46 +010021 update_process_times(user_mode_vm(get_irq_regs()));
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#endif
23/*
24 * In the SMP case we use the local APIC timer interrupt to do the
25 * profiling, except when we simulate SMP mode on a uniprocessor
26 * system, in that case we have to call the local interrupt handler.
27 */
28#ifndef CONFIG_X86_LOCAL_APIC
David Howells7d12e782006-10-05 14:55:46 +010029 profile_tick(CPU_PROFILING);
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#else
31 if (!using_apic_timer)
David Howells7d12e782006-10-05 14:55:46 +010032 smp_local_timer_interrupt();
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#endif
34}
35
36
37/* you can safely undefine this if you don't have the Neptune chipset */
38
39#define BUGGY_NEPTUN_TIMER
40
41/**
42 * do_timer_overflow - process a detected timer overflow condition
43 * @count: hardware timer interrupt count on overflow
44 *
45 * Description:
46 * This call is invoked when the jiffies count has not incremented but
47 * the hardware timer interrupt has. It means that a timer tick interrupt
48 * came along while the previous one was pending, thus a tick was missed
49 **/
50static inline int do_timer_overflow(int count)
51{
52 int i;
53
54 spin_lock(&i8259A_lock);
55 /*
56 * This is tricky when I/O APICs are used;
57 * see do_timer_interrupt().
58 */
59 i = inb(0x20);
60 spin_unlock(&i8259A_lock);
61
62 /* assumption about timer being IRQ0 */
63 if (i & 0x01) {
64 /*
65 * We cannot detect lost timer interrupts ...
66 * well, that's why we call them lost, don't we? :)
67 * [hmm, on the Pentium and Alpha we can ... sort of]
68 */
69 count -= LATCH;
70 } else {
71#ifdef BUGGY_NEPTUN_TIMER
72 /*
73 * for the Neptun bug we know that the 'latch'
74 * command doesn't latch the high and low value
75 * of the counter atomically. Thus we have to
76 * substract 256 from the counter
77 * ... funny, isnt it? :)
78 */
79
80 count -= 256;
81#else
82 printk("do_slow_gettimeoffset(): hardware timer problem?\n");
83#endif
84 }
85 return count;
86}