iPXE
rdtsc_timer.c File Reference

RDTSC timer. More...

#include <string.h>
#include <errno.h>
#include <ipxe/timer.h>
#include <ipxe/cpuid.h>
#include <ipxe/pit8254.h>

Go to the source code of this file.

Macros

#define TSC_CALIBRATE_US   1024
 Number of microseconds to use for TSC calibration.
#define TSC_SCALED_HZ   32
 Minimum resolution for scaled TSC timer.
#define colour   &tsc_per_us
 Colour for debug messages.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static __always_inline unsigned long rdtsc_raw (void)
 Get raw TSC value.
static __always_inline unsigned long rdtsc_scaled (void)
 Get TSC value, shifted to avoid rollover within a realistic timescale.
static unsigned long rdtsc_currticks (void)
 Get current system time in ticks.
static void rdtsc_udelay (unsigned long usecs)
 Delay for a fixed number of microseconds.
static int rdtsc_probe (void)
 Probe RDTSC timer.
struct timer rdtsc_timer __timer (TIMER_PREFERRED)
 RDTSC timer.

Variables

static unsigned long tsc_per_us
 TSC increment per microsecond.
static unsigned int tsc_scale
 TSC scale (expressed as a bit shift)
static unsigned long ticks_per_scaled_tsc
 Number of timer ticks per scaled TSC increment.

Detailed Description

RDTSC timer.

Definition in file rdtsc_timer.c.

Macro Definition Documentation

◆ TSC_CALIBRATE_US

#define TSC_CALIBRATE_US   1024

Number of microseconds to use for TSC calibration.

Definition at line 39 of file rdtsc_timer.c.

Referenced by rdtsc_probe().

◆ TSC_SCALED_HZ

#define TSC_SCALED_HZ   32

Minimum resolution for scaled TSC timer.

Definition at line 45 of file rdtsc_timer.c.

Referenced by rdtsc_probe().

◆ colour

#define colour   &tsc_per_us

Colour for debug messages.

Definition at line 57 of file rdtsc_timer.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ rdtsc_raw()

__always_inline unsigned long rdtsc_raw ( void )
inlinestatic

Get raw TSC value.

Return values
tscRaw TSC value

Definition at line 64 of file rdtsc_timer.c.

64 {
65 unsigned long raw;
66
67 __asm__ __volatile__ ( "rdtsc\n\t" : "=a" ( raw ) : : "edx" );
68 return raw;
69}
__be32 raw[7]
Definition CIB_PRM.h:0
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")

References __always_inline, __asm__(), __volatile__(), and raw.

Referenced by rdtsc_probe(), and rdtsc_udelay().

◆ rdtsc_scaled()

__always_inline unsigned long rdtsc_scaled ( void )
inlinestatic

Get TSC value, shifted to avoid rollover within a realistic timescale.

Return values
tscScaled TSC value

Definition at line 76 of file rdtsc_timer.c.

76 {
77 unsigned long scaled;
78
79 __asm__ __volatile__ ( "rdtsc\n\t"
80 "shrdl %b1, %%edx, %%eax\n\t"
81 : "=a" ( scaled ) : "c" ( tsc_scale ) : "edx" );
82 return scaled;
83}
static unsigned int tsc_scale
TSC scale (expressed as a bit shift)
Definition rdtsc_timer.c:51

References __always_inline, __asm__(), __volatile__(), and tsc_scale.

Referenced by rdtsc_currticks().

◆ rdtsc_currticks()

unsigned long rdtsc_currticks ( void )
static

Get current system time in ticks.

Return values
ticksCurrent time, in ticks

Definition at line 90 of file rdtsc_timer.c.

90 {
91 unsigned long scaled;
92
93 scaled = rdtsc_scaled();
94 return ( scaled * ticks_per_scaled_tsc );
95}
static unsigned long ticks_per_scaled_tsc
Number of timer ticks per scaled TSC increment.
Definition rdtsc_timer.c:54
static __always_inline unsigned long rdtsc_scaled(void)
Get TSC value, shifted to avoid rollover within a realistic timescale.
Definition rdtsc_timer.c:76

References rdtsc_scaled(), and ticks_per_scaled_tsc.

Referenced by __timer().

◆ rdtsc_udelay()

void rdtsc_udelay ( unsigned long usecs)
static

Delay for a fixed number of microseconds.

Parameters
usecsNumber of microseconds for which to delay

Definition at line 102 of file rdtsc_timer.c.

102 {
103 unsigned long start;
104 unsigned long elapsed;
105 unsigned long threshold;
106
107 start = rdtsc_raw();
108 threshold = ( usecs * tsc_per_us );
109 do {
110 elapsed = ( rdtsc_raw() - start );
111 } while ( elapsed < threshold );
112}
uint32_t start
Starting offset.
Definition netvsc.h:1
static unsigned long tsc_per_us
TSC increment per microsecond.
Definition rdtsc_timer.c:42
static __always_inline unsigned long rdtsc_raw(void)
Get raw TSC value.
Definition rdtsc_timer.c:64

References rdtsc_raw(), start, and tsc_per_us.

Referenced by __timer().

◆ rdtsc_probe()

int rdtsc_probe ( void )
static

Probe RDTSC timer.

Return values
rcReturn status code

Definition at line 119 of file rdtsc_timer.c.

119 {
120 unsigned long before;
121 unsigned long after;
122 unsigned long elapsed;
123 uint32_t apm;
124 uint32_t discard_a;
125 uint32_t discard_b;
127 int rc;
128
129 /* Check that TSC is invariant */
130 if ( ( rc = cpuid_supported ( CPUID_APM ) ) != 0 ) {
131 DBGC ( colour, "RDTSC cannot determine APM features: %s\n",
132 strerror ( rc ) );
133 return rc;
134 }
135 cpuid ( CPUID_APM, 0, &discard_a, &discard_b, &discard_c, &apm );
136 if ( ! ( apm & CPUID_APM_EDX_TSC_INVARIANT ) ) {
137 DBGC ( colour, "RDTSC has non-invariant TSC (%#08x)\n",
138 apm );
139 return -ENOTTY;
140 }
141
142 /* Calibrate udelay() timer via 8254 PIT */
143 before = rdtsc_raw();
144 pit8254_udelay ( TSC_CALIBRATE_US );
145 after = rdtsc_raw();
146 elapsed = ( after - before );
147 tsc_per_us = ( elapsed / TSC_CALIBRATE_US );
148 if ( ! tsc_per_us ) {
149 DBGC ( colour, "RDTSC has zero TSC per microsecond\n" );
150 return -EIO;
151 }
152
153 /* Calibrate currticks() scaling factor */
154 tsc_scale = 31;
155 ticks_per_scaled_tsc = ( ( 1UL << tsc_scale ) /
156 ( tsc_per_us * ( 1000000 / TICKS_PER_SEC ) ) );
158 tsc_scale--;
160 }
161 DBGC ( colour, "RDTSC has %ld tsc per us, %ld ticks per 2^%d tsc\n",
163 if ( ! ticks_per_scaled_tsc ) {
164 DBGC ( colour, "RDTSC has zero ticks per TSC\n" );
165 return -EIO;
166 }
167
168 return 0;
169}
#define colour
Colour for debug messages.
Definition acpi.c:42
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
long discard_c
Definition bigint.h:33
int cpuid_supported(uint32_t function)
Check whether or not CPUID function is supported.
Definition cpuid.c:76
#define CPUID_APM_EDX_TSC_INVARIANT
Invariant TSC.
Definition cpuid.h:77
#define CPUID_APM
Get APM information.
Definition cpuid.h:74
#define DBGC(...)
Definition compiler.h:505
#define EIO
Input/output error.
Definition errno.h:434
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
#define TSC_SCALED_HZ
Minimum resolution for scaled TSC timer.
Definition rdtsc_timer.c:45
#define TSC_CALIBRATE_US
Number of microseconds to use for TSC calibration.
Definition rdtsc_timer.c:39
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int32_t after
Final microcode version.
Definition ucode.h:7
int32_t before
Initial microcode version.
Definition ucode.h:5

References after, before, colour, CPUID_APM, CPUID_APM_EDX_TSC_INVARIANT, cpuid_supported(), DBGC, discard_c, EIO, ENOTTY, rc, rdtsc_raw(), strerror(), ticks_per_scaled_tsc, TICKS_PER_SEC, TSC_CALIBRATE_US, tsc_per_us, tsc_scale, and TSC_SCALED_HZ.

Referenced by __timer().

◆ __timer()

struct timer acpi_timer __timer ( TIMER_PREFERRED )
Initial value:
= {
.name = "acpi",
.probe = acpi_timer_probe,
.currticks = acpi_currticks,
.udelay = acpi_udelay,
}
static void acpi_udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition acpi_timer.c:82
static unsigned long acpi_currticks(void)
Get current system time in ticks.
Definition acpi_timer.c:60
static int acpi_timer_probe(void)
Probe ACPI power management timer.
Definition acpi_timer.c:104

RDTSC timer.

ACPI timer.

References __timer, rdtsc_currticks(), rdtsc_probe(), rdtsc_udelay(), and TIMER_PREFERRED.

Variable Documentation

◆ tsc_per_us

unsigned long tsc_per_us
static

TSC increment per microsecond.

Definition at line 42 of file rdtsc_timer.c.

Referenced by rdtsc_probe(), and rdtsc_udelay().

◆ tsc_scale

unsigned int tsc_scale
static

TSC scale (expressed as a bit shift)

We use this to avoid the need for 64-bit divsion on 32-bit systems.

Definition at line 51 of file rdtsc_timer.c.

Referenced by rdtsc_probe(), and rdtsc_scaled().

◆ ticks_per_scaled_tsc

unsigned long ticks_per_scaled_tsc
static

Number of timer ticks per scaled TSC increment.

Definition at line 54 of file rdtsc_timer.c.

Referenced by rdtsc_currticks(), and rdtsc_probe().