記憶體定址(一)硬體定址的基本原理:硬體中的分段和分頁機制,控制暫存器CR0與CR3

誰不小心的發表於2013-10-18

摘要:本文講述8086怎樣進行晶片級別的記憶體定址,linux又是如何在這些硬體的基礎上進行定址的。本文主要討論硬體和linux定址的基本原理,後續將討論分頁機制的具體實現,核心如何給自己分配主存,怎樣給程式分配線性地址。


一、定址流程


邏輯地址經過分段單元形成線性地址,然後經過分頁單元形成實體地址。


二、硬體中的分段


1.段選擇符和段暫存器


32位的邏輯地址包含16位的段選擇符和36位的偏移量。處理器的段暫存器用於存放段選擇符。其中cs暫存器有一個重要功能:指明當前特權級。


2.段描述符


每個段由8位的段描述符表示,存放在GDT和LDT中,GDT和LDT在主存中的位置和大小存放在gdtr和ldtr暫存器中。


關於段選擇符和段描述符,可以參考:保護模式程式設計之(一)——分段機制與GDT/LDThttp://blog.csdn.net/trochiluses/article/details/8968750


快速訪問段描述符

每當一個段選擇符被裝入暫存器的時候,相應的段描述符號就從記憶體裝入相應的非程式設計CPU暫存器,從此,邏輯地址的轉換不經過主存中的GDT或者LDT而是直接應用相關CPU暫存器即可。只有暫存器內容發生改變,才會訪問GDT或者LDT。


3.分段單元


邏輯地址的轉換過程如下:



三、硬體中的分頁


i386 CPU實現記憶體管理的基本思路是通過頁目錄和頁表兩極對映實現從線性地址到實體地址的轉換。原因:4GB的線性地址空間,如果我們採用一級對映,頁大小是4K,那麼需要的頁表項數量為4G/4K=1M;另外,一個頁表項的大小是8B,如此一個程式的頁表需要的儲存空間位8M。實際情況下,可能線性地址空間僅僅某一部分有效(例如0x00000000~0x0000ffff),此時如果採用二級頁表,可以避免一些無用線性地址的對映(如果相應的線性地址無效,那麼對應的頁目錄項設定為空)。


其中暫存器cr3用於存放當前程式正在使用的頁目錄基地址。dir用於指明目錄項,table用於指明表項,offset用於指明頁內偏移。8086處理器分頁原理如下圖:


頁目錄項和頁表項有同樣的結構;

它們都有4B共32b,具體佈局如下:



其中每個位的作用如下:

P--位0是存在(Present)標誌,用於指明表項對地址轉換是否有效。P=1表示有效;P=0表示無效。在頁轉換過程中,如果說涉及的頁目錄或頁表的表項無效,則會導致一個異常。如果P=0,那麼除表示表項無效外,其餘位可供程式自由使用,如圖4-18b所示。例如,作業系統可以使用這些位來儲存已儲存在磁碟上的頁面的序號。

R/W--位1是讀/寫(Read/Write)標誌。如果等於1,表示頁面可以被讀、寫或執行。如果為0,表示頁面只讀或可執行。當處理器執行在超級使用者特權級(級別0、1或2)時,則R/W位不起作用。頁目錄項中的R/W位對其所對映的所有頁面起作用。

U/S--位2是使用者/超級使用者(User/Supervisor)標誌。如果為1,那麼執行在任何特權級上的程式都可以訪問該頁面。如果為0,那麼頁面只能被執行在超級使用者特權級(0、1或2)上的程式訪問。頁目錄項中的U/S位對其所對映的所有頁面起作用。

A--位5是已訪問(Accessed)標誌。當處理器訪問頁表項對映的頁面時,頁表表項的這個標誌就會被置為1。當處理器訪問頁目錄表項對映的任何頁面時,頁目錄表項的這個標誌就會被置為1。處理器只負責設定該標誌,作業系統可通過定期地復位該標誌來統計頁面的使用情況。

D--位6是頁面已被修改(Dirty)標誌。當處理器對一個頁面執行寫操作時,就會設定對應頁表表項的D標誌。處理器並不會修改頁目錄項中的D標誌。

AVL--該欄位保留專供程式使用。處理器不會修改這幾位,以後的升級處理器也不會。

PAGE SIZE只用於頁目錄項,如果為1表示啟用大頁,2M或者4M


3.2擴充套件 分頁

從pentium開始,8086處理器引入了擴充套件分頁模式,它允許頁框大小是4M而非4K,它用於把大段連續的實體地址轉換成相應的實體地址。在這種情況下,核心不使用中間頁表進行地址轉換,進而節省記憶體並保留TLB項。擴充套件分頁機理如下:

擴充套件分頁的頁目錄項和普通分頁基本相同,除了:

1)page size位必須被設定
2)20位實體地址欄位只有高10位是有意義的
通過設定cr4處理器暫存器的PSE標誌能使得擴充分頁和常規分頁共存。

3.3物理 地址擴充套件(PAE)分頁機制

intel通過實體地址擴充套件機制,利用32位的線性地址可以定址36b的實體地址空間(不是同時可訪問的)。PAE的具體原理可以參考這裡http://blog.csdn.net/trochiluses/article/details/12853027


3.4 64位系統中的分頁

首先,32位下的分頁機制不再適用。因為如果仍然是4K頁,我們用48位線性地址來進行定址,那麼剩下48-12=52位,如果我們用其中的48位建立二級分頁機制,那麼每個程式的頁目錄項和頁表項將含有2^18,太大了。

X86_64下,頁大小是4K,定址位數是48,分頁級別是4,地址劃分:9+9+9+9+12

3.5硬體快取記憶體

處理器的cr0暫存器用於啟用或者禁用硬體快取記憶體,cr0中的nw標誌表明是通寫還是寫回策略。


3.6TLB

TLB相當於頁表的cache,每個cpu都有自己的TLB,與cache不同,TLB中的對應項不用同步,但是cpu的cr3暫存器發生修改的時候,表明當前執行程式發生了變化,此時要使得TLB所有專案無效。

四、控制暫存器CR0與CR3

控制暫存器(CR0~CR3)用於控制和確定處理器的操作模式以及當前執行任務的特性,CR0中含有控制處理器操作模式和狀態的系統控制標誌;CR1保留不用;CR2含有導致頁錯誤的線性地址;CR3中含有頁目錄表實體記憶體基地址,因此該暫存器也被稱為頁目錄基地址暫存器PDBR(Page-Directory Base address Register)。

4.1CR0中的保護控制位:

(1)PE:CR0的位0是啟用保護(Protection Enable)標誌。當設定該位時即開啟了保護模式;當復位時即進入實地址模式。這個標誌僅開啟段級保護,而並沒有啟用分頁機制。若要啟用分頁機制,那麼PE和PG標誌都要置位。
(2)PG:CR0的位31是分頁(Paging)標誌。當設定該位時即開啟了分頁機制;當復位時則禁止分頁機制,此時所有線性地址等同於實體地址。在開啟這個標誌之前必須已經或者同時開啟PE標誌。即若要啟用分頁機制,那麼PE和PG標誌都要置位。
(3)WP:對於Intel 80486或以上的CPU,CR0的位16是防寫(Write Proctect)標誌。當設定該標誌時,處理器會禁止超級使用者程式(例如特權級0的程式)向使用者級只讀頁面執行寫操作;當該位復位時則反之。該標誌有利於UNIX類作業系統在建立程式時實現寫時複製(Copy on Write)技術。
當改變PE和PG位時,必須小心。只有當執行程式至少有部分程式碼和資料線上性地址空間和實體地址空間中具有相同地址時,我們才能改變PG位的設定此時這部分具有相同地址的程式碼在分頁和未分頁世界之間起著橋樑的作用。無論是否開啟分頁機制,這部分程式碼都具有相同的地址。另外,在開啟分頁(PG=1)之前必須先重新整理頁高速緩衝TLB。
在修改該了PE位之後程式必須立刻使用一條跳轉指令,以重新整理處理器執行管道中已經獲取的不同模式下的任何指令。在設定PE位之前,程式必須初始化幾個系統段和控制暫存器。在系統剛上電時,處理器被複位成PE=0和PG=0(即真實模式狀態),以允許引導程式碼在啟用分段和分頁機制之前能夠初始化這些暫存器和資料結構。
4.2CR2和CR3

CR2和CR3用於分頁機制。CR3含有存放頁目錄表頁面的實體地址(注意,是實體地址!!!),因此CR3也被稱為PDBR。因為頁目錄表頁面是頁對齊的,所以該暫存器只有高20位是有效的。而低12位保留供更高階處理器使用,因此在往CR3中載入一個新值時低12位必須設定為0。
使用MOV指令載入CR3時具有讓頁高速緩衝無效的副作用。為了減少地址轉換所要求的匯流排週期數量,最近訪問的頁目錄和頁表會被存放在處理器的頁高速緩衝器件中,該緩衝器件被稱為轉換查詢緩衝區(Translation Lookaside Buffer,TLB)。只有當TLB中不包含要求的頁表項時才會使用額外的匯流排週期從記憶體中讀取頁表項。
即使CR0中的PG位處於復位狀態(PG=0),我們也能先載入CR3。以允許對分頁機制進行初始化。當切換任務時,CR3的內容也會隨之改變。但是如果新任務的CR3值與原任務的一樣,處理器就無需重新整理頁高速緩衝。這樣共享頁表的任務可以執行得更快。
CR2用於出現頁異常時報告出錯資訊。在報告頁異常時,處理器會把引起異常的線性地址存放在CR2中。因此作業系統中的頁異常處理程式可以通過檢查CR2的內容來確定線性地址空間中哪一個頁面引發了異常。

相關文章