Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: arch: x86: pull in pvclock headers

Copy over approximately clean versions of the pvclock headers into
tools. Reconcile headers/symbols missing in tools that are unneeded.

Signed-off-by: Oliver Upton <oupton@google.com>
Message-Id: <20210916181555.973085-2-oupton@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Oliver Upton and committed by
Paolo Bonzini
50006539 828ca896

+151
+48
tools/arch/x86/include/asm/pvclock-abi.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_X86_PVCLOCK_ABI_H 3 + #define _ASM_X86_PVCLOCK_ABI_H 4 + #ifndef __ASSEMBLY__ 5 + 6 + /* 7 + * These structs MUST NOT be changed. 8 + * They are the ABI between hypervisor and guest OS. 9 + * Both Xen and KVM are using this. 10 + * 11 + * pvclock_vcpu_time_info holds the system time and the tsc timestamp 12 + * of the last update. So the guest can use the tsc delta to get a 13 + * more precise system time. There is one per virtual cpu. 14 + * 15 + * pvclock_wall_clock references the point in time when the system 16 + * time was zero (usually boot time), thus the guest calculates the 17 + * current wall clock by adding the system time. 18 + * 19 + * Protocol for the "version" fields is: hypervisor raises it (making 20 + * it uneven) before it starts updating the fields and raises it again 21 + * (making it even) when it is done. Thus the guest can make sure the 22 + * time values it got are consistent by checking the version before 23 + * and after reading them. 24 + */ 25 + 26 + struct pvclock_vcpu_time_info { 27 + u32 version; 28 + u32 pad0; 29 + u64 tsc_timestamp; 30 + u64 system_time; 31 + u32 tsc_to_system_mul; 32 + s8 tsc_shift; 33 + u8 flags; 34 + u8 pad[2]; 35 + } __attribute__((__packed__)); /* 32 bytes */ 36 + 37 + struct pvclock_wall_clock { 38 + u32 version; 39 + u32 sec; 40 + u32 nsec; 41 + } __attribute__((__packed__)); 42 + 43 + #define PVCLOCK_TSC_STABLE_BIT (1 << 0) 44 + #define PVCLOCK_GUEST_STOPPED (1 << 1) 45 + /* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */ 46 + #define PVCLOCK_COUNTS_FROM_ZERO (1 << 2) 47 + #endif /* __ASSEMBLY__ */ 48 + #endif /* _ASM_X86_PVCLOCK_ABI_H */
+103
tools/arch/x86/include/asm/pvclock.h
··· 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 */ 9 + u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); 10 + u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); 11 + void pvclock_set_flags(u8 flags); 12 + unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); 13 + void pvclock_resume(void); 14 + 15 + void pvclock_touch_watchdogs(void); 16 + 17 + static __always_inline 18 + unsigned 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 + 26 + static __always_inline 27 + bool 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 + */ 39 + static 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 + 78 + static __always_inline 79 + u64 __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 + 87 + struct 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 94 + void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti); 95 + struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void); 96 + #else 97 + static 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 */