diff options
Diffstat (limited to 'gpxe/src/arch/i386/drivers/timer_rdtsc.c')
-rw-r--r-- | gpxe/src/arch/i386/drivers/timer_rdtsc.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/gpxe/src/arch/i386/drivers/timer_rdtsc.c b/gpxe/src/arch/i386/drivers/timer_rdtsc.c new file mode 100644 index 00000000..09b7df2f --- /dev/null +++ b/gpxe/src/arch/i386/drivers/timer_rdtsc.c @@ -0,0 +1,69 @@ + +#include <gpxe/init.h> +#include <gpxe/timer.h> +#include <errno.h> +#include <stdio.h> +#include <bits/cpu.h> +#include <bits/timer2.h> +#include <io.h> + + +#define rdtsc(low,high) \ + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define rdtscll(val) \ + __asm__ __volatile__ ("rdtsc" : "=A" (val)) + + +/* Measure how many clocks we get in one microsecond */ +static inline uint64_t calibrate_tsc(void) +{ + + uint64_t rdtsc_start; + uint64_t rdtsc_end; + + rdtscll(rdtsc_start); + i386_timer2_udelay(USECS_IN_MSEC); + rdtscll(rdtsc_end); + + return (rdtsc_end - rdtsc_start) / USECS_IN_MSEC; +} + +static uint32_t clocks_per_usec = 0; + +/* We measure time in microseconds. */ +static tick_t rdtsc_currticks(void) +{ + uint64_t clocks; + + /* Read the Time Stamp Counter */ + rdtscll(clocks); + + return clocks / clocks_per_usec; +} + +static int rdtsc_ts_init(void) +{ + + struct cpuinfo_x86 cpu_info; + + get_cpuinfo(&cpu_info); + if (cpu_info.features & X86_FEATURE_TSC) { + clocks_per_usec= calibrate_tsc(); + if (clocks_per_usec) { + DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n", + clocks_per_usec); + return 0; + } + } + + DBG("RDTSC ticksource not available on this machine.\n"); + return -ENODEV; +} + +struct timer rdtsc_ts __timer (01) = { + .init = rdtsc_ts_init, + .udelay = generic_currticks_udelay, + .currticks = rdtsc_currticks, +}; + |