Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
We now have two implementations for the timer API: one using the time-of-day counter at 40:70 and one using RDTSC. Both make use of timer2_udelay().
- Loading branch information
Michael Brown
committed
Oct 12, 2008
1 parent
e6f276e
commit 16f1e35
Showing
22 changed files
with
386 additions
and
284 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation; either version 2 of the | ||
* License, or any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
*/ | ||
|
||
/** @file | ||
* | ||
* RDTSC timer | ||
* | ||
*/ | ||
|
||
#include <assert.h> | ||
#include <gpxe/timer.h> | ||
#include <gpxe/timer2.h> | ||
|
||
/** | ||
* Number of TSC ticks per microsecond | ||
* | ||
* This is calibrated on the first use of the timer. | ||
*/ | ||
static unsigned long rdtsc_ticks_per_usec; | ||
|
||
/** | ||
* Delay for a fixed number of microseconds | ||
* | ||
* @v usecs Number of microseconds for which to delay | ||
*/ | ||
static void rdtsc_udelay ( unsigned long usecs ) { | ||
unsigned long start; | ||
unsigned long elapsed; | ||
|
||
/* Sanity guard, since we may divide by this */ | ||
if ( ! usecs ) | ||
usecs = 1; | ||
|
||
start = currticks(); | ||
if ( rdtsc_ticks_per_usec ) { | ||
/* Already calibrated; busy-wait until done */ | ||
do { | ||
elapsed = ( currticks() - start ); | ||
} while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) ); | ||
} else { | ||
/* Not yet calibrated; use timer2 and calibrate | ||
* based on result. | ||
*/ | ||
timer2_udelay ( usecs ); | ||
elapsed = ( currticks() - start ); | ||
rdtsc_ticks_per_usec = ( elapsed / usecs ); | ||
DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs " | ||
"(%ld MHz)\n", elapsed, usecs, | ||
( rdtsc_ticks_per_usec << TSC_SHIFT ) ); | ||
} | ||
} | ||
|
||
/** | ||
* Get number of ticks per second | ||
* | ||
* @ret ticks_per_sec Number of ticks per second | ||
*/ | ||
static unsigned long rdtsc_ticks_per_sec ( void ) { | ||
|
||
/* Calibrate timer, if not already done */ | ||
if ( ! rdtsc_ticks_per_usec ) | ||
udelay ( 1 ); | ||
|
||
/* Sanity check */ | ||
assert ( rdtsc_ticks_per_usec != 0 ); | ||
|
||
return ( rdtsc_ticks_per_usec * 1000 * 1000 ); | ||
} | ||
|
||
PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay ); | ||
PROVIDE_TIMER_INLINE ( rdtsc, currticks ); | ||
PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#ifndef _BITS_TIMER_H | ||
#define _BITS_TIMER_H | ||
|
||
/** @file | ||
* | ||
* i386-specific timer API implementations | ||
* | ||
*/ | ||
|
||
#include <gpxe/bios_timer.h> | ||
#include <gpxe/rdtsc_timer.h> | ||
|
||
#endif /* _BITS_TIMER_H */ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#ifndef _GPXE_BIOS_TIMER_H | ||
#define _GPXE_BIOS_TIMER_H | ||
|
||
/** @file | ||
* | ||
* BIOS timer | ||
* | ||
*/ | ||
|
||
#ifdef TIMER_PCBIOS | ||
#define TIMER_PREFIX_pcbios | ||
#else | ||
#define TIMER_PREFIX_pcbios __pcbios_ | ||
#endif | ||
|
||
#include <gpxe/timer2.h> | ||
|
||
/** | ||
* Delay for a fixed number of microseconds | ||
* | ||
* @v usecs Number of microseconds for which to delay | ||
*/ | ||
static inline __always_inline void | ||
TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) { | ||
/* BIOS timer is not high-resolution enough for udelay(), so | ||
* we use timer2 | ||
*/ | ||
timer2_udelay ( usecs ); | ||
} | ||
|
||
/** | ||
* Get number of ticks per second | ||
* | ||
* @ret ticks_per_sec Number of ticks per second | ||
*/ | ||
static inline __always_inline unsigned long | ||
TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) { | ||
/* BIOS timer ticks over at 18.2 ticks per second */ | ||
return 18; | ||
} | ||
|
||
#endif /* _GPXE_BIOS_TIMER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#ifndef _GPXE_RDTSC_TIMER_H | ||
#define _GPXE_RDTSC_TIMER_H | ||
|
||
/** @file | ||
* | ||
* RDTSC timer | ||
* | ||
*/ | ||
|
||
#ifdef TIMER_RDTSC | ||
#define TIMER_PREFIX_rdtsc | ||
#else | ||
#define TIMER_PREFIX_rdtsc __rdtsc_ | ||
#endif | ||
|
||
/** | ||
* RDTSC values can easily overflow an unsigned long. We discard the | ||
* low-order bits in order to obtain sensibly-scaled values. | ||
*/ | ||
#define TSC_SHIFT 8 | ||
|
||
/** | ||
* Get current system time in ticks | ||
* | ||
* @ret ticks Current time, in ticks | ||
*/ | ||
static inline __always_inline unsigned long | ||
TIMER_INLINE ( rdtsc, currticks ) ( void ) { | ||
unsigned long ticks; | ||
|
||
__asm__ __volatile__ ( "rdtsc\n\t" | ||
"shrdl %1, %%edx, %%eax\n\t" | ||
: "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" ); | ||
return ticks; | ||
} | ||
|
||
#endif /* _GPXE_RDTSC_TIMER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#ifndef _GPXE_TIMER2_H | ||
#define _GPXE_TIMER2_H | ||
|
||
/** @file | ||
* | ||
* Timer chip control | ||
* | ||
*/ | ||
|
||
extern void timer2_udelay ( unsigned long usecs ); | ||
|
||
#endif /* _GPXE_TIMER2_H */ |
Oops, something went wrong.