2005-04-17 02:20:36 +04:00
/*
2009-08-20 17:35:23 +04:00
* Copyright ( c ) 1991 , 1992 , 1995 Linus Torvalds
* Copyright ( c ) 1994 Alan Modra
* Copyright ( c ) 1995 Markus Kuhn
* Copyright ( c ) 1996 Ingo Molnar
* Copyright ( c ) 1998 Andrea Arcangeli
* Copyright ( c ) 2002 , 2006 Vojtech Pavlik
* Copyright ( c ) 2003 Andi Kleen
2005-04-17 02:20:36 +04:00
*
*/
2009-08-20 17:28:50 +04:00
# include <linux/clockchips.h>
2005-04-17 02:20:36 +04:00
# include <linux/interrupt.h>
2011-06-01 22:04:57 +04:00
# include <linux/i8253.h>
2005-04-17 02:20:36 +04:00
# include <linux/time.h>
2011-05-26 20:22:53 +04:00
# include <linux/export.h>
2005-04-17 02:20:36 +04:00
2009-08-20 17:35:23 +04:00
# include <asm/vsyscall.h>
# include <asm/x86_init.h>
2009-08-20 17:28:50 +04:00
# include <asm/i8259.h>
2009-08-20 17:35:23 +04:00
# include <asm/timer.h>
# include <asm/hpet.h>
# include <asm/time.h>
2005-04-17 02:20:36 +04:00
2009-08-20 18:07:40 +04:00
# ifdef CONFIG_X86_64
2011-05-23 17:31:24 +04:00
DEFINE_VVAR ( volatile unsigned long , jiffies ) = INITIAL_JIFFIES ;
2009-08-20 18:07:40 +04:00
# endif
2005-04-17 02:20:36 +04:00
unsigned long profile_pc ( struct pt_regs * regs )
{
unsigned long pc = instruction_pointer ( regs ) ;
2008-07-11 20:48:07 +04:00
if ( ! user_mode_vm ( regs ) & & in_lock_functions ( pc ) ) {
2006-09-26 12:52:28 +04:00
# ifdef CONFIG_FRAME_POINTER
2008-07-11 23:06:40 +04:00
return * ( unsigned long * ) ( regs - > bp + sizeof ( long ) ) ;
2006-09-26 12:52:28 +04:00
# else
2009-10-12 22:32:31 +04:00
unsigned long * sp =
( unsigned long * ) kernel_stack_pointer ( regs ) ;
2009-08-21 15:24:08 +04:00
/*
* Return address is either directly at stack pointer
* or above a saved flags . Eflags has bits 22 - 31 zero ,
* kernel addresses don ' t .
*/
2008-01-30 15:30:26 +03:00
if ( sp [ 0 ] > > 22 )
2006-09-26 12:52:28 +04:00
return sp [ 0 ] ;
if ( sp [ 1 ] > > 22 )
return sp [ 1 ] ;
# endif
}
2005-04-17 02:20:36 +04:00
return pc ;
}
EXPORT_SYMBOL ( profile_pc ) ;
/*
2009-08-20 18:07:40 +04:00
* Default timer interrupt handler for PIT / HPET
2005-04-17 02:20:36 +04:00
*/
2009-08-19 17:37:03 +04:00
static irqreturn_t timer_interrupt ( int irq , void * dev_id )
2005-04-17 02:20:36 +04:00
{
2009-08-20 17:28:50 +04:00
global_clock_event - > event_handler ( global_clock_event ) ;
2005-04-17 02:20:36 +04:00
return IRQ_HANDLED ;
}
2009-08-19 17:37:03 +04:00
static struct irqaction irq0 = {
. handler = timer_interrupt ,
. flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER ,
. name = " timer "
} ;
void __init setup_default_timer_irq ( void )
{
setup_irq ( 0 , & irq0 ) ;
}
/* Default timer init function */
2007-03-05 11:30:39 +03:00
void __init hpet_time_init ( void )
2005-04-17 02:20:36 +04:00
{
2007-02-16 12:28:04 +03:00
if ( ! hpet_enable ( ) )
setup_pit_timer ( ) ;
2009-08-19 17:37:03 +04:00
setup_default_timer_irq ( ) ;
}
2009-09-16 10:42:26 +04:00
static __init void x86_late_time_init ( void )
2009-08-19 17:37:03 +04:00
{
x86_init . timers . timer_init ( ) ;
2009-08-20 18:51:07 +04:00
tsc_init ( ) ;
2005-04-17 02:20:36 +04:00
}
2007-03-05 11:30:39 +03:00
/*
2009-08-19 17:37:03 +04:00
* Initialize TSC and delay the periodic timer init to
* late x86_late_time_init ( ) so ioremap works .
2007-03-05 11:30:39 +03:00
*/
2005-04-17 02:20:36 +04:00
void __init time_init ( void )
{
2009-08-19 17:37:03 +04:00
late_time_init = x86_late_time_init ;
2005-04-17 02:20:36 +04:00
}