From ea438cd7236d7a5d4aa9e6ae4c10e46d1ffea563 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Wed, 30 Jan 2008 13:31:03 +0100 Subject: [PATCH] --- yaml --- r: 79927 b: refs/heads/master c: 4e87173eacfd0d798aeeba14026893797826bc93 h: refs/heads/master i: 79925: 1430b389cc7367493b7042865cec5e307bc5430d 79923: 10a902e90baeea0e8b7468838d8f60d66485c2ea 79919: d850607a46d0e58bdd8acf0f3893269ac3445825 v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/tsc_64.c | 2 +- trunk/include/asm-x86/tsc.h | 37 ++++++++++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 9862146c06ca..368078a4ffb3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 16e2011be67b8625c1c600f9742c2279be3c0c68 +refs/heads/master: 4e87173eacfd0d798aeeba14026893797826bc93 diff --git a/trunk/arch/x86/kernel/tsc_64.c b/trunk/arch/x86/kernel/tsc_64.c index 204a9080af04..3723401c4593 100644 --- a/trunk/arch/x86/kernel/tsc_64.c +++ b/trunk/arch/x86/kernel/tsc_64.c @@ -306,7 +306,7 @@ static cycle_t read_tsc(void) static cycle_t __vsyscall_fn vread_tsc(void) { - cycle_t ret = (cycle_t)get_cycles_sync(); + cycle_t ret = (cycle_t)vget_cycles_sync(); return ret; } diff --git a/trunk/include/asm-x86/tsc.h b/trunk/include/asm-x86/tsc.h index d7b1c4e7a108..9b7d264897fa 100644 --- a/trunk/include/asm-x86/tsc.h +++ b/trunk/include/asm-x86/tsc.h @@ -33,14 +33,14 @@ static inline cycles_t get_cycles(void) } /* Like get_cycles, but make sure the CPU is synchronized. */ -static __always_inline cycles_t get_cycles_sync(void) +static __always_inline cycles_t __get_cycles_sync(void) { unsigned long long ret; unsigned eax, edx; /* - * Use RDTSCP if possible; it is guaranteed to be synchronous - * and doesn't cause a VMEXIT on Hypervisors + * Use RDTSCP if possible; it is guaranteed to be synchronous + * and doesn't cause a VMEXIT on Hypervisors */ alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP, ASM_OUTPUT2("=a" (eax), "=d" (edx)), @@ -55,11 +55,40 @@ static __always_inline cycles_t get_cycles_sync(void) */ alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC, "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); - rdtscll(ret); + return 0; +} + +static __always_inline cycles_t get_cycles_sync(void) +{ + unsigned long long ret; + ret = __get_cycles_sync(); + if (!ret) + rdtscll(ret); return ret; } +#ifdef CONFIG_PARAVIRT +/* + * For paravirt guests, some functionalities are executed through function + * pointers in the various pvops structures. + * These function pointers exist inside the kernel and can not + * be accessed by user space. To avoid this, we make a copy of the + * get_cycles_sync (called in kernel) but force the use of native_read_tsc. + * Ideally, the guest should set up it's own clock and vread + */ +static __always_inline long long vget_cycles_sync(void) +{ + unsigned long long ret; + ret = __get_cycles_sync(); + if (!ret) + ret = native_read_tsc(); + return ret; +} +#else +# define vget_cycles_sync() get_cycles_sync() +#endif + extern void tsc_init(void); extern void mark_tsc_unstable(char *reason); extern int unsynchronized_tsc(void);