x86/msr: Split out tsc.h

The TSC functionality is only related to MSRs by write_tsc(), and this really
does not want to be available as widely as is currently is.

asm/time.h shouldn't be including asm/msr.h, but this turns out to be
sufficiently tangled that I've chosen to break it out into it's own patch.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2025-08-19 19:52:48 +01:00
1 parent 9e54444371
commit 2b3d1c8a30
3 files changed
+50 -39

No files matched your search

-39
View File
@@ -98,45 +98,6 @@ static inline void msr_split(struct cpu_user_regs *regs, uint64_t val)
regs->rax = (uint32_t)val;
}
static inline uint64_t rdtsc(void)
{
uint64_t low, high;
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
return (high << 32) | low;
}
static inline uint64_t rdtsc_ordered(void)
{
uint64_t low, high, aux;
/*
* The RDTSC instruction is not serializing. Make it dispatch serializing
* for the purposes here by issuing LFENCE (or MFENCE if necessary) ahead
* of it.
*
* RDTSCP, otoh, "does wait until all previous instructions have executed
* and all previous loads are globally visible" (SDM) / "forces all older
* instructions to retire before reading the timestamp counter" (APM).
*/
alternative_io_2("lfence; rdtsc",
"mfence; rdtsc", X86_FEATURE_MFENCE_RDTSC,
"rdtscp", X86_FEATURE_RDTSCP,
ASM_OUTPUT2("=a" (low), "=d" (high), "=c" (aux)),
/* no inputs */);
return (high << 32) | low;
}
#define __write_tsc(val) wrmsrl(MSR_IA32_TSC, val)
#define write_tsc(val) ({ \
/* Reliable TSCs are in lockstep across all CPUs. We should \
* never write to them. */ \
ASSERT(!boot_cpu_has(X86_FEATURE_TSC_RELIABLE)); \
__write_tsc(val); \
})
#define rdpmc(counter,low,high) \
__asm__ __volatile__("rdpmc" \
: "=a" (low), "=d" (high) \
+1
View File
@@ -3,6 +3,7 @@
#define __X86_TIME_H__
#include <asm/msr.h>
#include <asm/tsc.h>
typedef u64 cycles_t;
+49
View File
@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef X86_TSC_H
#define X86_TSC_H
#include <asm/alternative.h>
static inline uint64_t rdtsc(void)
{
uint64_t low, high;
asm volatile ( "rdtsc" : "=a" (low), "=d" (high) );
return (high << 32) | low;
}
static inline uint64_t rdtsc_ordered(void)
{
uint64_t low, high, aux;
/*
* The RDTSC instruction is not serializing. Make it dispatch serializing
* for the purposes here by issuing LFENCE (or MFENCE if necessary) ahead
* of it.
*
* RDTSCP, otoh, "does wait until all previous instructions have executed
* and all previous loads are globally visible" (SDM) / "forces all older
* instructions to retire before reading the timestamp counter" (APM).
*/
alternative_io_2("lfence; rdtsc",
"mfence; rdtsc", X86_FEATURE_MFENCE_RDTSC,
"rdtscp", X86_FEATURE_RDTSCP,
ASM_OUTPUT2("=a" (low), "=d" (high), "=c" (aux)),
/* no inputs */);
return (high << 32) | low;
}
#define __write_tsc(val) wrmsrl(MSR_IA32_TSC, val)
/*
* Reliable TSCs are in lockstep across all CPUs. We should never write to
* them.
*/
#define write_tsc(val) ({ \
ASSERT(!boot_cpu_has(X86_FEATURE_TSC_RELIABLE)); \
__write_tsc(val); \
})
#endif /* X86_TSC_H */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.