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/* some helper functions for xen and kvm pv clock sources */
   8cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
   9u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
  10void pvclock_set_flags(u8 flags);
  11unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
  12void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
  13                            struct pvclock_vcpu_time_info *vcpu,
  14                            struct timespec *ts);
  15void pvclock_resume(void);
  16
  17void pvclock_touch_watchdogs(void);
  18
  19/*
  20 * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
  21 * yielding a 64-bit result.
  22 */
  23static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
  24{
  25        u64 product;
  26#ifdef __i386__
  27        u32 tmp1, tmp2;
  28#else
  29        ulong tmp;
  30#endif
  31
  32        if (shift < 0)
  33                delta >>= -shift;
  34        else
  35                delta <<= shift;
  36
  37#ifdef __i386__
  38        __asm__ (
  39                "mul  %5       ; "
  40                "mov  %4,%%eax ; "
  41                "mov  %%edx,%4 ; "
  42                "mul  %5       ; "
  43                "xor  %5,%5    ; "
  44                "add  %4,%%eax ; "
  45                "adc  %5,%%edx ; "
  46                : "=A" (product), "=r" (tmp1), "=r" (tmp2)
  47                : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
  48#elif defined(__x86_64__)
  49        __asm__ (
  50                "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]"
  51                : [lo]"=a"(product),
  52                  [hi]"=d"(tmp)
  53                : "0"(delta),
  54                  [mul_frac]"rm"((u64)mul_frac));
  55#else
  56#error implement me!
  57#endif
  58
  59        return product;
  60}
  61
  62static __always_inline
  63u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src)
  64{
  65        u64 delta = rdtsc_ordered() - src->tsc_timestamp;
  66        return pvclock_scale_delta(delta, src->tsc_to_system_mul,
  67                                   src->tsc_shift);
  68}
  69
  70static __always_inline
  71unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
  72                               cycle_t *cycles, u8 *flags)
  73{
  74        unsigned version;
  75        cycle_t ret, offset;
  76        u8 ret_flags;
  77
  78        version = src->version;
  79
  80        offset = pvclock_get_nsec_offset(src);
  81        ret = src->system_time + offset;
  82        ret_flags = src->flags;
  83
  84        *cycles = ret;
  85        *flags = ret_flags;
  86        return version;
  87}
  88
  89struct pvclock_vsyscall_time_info {
  90        struct pvclock_vcpu_time_info pvti;
  91} __attribute__((__aligned__(SMP_CACHE_BYTES)));
  92
  93#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
  94#define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1)
  95
  96int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
  97                                 int size);
  98struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu);
  99
 100#endif /* _ASM_X86_PVCLOCK_H */
 101