File: /Users/paulross/dev/linux/linux-3.13/arch/x86/include/asm/pvclock.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

       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 */
       8: cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
       9: u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
      10: void pvclock_set_flags(u8 flags);
      11: unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
      12: void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
      13:                 struct pvclock_vcpu_time_info *vcpu,
      14:                 struct timespec *ts);
      15: void pvclock_resume(void);
      16: 
      17: void 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:  */
      23: static 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: 
      62: static __always_inline
      63: u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src)
      64: {
      65:     u64 delta = __native_read_tsc() - src->tsc_timestamp;
      66:     return pvclock_scale_delta(delta, src->tsc_to_system_mul,
      67:                    src->tsc_shift);
      68: }
      69: 
      70: static __always_inline
      71: unsigned __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:     /* Note: emulated platforms which do not advertise SSE2 support
      80:      * result in kvmclock not using the necessary RDTSC barriers.
      81:      * Without barriers, it is possible that RDTSC instruction reads from
      82:      * the time stamp counter outside rdtsc_barrier protected section
      83:      * below, resulting in violation of monotonicity.
      84:      */
      85:     rdtsc_barrier();
      86:     offset = pvclock_get_nsec_offset(src);
      87:     ret = src->system_time + offset;
      88:     ret_flags = src->flags;
      89:     rdtsc_barrier();
      90: 
      91:     *cycles = ret;
      92:     *flags = ret_flags;
      93:     return version;
      94: }
      95: 
      96: struct pvclock_vsyscall_time_info {
      97:     struct pvclock_vcpu_time_info pvti;
      98: } __attribute__((__aligned__(SMP_CACHE_BYTES)));
      99: 
     100: #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
     101: #define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1)
     102: 
     103: int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
     104:                  int size);
     105: struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu);
     106: 
     107: #endif /* _ASM_X86_PVCLOCK_H */
     108: