中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

替换rdtsc汇编指令

TSC是时间戳计数器的缩写,它是Pentium兼容处理器中的一个计数器,它记录自启动以来处理器消耗的时钟周期数。在每个时钟到来时,该计数器自动加一。因为 TSC 随着处理器周期速率的变化而变化,所以它提供了非常高的精确度。它经常被用来分析和检测代码。TSC的值可以通过rdtsc指令来读取。

  • x86上代码段:
    static uint64_t Rdtsc() 
    { 
    uint32_t lo, hi; 
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 
    return (uint64_t)hi << 32 | lo; 
    }
  • 在鲲鹏上替换的方法:

    方法一:采用cntvct_el0,但其采用的是外部时钟频率,和rdtsc无法达到等价替换(rdtsc采用的是主频),可进行近似替换。

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

    其中Cent Speed和External Clock的值可由以下命令获取到:dmidecode |grep MHz

    方法二:使用Linux提供的获取时间函数clock_gettime进行近似替换。

    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和2.4基于服务器主频而定
    }

    方法三:ARM有Performance Monitors Control Register 系列寄存器,其中PMCCNTR_EL0就类似于x86的TSC寄存器。但默认情况用户态是不可读的,需要内核态使能后才能读取。具体可参考: http://ilinuxkernel.com/?p=1755

    1. 下载read aarch64 TSC ,解压压缩包,在arrch64_tsc目录下执行make命令,安装相应内核驱动,生成如下文件。

    2. 执行insmod pmu.ko命令安装内核模块,使能内核态(初次执行即可)。
    3. 代码替换。
      static uint64_t Rdtsc() 
      { 
      uint64_t count_num; 
      __asm__ __volatile__ ("mrs %0, PMCCNTR_EL0" : "+r" (count_num)); 
      return count_num;
      }