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>
This commit is contained in:
Glauber de Oliveira Costa 2008-01-30 13:31:03 +01:00 committed by Ingo Molnar
parent 16e2011be6
commit 4e87173eac
2 changed files with 34 additions and 5 deletions

View File

@ -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;
}

View File

@ -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);