3 #include <gpxe/timer.h>
6 #include <bits/timer2.h>
10 #define rdtsc(low,high) \
11 __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
13 #define rdtscll(val) \
14 __asm__ __volatile__ ("rdtsc" : "=A" (val))
16 static unsigned long long calibrate_tsc(void)
18 uint32_t startlow, starthigh;
19 uint32_t endlow, endhigh;
21 rdtsc(startlow,starthigh);
22 i386_timer2_udelay(USECS_IN_MSEC/2);
23 rdtsc(endlow,endhigh);
25 /* 64-bit subtract - gcc just messes up with long longs */
26 /* XXX ORLY? Check it. */
27 __asm__("subl %2,%0\n\t"
29 :"=a" (endlow), "=d" (endhigh)
30 :"g" (startlow), "g" (starthigh),
31 "0" (endlow), "1" (endhigh));
33 /* Error: ECPUTOOFAST */
37 endlow *= MSECS_IN_SEC*2;
41 * The CTC wasn't reliable: we got a hit on the very first read,
42 * or the CPU was so fast/slow that the quotient wouldn't fit in
48 static uint32_t clocks_per_second = 0;
50 static tick_t rtdsc_currticks(void)
52 uint32_t clocks_high, clocks_low;
55 /* Read the Time Stamp Counter */
56 rdtsc(clocks_low, clocks_high);
58 /* currticks = clocks / clocks_per_tick; */
61 :"r" (clocks_per_second/USECS_IN_SEC), "0" (clocks_low), "d" (clocks_high));
66 static int rtdsc_ts_init(void)
69 struct cpuinfo_x86 cpu_info;
71 get_cpuinfo(&cpu_info);
72 if (cpu_info.features & X86_FEATURE_TSC) {
73 clocks_per_second = calibrate_tsc();
74 if (clocks_per_second) {
75 DBG("RTDSC Ticksource installed. CPU running at %ld Mhz\n",
76 clocks_per_second/(1000*1000));
81 printf("RTDSC timer not available on this machine.\n");
85 struct timer rtdsc_ts __timer (01) = {
86 .init = rtdsc_ts_init,
87 .udelay = generic_currticks_udelay,
88 .currticks = rtdsc_currticks,