You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

timer_rdtsc.c 1.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #include <gpxe/init.h>
  2. #include <gpxe/timer.h>
  3. #include <errno.h>
  4. #include <stdio.h>
  5. #include <bits/cpu.h>
  6. #include <bits/timer2.h>
  7. #include <io.h>
  8. #define rdtsc(low,high) \
  9. __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
  10. #define rdtscll(val) \
  11. __asm__ __volatile__ ("rdtsc" : "=A" (val))
  12. /* Measure how many clocks we get in one microsecond */
  13. static inline uint64_t calibrate_tsc(void)
  14. {
  15. uint64_t rdtsc_start;
  16. uint64_t rdtsc_end;
  17. rdtscll(rdtsc_start);
  18. i386_timer2_udelay(USECS_IN_MSEC);
  19. rdtscll(rdtsc_end);
  20. return (rdtsc_end - rdtsc_start) / USECS_IN_MSEC;
  21. }
  22. static uint32_t clocks_per_usec = 0;
  23. /* We measure time in microseconds. */
  24. static tick_t rdtsc_currticks(void)
  25. {
  26. uint64_t clocks;
  27. /* Read the Time Stamp Counter */
  28. rdtscll(clocks);
  29. return clocks / clocks_per_usec;
  30. }
  31. static int rdtsc_ts_init(void)
  32. {
  33. struct cpuinfo_x86 cpu_info;
  34. get_cpuinfo(&cpu_info);
  35. if (cpu_info.features & X86_FEATURE_TSC) {
  36. clocks_per_usec= calibrate_tsc();
  37. if (clocks_per_usec) {
  38. DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n",
  39. clocks_per_usec);
  40. return 0;
  41. }
  42. }
  43. DBG("RDTSC ticksource not available on this machine.\n");
  44. return -ENODEV;
  45. }
  46. struct timer rdtsc_ts __timer (01) = {
  47. .init = rdtsc_ts_init,
  48. .udelay = generic_currticks_udelay,
  49. .currticks = rdtsc_currticks,
  50. };