pvclock.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #ifndef _ASM_X86_PVCLOCK_H
  2. #define _ASM_X86_PVCLOCK_H
  3. #include <linux/clocksource.h>
  4. #include <asm/pvclock-abi.h>
  5. /* some helper functions for xen and kvm pv clock sources */
  6. u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
  7. u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
  8. void pvclock_set_flags(u8 flags);
  9. unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
  10. void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
  11. struct pvclock_vcpu_time_info *vcpu,
  12. struct timespec *ts);
  13. void pvclock_resume(void);
  14. void pvclock_touch_watchdogs(void);
  15. static __always_inline
  16. unsigned pvclock_read_begin(const struct pvclock_vcpu_time_info *src)
  17. {
  18. unsigned version = src->version & ~1;
  19. /* Make sure that the version is read before the data. */
  20. virt_rmb();
  21. return version;
  22. }
  23. static __always_inline
  24. bool pvclock_read_retry(const struct pvclock_vcpu_time_info *src,
  25. unsigned version)
  26. {
  27. /* Make sure that the version is re-read after the data. */
  28. virt_rmb();
  29. return unlikely(version != src->version);
  30. }
  31. /*
  32. * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
  33. * yielding a 64-bit result.
  34. */
  35. static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
  36. {
  37. u64 product;
  38. #ifdef __i386__
  39. u32 tmp1, tmp2;
  40. #else
  41. ulong tmp;
  42. #endif
  43. if (shift < 0)
  44. delta >>= -shift;
  45. else
  46. delta <<= shift;
  47. #ifdef __i386__
  48. __asm__ (
  49. "mul %5 ; "
  50. "mov %4,%%eax ; "
  51. "mov %%edx,%4 ; "
  52. "mul %5 ; "
  53. "xor %5,%5 ; "
  54. "add %4,%%eax ; "
  55. "adc %5,%%edx ; "
  56. : "=A" (product), "=r" (tmp1), "=r" (tmp2)
  57. : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
  58. #elif defined(__x86_64__)
  59. __asm__ (
  60. "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]"
  61. : [lo]"=a"(product),
  62. [hi]"=d"(tmp)
  63. : "0"(delta),
  64. [mul_frac]"rm"((u64)mul_frac));
  65. #else
  66. #error implement me!
  67. #endif
  68. return product;
  69. }
  70. static __always_inline
  71. u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc)
  72. {
  73. u64 delta = tsc - src->tsc_timestamp;
  74. u64 offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
  75. src->tsc_shift);
  76. return src->system_time + offset;
  77. }
  78. struct pvclock_vsyscall_time_info {
  79. struct pvclock_vcpu_time_info pvti;
  80. } __attribute__((__aligned__(SMP_CACHE_BYTES)));
  81. #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
  82. #ifdef CONFIG_PARAVIRT_CLOCK
  83. void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti);
  84. struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void);
  85. #else
  86. static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void)
  87. {
  88. return NULL;
  89. }
  90. #endif
  91. #endif /* _ASM_X86_PVCLOCK_H */