1 /* 2 * Copyright (c) 1991,1992,1995 Linus Torvalds 3 * Copyright (c) 1994 Alan Modra 4 * Copyright (c) 1995 Markus Kuhn 5 * Copyright (c) 1996 Ingo Molnar 6 * Copyright (c) 1998 Andrea Arcangeli 7 * Copyright (c) 2002,2006 Vojtech Pavlik 8 * Copyright (c) 2003 Andi Kleen 9 * 10 */ 11 12 #include <linux/clockchips.h> 13 #include <linux/interrupt.h> 14 #include <linux/i8253.h> 15 #include <linux/time.h> 16 #include <linux/export.h> 17 18 #include <asm/vsyscall.h> 19 #include <asm/x86_init.h> 20 #include <asm/i8259.h> 21 #include <asm/timer.h> 22 #include <asm/hpet.h> 23 #include <asm/time.h> 24 profile_pc(struct pt_regs * regs)25unsigned long profile_pc(struct pt_regs *regs) 26 { 27 unsigned long pc = instruction_pointer(regs); 28 29 if (!user_mode(regs) && in_lock_functions(pc)) { 30 #ifdef CONFIG_FRAME_POINTER 31 return *(unsigned long *)(regs->bp + sizeof(long)); 32 #else 33 unsigned long *sp = 34 (unsigned long *)kernel_stack_pointer(regs); 35 /* 36 * Return address is either directly at stack pointer 37 * or above a saved flags. Eflags has bits 22-31 zero, 38 * kernel addresses don't. 39 */ 40 if (sp[0] >> 22) 41 return sp[0]; 42 if (sp[1] >> 22) 43 return sp[1]; 44 #endif 45 } 46 return pc; 47 } 48 EXPORT_SYMBOL(profile_pc); 49 50 /* 51 * Default timer interrupt handler for PIT/HPET 52 */ timer_interrupt(int irq,void * dev_id)53static irqreturn_t timer_interrupt(int irq, void *dev_id) 54 { 55 global_clock_event->event_handler(global_clock_event); 56 return IRQ_HANDLED; 57 } 58 59 static struct irqaction irq0 = { 60 .handler = timer_interrupt, 61 .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, 62 .name = "timer" 63 }; 64 setup_default_timer_irq(void)65void __init setup_default_timer_irq(void) 66 { 67 if (!nr_legacy_irqs()) 68 return; 69 setup_irq(0, &irq0); 70 } 71 72 /* Default timer init function */ hpet_time_init(void)73void __init hpet_time_init(void) 74 { 75 if (!hpet_enable()) 76 setup_pit_timer(); 77 setup_default_timer_irq(); 78 } 79 x86_late_time_init(void)80static __init void x86_late_time_init(void) 81 { 82 x86_init.timers.timer_init(); 83 tsc_init(); 84 } 85 86 /* 87 * Initialize TSC and delay the periodic timer init to 88 * late x86_late_time_init() so ioremap works. 89 */ time_init(void)90void __init time_init(void) 91 { 92 late_time_init = x86_late_time_init; 93 } 94