-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Oliver Upton
authored and
Paolo Bonzini
committed
Oct 18, 2021
1 parent
828ca89
commit 5000653
Showing
2 changed files
with
151 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef _ASM_X86_PVCLOCK_ABI_H | ||
#define _ASM_X86_PVCLOCK_ABI_H | ||
#ifndef __ASSEMBLY__ | ||
|
||
/* | ||
* These structs MUST NOT be changed. | ||
* They are the ABI between hypervisor and guest OS. | ||
* Both Xen and KVM are using this. | ||
* | ||
* pvclock_vcpu_time_info holds the system time and the tsc timestamp | ||
* of the last update. So the guest can use the tsc delta to get a | ||
* more precise system time. There is one per virtual cpu. | ||
* | ||
* pvclock_wall_clock references the point in time when the system | ||
* time was zero (usually boot time), thus the guest calculates the | ||
* current wall clock by adding the system time. | ||
* | ||
* Protocol for the "version" fields is: hypervisor raises it (making | ||
* it uneven) before it starts updating the fields and raises it again | ||
* (making it even) when it is done. Thus the guest can make sure the | ||
* time values it got are consistent by checking the version before | ||
* and after reading them. | ||
*/ | ||
|
||
struct pvclock_vcpu_time_info { | ||
u32 version; | ||
u32 pad0; | ||
u64 tsc_timestamp; | ||
u64 system_time; | ||
u32 tsc_to_system_mul; | ||
s8 tsc_shift; | ||
u8 flags; | ||
u8 pad[2]; | ||
} __attribute__((__packed__)); /* 32 bytes */ | ||
|
||
struct pvclock_wall_clock { | ||
u32 version; | ||
u32 sec; | ||
u32 nsec; | ||
} __attribute__((__packed__)); | ||
|
||
#define PVCLOCK_TSC_STABLE_BIT (1 << 0) | ||
#define PVCLOCK_GUEST_STOPPED (1 << 1) | ||
/* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */ | ||
#define PVCLOCK_COUNTS_FROM_ZERO (1 << 2) | ||
#endif /* __ASSEMBLY__ */ | ||
#endif /* _ASM_X86_PVCLOCK_ABI_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef _ASM_X86_PVCLOCK_H | ||
#define _ASM_X86_PVCLOCK_H | ||
|
||
#include <asm/barrier.h> | ||
#include <asm/pvclock-abi.h> | ||
|
||
/* some helper functions for xen and kvm pv clock sources */ | ||
u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); | ||
u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); | ||
void pvclock_set_flags(u8 flags); | ||
unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); | ||
void pvclock_resume(void); | ||
|
||
void pvclock_touch_watchdogs(void); | ||
|
||
static __always_inline | ||
unsigned pvclock_read_begin(const struct pvclock_vcpu_time_info *src) | ||
{ | ||
unsigned version = src->version & ~1; | ||
/* Make sure that the version is read before the data. */ | ||
rmb(); | ||
return version; | ||
} | ||
|
||
static __always_inline | ||
bool pvclock_read_retry(const struct pvclock_vcpu_time_info *src, | ||
unsigned version) | ||
{ | ||
/* Make sure that the version is re-read after the data. */ | ||
rmb(); | ||
return version != src->version; | ||
} | ||
|
||
/* | ||
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, | ||
* yielding a 64-bit result. | ||
*/ | ||
static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) | ||
{ | ||
u64 product; | ||
#ifdef __i386__ | ||
u32 tmp1, tmp2; | ||
#else | ||
unsigned long tmp; | ||
#endif | ||
|
||
if (shift < 0) | ||
delta >>= -shift; | ||
else | ||
delta <<= shift; | ||
|
||
#ifdef __i386__ | ||
__asm__ ( | ||
"mul %5 ; " | ||
"mov %4,%%eax ; " | ||
"mov %%edx,%4 ; " | ||
"mul %5 ; " | ||
"xor %5,%5 ; " | ||
"add %4,%%eax ; " | ||
"adc %5,%%edx ; " | ||
: "=A" (product), "=r" (tmp1), "=r" (tmp2) | ||
: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); | ||
#elif defined(__x86_64__) | ||
__asm__ ( | ||
"mulq %[mul_frac] ; shrd $32, %[hi], %[lo]" | ||
: [lo]"=a"(product), | ||
[hi]"=d"(tmp) | ||
: "0"(delta), | ||
[mul_frac]"rm"((u64)mul_frac)); | ||
#else | ||
#error implement me! | ||
#endif | ||
|
||
return product; | ||
} | ||
|
||
static __always_inline | ||
u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc) | ||
{ | ||
u64 delta = tsc - src->tsc_timestamp; | ||
u64 offset = pvclock_scale_delta(delta, src->tsc_to_system_mul, | ||
src->tsc_shift); | ||
return src->system_time + offset; | ||
} | ||
|
||
struct pvclock_vsyscall_time_info { | ||
struct pvclock_vcpu_time_info pvti; | ||
} __attribute__((__aligned__(64))); | ||
|
||
#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info) | ||
|
||
#ifdef CONFIG_PARAVIRT_CLOCK | ||
void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti); | ||
struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void); | ||
#else | ||
static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void) | ||
{ | ||
return NULL; | ||
} | ||
#endif | ||
|
||
#endif /* _ASM_X86_PVCLOCK_H */ |