本篇內(nèi)容主要講解“如何使用PAE分頁(yè)模式”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何使用PAE分頁(yè)模式”吧!
興化網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,興化網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為興化上千多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的興化做網(wǎng)站的公司定做!
前言
物理地址擴(kuò)展 Physical Address Extension(縮寫(xiě)PAE)。
解釋:正常情況32位CPU可以存取4G的物理內(nèi)存,但在現(xiàn)實(shí)中,實(shí)際情況是內(nèi)存的發(fā)展速度大于CPU的發(fā)展速度,所以才有了讓32位CPU存取超過(guò)4G內(nèi)存的需求。實(shí)現(xiàn)方式就是給CPU增加了4根地址線,達(dá)到36根,于是可尋址64G大小的內(nèi)存。
Intel到目前為止設(shè)計(jì)了4種分頁(yè)模式,分別是:32位、PAE、4-level、5-level這四種模式。本文主要講了Intel是如何設(shè)計(jì)PAE模式的頁(yè)表相關(guān)數(shù)據(jù)結(jié)構(gòu)。
“Chapter 4 Paging”部分,是筆者在閱讀Intel手冊(cè)時(shí)做的翻譯筆記,對(duì)應(yīng)原文的 Volume3: Chapter 4 Paging。翻譯有不準(zhǔn)確的地方,以原文為準(zhǔn)??梢栽谶@里下載手冊(cè)。Intel? 64 and IA-32 Architectures Software Developer Manuals
“實(shí)驗(yàn)題”部分,實(shí)現(xiàn)了一個(gè)可以瀏覽進(jìn)程頁(yè)表的小工具,可以在這里查看源碼。github源碼
Chapter 4 Paging
4.1 分頁(yè)模式和控制位
分頁(yè)控制有關(guān)的寄存器
CR0 標(biāo)志位:WP(bit 16)、PG(bit 31)
CR4 標(biāo)志位:PSE(bit 4)、PAE(bit 5)、PGE(bit 7)、PCIDE(bit 17)、SMEP(bit 20)、SMAP(bit 21)、PKE(bit 22)、CET(bit 23)、PKS(bit 24)
IA32_EFER MSR 標(biāo)志位:LEM(bit 8)、NXE(bit 11)
EFLAGS 標(biāo)志位:AC(bit 18)
軟件(應(yīng)該指操作系統(tǒng))如何啟用分頁(yè)功能:確保CR3中是分頁(yè)結(jié)構(gòu)表的物理內(nèi)存地址,然后使用MOV指令置CR0.PG位。
4.1.1 四種分頁(yè)模式
本節(jié)內(nèi)容:根據(jù) CR0.PG、CR4.PAE、CR4.LA57和IA32_EFER.LME,判斷是否啟用分頁(yè),以及是開(kāi)啟的什么分頁(yè)模式。
CR0.PG = 0 表示未啟用分頁(yè)模式,此時(shí)會(huì)把線性地址直接當(dāng)作物理地址使用。
CR0.PG = 1 表示啟用分頁(yè)模式。 Paging can be enabled only if protection is enabled (CR0.PE = 1)。此時(shí)由CR4.PAE、CR4.LA57、和IA32_EFER.LME決定啟用哪種分頁(yè)模式。
32-bit paging 模式 CR4.PAE = 0 (詳見(jiàn)4.3節(jié))
PAE paging 模式 CR4.PAE = 1 and IA32_EFER.LME = 0 (詳見(jiàn)4.4節(jié))
4-level paging 模式 CR4.PAE = 1, IA32_EFER.LME = 1, and CR4.LA57 = 0 (4表示4層表尋找Pages頁(yè),詳見(jiàn)4.5節(jié))
5-level paging 模式 CR4.PAE = 1, IA32_EFER.LME = 1, and CR4.LA57 = 1 (5表示5層表尋找Pages頁(yè),詳見(jiàn)4.5節(jié))
32-bit 和PAG模式用于保護(hù)模式32位模式,IA32_EFER.LME = 0
4-level和5-level模式用于64位模式(IA-32e表示64位模式),IA32_EFER.LME = 1
四種模式的區(qū)別:
線性地址寬度
物理地址寬度
分頁(yè)大?。?K、2M、4M、1G
支持execute-disable,數(shù)據(jù)執(zhí)行保護(hù)
支持PCIDs,操作系統(tǒng)可以啟用緩存線性地址的功能,不是很懂,先放放
支持 protection keys,不知道干嘛的
4-level 和 5-level模式還有兩個(gè)子模式:
兼容模式:兼容32位的模式
64位模式:雖然是64位線性地址,但是實(shí)際上4-level只使用了低48位做線性地址,而5-level頁(yè)只使用低57位,物理地址線都只有52根。
4.1.2 啟用和切換分頁(yè)模式
本節(jié)內(nèi)容:根據(jù) CR0.PG、CR4.PAE、CR4.LA57和IA32_EFER.LME,如何啟用并且切換不同的分頁(yè)模式
講解在不同模式之間切換的規(guī)則,這部分不感興趣,略過(guò)。
4.1.3 分頁(yè)屬性控制
本節(jié)內(nèi)容:通過(guò)CR0.WP、CR4.PSE、CR4.PGE、CR4.PCIDE、CR4.SMEP、CR4.SMAP、CR4.PKE、CR4.CET、CR4.PKS和IA32_EFER.NXE控制在不同分頁(yè)模式下Pages的屬性
CR0.WP
寫(xiě)入數(shù)據(jù)保護(hù)標(biāo)志位:
等于0, supervisor-mode(應(yīng)該指0環(huán)應(yīng)用程序)可以向具有只讀屬性的頁(yè)寫(xiě)數(shù)據(jù);等于1,則不可以操作。
這個(gè)標(biāo)志位對(duì)User-mode(應(yīng)該時(shí)3環(huán)應(yīng)用程序)沒(méi)有影響,因?yàn)橹灰侵蛔x屬性的頁(yè),3環(huán)程序都不能寫(xiě)。
(4.6節(jié)有更詳細(xì)的介紹)
CR4.PSE
是否啟用4M分頁(yè):
只對(duì)32-bit paging 模式作用,等于0,表示分頁(yè)大小只能是4K;等于1,可以選擇4K或4M分頁(yè)。其它三種模式的分頁(yè)大小可以自由選擇,不受該位的控制。(4.3節(jié)有更詳細(xì)的介紹)
CR4.PGE
是否啟用全局共享頁(yè):
等于0,不同進(jìn)程間不會(huì)共享物理內(nèi)存;等于1,進(jìn)程間可以共享物理內(nèi)存。(可能翻譯的不對(duì),帖上原文)
CR4.PGE enables global pages. If CR4.PGE = 0, no translations are shared across address spaces; if CR4.PGE = 1,
specified translations may be shared across address spaces.(4.10.2.4節(jié)有更詳細(xì)的介紹)
CR4.PCIDE
啟用process-context identifiers,對(duì)4-level 和 5-level模式作用。
PCIDs邏輯處理器緩存多個(gè)線性地址。(4.10.1節(jié)有更詳細(xì)的介紹)
CR4.SMEP
If CR4.SMEP = 1, software operating in supervisor mode cannot fetch instructions from linear addresses that are accessible in user mode.(4.6節(jié)有更詳細(xì)的介紹)
CR4.SMAP
If CR4.SMAP = 1, software operating in supervisor mode cannot access data at linear addresses that are accessible in user mode. Software can override this protection by setting EFLAGS.AC.
CR4.PKE and CR4.PKS
4-level和5-level模式將每一個(gè)線性地址與保護(hù)key相關(guān)聯(lián)。
CR4.PKE=1時(shí),PKRU寄存器表示,user-mode的線性地址所關(guān)聯(lián)的保護(hù)key,是否可讀或可寫(xiě)。
CR4.PKS=1時(shí), the IA32_PKRS MSR does the same for supervisor-mode linear addresses.
CR4.CET
這個(gè)好難理解。
If CR4.CET = 1, certain memory accesses are identified as shadow-stack accesses and certain linear addresses translate to
shadow-stack pages.
IA32_EFER.NXE
執(zhí)行保護(hù),對(duì)4-level 和 5-level模式作用。如果設(shè)為1,則不能執(zhí)行指令,但是可以讀指令。
4.1.4 Enumeration of Paging Features by CPUID
這部分保護(hù)標(biāo)志位的意義和用法。
PSE: page-size extensions for 32-bit paging.
PAE: physical-address extension.
PGE: global-page support.
PAT: page-attribute table.
PSE-36: page-size extensions with 40-bit physical-address extension.
PCID: process-context identifiers.
SMEP: supervisor-mode execution prevention.
SMAP: supervisor-mode access prevention.
PKU: protection keys for user-mode pages.
OSPKE: enabling of protection keys for user-mode pages.
CET: control-flow enforcement technology.
LA57: 57-bit linear addresses and 5-level paging.
PKS: protection keys for supervisor-mode pages.
NX: execute disable.
Page1GB: 1-GByte pages.
LM: IA-32e mode support.
CPUID.80000008H:EAX[7:0] reports the physical-address width supported by the processor.
CPUID.80000008H:EAX[15:8] reports the linear-address width supported by the processor.
4.2 分層頁(yè)表結(jié)構(gòu)概覽
不同模式使用的頁(yè)表結(jié)構(gòu)是不一樣的,有的只是用2張表,有的則更多。
每張表的大小都是4096字節(jié),對(duì)于32-bit模式,每一項(xiàng)是4字節(jié),共1024項(xiàng);對(duì)于其它三種模式,每一項(xiàng)是8字節(jié),每張表512項(xiàng)。PAE模式是個(gè)特例,它的第一張表只有4項(xiàng)。
不同模式對(duì)線性地址的處理是不一樣的,詳細(xì)章節(jié)會(huì)講。
這里提出了兩個(gè)名詞:page frame 線性地址中用來(lái)尋址的部分;page offset 線性地址中用作偏移的部分。
每一項(xiàng)中的地址部分都是物理內(nèi)存地址。
第一張表總是保存在CR3寄存器中。
四種模式解析線性地址(4K分頁(yè)舉例):
32-bit模式:32:22(10位)表1下標(biāo),21:12(10位)表2下標(biāo),11:0(12位)用作分頁(yè)內(nèi)的偏移量。
PAE模式:31:30(2位)表1下標(biāo),29:21(9位)表2下標(biāo),20:12(9位)表3下標(biāo),11:0(12位)分頁(yè)內(nèi)的偏移量。
4-level模式:每張表都是512項(xiàng),總共4張表,所以47:39、38:30、29:21、20:12對(duì)應(yīng)4張表的下標(biāo),11:0(12位)分頁(yè)內(nèi)的偏移量。
5-level模式:使用5張表,56:48是第一張表下標(biāo),其余的根4-level模式的一樣。
總結(jié)上面的解析線性地址過(guò)程,其實(shí)就是查表,查表,再查表。有些情況查表過(guò)程可能會(huì)中斷,比如說(shuō)遇到缺頁(yè)異常時(shí)。
還有兩種特殊的情況:
查表過(guò)程中,剩余沒(méi)有解析的線性地址寬度超過(guò)12位,如果當(dāng)前表項(xiàng)的屬性位bit 7(PS位—page size)等于1,當(dāng)前項(xiàng)就是最后的頁(yè)
查表過(guò)程中,剩余沒(méi)有解析的線性地址寬度等于12位,bit 7不再是PS位,另有它用,當(dāng)前項(xiàng)則指向另一個(gè)表
對(duì)上述的第一種情況舉例:
32-bit模式,如果分頁(yè)大小是4M(CR4.PSE=1),那么表1就是存儲(chǔ)的頁(yè),總共1024項(xiàng),1024*4M=4G,正好尋址4G空間,表2就不存在了。再比如,PAE模式下,如果分頁(yè)大小是2M,查到第2張表就時(shí)頁(yè)了,此時(shí)沒(méi)有了表3。
不同的表結(jié)構(gòu)都有名字,參考下圖:
對(duì)于上面的縮寫(xiě),通常我們有下面的叫法:
PTE 頁(yè)表,存放的每一項(xiàng)是最終的Pages物理地址,32位的分頁(yè)大小有4K、2M、4M,64位則能擴(kuò)展到1G大小
PDE 頁(yè)目錄表,存放的每一項(xiàng)是PTE
PDPTE頁(yè)目錄指針表,PAE模式只有4項(xiàng),4-level和5-level模式都是填滿的512項(xiàng),每一項(xiàng)指向一個(gè)頁(yè)目錄表。
PML4E和PML5E暫時(shí)也不知道,實(shí)際上用法類似,各增加一層表的
4.4 PAE 分頁(yè)模式
寄存器標(biāo)志位:
CR0.PG = 1
CR4.PAE = 1
IA32_EFER.LME = 0
4.4.1 PDPTE寄存器
CR3指向 page-directory-pointer表。其中:
4:0 沒(méi)有用
31:5 存放指向表的物理地址
63:52 沒(méi)有用
page-dirctory-pointer表中由4個(gè)8字節(jié)的大小的PDPTEs組成,每個(gè)可尋址1-GByte大小的線性地址空間。
對(duì)應(yīng)這4個(gè)PDPTE,邏輯處理器內(nèi)部維護(hù)著與之對(duì)應(yīng)的四個(gè)non-architectural寄存器,分別是PDPTE0、PDPTE1、PDPTE2、PDPTE3。出現(xiàn)下面幾種情況時(shí),邏輯處理器會(huì)重新加載內(nèi)存中的PDPTEs到4個(gè)寄存器:
如果使用MOV to CR0或MOV to CR4指令修改了這些寄存器中的標(biāo)志位(CR0.CD, CR0.NW, CR0.PG, CR4.PAE, CR4.PGE, CR4.PSE, or CR4.SMEP),PDPTESs會(huì)從CR3中執(zhí)行的地址重新加載
在PAE分頁(yè)模式,如果下執(zhí)行MOV to CR3指令,PDPTESs會(huì)從CR3中執(zhí)行的地址重新加載
在PAE分頁(yè)模式,如果CR3中的值被task switch修改,會(huì)從新的CR3中加載PDPTEs
下表中說(shuō)明了PDPTE的結(jié)構(gòu):
位 用途
0(P) Present,等于1表示此項(xiàng)指向一個(gè)頁(yè)目錄表,等于0則此項(xiàng)不包含頁(yè)目錄表
2:1 保留位,必須填0
3(PWT) Page-level write-through,用來(lái)間接確定訪問(wèn)頁(yè)目錄表所需要的內(nèi)存屬性(詳見(jiàn)4.9節(jié))
4(PCD) Page-level cache disable,用來(lái)間接確定訪問(wèn)頁(yè)目錄表所需要的內(nèi)存屬性(詳見(jiàn)4.9節(jié))
8:5 保留位,必須填0
11:9 忽略
(M-1):12 指向頁(yè)目錄表的4K對(duì)齊的物理地址
63:M 保留位,必須填0
注:M表示MAXPHYADDR,最大物理地址寬度,該手冊(cè)中是52根地址線。
4.4.2 線性地址轉(zhuǎn)物理地址
PAE模式下,可以使用4K或2M分頁(yè)。
如何確定是4K分頁(yè)還是2M分頁(yè):
線性地址的31:30(2位)用來(lái)選擇4個(gè)PDPTE寄存器中一個(gè),稱為PDPTEi,i等于這兩位的值。每個(gè)PDPTEi可以對(duì)應(yīng)1G大小的線性地址空間。如果PDPTEi的P位是0,那么這一項(xiàng)就是無(wú)效的,就是說(shuō)該項(xiàng)不包含對(duì)應(yīng)的頁(yè)目錄表,同時(shí)會(huì)產(chǎn)生一個(gè)page-fault異常(詳見(jiàn)4.7節(jié))。
如果PDPTEi的P位是1,那么其51:12(40位)指向了頁(yè)目錄表的物理地址。每個(gè)頁(yè)目錄表由512項(xiàng)8字節(jié)的PDEs組成。
意思就是線性地址的前兩位用于確定頁(yè)目錄指針表(PDPTE)的下標(biāo),找到4個(gè)中的一個(gè)頁(yè)目錄表。
頁(yè)目錄表,每個(gè)頁(yè)面錄表含有512個(gè)表項(xiàng),每個(gè)表項(xiàng)8字節(jié)大小,指向一個(gè)頁(yè)表或者指向一個(gè)2M的頁(yè),這要根據(jù)下面介紹的PS標(biāo)志位來(lái)確定。
如果PDE’s頁(yè)目錄表項(xiàng)的PS位等于1,說(shuō)明這一項(xiàng)指向的就是一個(gè)最終的2M的分頁(yè),物理地址由該項(xiàng)的51:21(31位)和20:0(21位)確定。物理地址線最大52根,有的CPU是36根,那么高位就是35:21(15位),有的CPU有52根的,高位才是51:21。
如果PDE’s頁(yè)目錄表項(xiàng)的PS位等于0,說(shuō)明這一項(xiàng)指向的是頁(yè)表。頁(yè)表的物理地址跟上面的情況一樣也分為36根物理地址線和52根物理地址線。
如果是2M分頁(yè),那么線性地址后30位中,29:21(9位)用來(lái)作為表2(頁(yè)目錄表)的下標(biāo)索引,來(lái)確定最終的頁(yè)地址;20:0(21位)作為2M頁(yè)內(nèi)的偏移量。
如果是4K分頁(yè),那么線性地址后30位中,29:21(9位)作為表2(頁(yè)目錄表)的下標(biāo)索引,20:12(9位)作為表3(頁(yè)表)的下標(biāo)索引,11:0(12位)作為4K頁(yè)內(nèi)的偏移量。
如果頁(yè)目錄表項(xiàng)(PDE)或者頁(yè)表項(xiàng)(PTE)的P位(bit 0)等于0,或者置位它們的任意一位保留位,這個(gè)表項(xiàng)將會(huì)失效,并且會(huì)引起page-fault異常(詳見(jiàn)4.7節(jié))。
PAE模式中的保留位有下面幾個(gè):
If the P flag (bit 0) of a PDE or a PTE is 1, bits 62:MAXPHYADDR are reserved.
If the P flag and the PS flag (bit 7) of a PDE are both 1, bits 20:13 are reserved.
If IA32_EFER.NXE = 0 and the P flag of a PDE or a PTE is 1, the XD flag (bit 63) is reserved
If the PAT is not supported:
— If the P flag of a PTE is 1, bit 7 is reserved.
— If the P flag and the PS flag of a PDE are both 1, bit 12 is reserved.
下圖是4K分頁(yè)的線性地址轉(zhuǎn)物理地址的過(guò)程示意圖。
下圖是2M分頁(yè)的線性地址轉(zhuǎn)物理地址的過(guò)程示意圖。
下圖是PDPTE、PDE-2M、PDE-4K、PTE各表項(xiàng)結(jié)構(gòu)的示意圖:
手冊(cè)中給出了PDE-2M、PDE、PTE結(jié)構(gòu)的詳細(xì)解釋,是下面三個(gè)表:
首先是PDE-2M表項(xiàng)結(jié)構(gòu)解析:Table 4-9. Format of a PAE Page-Directory Entry that Maps a 2-MByte Page
位 用途
0(P) Present,必須等于1,表示該項(xiàng)指向一個(gè)2M分頁(yè)
1(R/W) Read/Write,如果為0,不允許向2M的分頁(yè)寫(xiě)數(shù)據(jù)
2(U/S) User/supervisor,權(quán)限標(biāo)志位,等于0則3環(huán)程序不能訪問(wèn)2M的分頁(yè)
3(PWT) Page-level write-through,用來(lái)間接確定訪問(wèn)2M分頁(yè)所需要的內(nèi)存屬性
4(PCD) Page-level cache disable,用來(lái)間接確定訪問(wèn)2M分頁(yè)所需要的內(nèi)存屬性
5(A) Accessed,標(biāo)志這個(gè)2M分頁(yè)是否已經(jīng)被訪問(wèn)過(guò)
6(D) Dirty,標(biāo)志這個(gè)2M分頁(yè)是否已經(jīng)被寫(xiě)入過(guò)數(shù)據(jù)
7(PS) Page size,分頁(yè)大小標(biāo)志位,必須等于1(否則這項(xiàng)的意義變?yōu)橹赶?K分頁(yè)的頁(yè)表)
8(G) Gloabe,如果CR4.PGE等于1,該位用來(lái)確定這個(gè)頁(yè)是否是全局共享的頁(yè)
11:9 Ignored
12(PAT) 如果支持PAT,則用來(lái)間接確定訪問(wèn)2M分頁(yè)所需要的內(nèi)存屬性
20:13 Reserved,保留位,必須是0
(M-1):21 2M分頁(yè)的物理地址,36根物理線是35:21(15位),有的CPU有52根線的,是51:21
62:M Reserved,保留位,必須是0
63(XD) 如果 IA32_EFER.NXE標(biāo)志位等于1,則該頁(yè)中的數(shù)據(jù)不可執(zhí)行(從該頁(yè)中獲取指令將被禁止); IA32_EFER.NXE等于0,該位位保留位,必須填0
PDE表項(xiàng)結(jié)構(gòu)解析:Table 4-10. Format of a PAE Page-Directory Entry that References a Page Table
位 用途
0(P) Present,必須等于1,表示該項(xiàng)指向一個(gè)頁(yè)表
1(R/W) Read/Write,如果為0,不允許向其包含的1024個(gè)頁(yè)(共2M)寫(xiě)數(shù)據(jù)
2(U/S) User/supervisor,權(quán)限標(biāo)志位,等于0則3環(huán)程序不能訪問(wèn)其包含的1024個(gè)頁(yè)(共2M)
3(PWT) Page-level write-through,用來(lái)間接確定訪問(wèn)頁(yè)表所需要的內(nèi)存屬性
4(PCD) Page-level cache disable,用來(lái)間接確定訪問(wèn)頁(yè)表所需要的內(nèi)存屬性
5(A) Accessed,標(biāo)志這個(gè)表項(xiàng)已經(jīng)被訪問(wèn)了(被線性地址翻譯器訪問(wèn)了)
6(D) Ignored
7(PS) Page size,分頁(yè)大小標(biāo)志位,必須等于0
11:8 Ignored
(M-1):12 頁(yè)表的物理地址,36根物理線的CPU是25:12(24位),有的CPU有52根線的,是51:12(40位)
62:M Reserved,保留位,必須是0
63(XD) 如果 IA32_EFER.NXE標(biāo)志位等于1,則該項(xiàng)指向的頁(yè)表中的所有頁(yè)(1024個(gè)頁(yè))中的數(shù)據(jù)不可執(zhí)行; IA32_EFER.NXE等于0,該位位保留位,必須填0
PTE表項(xiàng)結(jié)構(gòu)解析:Table 4-11. Format of a PAE Page-Table Entry that Maps a 4-KByte Page
位 用途
0(P) Present,必須等于1,表示該項(xiàng)指向一個(gè)4K分頁(yè)
1(R/W) Read/Write,如果為0,不允許向4K的分頁(yè)寫(xiě)數(shù)據(jù)
2(U/S) User/supervisor,權(quán)限標(biāo)志位,等于0則3環(huán)程序不能訪問(wèn)4K的分頁(yè)
3(PWT) Page-level write-through,用來(lái)間接確定訪問(wèn)4K分頁(yè)所需要的內(nèi)存屬性
4(PCD) Page-level cache disable,用來(lái)間接確定訪問(wèn)4K分頁(yè)所需要的內(nèi)存屬性
5(A) Accessed,標(biāo)志這個(gè)4K分頁(yè)是否已經(jīng)被訪問(wèn)過(guò)
6(D) Dirty,標(biāo)志這個(gè)4K分頁(yè)是否已經(jīng)被寫(xiě)入過(guò)數(shù)據(jù)
7(PAT) 如果支持PAT,則用來(lái)間接確定訪問(wèn)4K分頁(yè)所需要的內(nèi)存屬性
8(G) Gloabe,如果CR4.PGE等于1,該位用來(lái)確定這個(gè)頁(yè)是否是全局共享的頁(yè)
11:9 Ignored
(M-1):12 4K分頁(yè)的物理地址,36根物理線的CPU是25:12(24位),有的CPU有52根線的,是51:12(40位)
62:M Reserved,保留位,必須是0
63(XD) 如果 IA32_EFER.NXE標(biāo)志位等于1,則該頁(yè)中的數(shù)據(jù)不可執(zhí)行(從該頁(yè)中獲取指令將被禁止); IA32_EFER.NXE等于0,該位位保留位,必須填0
實(shí)驗(yàn)題:實(shí)現(xiàn)頁(yè)表瀏覽工具
0. 查看源碼
github源碼
1. 環(huán)境設(shè)置
測(cè)試操作系統(tǒng):winxp sp3
開(kāi)發(fā)環(huán)境配置:
VS2015 實(shí)現(xiàn)MFC對(duì)話框工程
WDK 7.1.0開(kāi)發(fā)winxp驅(qū)動(dòng)
如何啟用PAE模式?
讀者可以檢索關(guān)鍵字“winxp pae”,會(huì)搜索到很多關(guān)于winxp系統(tǒng)啟用PAE模式的教程。
2. MFC瀏覽工具的代碼實(shí)現(xiàn)
工具的使用效果如下圖:
第一欄,顯示系統(tǒng)中的所有進(jìn)程,通過(guò)調(diào)用CreateToolhelp32Snapshot 實(shí)現(xiàn)遍歷進(jìn)程。
第二欄,展示頁(yè)目錄指針表的表項(xiàng)(PDPTE),選中上級(jí)目錄的某個(gè)進(jìn)程后,MFC程序調(diào)用驅(qū)動(dòng)程序接口,加載該進(jìn)程的PDPTE,最后展示有效表項(xiàng)。
第三欄,展示頁(yè)目錄表的表項(xiàng)(PDE),選中上級(jí)目錄的某個(gè)PDPTE表項(xiàng)后,與上述類似流程。
第四欄,展示頁(yè)表項(xiàng)(PTE),流程與上述類似。
關(guān)于加載進(jìn)程頁(yè)表速度慢的問(wèn)題:
對(duì)于PAE模式,進(jìn)程的頁(yè)表項(xiàng)數(shù)量總共有:4 PDPTE x 512 PDE x 512 PTE
在最初版本的工具設(shè)計(jì)中,使用3層循環(huán)來(lái)遍歷頁(yè)表項(xiàng),一次性加載某個(gè)進(jìn)程的所有頁(yè)表。但是出現(xiàn)加載速度慢的問(wèn)題。所以改進(jìn)了加載方式,變成根據(jù)索引加載一個(gè)PDPTE表項(xiàng)下的512項(xiàng)PDE,或者加載一個(gè)PDE表項(xiàng)下的512個(gè)PTE,這樣改進(jìn)之后,加載速度明顯改善。
代碼:定義保存頁(yè)表數(shù)據(jù)的結(jié)構(gòu)體
namespace PAEPaging
{
struct PDE_T
{
PDE val;
PTE PTEs[512];
BOOL LoadedFlag;
};
struct PDPTE_T
{
PDPTE val;
PDE_T PDEs[512];
BOOL LoadedFlag;
};
struct PDPTE_TT
{
ULONG cr3Val;
PDPTE_T PDPTEs[4];
};
}
代碼:調(diào)用驅(qū)動(dòng)接口,加載頁(yè)表的實(shí)現(xiàn)
BOOL COperateKernel::LoadPages(DWORD dwPID, __in DWORD dwPDPTEIdx, __in DWORD dwPDEIdx, PAEPaging::PDPTE_TT* tt)
{
...
if (DeviceIoControl(hFile, IOCTL_GET_PAGES_PAE, inBuff, sizeof(inBuff), outBuff, sizeof(outBuff),
&dwBytesRead, NULL))
{
DWORD dwOutBuffOffset = 0;
// 加載 PDPTE 表
if (dwPDPTEIdx == -1 && dwPDEIdx == -1)
{
for (int i = 0; i < 4; i++)
{
PAEPaging::PDPTE *pPDPTE = (PAEPaging::PDPTE*)((DWORD)outBuff + dwOutBuffOffset);
tt->PDPTEs[i].val = *pPDPTE;
dwOutBuffOffset += sizeof(PAEPaging::PDPTE);
}
}
// 加載 PDE 表
else if (dwPDPTEIdx != -1 && dwPDEIdx == -1)
{
for (int i = 0; i < 512; i++)
{
PAEPaging::PDE *pPDE = (PAEPaging::PDE*)((DWORD)outBuff + dwOutBuffOffset);
tt->PDPTEs[dwPDPTEIdx].PDEs[i].val.uint64 = pPDE->uint64;
dwOutBuffOffset += sizeof(PAEPaging::PDE);
}
}
// 加載 PTE 表
else if (dwPDPTEIdx != -1 && dwPDEIdx != -1)
{
for (int i = 0; i < 512; i++)
{
PAEPaging::PTE *pPTE = (PAEPaging::PTE*)((DWORD)outBuff + dwOutBuffOffset);
tt->PDPTEs[dwPDPTEIdx].PDEs[dwPDEIdx].PTEs[i] = *pPTE;
dwOutBuffOffset += sizeof(PAEPaging::PTE);
}
}
bRet = TRUE;
}
...
}
3. 驅(qū)動(dòng)代碼的實(shí)現(xiàn)
NTSTATUS GetProcessPages(PVOID pInBuff, PVOID pOutBuff, ULONG nOutLength, ULONG* nBytes)
{
...
// 加載 PDPTE 表
if (nPDPTEIdx == -1 && nPDEIdx == -1)
{
for (int i = 0; i < 4; i++)
{
ULONG64 paPDPTE = paCR3 + 8 * i;
ULONG64 PDPTE = GetQuadByPA(paPDPTE);
*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PDPTE;
nWriteOffset += sizeof(ULONG64);
}
}
// 加載 PDE 表
else if (nPDPTEIdx != -1 && nPDEIdx == -1)
{
ULONG64 paPDPTE = paCR3 + 8 * nPDPTEIdx;
ULONG64 PDPTE = GetQuadByPA(paPDPTE) & 0xFFFFFF000;
for (int i = 0; i < 512; i++)
{
ULONG64 paPDE = PDPTE + 8 * i;
ULONG64 PDE = GetQuadByPA(paPDE);
*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PDE;
nWriteOffset += sizeof(ULONG64);
}
}
// 加載 PTE 表
else if (nPDPTEIdx != -1 && nPDEIdx != -1)
{
ULONG64 paPDPTE = paCR3 + 8 * nPDPTEIdx;
ULONG64 PDPTE = GetQuadByPA(paPDPTE) & 0xFFFFFF000;
ULONG64 paPDE = PDPTE + 8 * nPDEIdx;
ULONG64 PDE = GetQuadByPA(paPDE) & 0xFFFFFF000;
for (int i = 0; i < 512; i++)
{
ULONG64 paPTE = PDE + 8 * i;
ULONG64 PTE = GetQuadByPA(paPTE);
*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PTE;
nWriteOffset += sizeof(ULONG64);
}
}
...
}
到此,相信大家對(duì)“如何使用PAE分頁(yè)模式”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!