| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* defines for inline arch setup functions */ | 
 | 2 |  | 
 | 3 | #include <asm/apic.h> | 
| Ingo Molnar | 306e440 | 2005-06-30 02:58:55 -0700 | [diff] [blame] | 4 | #include <asm/i8259.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5 |  | 
 | 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 |  | 
 | 17 | static inline void do_timer_interrupt_hook(struct pt_regs *regs) | 
 | 18 | { | 
 | 19 | 	do_timer(regs); | 
 | 20 | #ifndef CONFIG_SMP | 
 | 21 | 	update_process_times(user_mode(regs)); | 
 | 22 | #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 | 
 | 29 | 	profile_tick(CPU_PROFILING, regs); | 
 | 30 | #else | 
 | 31 | 	if (!using_apic_timer) | 
 | 32 | 		smp_local_timer_interrupt(regs); | 
 | 33 | #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 |  **/ | 
 | 50 | static 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 | } |