3 #include <gpxe/timer.h>
7 #include <bits/timer2.h>
11 #define rdtsc(low,high) \
12 __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
14 #define rdtscll(val) \
15 __asm__ __volatile__ ("rdtsc" : "=A" (val))
17 static unsigned long long calibrate_tsc(void)
19 uint32_t startlow, starthigh;
20 uint32_t endlow, endhigh;
22 rdtsc(startlow,starthigh);
23 i386_timer2_udelay(USECS_IN_MSEC/2);
24 rdtsc(endlow,endhigh);
26 /* 64-bit subtract - gcc just messes up with long longs */
27 /* XXX ORLY? Check it. */
28 __asm__("subl %2,%0\n\t"
30 :"=a" (endlow), "=d" (endhigh)
31 :"g" (startlow), "g" (starthigh),
32 "0" (endlow), "1" (endhigh));
34 /* Error: ECPUTOOFAST */
38 endlow *= MSECS_IN_SEC*2;
42 * The CTC wasn't reliable: we got a hit on the very first read,
43 * or the CPU was so fast/slow that the quotient wouldn't fit in
49 static uint32_t clocks_per_second = 0;
51 static tick_t rtdsc_currticks(void)
53 uint32_t clocks_high, clocks_low;
56 /* Read the Time Stamp Counter */
57 rdtsc(clocks_low, clocks_high);
59 /* currticks = clocks / clocks_per_tick; */
62 :"r" (clocks_per_second/USECS_IN_SEC), "0" (clocks_low), "d" (clocks_high));
67 static int rtdsc_ts_init(void)
70 struct cpuinfo_x86 cpu_info;
72 get_cpuinfo(&cpu_info);
73 if (cpu_info.features & X86_FEATURE_TSC) {
74 clocks_per_second = calibrate_tsc();
75 if (clocks_per_second) {
76 DBG("RTDSC Ticksource installed. CPU running at %ld Mhz\n",
77 clocks_per_second/(1000*1000));
82 DBG("RTDSC timer not available on this machine.\n");
86 struct timer rtdsc_ts __timer (01) = {
87 .init = rtdsc_ts_init,
88 .udelay = generic_currticks_udelay,
89 .currticks = rtdsc_currticks,