書名: x86/x64體系探索及編程作者名: 鄧志著本章字?jǐn)?shù): 498字更新時間: 2019-03-01 11:49:37
第4章 處理器的身份
我需要了解處理器的型號、廠商、有什么具體的特性等這些關(guān)于處理器的參數(shù),應(yīng)該怎么辦?x86/x64處理器上提供了CPUID指令用來查看和識別身份。
4.1 測試是否支持CPUID指令
eflags寄存器的bit 21是ID(Processor Feature Identification)標(biāo)志位,在286處理器中flags是16位的,在386處理器中eflags擴(kuò)展為32位,bit 21是reserved。CPUID指令從Intel 486處理器上開始加入,因此除非你在古老的機(jī)器上運(yùn)行,否則沒必要檢測處理器是否支持CPUID指令。
實(shí)驗(yàn)4-1:測試是否支持CPUID指令
test_CPUID()在源文件lib\lib16.asm里,在topic04\ex4-1\目錄有實(shí)驗(yàn)代碼:
代碼清單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標(biāo)志位,如果能成功修改,就表示支持CPUID指令。
4.2 CPUID指令的術(shù)語及表達(dá)
Intel64手冊里對CPUID指令廣泛使用了如下一些表達(dá)形式和術(shù)語。
leaf(葉)
功能號使用leaf術(shù)語,例如:CPUID的01號功能,你可以稱其為CPUID的01 leaf(葉)。
sub-leaf(子葉)
對于一些較復(fù)雜的信息查詢,往往需要一個輔助的子號。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指令的描述形式
當(dāng)軟件需要判斷某項(xiàng)功能處理器是否支持時,使用CPUID指令進(jìn)行查詢,在Intel手冊中使用了下面的描述形式。
上面是判斷處理器是否支持PAE(Physical Address Extensions)功能時的描述,當(dāng)CPUID.01H:EDX[6]的值為1時,表示支持PAE功能。
4.3 基本信息與擴(kuò)展信息
從CPUID指令獲得的信息有兩大類:basic(基本)和extended(擴(kuò)展),要獲得信息必須要先提供相應(yīng)的leaf(功能號),每一類信息都有最大的功能號限制。
某些功能號下面還有許多sub-leaf(子葉),也就是信息的子集。使用CPUID指令之前在eax寄存器提供要查詢的某個信息相應(yīng)的功能號。
mov eax,0 ; 功能號 0(main leaf) cpuid ; 查詢 0 號信息
返回的相應(yīng)信息放在eax、ebx、ecx,以及edx寄存器中。這些信息是32位的,因此在64位模式下,rax、rbx、rcx,以及rdx寄存器的高32位被清0。
查詢最大leaf(功能)號
CPUID指令被使用來查詢處理器所支持的特性,因此CPUID所支持的leaf數(shù)量是與處理器相關(guān)的。很多時候,在使用某個leaf查詢之前,必須判斷處理器是否支持該leaf。
典型地,在使用0BH號功能時,應(yīng)先查詢處理器是否支持0BH號功能。
基本最大功能號
使用CPUID的00H leaf來查詢,最大的基本功能號返回在EAX寄存器里。
mov eax,0 ; 功能號 0(main leaf) cpuid ; 查詢 0 號信息 cmp eax,0BH ; 判斷是否支持 0B leaf jb no_support ; 假如不支持...
擴(kuò)展最大功能號
同樣,最大的擴(kuò)展功能號也可以查詢。
mov eax,80000000 ; 功能號 80000000(main leaf) cpuid ; 查詢最大擴(kuò)展功能號 cmp eax,80000001H ; 判斷是否支持 80000001 leaf jb no_support ; 假如不支持...
輸入80000000H功能號,從返回的EAX寄存器里可以得到最大的擴(kuò)展功能號。
功能號0也返回處理器廠商名,在Intel的機(jī)器上返回的是:ebx寄存器是“Genu”,ecx寄存器是“ntel”,edx寄存器是“ineI”,組合起來是“GenuineIntel”,在AMD的機(jī)器上是“AuthenticAMD”。
實(shí)驗(yàn)4-2:獲得basic和extended功能號
實(shí)驗(yàn)的源碼在\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里運(yùn)行的結(jié)果如下所示。
Bochs是模擬Intel系列的CPU,在筆者的AMD真實(shí)機(jī)器上最大basic功能號是0x00000005,最大extended功能號是0x8000001A,在另一臺Intel i5機(jī)器上分別是0Bh和80000008h:
Intel的處理器上目前的最大basic功能號是0DH,最大extended功能號是80000008H(依賴于每個機(jī)器的實(shí)現(xiàn))。Intel手冊中指示Core i7處理器(Westmere架構(gòu))最大的basic功能號是0BH,最大的extended功能號是80000008H。
如果在eax中輸入的功能號超過了最大的功能號,那么將返回basic最大功能號的信息。
當(dāng)eax=0Eh時,返回的信息和eax=0Dh一致,當(dāng)eax=80000009h時返回的信息也和eax=0Dh一致。
實(shí)驗(yàn)4-3:分別使用0Dh和0Eh,以及80000008h和80000009h來運(yùn)行獲得信息
由于在目前的Intel上0Dh是最大basic功能號,80000008h是最大的擴(kuò)展功能號,因此本實(shí)驗(yàn)的目的是驗(yàn)證Intel所說的話。
代碼清單4-3(topic04\ex4-3\setup.asm):
;; 現(xiàn)在得到最大功能號 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 ; 打印寄存器的值 ;; 現(xiàn)在得到 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 ; 打印寄存器的值 ;; 現(xiàn)在測試 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中運(yùn)行的結(jié)果。
可以看出,當(dāng)eax分別等于0Dh、0Eh和80000009h時,所返回的信息是一樣的。在筆者的AMD真實(shí)機(jī)器上運(yùn)行上面的例子,得不到輸出結(jié)果,目前在AMD的機(jī)器上最大的basic功能號是06H,而extended功能號則達(dá)到了8000001Bh。
請注意:當(dāng)輸入的功能號<=最大功能號時,如果CPU并不支持該功能號,則所有寄存器返回0值,eax=ebx=ecx=edx=0。
由于在Bochs上所支持的最大basic功能號是0Dh,如果以0Ch去訪問CPUID指令(0Ch功能號CPU不支持),返回的寄存器將全是0值(eax<=maxinum number)。
當(dāng)輸入功能號>最大功能號時,訪問CPUID,返回的將是最大功能號的信息,也就是上面做的實(shí)驗(yàn)所證明的。
4.4 處理器的型號(family,model與stepping)
由CPUID.01H:EAX可返回處理器的家族、模型及步進(jìn)信息。
EAX[11:8]得到family編碼,典型地,P6家族處理器的family編碼是06H,Pentium4家族的family編碼是0FH。EAX[27:20]得到擴(kuò)展的family值。EAX[7:4]得到處理器在家族中的model。EAX[19:16]得到擴(kuò)展的model值。
在這些處理器信息里,最重要的是family與model。由于x86處理器的龐大和混亂,在Intel文檔的相關(guān)描述中,使用了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;
現(xiàn)在我們可以做個實(shí)驗(yàn)。
實(shí)驗(yàn)4-4:獲得處理器的DisplayFamily與DisplayModel
實(shí)驗(yàn)的完整源碼在topic04\ex4-4\setup.asm文件里,調(diào)用了lib\lib16.asm文件里面的get_DisplayFamily_DisplayModel()過程來獲得DisplayFamily和DisplayModel值,下面是運(yùn)行結(jié)果。
在筆者實(shí)驗(yàn)的機(jī)器上的處理器DispalyFamily是06H,DisplayModel是25H,根據(jù)Intel的說明這個Model是屬于32nm制程的Core i3/i5/i7 Mobile處理器(屬于Westmere微架構(gòu))。
它的ExtendedModel值是0010B,Model值是0101B,組合起來是:25H。那么這個處理器模型將被描述為:06_25H。這種DisplayFamily_DisplayModel的模型相當(dāng)重要,在Intel手冊的描述中使用這種方式來區(qū)別處理器的模型。
在Intel的機(jī)器上,06H家族和0FH家族是兩大派系,0FH家族典型地是指Pentium4處理器系列。而06H家族很龐大,從早期的Pentium Pro、PentiumII到今天的Westmere/SandyBridge微架構(gòu)的i7/i5/i3處理器都屬于06H家族。在如此龐大的06H家族,要靠它的DisplayModel來識別每一代架構(gòu)的處理器。05H家族則屬于Pentium處理器。
4.5 最大的物理地址和線性地址
在CPUID.80000008H葉里,我們可以獲取處理器所支持的最大物理地址和線性地址的寬度。
上面的實(shí)驗(yàn)中80000008h功能號返回的eax值為0x00003028,低byte是物理地址寬度,值為28h就是40位,接著是線性地址寬度。當(dāng)CPU支持long mode時,這個值是30h,否則就是20h,這表明long mode下最高支持48位的線性地址,線性地址的高16位被用做sign位,在32位的機(jī)器上這個值是20h(32位)。
MAXPHYADDR值
在Intel中廣泛使用MAXPHYADDR這個術(shù)語來表示最大的物理地址。80000008H leaf返回的EAX[7:0]被稱為MAXPHYADDR。
當(dāng)處理器不支持80000008H leaf(功能)時,如果檢測到CPUID.01H:EDX[6]=1(即:PAE=1)則支持最高36位物理地址。如果此時PAE也并不支持,那么MAXPHYADDR就是32位。
4.6 處理器擴(kuò)展?fàn)顟B(tài)信息
實(shí)際上0Dh功能號是獲得處理器對Processor Extended State(處理器擴(kuò)展?fàn)顟B(tài))的支持度,這在AVX指令編程里非常重要。在最新的Sandy Bridge架構(gòu)的處理器中,支持度只使用了3位。
Processor Extended State(處理器擴(kuò)展?fàn)顟B(tài))是什么?
0Dh功能號是一個功能集,在前面的例子中:
mov eax,0Dh ; 0Dh 功能號 mov ecx,0 ; main leaf(主葉)功能 cpuid ; 得到 0Dh 的 main leaf功能
這個main leaf功能就可以獲得CPU目前對處理器狀態(tài)信息的支持度,eax和edx寄存器返回processor extended state的enable/disable位圖。
返回的edx和eax寄存器組成一個64位的Processor Extended State功能表,高32位在edx寄存器,低32位在eax寄存器。在處理器的規(guī)劃中,每1位對應(yīng)一個擴(kuò)展?fàn)顟B(tài)功能enable位。為1時支持該狀態(tài),為0時不支持。
這個Processor Extended State值將影響到XCR0(Extended Control Register)的值。當(dāng)State值的某位為0時,那么XCR0的相應(yīng)位為保留位(此位不能被XSETBV指令設(shè)置)。
目前的x86處理器中(包括Intel和AMD)僅使用了低3位(Bit 0~Bit2)。Bit 0對應(yīng)X87 FPU狀態(tài),Bit 1對應(yīng)SSE狀態(tài),這兩位一般都能返回1,表示CPU支持X87 FPU和SSE功能。Bit 2對應(yīng)YMM狀態(tài)。
YMM狀態(tài)在Intel的Sandy Bridge架構(gòu)和AMD的bulldozer架構(gòu)中得到了支持,也就是說CPU支持AVX指令集。因此,在這種處理器以上才返回YMM狀態(tài)位為1值。
圖中的陰影部分為reserved(保留位),未來的處理器可能會使用這些位來支持更多的處理器狀態(tài)信息。保留位的值全部為0。
看看前面在Bochs里運(yùn)行的結(jié)果。
得到的結(jié)果表明:CPU支持x87 FPU和SSE狀態(tài)而不支持YMM狀態(tài),也就是說不支持AVX指令。值得注意的是,由于Bochs模擬實(shí)現(xiàn)了CPUID 0DH號功能,因此可以使用0DH leaf進(jìn)行查詢。實(shí)際上,在不支持AVX指令的處理器上,并不支持CPUID 0DH leaf。
4.6.1 探測Processor Extended State子葉
由于eax返回的是處理器對Processor Extended State的enable位,在未來的處理器中可能加入更多的支持,因此在使用前應(yīng)該探測處理器到底支持了哪些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 ; 該位不支持,繼續(xù)探測 cpuid ; 探測 mov ecx,[detect_value] mov [state + ecx * 4],eax ; 保存子葉 size mov [state + ecx * 4 + 4],ebx ; 保存子葉 offset next_detect: inc dword [detect_value] ; 繼續(xù)探測下一個子葉 cmp dword [detect_value],62 ; 小于等于 62 就繼續(xù) jle detect next: ... ...
假如CPU支持AVX指令,那么CPUID(eax=0Dh,ecx=0h):EAX[YMM]為1,也就是eax的Bit 2為1,因此從第2位開始探測,假如Bit 3是支持的,繼續(xù)探測Bit 3,以此類推……
記錄下來:在上面的64位Processor Extended State值中每1位代表一個子葉,從Bit 2(YMM狀態(tài))開始。
在Processor Extended State中X87 FPU state是必須要支持的,它必定為1,而 SSE state也就是XMM寄存器狀態(tài),也是支持的,這時Bit 1位是保留。所以從Bit 2開始探測直至Bit 62位,Bit 63位是保留未用。
4.6.2 Processor Extended State子葉所需內(nèi)存size
在main leaf(eax=0Dh,ecx=0h)里,ebx和ecx寄存器都返回一個內(nèi)存size。
ebx寄存器返回的是在XCR0(Extended Control Register)里設(shè)置了開啟某個位去支持處理器狀態(tài)所需要的內(nèi)存size。
XCR0的結(jié)構(gòu)與上面CPUID(EAX=0Dh,ECX=0H) 返回的64位Processor Extended State值結(jié)構(gòu)是一樣的。XCR0可以設(shè)置SSE狀態(tài)為disable(關(guān)閉),這樣CPU將不會保存SSE(即:XMM寄存器)的值。
Processor Extended State與XCR0的關(guān)系
XCR0是一個功能開關(guān),用來開啟或關(guān)閉某些state的保存。而CPUID(eax=0Dh,ecx=00h)返回的Processor Extended State值將決定處理器保存哪些state信息的能力。
OS可以通過XSETBV指令對XCR0進(jìn)行相應(yīng)的設(shè)置,如果某位被disable掉,這時候,XCR0與CPU支持的64位Processor Extended State值會不一致。因此,ebx寄存器返回的是這個XCR0設(shè)置的保存狀態(tài)所需要的內(nèi)存size。
ecx寄存器返回的是CPU所支持的所有狀態(tài)(即:在main leaf里返回eax的位圖),保存這些狀態(tài)所需要的總內(nèi)存size,因此,ebx不一定等于ecx(取決于XCR0是否開啟相應(yīng)的位)。
如果CPUID(eax=0Dh,ecx=0h)返回的eax寄存器為07H值,那么說明它支持AVX指令,這樣的話就可以接著使用0Dh的2號子葉去查看相關(guān)的信息。
在AMD處理器上支持LWP指令,Bit 62位是LWP state位,所以在AMD里就可以查看62號子葉的信息。
下面是查看子葉號為62的相關(guān)信息(如果CPU支持)。
mov eax,0Dh ; 0Dh 功能號 mov ecx,62 ; AMD機(jī)器上的62號子葉功能 cpuid
4.6.3 Processor Extended State的保存
Processor Extended State通過使用XSAVE指令來保存處理器的狀態(tài),在內(nèi)存中處理器的state映像看起來如下。
實(shí)際情況還要更復(fù)雜些,SSE和YMM狀態(tài)的保存,還取決于XSAVE指令提供的64位MASK碼和XCR0上面所述的相應(yīng)位的enable(開啟),如果XCR0.YMM=0表明不保存YMM狀態(tài),那么圖中的YMM state區(qū)域是0值(不被更新)。
mov edx,0 mov eax,3 ; 不保存 YMM state xsave [state_image] ; 根據(jù) 64位的 Mask值和XCR0位進(jìn)行保存
同樣,在edx:eax這個64位的mask碼值中,如果YMM state mask位為0,YMM state區(qū)域也不被更新,必須XCR0和MASK值同時被置1(AND與關(guān)系)區(qū)域才被更新。
回到上面的例子,由于不支持AVX指令,所以eax返回0x03,表明僅支持X87 FPU和SSE狀態(tài)。而ebx和ecx寄存器的返回值是0x240,這個值就等于512+64=576(0x240),X87 FPU需要512字節(jié),還要加上一個header部分。這個header的首64位(8 bytes)是一個XSTATE_BV結(jié)構(gòu),當(dāng)XSAVE保存狀態(tài)時,用來記錄部分狀態(tài)被保存了。若保存X87 FPU和SSE狀態(tài),就設(shè)置Bit 0和Bit 1為1,反之將清0。
4.6.4 Processor Extended State的恢復(fù)
使用XRSTOR指令可以從內(nèi)存的state映像中恢復(fù)原來保存的state信息。
header結(jié)構(gòu)是64字節(jié),首8字節(jié)是一個64位的MASK值,用來記錄在state映像中哪些區(qū)域是被保存過的(被更新過),相應(yīng)的位為1時表示image中的相應(yīng)的區(qū)域被更新,如:YMM state區(qū)域中被保存過,那么XSTATE_BV[2]=1(Bit 2對應(yīng)于YMM state位)。
XSTATE_BV的位在執(zhí)行XSAVE指令保存state時被CPU設(shè)置。當(dāng)執(zhí)行xrstor指令時,CPU會根據(jù)XSTATE_BV中哪一位被置位,而做相應(yīng)的恢復(fù)。
4.7 處理器的特性
EAX=01h號功能將獲得處理器的基本信息,它是CPUID中一個重要的功能號,eax寄存器返回處理器的Model、Family、Stepping等信息。在ebx寄存器中:ebx[15:8]返回CLFLUSH line size,這個值乘8就可以得到Cache line的size,ebx[23:16]返回邏輯處理器最大可尋址的數(shù)目。
實(shí)驗(yàn)4-5:查看CPU的cache line size和Maximum logic processor
實(shí)驗(yàn)的完整源碼在\topic04\ex4-5\setup.asm文件里,下面是在VMware里的運(yùn)行結(jié)果。
在VMware中筆者設(shè)置processor core的數(shù)目為4個,上面顯示的logic processor是4個,ebx[15:8]的值是0x08,所以它的cache line size是64(0x40)字節(jié)。
在ecx和edx寄存器中返回CPU支持的種類繁多的特性,下面分別是ecx和edx寄存器返回值所對應(yīng)的功能。
這些特性是處理器硬件物理上所支持的功能,利用CPUID指令可以檢測處理器所支持的特性。
可是CPUID.EAX=01H在ECX和EDX返回的某些特性是由軟件設(shè)置的。還有部分特性受到MSR(Model Specific Register)的設(shè)置影響。
例如:ECX寄存器的bit 27是OSXSAVE標(biāo)志位,這個標(biāo)志位并不是硬件特性,是由軟件設(shè)置而來的,在OS里為了開啟AVX指令使用環(huán)境,OS最終會設(shè)置CR4的Bit 18位CR4.OSXSAVE=1,處理器會根據(jù)這個位來置CPUID(EAX=01h):ECX[27]標(biāo)志,也就是上面的ECX[OSXSAVE]標(biāo)志位。軟件使用AVX指令前會讀取這個標(biāo)志位,確認(rèn)OS已經(jīng)準(zhǔn)備好AVX指令的執(zhí)行環(huán)境。
檢測CPU是否支持AVX指令的是Bit 28 AVX標(biāo)志位,而Bit 26位是XSAVE標(biāo)志位,它用于檢測CPU是否支持XSAVE/XRSTOR、XSETBV/XGETBV指令和XCR0。
4.8 處理器的Cache與TLB信息
CPUID.EAX=02H用來獲得關(guān)于CPU的Cache與TLB信息。
mov eax,02H ; 02號功能 cpuid
eax寄存器的最低字節(jié)(byte 0)是需要執(zhí)行CPUID.EAX=02H的次數(shù)。
上面這個最低字節(jié)的值為01,表明只需要執(zhí)行一次CPUID.EAX=02H就能獲得完整的信息。
寄存器的MSB(Bit31)位是個標(biāo)志位,為0指示有效,為1指示無效。
eax、ebx、ecx和edx寄存器中的每個字節(jié)指示一個信息(除EAX寄存器的byte 0外)。
如果是FF字節(jié)表示CPUID.EAX=02H不返回cache及TLB信息,需要執(zhí)行CPUID.EAX=04H進(jìn)行查詢。
實(shí)驗(yàn)4-6:使用CPUID.EAX=02H查看cache及TLB信息
實(shí)驗(yàn)的源碼在\topic04\ex4-6\setup.asm中,下面是在VMware中的運(yùn)行結(jié)果。
上面的信息是在VMware下打印出來的,從這個結(jié)果,我們可以看出來以下信息。
處理器的Cache和TLB情況也可以從CPUID.EAX=04H里獲得,04H功能號是一個集,以ECX輸入一個子葉號,枚舉出處理器Cache的所有信息。
首先以ECX=0H子葉開始查詢,在eax寄存器返回,我們所關(guān)心的是以下幾個位域。
EAX[4:0]返回cache的類型,分別是:1=Data cache,2=Instruction cache,3=Unified cache,0值是終止標(biāo)志,表示已經(jīng)沒有子葉可以枚舉了,其他值是保留的。
EAX[7:5]返回cache的level,EAX[31:26]域里也可以查詢得到處理器的core數(shù),這個查詢結(jié)果值需要加上1才是真正的值。
接下來EBX寄存器的返回信息是:EBX[11:00]是line size,EBX[21:12]是physical line partition,EBX[31:22]返回cache的way數(shù)。最后ECX寄存器返回32位的cache set數(shù)量。
實(shí)驗(yàn)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開始進(jìn)行探測,直至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)。
每一項(xiàng)加上1,是因?yàn)榉祷氐男畔⒓由?才是完整的值。這個計算的過程在print_cache_info()過程里,讀者可以在topic04\ex4-7\setup.asm源碼里看到。下面是在VMware中的運(yùn)行結(jié)果。
對比一下上面的運(yùn)行結(jié)果和使用CPUID.EAX=02H查詢到的結(jié)果,看是否一致。上面的結(jié)果是:
1級Data-cache的size是32KB(值為0x8000),8-way 64 set結(jié)構(gòu)。1級Instruction-cache的size同樣是32KB(值為0x8000),4-way 128 set結(jié)構(gòu)。2級cache的size是256KB(值為0x40000),8-way 512 set結(jié)構(gòu)。3級cache的size是3MB(值為0x300000),屬于12-way 4096 set結(jié)構(gòu)。
對比結(jié)果cache size和cache結(jié)構(gòu)是一樣的,在這個例子里沒有完整打印詳細(xì)的信息,讀者朋友可以自行加入更完整的顯示。這個例子探測到子葉號ECX=03H為止,ECX=04H已經(jīng)不支持了。
讓人感到沮喪的是:在AMD的機(jī)器上并不支持EAX=02H到EAX=04H的功能號!
是的,這確實(shí)讓人反感,在AMD的機(jī)器上basic功能號支持EAX=01H、EAX=05H、EAX=06H以及EAX=0DH,這4個功能號??墒茿MD比Intel支持更多的extended功能號,根據(jù)AMD的CPUID specification指示,最多達(dá)到了8000001EH,而Intel只支持到80000008H。
在AMD機(jī)器上可以使用80000005H、80000006H,以及8000001DH擴(kuò)展功能號查詢cache和TLB的相關(guān)信息。
4.9 MONITOR/MWAIT信息
在CPUID.EAX=01H功能里返回的ECX[3]可以查詢處理器是否支持MONITOR與MWAIT指令,MONITOR/MWAIT指令用來監(jiān)控某個線性地址范圍內(nèi)沒發(fā)生store操作進(jìn)入一個被優(yōu)化的狀態(tài)。
下面是一個典型的MONITOR/MWAIT指令使用序列。
@Loop: bt dword [WorkQueue],0 ; 測試 WorkQueue == 1 ? jnc no_work ... ... ; 執(zhí)行其他調(diào)度 jmp @Loop ;;; 當(dāng) WorkQueue == 0 時: no_work: mov eax,WorkQueue ; 監(jiān)控地址 mov ecx,0 ; 0 extensions mov edx,0 ; 0 hints MONITOR ; 進(jìn)入監(jiān)控 bt dword [WorkQueue],0 ; 測試 WorkQueue jc @Loop ; WorkdQueue == 1 時重新循環(huán) sti ; 允許被中斷事件退出優(yōu)化的狀態(tài) mov eax,0 ; 0 hints mov ecx,0 ; 0 extensions MWAIT ; wait jmp @Loop
monitor/mwait指令的使用情形有些與pause指令類似,在Idle Loop(空閑的循環(huán))中用來提高處理器的性能和減少能耗。pause常用于OS的自旋鎖,monitor/mwait對某個地址范圍做監(jiān)控,這個地址范圍內(nèi)沒發(fā)生store操作就進(jìn)入優(yōu)化的狀態(tài),由mwait等待某些事件而退出,因地址store操作而退出或者因某些中斷類的事件發(fā)生。
執(zhí)行CPUID.05H在EAX[15:00]里返回Smallest monitor-line size,在EBX[15:00]里返回Largest monitor-line size。在MSR IA32_MONITOR_FILTER_LINE_SIZE里可以對這些值進(jìn)行設(shè)置,從而影響CPUID.05H leaf的讀取結(jié)果。
4.10 處理器的long mode
extended功能號80000001H是一個很重要的CPUID leaf,里面有最為重要的Long Mode標(biāo)志位,用來查詢處理器是否支持long mode,在AMD的機(jī)器上80000001H具有很多特性,而Intel的機(jī)器上許多為保留位。
最重要的位是EDX[29]返回long mode標(biāo)志,EDX[11]是SYSCALL/SYSRET指令支持標(biāo)志位,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的代碼。
- ArchiCAD 19:The Definitive Guide
- Practical Data Analysis
- 腦動力:C語言函數(shù)速查效率手冊
- 輕松學(xué)C#
- 輕松學(xué)Java Web開發(fā)
- 計算機(jī)原理
- 21天學(xué)通Visual Basic
- Blender Compositing and Post Processing
- Excel 2007技巧大全
- 單片機(jī)技術(shù)一學(xué)就會
- 單片機(jī)C語言應(yīng)用100例
- 計算機(jī)與信息技術(shù)基礎(chǔ)上機(jī)指導(dǎo)
- FPGA/CPLD應(yīng)用技術(shù)(Verilog語言版)
- 電腦日常使用與維護(hù)322問
- 基于Proteus的單片機(jī)應(yīng)用技術(shù)