0001
0002 #ifndef _ASM_X86_PVCLOCK_H
0003 #define _ASM_X86_PVCLOCK_H
0004
0005 #include <asm/barrier.h>
0006 #include <asm/pvclock-abi.h>
0007
0008
0009 u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
0010 u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
0011 void pvclock_set_flags(u8 flags);
0012 unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
0013 void pvclock_resume(void);
0014
0015 void pvclock_touch_watchdogs(void);
0016
0017 static __always_inline
0018 unsigned pvclock_read_begin(const struct pvclock_vcpu_time_info *src)
0019 {
0020 unsigned version = src->version & ~1;
0021
0022 rmb();
0023 return version;
0024 }
0025
0026 static __always_inline
0027 bool pvclock_read_retry(const struct pvclock_vcpu_time_info *src,
0028 unsigned version)
0029 {
0030
0031 rmb();
0032 return version != src->version;
0033 }
0034
0035
0036
0037
0038
0039 static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
0040 {
0041 u64 product;
0042 #ifdef __i386__
0043 u32 tmp1, tmp2;
0044 #else
0045 unsigned long tmp;
0046 #endif
0047
0048 if (shift < 0)
0049 delta >>= -shift;
0050 else
0051 delta <<= shift;
0052
0053 #ifdef __i386__
0054 __asm__ (
0055 "mul %5 ; "
0056 "mov %4,%%eax ; "
0057 "mov %%edx,%4 ; "
0058 "mul %5 ; "
0059 "xor %5,%5 ; "
0060 "add %4,%%eax ; "
0061 "adc %5,%%edx ; "
0062 : "=A" (product), "=r" (tmp1), "=r" (tmp2)
0063 : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
0064 #elif defined(__x86_64__)
0065 __asm__ (
0066 "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]"
0067 : [lo]"=a"(product),
0068 [hi]"=d"(tmp)
0069 : "0"(delta),
0070 [mul_frac]"rm"((u64)mul_frac));
0071 #else
0072 #error implement me!
0073 #endif
0074
0075 return product;
0076 }
0077
0078 static __always_inline
0079 u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc)
0080 {
0081 u64 delta = tsc - src->tsc_timestamp;
0082 u64 offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
0083 src->tsc_shift);
0084 return src->system_time + offset;
0085 }
0086
0087 struct pvclock_vsyscall_time_info {
0088 struct pvclock_vcpu_time_info pvti;
0089 } __attribute__((__aligned__(64)));
0090
0091 #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
0092
0093 #ifdef CONFIG_PARAVIRT_CLOCK
0094 void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti);
0095 struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void);
0096 #else
0097 static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void)
0098 {
0099 return NULL;
0100 }
0101 #endif
0102
0103 #endif