Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e87173e authored by Glauber de Oliveira Costa's avatar Glauber de Oliveira Costa Committed by Ingo Molnar
Browse files

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: default avatarGlauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 16e2011b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
}

+33 −4
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ 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;
@@ -55,10 +55,39 @@ 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");

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