Rate This Document
Findability
Accuracy
Completeness
Readability

Replacing the rdtsc Assembly Instruction

Time Stamp Counter (TSC) is a counter in the Pentium-compatible processor and records the number of clock cycles consumed by the processor since the startup. The counter automatically increases by 1 for each cycle. Because TSC varies with the processor cycle rate, it provides extremely high accuracy. It is often used to analyze and detect code. The TSC value can be read by running the rdtsc instruction.

  • Code on x86:
    static uint64_t Rdtsc() 
    { 
    uint32_t lo, hi; 
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 
    return (uint64_t)hi << 32 | lo; 
    }
  • Alternatives for Kunpeng processors:

    Method 1: Use cntvct_el0 for approximate replacement because it uses external clock frequency, while rdtsc uses dominant frequency.

    static uint64_t Rdtsc() 
    { 
    uint64_t count_num; 
    Current_Speed = 2400; // Current Speed = 2400 MHz 
    External_Clock = 100; // External Clock = 100 MHz 
    __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (count_num)); 
    return count_num * (Current_Speed / External_Clock);
    }

    The values of Cent Speed and External Clock can be obtained by running the dmidecode |grep MHz command.

    Method 2: Use the clock_gettime function provided by Linux for approximate replacement.

    static uint64_t Rdtsc() 
    { 
    struct timespec tmp; 
    clock_gettime(CLOCK_MONOTONIC, &tmp); 
    return tmp.tv_sec*2400000000+(uint64_t)tmp.tv_nsec*2.4; // 2400000000 and 2.4 are determined based on the server dominant frequency.
    }

    Method 3: Arm has the Performance Monitor Control Register (PMCR), among which PMCCNTR_EL0 is similar to the TSC register of x86. By default, the register is unreadable in user mode and can be read only after the kernel mode is enabled. For details, visit http://zhiyisun.github.io/2016/03/02/How-to-Use-Performance-Monitor-Unit-(PMU)-of-64-bit-ARMv8-A-in-Linux.html.

    1. Download read aarch64 TSC, decompress the package, and run the make command in the arrch64_tsc directory to install the corresponding kernel driver. The following file is generated.

    2. Run the insmod pmu.ko command to install the kernel module and enable the kernel mode. (Perform this step for the first time.)
    3. Replace the code.
      static uint64_t Rdtsc() 
      { 
      uint64_t count_num; 
      __asm__ __volatile__ ("mrs %0, PMCCNTR_EL0" : "+r" (count_num)); 
      return count_num;
      }