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