iPXE
Macros | Functions | Variables
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. More...
 
#define TSC_SCALED_HZ   32
 Minimum resolution for scaled TSC timer. More...
 
#define colour   &tsc_per_us
 Colour for debug messages. More...
 

Functions

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

Variables

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

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.

◆ TSC_SCALED_HZ

#define TSC_SCALED_HZ   32

Minimum resolution for scaled TSC timer.

Definition at line 45 of file rdtsc_timer.c.

◆ 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()

static __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 }
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
__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")
__be32 raw[7]
Definition: CIB_PRM.h:28

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

Referenced by rdtsc_probe(), and rdtsc_udelay().

◆ rdtsc_scaled()

static __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
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
__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 __asm__(), __volatile__(), and tsc_scale.

Referenced by rdtsc_currticks().

◆ rdtsc_currticks()

static 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 __always_inline unsigned long rdtsc_scaled(void)
Get TSC value, shifted to avoid rollover within a realistic timescale.
Definition: rdtsc_timer.c:76
static unsigned long ticks_per_scaled_tsc
Number of timer ticks per scaled TSC increment.
Definition: rdtsc_timer.c:54

References rdtsc_scaled(), and ticks_per_scaled_tsc.

◆ rdtsc_udelay()

static 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:12
static __always_inline unsigned long rdtsc_raw(void)
Get raw TSC value.
Definition: rdtsc_timer.c:64
static unsigned long tsc_per_us
TSC increment per microsecond.
Definition: rdtsc_timer.c:42

References rdtsc_raw(), start, and tsc_per_us.

◆ rdtsc_probe()

static 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--;
159  ticks_per_scaled_tsc >>= 1;
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 }
int cpuid_supported(uint32_t function)
Check whether or not CPUID function is supported.
Definition: cpuid.c:75
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define TICKS_PER_SEC
Number of ticks per second.
Definition: timer.h:15
#define DBGC(...)
Definition: compiler.h:505
#define colour
Colour for debug messages.
Definition: rdtsc_timer.c:57
#define CPUID_APM_EDX_TSC_INVARIANT
Invariant TSC.
Definition: cpuid.h:64
static unsigned int tsc_scale
TSC scale (expressed as a bit shift)
Definition: rdtsc_timer.c:51
static unsigned long ticks_per_scaled_tsc
Number of timer ticks per scaled TSC increment.
Definition: rdtsc_timer.c:54
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define TSC_CALIBRATE_US
Number of microseconds to use for TSC calibration.
Definition: rdtsc_timer.c:39
unsigned int uint32_t
Definition: stdint.h:12
static __always_inline unsigned long rdtsc_raw(void)
Get raw TSC value.
Definition: rdtsc_timer.c:64
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
static unsigned long tsc_per_us
TSC increment per microsecond.
Definition: rdtsc_timer.c:42
#define CPUID_APM
Get APM information.
Definition: cpuid.h:61
#define EIO
Input/output error.
Definition: errno.h:433
long discard_c
Definition: bigint.h:30
#define TSC_SCALED_HZ
Minimum resolution for scaled TSC timer.
Definition: rdtsc_timer.c:45

References 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.

◆ __timer()

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

RDTSC timer.

ACPI timer.

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().