2012-07-09 40 views
2

我寫了一個程序,它讀取了Intel芯片上的APERF/MPERF計數器(http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf的第2頁)。硬件處理器計數器錯誤復位

這些計數器可通過readmsr/writemsr指令讀取/寫入,我目前只是通過Windows 7中的設備驅動程序定期讀取它們。計數器爲64位,每個處理器時鐘,所以你會期望它們在很長一段時間內溢出,但是當我讀取計數器時,它們的值會跳轉,就好像它們被另一個程序重置一樣。

有什麼方法可以找出什麼程序將重置櫃檯?其他的東西是否會導致不正確的值被讀取?下面附上我使用的相關程序集和相應的C函數。 rdmsr的64位結果保存在eax:edx中,爲了確保我沒有遺漏r_x寄存器中的任何數字,我多次運行該命令來檢查它們。

C:

long long test1, test2, test3, test4; 
test1 = TST1(); 
test2 = TST2(); 
test3 = TST3(); 
test4 = TST4(); 
status = RtlStringCbPrintfA(buffer, sizeof(buffer), "Value: %llu %llu %llu %llu\n", test1, test2, test3, test4); 

大會:

;;;;;;;;;;;;;;;;;;; 
PUBLIC TST1 
TST1 proc 
    mov ecx, 231 ; 0xE7 
    rdmsr 
    ret ; returns rax 
TST1 endp 

;;;;;;;;;;;;;;;;;;; 
PUBLIC TST2 
TST2 proc 
    mov ecx, 231 ; 0xE7 
    rdmsr 
    mov rax, rbx 
    ret ; returns rax 
TST2 endp 

;;;;;;;;;;;;;;;;;;; 
PUBLIC TST3 
TST3 proc 
    mov ecx, 231 ; 0xE7 
    rdmsr 
    mov rax, rcx 
    ret ; returns rax 
TST3 endp 

;;;;;;;;;;;;;;;;;;; 
PUBLIC TST4 
TST4 proc 
    mov ecx, 231 ; 0xE7 
    rdmsr 
    mov rax, rdx 
    ret ; returns rax 
TST4 endp 

,打印出來的結果是一樣的東西下面,但都沒有改變的唯一寄存器是RAX寄存器,它不會增加單調(可跳轉):

Value: 312664 37 231 0 
Value: 252576 37 231 0 
Value: 1051857 37 231 0 
+2

你正在讀取特定CPU上的寄存器還是現在的哪個? – 2012-07-09 21:31:24

+0

這是一個很好的觀點,我在任何核心碰巧是當前運行的代碼。 (我使用i5和i7機器作爲測試機器)。另一方面,我期望rdx寄存器從其中一個CPU上的0 *最終增加,而不是始終保持爲零。 – Shookit 2012-07-10 00:44:03

+0

另外,是否可以只運行一個特定內核的驅動程序? – Shookit 2012-07-11 02:11:53

回答

2

我無法弄清楚什麼是重置我的公司unters,但我能夠確定頻率。英特爾文檔指出,當一個計數器溢出時,另一個計數器也會。所以即使計數器不斷重置,aperf和mperf的比率仍然代表處理器的頻率。

0

似乎Windows 7和Windows 8讀取並重置AMD處理器上的可寫APERF/MPERF計數器。因此,您需要訪問0xc00000E7/E8寄存器中的只讀APERF/MPERF計數器。

但有一個新問題。在一些最新的AMD處理器(系列0x16處理器)上,這些寄存器並不總是被支持。要確定這些寄存器是否受支持,您必須讀取CPUID Fn8000_0007_EDX中的EffFreqRO位。如前所述,這一切僅適用於AMD處理器。