Software Tuning, Performance Optimization & Platform Monitoring
Discussion regarding monitoring and software tuning methodologies, Performance Monitoring Unit (PMU) of Intel microprocessors, and platform updating.

TSC frequency computation


Hi all,

To compute the average frequency, two counters are needed : IA32_APERF and IA32_MPERF

According to Intel specifications Volume 3 section 14.5.5, the average frequency is :

     delta ((IA32_APERF) / delta (IA32_MPERF)) * (TSC frequency)

According to Volume 3, there are two methods to compute TSC frequency:

1°) To compute "TSC frequency", we need to know the "nominal core crystal clock frequency":

Section 18.7.3 (Volume 3 specifications Intel) says that Nominal TSC frequency is obtained from (CPUID.15H.ECX[31:0] * CPUID.15H.EBX[31:0] ) / (CPUID.15H.EAX[31:0])

2°) To compute "TSC frequency", we can use MSR_PLATFORM_INFO[15 :8]


With the first method (ivy bridge microarchitecture) : "TSC frequency" = ecx*(ebx/eax) = 98889 Hz

Indeed, the output of "cpuid -l0x15" is :

eax = 00000007 (hexa)

ebx = 00000340 (hexa)

ecx = 00000340 (hexa)


With the second method


Indeed, the output of rdmsr 0xCE is :


TSC frequency = 20 * 100 MHz

TSC frequency = 2000 MHz


With the second method, TSC frequency is much more higher (x 10 000) than its value computed with the first method

What is the correct value?

best regards

joel penhoat




0 Kudos
1 Reply
Black Belt

The method based on CPUID is a new one and is probably not supported on a processor as old as Ivy Bridge? 

I don't have any CPUID dumps on Ivy Bridge systems, but you should certainly check the value returned in %eax by CPUID with an initial %eax value of 0x0.  This will be the maximum %eax value supported for "basic" CPUID information.   My systems before Skylake Xeon all have maximum values smaller than 0x15:

  • Westmere:         0x0b
  • Sandy Bridge:   0x0d
  • Haswell:             0x0f
  • Broadwell:         0x14
  • Skylake Xeon:   0x16
  • CascadeLake:   0x16

On a Cascade Lake Xeon system, CPUID with %eax=0x15 returns

   0x00000015 0x00: eax=0x00000002 ebx=0x000000d8 ecx=0x00000000 edx=0x00000000

So even these relatively new processors don't provide information about the "crystal clock frequency" in ECX.  The EBX and EAX values show a multiplier of 216/2.  Given the known TSC clock of 2700 MHz, these imply a "crystal clock frequency" of 25 MHz.

On the same system, CPUID with EAX=0x16 returns:

   0x00000016 0x00: eax=0x00000a8c ebx=0x00000fa0 ecx=0x00000064 edx=0x00000000

EAX gives the CPU base frequency in MHz: 0xa8c = 2700
EBX gives the maximum CPU frequency: 0xfa0 = 4000
ECX gives the "bus" frequency in MHz: 0x64 = 100

Note that the "crystal" frequency and the "bus" frequency are not the same.  This is reflected in the behavior of the performance counters for Reference Cycles Not Halted.  In previous processors this counter would increment by the CPU multiplier ratio once every "tick" of the "base clock" -- i.e., increment by 27 every 10 nanoseconds (for a 100 MHz base clock).   On SKX/CLX, the Reference Cycles Not Halted now increments only once every "crystal clock" cycles -- e.g., with a 2700 MHz TSC and a 25 MHz "crystal clock", the counter increments by 108 every 40 ns.

0 Kudos