linux/arch/x86/include/asm/pvclock.h
<<
>>
Prefs
   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 */
  17u64 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
  90u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc)
  91{
  92        u64 delta = tsc - src->tsc_timestamp;
  93        u64 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 */
 105