Step to UEFI (9)—-使用RDTSC计算当前CPU 频率

很早之前Intel曾经提供过一个使用RDTSC在DOS下计算CPU频率的程序(在CPUID的Datasheet中)。简单的说就是延时一个固定的时间,然后看这个时间内经过了多少个指令周期,经过计算就能得到CPU的频率。下面的程序实现了在UEFI环境下计算频率的功能,同时也可以作为插入汇编指令的参考。需要注意,这是32位UEFI环境下,如果在64位的Shell环境下这样做是不行的。

//
// FreqCalc.C
//

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellLib.h>

EFI_SYSTEM_TABLE	*gST;
EFI_BOOT_SERVICES  	*gBS;

UINT64 rdtsc()
{
  UINT64 value;
  __asm
  {
     rdtsc
     mov dword ptr value,eax
     mov dword ptr [value + 4],edx
  } 

  return  value;
}

//
// Entry point function - ShowVersion
//
EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{

  UINT64  elsp;

  gST = SystemTable;
  gBS = SystemTable->BootServices;

  elsp=rdtsc();
  gBS -> Stall(1000000);  
  Print(L"CPU Frequency: %ld \n", rdtsc()-elsp);

  return EFI_SUCCESS;
}

 

程序运行的结果:

cpuz

虚拟机中运行的CPUZ读取的结果:

freqcalc

代码下载

FreqCalc

特别的,有资料指出在当前的多核环境下,这样的方法并不准确,具体的原因请参考下面的文章

1. http://blog.csdn.net/solstice/article/details/5196544 “多核时代不宜再用 x86 的 RDTSC 指令测试指令周期和时间”
2. http://blog.chinaunix.net/uid-24774106-id-2779245.html “使用rdtsc指令,测量程序的运行速度”

《Step to UEFI (9)—-使用RDTSC计算当前CPU 频率》有3个想法

  1. Hi Sir, 使用x64 , –> run “build -a X64 -p AppPkg\AppPkg.dsc” ,,,,無法build “__asm”

    error message as below:
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(15) : error C4235:
    nonstandard extension used : ‘__asm’ keyword not supported on this architecture
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2146:
    syntax error : missing ‘;’ before identifier ‘mov’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : warning C4550
    : expression evaluates to a function which is missing an argument list
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2065:
    ‘mov’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2146:
    syntax error : missing ‘;’ before identifier ‘dword’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2065:
    ‘dword’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2146:
    syntax error : missing ‘;’ before identifier ‘ptr’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2065:
    ‘ptr’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(18) : error C2146:
    syntax error : missing ‘;’ before identifier ‘value’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2065:
    ‘eax’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2146:
    syntax error : missing ‘;’ before identifier ‘mov’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2065:
    ‘mov’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2146:
    syntax error : missing ‘;’ before identifier ‘dword’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2065:
    ‘dword’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2146:
    syntax error : missing ‘;’ before identifier ‘ptr’
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2065:
    ‘ptr’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(19) : error C2109:
    subscript requires array or pointer type
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(20) : error C2065:
    ‘edx’ : undeclared identifier
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.c(20) : error C2143:
    syntax error : missing ‘;’ before ‘}’
    NMAKE : fatal error U1077: ‘”C:\Program Files (x86)\Microsoft Visual Studio 12.0
    \Vc\bin\x86_amd64\cl.exe”‘ : return code ‘0x2’
    Stop.

    build…
    : error 7000: Failed to execute command
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\nmake.exe /no
    logo tbuild [d:\src\eadk\20141115\Build\AppPkg\DEBUG_VS2012x86\X64\AppPkg\Applic
    ations\FreqCalc\FreqCalc]

    build…
    : error F002: Failed to build module
    d:\src\eadk\20141115\AppPkg\Applications\FreqCalc\FreqCalc.inf [X64, VS2
    012×86, DEBUG]

    – Failed –
    Build end time: 18:14:19, Feb.25 2015
    Build total time: 00:00:20

    1. 我的实验是在 ia32下做的,x64http://www.lab-z.com/wp-admin/edit-comments.php#comments-form的话,不支持 asm 内嵌汇编了

      1. 感謝您的回覆!但是我的測試機台都是UEFI X64 system. 那請教您有什方法可以將asm code可以將它,,,build 成功且能RUN在X64 uefi Shell ?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注