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