xref: /aosp_15_r20/external/coreboot/src/include/cpu/x86/tsc.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef CPU_X86_TSC_H
4 #define CPU_X86_TSC_H
5 
6 #include <stdint.h>
7 
8 #if CONFIG(TSC_SYNC_MFENCE)
9 #define TSC_SYNC "mfence\n"
10 #elif CONFIG(TSC_SYNC_LFENCE)
11 #define TSC_SYNC "lfence\n"
12 #else
13 #define TSC_SYNC
14 #endif
15 
16 struct tsc_struct {
17 	unsigned int lo;
18 	unsigned int hi;
19 };
20 typedef struct tsc_struct tsc_t;
21 
rdtsc(void)22 static inline tsc_t rdtsc(void)
23 {
24 	tsc_t res;
25 	asm volatile (
26 		TSC_SYNC
27 		"rdtsc"
28 		: "=a" (res.lo), "=d"(res.hi) /* outputs */
29 	);
30 	return res;
31 }
32 
33 /* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow.
34  * This code is used to prevent use of libgcc's umoddi3.
35  */
multiply_to_tsc(tsc_t * const tsc,const u32 a,const u32 b)36 static inline void multiply_to_tsc(tsc_t *const tsc, const u32 a, const u32 b)
37 {
38 	tsc->lo = (a & 0xffff) * (b & 0xffff);
39 	tsc->hi = ((tsc->lo >> 16)
40 		+ ((a & 0xffff) * (b >> 16))
41 		+ ((b & 0xffff) * (a >> 16)));
42 	tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff);
43 	tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16);
44 }
45 
tsc_to_uint64(tsc_t tstamp)46 static inline uint64_t tsc_to_uint64(tsc_t tstamp)
47 {
48 	return (((uint64_t)tstamp.hi) << 32) + tstamp.lo;
49 }
50 
rdtscll(void)51 static inline unsigned long long rdtscll(void)
52 {
53 	return tsc_to_uint64(rdtsc());
54 }
55 
56 /* Provided by CPU/chipset code for the TSC rate in MHz. */
57 unsigned long tsc_freq_mhz(void);
58 
tsc_constant_rate(void)59 static inline int tsc_constant_rate(void)
60 {
61 	return !CONFIG(UNKNOWN_TSC_RATE);
62 }
63 
64 #endif /* CPU_X86_TSC_H */
65