linux/tools/arch/x86/include/asm/pvclock.h
<<
>>
Prefs
   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 */
 104