Synchronize rdtsc instructions
The CPU can arbitrarily reorder calls to rdtsc, significantly reducing the precision of timing using the CPUs time stamp counter. Unfortunately the method of synchronizing rdtsc is different on AMD and Intel CPUs. There is a generic method, using the cpuid instruction, but that uses up a lot of registers, and is very slow. Hence, use the correct lfence/mfence instructions (for CPUs that we know support it) Change-Id: I17ecb48d283f38f23148c13159aceda704c64ea5 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/1422 Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
4c29d7f27d
commit
0db6820b10
|
@ -25,6 +25,7 @@ config CPU_AMD_AGESA
|
||||||
default y if CPU_AMD_AGESA_FAMILY15
|
default y if CPU_AMD_AGESA_FAMILY15
|
||||||
default y if CPU_AMD_AGESA_FAMILY15_TN
|
default y if CPU_AMD_AGESA_FAMILY15_TN
|
||||||
default n
|
default n
|
||||||
|
select TSC_SYNC_LFENCE
|
||||||
|
|
||||||
if CPU_AMD_AGESA
|
if CPU_AMD_AGESA
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ config CPU_AMD_MODEL_10XXX
|
||||||
select SSE
|
select SSE
|
||||||
select SSE2
|
select SSE2
|
||||||
select MMCONF_SUPPORT_DEFAULT
|
select MMCONF_SUPPORT_DEFAULT
|
||||||
|
select TSC_SYNC_LFENCE
|
||||||
|
|
||||||
if CPU_AMD_MODEL_10XXX
|
if CPU_AMD_MODEL_10XXX
|
||||||
config CPU_ADDR_BITS
|
config CPU_ADDR_BITS
|
||||||
|
|
|
@ -3,6 +3,7 @@ config CPU_AMD_MODEL_FXX
|
||||||
select MMX
|
select MMX
|
||||||
select SSE
|
select SSE
|
||||||
select SSE2
|
select SSE2
|
||||||
|
select TSC_SYNC_LFENCE
|
||||||
|
|
||||||
if CPU_AMD_MODEL_FXX
|
if CPU_AMD_MODEL_FXX
|
||||||
config UDELAY_IO
|
config UDELAY_IO
|
||||||
|
|
|
@ -2,3 +2,4 @@ config CPU_INTEL_MODEL_1067X
|
||||||
bool
|
bool
|
||||||
select SMP
|
select SMP
|
||||||
select SSE2
|
select SSE2
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
|
|
@ -4,9 +4,9 @@ config CPU_INTEL_MODEL_106CX
|
||||||
select SSE2
|
select SSE2
|
||||||
select UDELAY_LAPIC
|
select UDELAY_LAPIC
|
||||||
select AP_IN_SIPI_WAIT
|
select AP_IN_SIPI_WAIT
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
|
||||||
config CPU_ADDR_BITS
|
config CPU_ADDR_BITS
|
||||||
int
|
int
|
||||||
default 32
|
default 32
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ config CPU_SPECIFIC_OPTIONS
|
||||||
select SMM_TSEG
|
select SMM_TSEG
|
||||||
select MICROCODE_IN_CBFS
|
select MICROCODE_IN_CBFS
|
||||||
#select AP_IN_SIPI_WAIT
|
#select AP_IN_SIPI_WAIT
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
|
||||||
config BOOTBLOCK_CPU_INIT
|
config BOOTBLOCK_CPU_INIT
|
||||||
string
|
string
|
||||||
|
|
|
@ -4,3 +4,4 @@ config CPU_INTEL_MODEL_6EX
|
||||||
select SSE2
|
select SSE2
|
||||||
select UDELAY_LAPIC
|
select UDELAY_LAPIC
|
||||||
select AP_IN_SIPI_WAIT
|
select AP_IN_SIPI_WAIT
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
|
|
@ -4,3 +4,4 @@ config CPU_INTEL_MODEL_6FX
|
||||||
select SSE2
|
select SSE2
|
||||||
select UDELAY_LAPIC
|
select UDELAY_LAPIC
|
||||||
select AP_IN_SIPI_WAIT
|
select AP_IN_SIPI_WAIT
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
|
|
@ -23,6 +23,22 @@ config TSC_CALIBRATE_WITH_IO
|
||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config TSC_SYNC_LFENCE
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
The CPU driver should select this if the CPU needs
|
||||||
|
to execute an lfence instruction in order to synchronize
|
||||||
|
rdtsc. This is true for all modern AMD CPUs.
|
||||||
|
|
||||||
|
config TSC_SYNC_MFENCE
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
The CPU driver should select this if the CPU needs
|
||||||
|
to execute an mfence instruction in order to synchronize
|
||||||
|
rdtsc. This is true for all modern Intel CPUs.
|
||||||
|
|
||||||
config XIP_ROM_SIZE
|
config XIP_ROM_SIZE
|
||||||
hex
|
hex
|
||||||
default ROM_SIZE if ROMCC
|
default ROM_SIZE if ROMCC
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
#ifndef CPU_X86_TSC_H
|
#ifndef CPU_X86_TSC_H
|
||||||
#define CPU_X86_TSC_H
|
#define CPU_X86_TSC_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 {
|
struct tsc_struct {
|
||||||
unsigned lo;
|
unsigned lo;
|
||||||
unsigned hi;
|
unsigned hi;
|
||||||
|
@ -10,10 +18,11 @@ typedef struct tsc_struct tsc_t;
|
||||||
static inline tsc_t rdtsc(void)
|
static inline tsc_t rdtsc(void)
|
||||||
{
|
{
|
||||||
tsc_t res;
|
tsc_t res;
|
||||||
__asm__ __volatile__ (
|
asm volatile (
|
||||||
|
TSC_SYNC
|
||||||
"rdtsc"
|
"rdtsc"
|
||||||
: "=a" (res.lo), "=d"(res.hi) /* outputs */
|
: "=a" (res.lo), "=d"(res.hi) /* outputs */
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +31,11 @@ static inline tsc_t rdtsc(void)
|
||||||
static inline unsigned long long rdtscll(void)
|
static inline unsigned long long rdtscll(void)
|
||||||
{
|
{
|
||||||
unsigned long long val;
|
unsigned long long val;
|
||||||
asm volatile ("rdtsc" : "=A" (val));
|
asm volatile (
|
||||||
|
TSC_SYNC
|
||||||
|
"rdtsc"
|
||||||
|
: "=A" (val)
|
||||||
|
);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue