書名: x86/x64體系探索及編程作者名: 鄧志著本章字數: 558字更新時間: 2019-03-01 11:49:36
第4章 處理器的身份
我需要了解處理器的型號、廠商、有什么具體的特性等這些關于處理器的參數,應該怎么辦?x86/x64處理器上提供了CPUID指令用來查看和識別身份。
4.1 測試是否支持CPUID指令
eflags寄存器的bit 21是ID(Processor Feature Identification)標志位,在286處理器中flags是16位的,在386處理器中eflags擴展為32位,bit 21是reserved。CPUID指令從Intel 486處理器上開始加入,因此除非你在古老的機器上運行,否則沒必要檢測處理器是否支持CPUID指令。
實驗4-1:測試是否支持CPUID指令
test_CPUID()在源文件lib\lib16.asm里,在topic04\ex4-1\目錄有實驗代碼:
代碼清單4-1(lib\lib16.asm):
;--------------------------------------------------- ; test_CPUID():測試是否支持 CPUID 指令 ; output: ; 1 - support, 0 - no support ;--------------------------------------------------- __test_CPUID: pushfd ; save eflags DWORD size mov eax,dword [esp] ; get old eflags xor dword [esp],0x200000 ; xor the eflags.ID bit popfd ; set eflags register pushfd ; save eflags again pop ebx ; get new eflags cmp eax,ebx ; test eflags.ID has been modify setnz al ; OK! support CPUID instruction movzx eax,al ret
修改eflags寄存器的bit 21標志位,如果能成功修改,就表示支持CPUID指令。
4.2 CPUID指令的術語及表達
Intel64手冊里對CPUID指令廣泛使用了如下一些表達形式和術語。
leaf(葉)
功能號使用leaf術語,例如:CPUID的01號功能,你可以稱其為CPUID的01 leaf(葉)。
sub-leaf(子葉)
對于一些較復雜的信息查詢,往往需要一個輔助的子號。EAX寄存器輸入的是main leaf(主葉號),ECX寄存器提供的是sub-leaf(子葉號)。
mov eax,0Bh ; main leaf mov ecx,0 ; sub-leaf cpuid
如上所示,0B號功能就是main leaf(主葉),ECX提供的0號就是sub-leaf(子葉)。
CPUID指令的描述形式
當軟件需要判斷某項功能處理器是否支持時,使用CPUID指令進行查詢,在Intel手冊中使用了下面的描述形式。
上面是判斷處理器是否支持PAE(Physical Address Extensions)功能時的描述,當CPUID.01H:EDX[6]的值為1時,表示支持PAE功能。
4.3 基本信息與擴展信息
從CPUID指令獲得的信息有兩大類:basic(基本)和extended(擴展),要獲得信息必須要先提供相應的leaf(功能號),每一類信息都有最大的功能號限制。
某些功能號下面還有許多sub-leaf(子葉),也就是信息的子集。使用CPUID指令之前在eax寄存器提供要查詢的某個信息相應的功能號。
mov eax,0 ; 功能號 0(main leaf) cpuid ; 查詢 0 號信息
返回的相應信息放在eax、ebx、ecx,以及edx寄存器中。這些信息是32位的,因此在64位模式下,rax、rbx、rcx,以及rdx寄存器的高32位被清0。
查詢最大leaf(功能)號
CPUID指令被使用來查詢處理器所支持的特性,因此CPUID所支持的leaf數量是與處理器相關的。很多時候,在使用某個leaf查詢之前,必須判斷處理器是否支持該leaf。
典型地,在使用0BH號功能時,應先查詢處理器是否支持0BH號功能。
基本最大功能號
使用CPUID的00H leaf來查詢,最大的基本功能號返回在EAX寄存器里。
mov eax,0 ; 功能號 0(main leaf) cpuid ; 查詢 0 號信息 cmp eax,0BH ; 判斷是否支持 0B leaf jb no_support ; 假如不支持...
擴展最大功能號
同樣,最大的擴展功能號也可以查詢。
mov eax,80000000 ; 功能號 80000000(main leaf) cpuid ; 查詢最大擴展功能號 cmp eax,80000001H ; 判斷是否支持 80000001 leaf jb no_support ; 假如不支持...
輸入80000000H功能號,從返回的EAX寄存器里可以得到最大的擴展功能號。
功能號0也返回處理器廠商名,在Intel的機器上返回的是:ebx寄存器是“Genu”,ecx寄存器是“ntel”,edx寄存器是“ineI”,組合起來是“GenuineIntel”,在AMD的機器上是“AuthenticAMD”。
實驗4-2:獲得basic和extended功能號
實驗的源碼在\topic04\ex4-2\setup.asm文件里。
代碼清單4-2(topic04\ex4-2\setup.asm):
call test_CPUID test ax,ax jz no_support ;; 獲得最大 basic 功能號 mov eax,0 cpuid mov esi,eax mov di,value_address call get_dword_hex_string mov si,basic_message call puts mov si,value_address call puts call println ;; 獲得最大 extended 功能號 mov eax,0x80000000 cpuid mov esi,eax mov di,value_address call get_dword_hex_string mov si,extend_message call puts mov si,value_address call puts call println jmp $ no_support: mov si,[message_table + eax * 2] call puts jmp $ support_message db 'support CPUID instruction',13,10,0 no_support_message db 'no support CPUID instruction',13,10,0 message_table dw no_support_message,support_message,0 basic_message db 'maximun basic function:0x',0 extend_message db 'maximun extended function:0x',0 value_address dd 0,0,0
在Bochs里運行的結果如下所示。
Bochs是模擬Intel系列的CPU,在筆者的AMD真實機器上最大basic功能號是0x00000005,最大extended功能號是0x8000001A,在另一臺Intel i5機器上分別是0Bh和80000008h:
Intel的處理器上目前的最大basic功能號是0DH,最大extended功能號是80000008H(依賴于每個機器的實現)。Intel手冊中指示Core i7處理器(Westmere架構)最大的basic功能號是0BH,最大的extended功能號是80000008H。
如果在eax中輸入的功能號超過了最大的功能號,那么將返回basic最大功能號的信息。
當eax=0Eh時,返回的信息和eax=0Dh一致,當eax=80000009h時返回的信息也和eax=0Dh一致。
實驗4-3:分別使用0Dh和0Eh,以及80000008h和80000009h來運行獲得信息
由于在目前的Intel上0Dh是最大basic功能號,80000008h是最大的擴展功能號,因此本實驗的目的是驗證Intel所說的話。
代碼清單4-3(topic04\ex4-3\setup.asm):
;; 現在得到最大功能號 0DH 的信息 mov si,msg1 call puts mov eax,0Dh cpuid mov [eax_value],eax mov [ebx_value],ebx mov [ecx_value],ecx mov [edx_value],edx call print_register_value ; 打印寄存器的值 ; 測試輸入功能號為 eax=0Eh mov si,msg2 call puts mov eax,0Eh cpuid mov [eax_value],eax mov [ebx_value],ebx mov [ecx_value],ecx mov [edx_value],edx call print_register_value ; 打印寄存器的值 ;; 現在得到 extended 最大功能號 80000008h 的信息 mov si,msg3 call puts mov eax,80000008h cpuid mov [eax_value],eax mov [ebx_value],ebx mov [ecx_value],ecx mov [edx_value],edx call print_register_value ; 打印寄存器的值 ;; 現在測試 extended 最大功能號 80000009 的信息 mov si,msg4 call puts mov eax,80000009h cpuid mov [eax_value],eax mov [ebx_value],ebx mov [ecx_value],ecx mov [edx_value],edx call print_register_value ; 打印寄存器的值
下面是在Bochs中運行的結果。
可以看出,當eax分別等于0Dh、0Eh和80000009h時,所返回的信息是一樣的。在筆者的AMD真實機器上運行上面的例子,得不到輸出結果,目前在AMD的機器上最大的basic功能號是06H,而extended功能號則達到了8000001Bh。
請注意:當輸入的功能號<=最大功能號時,如果CPU并不支持該功能號,則所有寄存器返回0值,eax=ebx=ecx=edx=0。
由于在Bochs上所支持的最大basic功能號是0Dh,如果以0Ch去訪問CPUID指令(0Ch功能號CPU不支持),返回的寄存器將全是0值(eax<=maxinum number)。
當輸入功能號>最大功能號時,訪問CPUID,返回的將是最大功能號的信息,也就是上面做的實驗所證明的。
4.4 處理器的型號(family,model與stepping)
由CPUID.01H:EAX可返回處理器的家族、模型及步進信息。
EAX[11:8]得到family編碼,典型地,P6家族處理器的family編碼是06H,Pentium4家族的family編碼是0FH。EAX[27:20]得到擴展的family值。EAX[7:4]得到處理器在家族中的model。EAX[19:16]得到擴展的model值。
在這些處理器信息里,最重要的是family與model。由于x86處理器的龐大和混亂,在Intel文檔的相關描述中,使用了family和model的配合來描述處理器的特性,例如下面的這個描述。
DisplayFamily值的計算方法如下。
if (Family == 0FH) { DisplayFamily=ExtendedFamily + Family; } else DisplayFamily=Family;
可見,只有在Pentium4以后的處理器才支持ExtendedFamily編號。DisplayModel值的計算方法如下。
if (Family == 06H || Family == 0FH) { DisplayModel=ExtendedModel << 4 + Model; } else DisplayModel=Model;
現在我們可以做個實驗。
實驗4-4:獲得處理器的DisplayFamily與DisplayModel
實驗的完整源碼在topic04\ex4-4\setup.asm文件里,調用了lib\lib16.asm文件里面的get_DisplayFamily_DisplayModel()過程來獲得DisplayFamily和DisplayModel值,下面是運行結果。
在筆者實驗的機器上的處理器DispalyFamily是06H,DisplayModel是25H,根據Intel的說明這個Model是屬于32nm制程的Core i3/i5/i7 Mobile處理器(屬于Westmere微架構)。
它的ExtendedModel值是0010B,Model值是0101B,組合起來是:25H。那么這個處理器模型將被描述為:06_25H。這種DisplayFamily_DisplayModel的模型相當重要,在Intel手冊的描述中使用這種方式來區別處理器的模型。
在Intel的機器上,06H家族和0FH家族是兩大派系,0FH家族典型地是指Pentium4處理器系列。而06H家族很龐大,從早期的Pentium Pro、PentiumII到今天的Westmere/SandyBridge微架構的i7/i5/i3處理器都屬于06H家族。在如此龐大的06H家族,要靠它的DisplayModel來識別每一代架構的處理器。05H家族則屬于Pentium處理器。
4.5 最大的物理地址和線性地址
在CPUID.80000008H葉里,我們可以獲取處理器所支持的最大物理地址和線性地址的寬度。
上面的實驗中80000008h功能號返回的eax值為0x00003028,低byte是物理地址寬度,值為28h就是40位,接著是線性地址寬度。當CPU支持long mode時,這個值是30h,否則就是20h,這表明long mode下最高支持48位的線性地址,線性地址的高16位被用做sign位,在32位的機器上這個值是20h(32位)。
MAXPHYADDR值
在Intel中廣泛使用MAXPHYADDR這個術語來表示最大的物理地址。80000008H leaf返回的EAX[7:0]被稱為MAXPHYADDR。
當處理器不支持80000008H leaf(功能)時,如果檢測到CPUID.01H:EDX[6]=1(即:PAE=1)則支持最高36位物理地址。如果此時PAE也并不支持,那么MAXPHYADDR就是32位。
4.6 處理器擴展狀態信息
實際上0Dh功能號是獲得處理器對Processor Extended State(處理器擴展狀態)的支持度,這在AVX指令編程里非常重要。在最新的Sandy Bridge架構的處理器中,支持度只使用了3位。
Processor Extended State(處理器擴展狀態)是什么?
0Dh功能號是一個功能集,在前面的例子中:
mov eax,0Dh ; 0Dh 功能號 mov ecx,0 ; main leaf(主葉)功能 cpuid ; 得到 0Dh 的 main leaf功能
這個main leaf功能就可以獲得CPU目前對處理器狀態信息的支持度,eax和edx寄存器返回processor extended state的enable/disable位圖。
返回的edx和eax寄存器組成一個64位的Processor Extended State功能表,高32位在edx寄存器,低32位在eax寄存器。在處理器的規劃中,每1位對應一個擴展狀態功能enable位。為1時支持該狀態,為0時不支持。
這個Processor Extended State值將影響到XCR0(Extended Control Register)的值。當State值的某位為0時,那么XCR0的相應位為保留位(此位不能被XSETBV指令設置)。
目前的x86處理器中(包括Intel和AMD)僅使用了低3位(Bit 0~Bit2)。Bit 0對應X87 FPU狀態,Bit 1對應SSE狀態,這兩位一般都能返回1,表示CPU支持X87 FPU和SSE功能。Bit 2對應YMM狀態。
YMM狀態在Intel的Sandy Bridge架構和AMD的bulldozer架構中得到了支持,也就是說CPU支持AVX指令集。因此,在這種處理器以上才返回YMM狀態位為1值。
圖中的陰影部分為reserved(保留位),未來的處理器可能會使用這些位來支持更多的處理器狀態信息。保留位的值全部為0。
看看前面在Bochs里運行的結果。
得到的結果表明:CPU支持x87 FPU和SSE狀態而不支持YMM狀態,也就是說不支持AVX指令。值得注意的是,由于Bochs模擬實現了CPUID 0DH號功能,因此可以使用0DH leaf進行查詢。實際上,在不支持AVX指令的處理器上,并不支持CPUID 0DH leaf。
4.6.1 探測Processor Extended State子葉
由于eax返回的是處理器對Processor Extended State的enable位,在未來的處理器中可能加入更多的支持,因此在使用前應該探測處理器到底支持了哪些Prcessor Extended State。
mov eax,0Dh ; 0Dh 功能號 mov ecx,0 ; main leaf(主葉)功能 cpuid ; 得到 0Dh 的 main leaf功能,在edx:eax返回對 ; processor extended state的支持位 mov [extended_state],eax ; 保存 enable 位 mov [extended_size],ebx ; 保存整個exended state的size值 mov dword [detect_value],2 ; 從Bit2 開始探測 detect: mov eax,0Dh ; 0Dh 功能號 mov ecx,[detect_value] ; sub-leaves 子葉號 bt dword [extended_state],ecx ; Bit n == 1 ? jnc next_detect ; 該位不支持,繼續探測 cpuid ; 探測 mov ecx,[detect_value] mov [state + ecx * 4],eax ; 保存子葉 size mov [state + ecx * 4 + 4],ebx ; 保存子葉 offset next_detect: inc dword [detect_value] ; 繼續探測下一個子葉 cmp dword [detect_value],62 ; 小于等于 62 就繼續 jle detect next: ... ...
假如CPU支持AVX指令,那么CPUID(eax=0Dh,ecx=0h):EAX[YMM]為1,也就是eax的Bit 2為1,因此從第2位開始探測,假如Bit 3是支持的,繼續探測Bit 3,以此類推……
記錄下來:在上面的64位Processor Extended State值中每1位代表一個子葉,從Bit 2(YMM狀態)開始。
在Processor Extended State中X87 FPU state是必須要支持的,它必定為1,而 SSE state也就是XMM寄存器狀態,也是支持的,這時Bit 1位是保留。所以從Bit 2開始探測直至Bit 62位,Bit 63位是保留未用。
4.6.2 Processor Extended State子葉所需內存size
在main leaf(eax=0Dh,ecx=0h)里,ebx和ecx寄存器都返回一個內存size。
ebx寄存器返回的是在XCR0(Extended Control Register)里設置了開啟某個位去支持處理器狀態所需要的內存size。
XCR0的結構與上面CPUID(EAX=0Dh,ECX=0H) 返回的64位Processor Extended State值結構是一樣的。XCR0可以設置SSE狀態為disable(關閉),這樣CPU將不會保存SSE(即:XMM寄存器)的值。
Processor Extended State與XCR0的關系
XCR0是一個功能開關,用來開啟或關閉某些state的保存。而CPUID(eax=0Dh,ecx=00h)返回的Processor Extended State值將決定處理器保存哪些state信息的能力。
OS可以通過XSETBV指令對XCR0進行相應的設置,如果某位被disable掉,這時候,XCR0與CPU支持的64位Processor Extended State值會不一致。因此,ebx寄存器返回的是這個XCR0設置的保存狀態所需要的內存size。
ecx寄存器返回的是CPU所支持的所有狀態(即:在main leaf里返回eax的位圖),保存這些狀態所需要的總內存size,因此,ebx不一定等于ecx(取決于XCR0是否開啟相應的位)。
如果CPUID(eax=0Dh,ecx=0h)返回的eax寄存器為07H值,那么說明它支持AVX指令,這樣的話就可以接著使用0Dh的2號子葉去查看相關的信息。
在AMD處理器上支持LWP指令,Bit 62位是LWP state位,所以在AMD里就可以查看62號子葉的信息。
下面是查看子葉號為62的相關信息(如果CPU支持)。
mov eax,0Dh ; 0Dh 功能號 mov ecx,62 ; AMD機器上的62號子葉功能 cpuid
4.6.3 Processor Extended State的保存
Processor Extended State通過使用XSAVE指令來保存處理器的狀態,在內存中處理器的state映像看起來如下。
實際情況還要更復雜些,SSE和YMM狀態的保存,還取決于XSAVE指令提供的64位MASK碼和XCR0上面所述的相應位的enable(開啟),如果XCR0.YMM=0表明不保存YMM狀態,那么圖中的YMM state區域是0值(不被更新)。
mov edx,0 mov eax,3 ; 不保存 YMM state xsave [state_image] ; 根據 64位的 Mask值和XCR0位進行保存
同樣,在edx:eax這個64位的mask碼值中,如果YMM state mask位為0,YMM state區域也不被更新,必須XCR0和MASK值同時被置1(AND與關系)區域才被更新。
回到上面的例子,由于不支持AVX指令,所以eax返回0x03,表明僅支持X87 FPU和SSE狀態。而ebx和ecx寄存器的返回值是0x240,這個值就等于512+64=576(0x240),X87 FPU需要512字節,還要加上一個header部分。這個header的首64位(8 bytes)是一個XSTATE_BV結構,當XSAVE保存狀態時,用來記錄部分狀態被保存了。若保存X87 FPU和SSE狀態,就設置Bit 0和Bit 1為1,反之將清0。
4.6.4 Processor Extended State的恢復
使用XRSTOR指令可以從內存的state映像中恢復原來保存的state信息。
header結構是64字節,首8字節是一個64位的MASK值,用來記錄在state映像中哪些區域是被保存過的(被更新過),相應的位為1時表示image中的相應的區域被更新,如:YMM state區域中被保存過,那么XSTATE_BV[2]=1(Bit 2對應于YMM state位)。
XSTATE_BV的位在執行XSAVE指令保存state時被CPU設置。當執行xrstor指令時,CPU會根據XSTATE_BV中哪一位被置位,而做相應的恢復。
4.7 處理器的特性
EAX=01h號功能將獲得處理器的基本信息,它是CPUID中一個重要的功能號,eax寄存器返回處理器的Model、Family、Stepping等信息。在ebx寄存器中:ebx[15:8]返回CLFLUSH line size,這個值乘8就可以得到Cache line的size,ebx[23:16]返回邏輯處理器最大可尋址的數目。
實驗4-5:查看CPU的cache line size和Maximum logic processor
實驗的完整源碼在\topic04\ex4-5\setup.asm文件里,下面是在VMware里的運行結果。
在VMware中筆者設置processor core的數目為4個,上面顯示的logic processor是4個,ebx[15:8]的值是0x08,所以它的cache line size是64(0x40)字節。
在ecx和edx寄存器中返回CPU支持的種類繁多的特性,下面分別是ecx和edx寄存器返回值所對應的功能。
這些特性是處理器硬件物理上所支持的功能,利用CPUID指令可以檢測處理器所支持的特性。
可是CPUID.EAX=01H在ECX和EDX返回的某些特性是由軟件設置的。還有部分特性受到MSR(Model Specific Register)的設置影響。
例如:ECX寄存器的bit 27是OSXSAVE標志位,這個標志位并不是硬件特性,是由軟件設置而來的,在OS里為了開啟AVX指令使用環境,OS最終會設置CR4的Bit 18位CR4.OSXSAVE=1,處理器會根據這個位來置CPUID(EAX=01h):ECX[27]標志,也就是上面的ECX[OSXSAVE]標志位。軟件使用AVX指令前會讀取這個標志位,確認OS已經準備好AVX指令的執行環境。
檢測CPU是否支持AVX指令的是Bit 28 AVX標志位,而Bit 26位是XSAVE標志位,它用于檢測CPU是否支持XSAVE/XRSTOR、XSETBV/XGETBV指令和XCR0。
4.8 處理器的Cache與TLB信息
CPUID.EAX=02H用來獲得關于CPU的Cache與TLB信息。
mov eax,02H ; 02號功能 cpuid
eax寄存器的最低字節(byte 0)是需要執行CPUID.EAX=02H的次數。
上面這個最低字節的值為01,表明只需要執行一次CPUID.EAX=02H就能獲得完整的信息。
寄存器的MSB(Bit31)位是個標志位,為0指示有效,為1指示無效。
eax、ebx、ecx和edx寄存器中的每個字節指示一個信息(除EAX寄存器的byte 0外)。
如果是FF字節表示CPUID.EAX=02H不返回cache及TLB信息,需要執行CPUID.EAX=04H進行查詢。
實驗4-6:使用CPUID.EAX=02H查看cache及TLB信息
實驗的源碼在\topic04\ex4-6\setup.asm中,下面是在VMware中的運行結果。
上面的信息是在VMware下打印出來的,從這個結果,我們可以看出來以下信息。
處理器的Cache和TLB情況也可以從CPUID.EAX=04H里獲得,04H功能號是一個集,以ECX輸入一個子葉號,枚舉出處理器Cache的所有信息。
首先以ECX=0H子葉開始查詢,在eax寄存器返回,我們所關心的是以下幾個位域。
EAX[4:0]返回cache的類型,分別是:1=Data cache,2=Instruction cache,3=Unified cache,0值是終止標志,表示已經沒有子葉可以枚舉了,其他值是保留的。
EAX[7:5]返回cache的level,EAX[31:26]域里也可以查詢得到處理器的core數,這個查詢結果值需要加上1才是真正的值。
接下來EBX寄存器的返回信息是:EBX[11:00]是line size,EBX[21:12]是physical line partition,EBX[31:22]返回cache的way數。最后ECX寄存器返回32位的cache set數量。
實驗4-7:使用CPUID.EAX=04H/ECX=n來查看cache及TLB信息
下面是部分代碼片斷,完整的源碼在topic04\ex4-7\setup.asm里。
代碼清單4-4:
@@1: mov ecx,[sub_leaves] ; 子葉號 mov esi,ecx mov di,value_address call get_hex_string mov si,msg call puts mov si,value_address call puts mov si,msg2 call puts mov eax,04 ; 探測 ECX=n cpuid mov [eax_value],eax ; 保存各個寄存器的值 mov [ebx_value],ebx mov [ecx_value],ecx mov [edx_value],edx inc dword [sub_leaves] ; 下一個子葉號 call print_cache_info ; 打印信息 test eax,eax jnz @@1
從子葉ECX=0H開始進行探測,直至EAX[4:0]為0(表示沒有下一個子葉),每一個子葉得到的cache size的計算方法如下。
cache size=line size×line partition×way×set
也就是等于:(EBX[11:00]+1)*(EBX[21:12]+1)*(EBX[31:22]+1)*(ECX+1)。
每一項加上1,是因為返回的信息加上1才是完整的值。這個計算的過程在print_cache_info()過程里,讀者可以在topic04\ex4-7\setup.asm源碼里看到。下面是在VMware中的運行結果。
對比一下上面的運行結果和使用CPUID.EAX=02H查詢到的結果,看是否一致。上面的結果是:
1級Data-cache的size是32KB(值為0x8000),8-way 64 set結構。1級Instruction-cache的size同樣是32KB(值為0x8000),4-way 128 set結構。2級cache的size是256KB(值為0x40000),8-way 512 set結構。3級cache的size是3MB(值為0x300000),屬于12-way 4096 set結構。
對比結果cache size和cache結構是一樣的,在這個例子里沒有完整打印詳細的信息,讀者朋友可以自行加入更完整的顯示。這個例子探測到子葉號ECX=03H為止,ECX=04H已經不支持了。
讓人感到沮喪的是:在AMD的機器上并不支持EAX=02H到EAX=04H的功能號!
是的,這確實讓人反感,在AMD的機器上basic功能號支持EAX=01H、EAX=05H、EAX=06H以及EAX=0DH,這4個功能號??墒茿MD比Intel支持更多的extended功能號,根據AMD的CPUID specification指示,最多達到了8000001EH,而Intel只支持到80000008H。
在AMD機器上可以使用80000005H、80000006H,以及8000001DH擴展功能號查詢cache和TLB的相關信息。
4.9 MONITOR/MWAIT信息
在CPUID.EAX=01H功能里返回的ECX[3]可以查詢處理器是否支持MONITOR與MWAIT指令,MONITOR/MWAIT指令用來監控某個線性地址范圍內沒發生store操作進入一個被優化的狀態。
下面是一個典型的MONITOR/MWAIT指令使用序列。
@Loop: bt dword [WorkQueue],0 ; 測試 WorkQueue == 1 ? jnc no_work ... ... ; 執行其他調度 jmp @Loop ;;; 當 WorkQueue == 0 時: no_work: mov eax,WorkQueue ; 監控地址 mov ecx,0 ; 0 extensions mov edx,0 ; 0 hints MONITOR ; 進入監控 bt dword [WorkQueue],0 ; 測試 WorkQueue jc @Loop ; WorkdQueue == 1 時重新循環 sti ; 允許被中斷事件退出優化的狀態 mov eax,0 ; 0 hints mov ecx,0 ; 0 extensions MWAIT ; wait jmp @Loop
monitor/mwait指令的使用情形有些與pause指令類似,在Idle Loop(空閑的循環)中用來提高處理器的性能和減少能耗。pause常用于OS的自旋鎖,monitor/mwait對某個地址范圍做監控,這個地址范圍內沒發生store操作就進入優化的狀態,由mwait等待某些事件而退出,因地址store操作而退出或者因某些中斷類的事件發生。
執行CPUID.05H在EAX[15:00]里返回Smallest monitor-line size,在EBX[15:00]里返回Largest monitor-line size。在MSR IA32_MONITOR_FILTER_LINE_SIZE里可以對這些值進行設置,從而影響CPUID.05H leaf的讀取結果。
4.10 處理器的long mode
extended功能號80000001H是一個很重要的CPUID leaf,里面有最為重要的Long Mode標志位,用來查詢處理器是否支持long mode,在AMD的機器上80000001H具有很多特性,而Intel的機器上許多為保留位。
最重要的位是EDX[29]返回long mode標志,EDX[11]是SYSCALL/SYSRET指令支持標志位,EDX[26]是1G-page支持位。
mov eax,80000000H cpuid cmp eax,80000001H ; < 80000001h ? jb no_support mov eax,80000001H cpuid bt edx,29 ; 測試是否支持 long mode jnc no_support ... ...
上面是典型的測試處理器是否支持long mode的代碼。
- Practical Ansible 2
- 網絡服務器架設(Windows Server+Linux Server)
- Getting Started with Oracle SOA B2B Integration:A Hands-On Tutorial
- 影視后期制作(Avid Media Composer 5.0)
- 最簡數據挖掘
- Windows 7寶典
- 統計學習理論與方法:R語言版
- 基于32位ColdFire構建嵌入式系統
- Nginx高性能Web服務器詳解
- 筆記本電腦維修90個精選實例
- 網絡管理工具實用詳解
- 基于人工免疫原理的檢測系統模型及其應用
- Natural Language Processing and Computational Linguistics
- 基于Quartus Ⅱ的數字系統Verilog HDL設計實例詳解
- 巧學活用Photoshop