2007-03-06 12:42:05 +03:00
/*
2007-10-13 01:04:23 +04:00
* x86 TSC related functions
2007-03-06 12:42:05 +03:00
*/
2007-10-13 01:04:23 +04:00
# ifndef _ASM_X86_TSC_H
# define _ASM_X86_TSC_H
2007-03-06 12:42:05 +03:00
# include <asm/processor.h>
2007-10-13 01:04:23 +04:00
# define NS_SCALE 10 /* 2^10, carefully chosen */
# define US_SCALE 32 /* 2^32, arbitralrily chosen */
2007-03-06 12:42:05 +03:00
/*
* Standard way to access the cycle counter .
*/
typedef unsigned long long cycles_t ;
extern unsigned int cpu_khz ;
extern unsigned int tsc_khz ;
static inline cycles_t get_cycles ( void )
{
unsigned long long ret = 0 ;
# ifndef CONFIG_X86_TSC
if ( ! cpu_has_tsc )
return 0 ;
# endif
# if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
rdtscll ( ret ) ;
# endif
return ret ;
}
/* Like get_cycles, but make sure the CPU is synchronized. */
static __always_inline cycles_t get_cycles_sync ( void )
{
unsigned long long ret ;
2007-05-11 09:22:14 +04:00
unsigned eax , edx ;
2007-03-06 12:42:05 +03:00
2007-05-02 21:27:21 +04:00
/*
* Use RDTSCP if possible ; it is guaranteed to be synchronous
* and doesn ' t cause a VMEXIT on Hypervisors
*/
alternative_io ( ASM_NOP3 , " .byte 0x0f,0x01,0xf9 " , X86_FEATURE_RDTSCP ,
2007-05-11 09:22:14 +04:00
ASM_OUTPUT2 ( " =a " ( eax ) , " =d " ( edx ) ) ,
" a " ( 0U ) , " d " ( 0U ) : " ecx " , " memory " ) ;
ret = ( ( ( unsigned long long ) edx ) < < 32 ) | ( ( unsigned long long ) eax ) ;
2007-05-02 21:27:21 +04:00
if ( ret )
return ret ;
2007-03-06 12:42:05 +03:00
/*
* Don ' t do an additional sync on CPUs where we know
* RDTSC is already synchronous :
*/
alternative_io ( " cpuid " , ASM_NOP2 , X86_FEATURE_SYNC_RDTSC ,
" =a " ( eax ) , " 0 " ( 1 ) : " ebx " , " ecx " , " edx " , " memory " ) ;
rdtscll ( ret ) ;
return ret ;
}
extern void tsc_init ( void ) ;
2007-05-02 21:27:08 +04:00
extern void mark_tsc_unstable ( char * reason ) ;
2007-03-06 12:42:05 +03:00
extern int unsynchronized_tsc ( void ) ;
extern void init_tsc_clocksource ( void ) ;
2007-07-19 12:49:23 +04:00
int check_tsc_unstable ( void ) ;
2007-03-06 12:42:05 +03:00
/*
* Boot - time check whether the TSCs are synchronized across
* all CPUs / cores :
*/
extern void check_tsc_sync_source ( int cpu ) ;
extern void check_tsc_sync_target ( void ) ;
2007-10-13 01:04:06 +04:00
# ifdef CONFIG_X86_64
extern void tsc_calibrate ( void ) ;
# endif
2007-03-06 12:42:05 +03:00
# endif