Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
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 /* some helper functions for xen and kvm pv clock sources */
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     /* Make sure that the version is read before the data. */
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     /* Make sure that the version is re-read after the data. */
0031     rmb();
0032     return version != src->version;
0033 }
0034 
0035 /*
0036  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
0037  * yielding a 64-bit result.
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 /* _ASM_X86_PVCLOCK_H */