Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/msr: Move rdtsc{,_ordered}() to <asm/tsc.h>

Relocate rdtsc{,_ordered}() from <asm/msr.h> to <asm/tsc.h>.

[ mingo: Do not remove the <asm/tsc.h> inclusion from <asm/msr.h>
just yet, to reduce -next breakages. We can do this later
on, separately, shortly before the next -rc1. ]

Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Uros Bizjak <ubizjak@gmail.com>
Link: https://lore.kernel.org/r/20250427092027.1598740-3-xin@zytor.com

authored by

Xin Li (Intel) and committed by
Ingo Molnar
288a4ff0 efef7f18

+55 -54
-54
arch/x86/include/asm/msr.h
··· 153 153 extern int rdmsr_safe_regs(u32 regs[8]); 154 154 extern int wrmsr_safe_regs(u32 regs[8]); 155 155 156 - /** 157 - * rdtsc() - returns the current TSC without ordering constraints 158 - * 159 - * rdtsc() returns the result of RDTSC as a 64-bit integer. The 160 - * only ordering constraint it supplies is the ordering implied by 161 - * "asm volatile": it will put the RDTSC in the place you expect. The 162 - * CPU can and will speculatively execute that RDTSC, though, so the 163 - * results can be non-monotonic if compared on different CPUs. 164 - */ 165 - static __always_inline u64 rdtsc(void) 166 - { 167 - EAX_EDX_DECLARE_ARGS(val, low, high); 168 - 169 - asm volatile("rdtsc" : EAX_EDX_RET(val, low, high)); 170 - 171 - return EAX_EDX_VAL(val, low, high); 172 - } 173 - 174 - /** 175 - * rdtsc_ordered() - read the current TSC in program order 176 - * 177 - * rdtsc_ordered() returns the result of RDTSC as a 64-bit integer. 178 - * It is ordered like a load to a global in-memory counter. It should 179 - * be impossible to observe non-monotonic rdtsc_unordered() behavior 180 - * across multiple CPUs as long as the TSC is synced. 181 - */ 182 - static __always_inline u64 rdtsc_ordered(void) 183 - { 184 - EAX_EDX_DECLARE_ARGS(val, low, high); 185 - 186 - /* 187 - * The RDTSC instruction is not ordered relative to memory 188 - * access. The Intel SDM and the AMD APM are both vague on this 189 - * point, but empirically an RDTSC instruction can be 190 - * speculatively executed before prior loads. An RDTSC 191 - * immediately after an appropriate barrier appears to be 192 - * ordered as a normal load, that is, it provides the same 193 - * ordering guarantees as reading from a global memory location 194 - * that some other imaginary CPU is updating continuously with a 195 - * time stamp. 196 - * 197 - * Thus, use the preferred barrier on the respective CPU, aiming for 198 - * RDTSCP as the default. 199 - */ 200 - asm volatile(ALTERNATIVE_2("rdtsc", 201 - "lfence; rdtsc", X86_FEATURE_LFENCE_RDTSC, 202 - "rdtscp", X86_FEATURE_RDTSCP) 203 - : EAX_EDX_RET(val, low, high) 204 - /* RDTSCP clobbers ECX with MSR_TSC_AUX. */ 205 - :: "ecx"); 206 - 207 - return EAX_EDX_VAL(val, low, high); 208 - } 209 - 210 156 static inline u64 native_read_pmc(int counter) 211 157 { 212 158 EAX_EDX_DECLARE_ARGS(val, low, high);
+55
arch/x86/include/asm/tsc.h
··· 5 5 #ifndef _ASM_X86_TSC_H 6 6 #define _ASM_X86_TSC_H 7 7 8 + #include <asm/asm.h> 8 9 #include <asm/cpufeature.h> 9 10 #include <asm/processor.h> 10 11 #include <asm/msr.h> 12 + 13 + /** 14 + * rdtsc() - returns the current TSC without ordering constraints 15 + * 16 + * rdtsc() returns the result of RDTSC as a 64-bit integer. The 17 + * only ordering constraint it supplies is the ordering implied by 18 + * "asm volatile": it will put the RDTSC in the place you expect. The 19 + * CPU can and will speculatively execute that RDTSC, though, so the 20 + * results can be non-monotonic if compared on different CPUs. 21 + */ 22 + static __always_inline u64 rdtsc(void) 23 + { 24 + EAX_EDX_DECLARE_ARGS(val, low, high); 25 + 26 + asm volatile("rdtsc" : EAX_EDX_RET(val, low, high)); 27 + 28 + return EAX_EDX_VAL(val, low, high); 29 + } 30 + 31 + /** 32 + * rdtsc_ordered() - read the current TSC in program order 33 + * 34 + * rdtsc_ordered() returns the result of RDTSC as a 64-bit integer. 35 + * It is ordered like a load to a global in-memory counter. It should 36 + * be impossible to observe non-monotonic rdtsc_unordered() behavior 37 + * across multiple CPUs as long as the TSC is synced. 38 + */ 39 + static __always_inline u64 rdtsc_ordered(void) 40 + { 41 + EAX_EDX_DECLARE_ARGS(val, low, high); 42 + 43 + /* 44 + * The RDTSC instruction is not ordered relative to memory 45 + * access. The Intel SDM and the AMD APM are both vague on this 46 + * point, but empirically an RDTSC instruction can be 47 + * speculatively executed before prior loads. An RDTSC 48 + * immediately after an appropriate barrier appears to be 49 + * ordered as a normal load, that is, it provides the same 50 + * ordering guarantees as reading from a global memory location 51 + * that some other imaginary CPU is updating continuously with a 52 + * time stamp. 53 + * 54 + * Thus, use the preferred barrier on the respective CPU, aiming for 55 + * RDTSCP as the default. 56 + */ 57 + asm volatile(ALTERNATIVE_2("rdtsc", 58 + "lfence; rdtsc", X86_FEATURE_LFENCE_RDTSC, 59 + "rdtscp", X86_FEATURE_RDTSCP) 60 + : EAX_EDX_RET(val, low, high) 61 + /* RDTSCP clobbers ECX with MSR_TSC_AUX. */ 62 + :: "ecx"); 63 + 64 + return EAX_EDX_VAL(val, low, high); 65 + } 11 66 12 67 /* 13 68 * Standard way to access the cycle counter.