| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #ifndef CPU_X86_TSC_H |
| #define CPU_X86_TSC_H |
| |
| #include <stdint.h> |
| |
| #if CONFIG(TSC_SYNC_MFENCE) |
| #define TSC_SYNC "mfence\n" |
| #elif CONFIG(TSC_SYNC_LFENCE) |
| #define TSC_SYNC "lfence\n" |
| #else |
| #define TSC_SYNC |
| #endif |
| |
| struct tsc_struct { |
| unsigned int lo; |
| unsigned int hi; |
| }; |
| typedef struct tsc_struct tsc_t; |
| |
| static inline tsc_t rdtsc(void) |
| { |
| tsc_t res; |
| asm volatile ( |
| TSC_SYNC |
| "rdtsc" |
| : "=a" (res.lo), "=d"(res.hi) /* outputs */ |
| ); |
| return res; |
| } |
| |
| /* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow. |
| * This code is used to prevent use of libgcc's umoddi3. |
| */ |
| static inline void multiply_to_tsc(tsc_t *const tsc, const u32 a, const u32 b) |
| { |
| tsc->lo = (a & 0xffff) * (b & 0xffff); |
| tsc->hi = ((tsc->lo >> 16) |
| + ((a & 0xffff) * (b >> 16)) |
| + ((b & 0xffff) * (a >> 16))); |
| tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff); |
| tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16); |
| } |
| |
| static inline uint64_t tsc_to_uint64(tsc_t tstamp) |
| { |
| return (((uint64_t)tstamp.hi) << 32) + tstamp.lo; |
| } |
| |
| static inline unsigned long long rdtscll(void) |
| { |
| return tsc_to_uint64(rdtsc()); |
| } |
| |
| /* Provided by CPU/chipset code for the TSC rate in MHz. */ |
| unsigned long tsc_freq_mhz(void); |
| |
| static inline int tsc_constant_rate(void) |
| { |
| return !CONFIG(UNKNOWN_TSC_RATE); |
| } |
| |
| #endif /* CPU_X86_TSC_H */ |