@ -116,6 +116,158 @@ fail:
return 0 ;
}
/*
* This reads the current MSB of the PIT counter , and
* checks if we are running on sufficiently fast and
* non - virtualized hardware .
*
* Our expectations are :
*
* - the PIT is running at roughly 1.19 MHz
*
* - each IO is going to take about 1u s on real hardware ,
* but we allow it to be much faster ( by a factor of 10 ) or
* _slightly_ slower ( ie we allow up to a 2u s read + counter
* update - anything else implies a unacceptably slow CPU
* or PIT for the fast calibration to work .
*
* - with 256 PIT ticks to read the value , we have 214u s to
* see the same MSB ( and overhead like doing a single TSC
* read per MSB value etc ) .
*
* - We ' re doing 2 reads per loop ( LSB , MSB ) , and we expect
* them each to take about a microsecond on real hardware .
* So we expect a count value of around 100. But we ' ll be
* generous , and accept anything over 50.
*
* - if the PIT is stuck , and we see * many * more reads , we
* return early ( and the next caller of pit_expect_msb ( )
* then consider it a failure when they don ' t see the
* next expected value ) .
*
* These expectations mean that we know that we have seen the
* transition from one expected value to another with a fairly
* high accuracy , and we didn ' t miss any events . We can thus
* use the TSC value at the transitions to calculate a pretty
* good value for the TSC frequencty .
*/
static inline int pit_verify_msb ( unsigned char val )
{
/* Ignore LSB */
inb ( 0x42 ) ;
return inb ( 0x42 ) = = val ;
}
static inline int pit_expect_msb ( unsigned char val , u64 * tscp ,
unsigned long * deltap )
{
int count ;
u64 tsc = 0 , prev_tsc = 0 ;
for ( count = 0 ; count < 50000 ; count + + ) {
if ( ! pit_verify_msb ( val ) )
break ;
prev_tsc = tsc ;
tsc = rdtsc ( ) ;
}
* deltap = rdtsc ( ) - prev_tsc ;
* tscp = tsc ;
/*
* We require _some_ success , but the quality control
* will be based on the error terms on the TSC values .
*/
return count > 5 ;
}
/*
* How many MSB values do we want to see ? We aim for
* a maximum error rate of 500 ppm ( in practice the
* real error is much smaller ) , but refuse to spend
* more than 50 ms on it .
*/
# define MAX_QUICK_PIT_MS 50
# define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
static unsigned long quick_pit_calibrate ( void )
{
int i ;
u64 tsc , delta ;
unsigned long d1 , d2 ;
/* Set the Gate high, disable speaker */
outb ( ( inb ( 0x61 ) & ~ 0x02 ) | 0x01 , 0x61 ) ;
/*
* Counter 2 , mode 0 ( one - shot ) , binary count
*
* NOTE ! Mode 2 decrements by two ( and then the
* output is flipped each time , giving the same
* final output frequency as a decrement - by - one ) ,
* so mode 0 is much better when looking at the
* individual counts .
*/
outb ( 0xb0 , 0x43 ) ;
/* Start at 0xffff */
outb ( 0xff , 0x42 ) ;
outb ( 0xff , 0x42 ) ;
/*
* The PIT starts counting at the next edge , so we
* need to delay for a microsecond . The easiest way
* to do that is to just read back the 16 - bit counter
* once from the PIT .
*/
pit_verify_msb ( 0 ) ;
if ( pit_expect_msb ( 0xff , & tsc , & d1 ) ) {
for ( i = 1 ; i < = MAX_QUICK_PIT_ITERATIONS ; i + + ) {
if ( ! pit_expect_msb ( 0xff - i , & delta , & d2 ) )
break ;
/*
* Iterate until the error is less than 500 ppm
*/
delta - = tsc ;
if ( d1 + d2 > = delta > > 11 )
continue ;
/*
* Check the PIT one more time to verify that
* all TSC reads were stable wrt the PIT .
*
* This also guarantees serialization of the
* last cycle read ( ' d2 ' ) in pit_expect_msb .
*/
if ( ! pit_verify_msb ( 0xfe - i ) )
break ;
goto success ;
}
}
debug ( " Fast TSC calibration failed \n " ) ;
return 0 ;
success :
/*
* Ok , if we get here , then we ' ve seen the
* MSB of the PIT decrement ' i ' times , and the
* error has shrunk to less than 500 ppm .
*
* As a result , we can depend on there not being
* any odd delays anywhere , and the TSC reads are
* reliable ( within the error ) .
*
* kHz = ticks / time - in - seconds / 1000 ;
* kHz = ( t2 - t1 ) / ( I * 256 / PIT_TICK_RATE ) / 1000
* kHz = ( ( t2 - t1 ) * PIT_TICK_RATE ) / ( I * 256 * 1000 )
*/
delta * = PIT_TICK_RATE ;
delta / = ( i * 256 * 1000 ) ;
debug ( " Fast TSC calibration using PIT \n " ) ;
return delta / 1000 ;
}
void timer_set_base ( u64 base )
{
gd - > arch . tsc_base = base ;
@ -142,6 +294,10 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
unsigned long fast_calibrate ;
fast_calibrate = try_msr_calibrate_tsc ( ) ;
if ( fast_calibrate )
return fast_calibrate ;
fast_calibrate = quick_pit_calibrate ( ) ;
if ( ! fast_calibrate )
panic ( " TSC frequency is ZERO " ) ;