2005-04-16 15:20:36 -07:00
/*
2009-08-20 15:35:23 +02: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-16 15:20:36 -07:00
*
*/
2009-08-20 15:28:50 +02:00
# include <linux/clockchips.h>
2005-04-16 15:20:36 -07:00
# include <linux/interrupt.h>
2011-06-01 19:04:57 +01:00
# include <linux/i8253.h>
2005-04-16 15:20:36 -07:00
# include <linux/time.h>
2011-05-26 12:22:53 -04:00
# include <linux/export.h>
2005-04-16 15:20:36 -07:00
2009-08-20 15:35:23 +02:00
# include <asm/vsyscall.h>
# include <asm/x86_init.h>
2009-08-20 15:28:50 +02:00
# include <asm/i8259.h>
2009-08-20 15:35:23 +02:00
# include <asm/timer.h>
# include <asm/hpet.h>
# include <asm/time.h>
2005-04-16 15:20:36 -07:00
2009-08-20 16:07:40 +02:00
# ifdef CONFIG_X86_64
2014-09-23 10:50:56 -07:00
__visible volatile unsigned long jiffies __cacheline_aligned = INITIAL_JIFFIES ;
2009-08-20 16:07:40 +02:00
# endif
2005-04-16 15:20:36 -07:00
unsigned long profile_pc ( struct pt_regs * regs )
{
unsigned long pc = instruction_pointer ( regs ) ;
2015-03-18 18:33:33 -07:00
if ( ! user_mode ( regs ) & & in_lock_functions ( pc ) ) {
2006-09-26 10:52:28 +02:00
# ifdef CONFIG_FRAME_POINTER
2008-07-11 16:06:40 -03:00
return * ( unsigned long * ) ( regs - > bp + sizeof ( long ) ) ;
2006-09-26 10:52:28 +02:00
# else
2009-10-12 11:32:31 -07:00
unsigned long * sp =
( unsigned long * ) kernel_stack_pointer ( regs ) ;
2009-08-21 13:24:08 +02: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 13:30:26 +01:00
if ( sp [ 0 ] > > 22 )
2006-09-26 10:52:28 +02:00
return sp [ 0 ] ;
if ( sp [ 1 ] > > 22 )
return sp [ 1 ] ;
# endif
}
2005-04-16 15:20:36 -07:00
return pc ;
}
EXPORT_SYMBOL ( profile_pc ) ;
/*
2009-08-20 16:07:40 +02:00
* Default timer interrupt handler for PIT / HPET
2005-04-16 15:20:36 -07:00
*/
2009-08-19 15:37:03 +02:00
static irqreturn_t timer_interrupt ( int irq , void * dev_id )
2005-04-16 15:20:36 -07:00
{
2009-08-20 15:28:50 +02:00
global_clock_event - > event_handler ( global_clock_event ) ;
2005-04-16 15:20:36 -07:00
return IRQ_HANDLED ;
}
2009-08-19 15:37:03 +02:00
static struct irqaction irq0 = {
. handler = timer_interrupt ,
2014-03-04 21:35:05 +01:00
. flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER ,
2009-08-19 15:37:03 +02:00
. name = " timer "
} ;
2017-06-13 10:30:29 +08:00
static void __init setup_default_timer_irq ( void )
2009-08-19 15:37:03 +02:00
{
2014-07-21 11:38:40 +03:00
if ( ! nr_legacy_irqs ( ) )
return ;
2009-08-19 15:37:03 +02:00
setup_irq ( 0 , & irq0 ) ;
}
/* Default timer init function */
2007-03-05 00:30:39 -08:00
void __init hpet_time_init ( void )
2005-04-16 15:20:36 -07:00
{
2007-02-16 01:28:04 -08:00
if ( ! hpet_enable ( ) )
setup_pit_timer ( ) ;
2009-08-19 15:37:03 +02:00
setup_default_timer_irq ( ) ;
}
2009-09-16 08:42:26 +02:00
static __init void x86_late_time_init ( void )
2009-08-19 15:37:03 +02:00
{
x86_init . timers . timer_init ( ) ;
2009-08-20 16:51:07 +02:00
tsc_init ( ) ;
2005-04-16 15:20:36 -07:00
}
2007-03-05 00:30:39 -08:00
/*
2009-08-19 15:37:03 +02:00
* Initialize TSC and delay the periodic timer init to
* late x86_late_time_init ( ) so ioremap works .
2007-03-05 00:30:39 -08:00
*/
2005-04-16 15:20:36 -07:00
void __init time_init ( void )
{
2009-08-19 15:37:03 +02:00
late_time_init = x86_late_time_init ;
2005-04-16 15:20:36 -07:00
}