diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-30 07:31:03 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:03 -0500 |
commit | 4e87173eacfd0d798aeeba14026893797826bc93 (patch) | |
tree | 14a47677f3cc7074a5b190e159873b925c8deb77 /include | |
parent | 16e2011be67b8625c1c600f9742c2279be3c0c68 (diff) |
x86: split get_cycles_sync
This patch splits get_cycles_sync() into __get_cycles_sync(),
and the rdtscll part. Paravirt guests cannot issue rdtscl directly,
as it involves a function call in vdso area.
So, using the __get_cycles_sync() base, we introduce vget_cycles_sync,
which then calls the native version of rdtscll. Ideally, however, a guest
should define its own clocksource, together with a vread function
Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-x86/tsc.h | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h index d7b1c4e7a108..9b7d264897fa 100644 --- a/include/asm-x86/tsc.h +++ b/include/asm-x86/tsc.h | |||
@@ -33,14 +33,14 @@ static inline cycles_t get_cycles(void) | |||
33 | } | 33 | } |
34 | 34 | ||
35 | /* Like get_cycles, but make sure the CPU is synchronized. */ | 35 | /* Like get_cycles, but make sure the CPU is synchronized. */ |
36 | static __always_inline cycles_t get_cycles_sync(void) | 36 | static __always_inline cycles_t __get_cycles_sync(void) |
37 | { | 37 | { |
38 | unsigned long long ret; | 38 | unsigned long long ret; |
39 | unsigned eax, edx; | 39 | unsigned eax, edx; |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Use RDTSCP if possible; it is guaranteed to be synchronous | 42 | * Use RDTSCP if possible; it is guaranteed to be synchronous |
43 | * and doesn't cause a VMEXIT on Hypervisors | 43 | * and doesn't cause a VMEXIT on Hypervisors |
44 | */ | 44 | */ |
45 | alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP, | 45 | alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP, |
46 | ASM_OUTPUT2("=a" (eax), "=d" (edx)), | 46 | ASM_OUTPUT2("=a" (eax), "=d" (edx)), |
@@ -55,11 +55,40 @@ static __always_inline cycles_t get_cycles_sync(void) | |||
55 | */ | 55 | */ |
56 | alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC, | 56 | alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC, |
57 | "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); | 57 | "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); |
58 | rdtscll(ret); | ||
59 | 58 | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static __always_inline cycles_t get_cycles_sync(void) | ||
63 | { | ||
64 | unsigned long long ret; | ||
65 | ret = __get_cycles_sync(); | ||
66 | if (!ret) | ||
67 | rdtscll(ret); | ||
60 | return ret; | 68 | return ret; |
61 | } | 69 | } |
62 | 70 | ||
71 | #ifdef CONFIG_PARAVIRT | ||
72 | /* | ||
73 | * For paravirt guests, some functionalities are executed through function | ||
74 | * pointers in the various pvops structures. | ||
75 | * These function pointers exist inside the kernel and can not | ||
76 | * be accessed by user space. To avoid this, we make a copy of the | ||
77 | * get_cycles_sync (called in kernel) but force the use of native_read_tsc. | ||
78 | * Ideally, the guest should set up it's own clock and vread | ||
79 | */ | ||
80 | static __always_inline long long vget_cycles_sync(void) | ||
81 | { | ||
82 | unsigned long long ret; | ||
83 | ret = __get_cycles_sync(); | ||
84 | if (!ret) | ||
85 | ret = native_read_tsc(); | ||
86 | return ret; | ||
87 | } | ||
88 | #else | ||
89 | # define vget_cycles_sync() get_cycles_sync() | ||
90 | #endif | ||
91 | |||
63 | extern void tsc_init(void); | 92 | extern void tsc_init(void); |
64 | extern void mark_tsc_unstable(char *reason); | 93 | extern void mark_tsc_unstable(char *reason); |
65 | extern int unsynchronized_tsc(void); | 94 | extern int unsynchronized_tsc(void); |