MMU與CACHE詳解_第1頁
MMU與CACHE詳解_第2頁
MMU與CACHE詳解_第3頁
MMU與CACHE詳解_第4頁
MMU與CACHE詳解_第5頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、ARM920T的MMU與Cache目錄    虛擬地址和物理地址的概念     虛擬內(nèi)存管理     ARM920T的CP15協(xié)處理器      MMU      Cache      操作MMU和Cache的內(nèi)核啟動(dòng)代碼      參考資料 索引虛擬地址和物理地址的概念    CPU通過

2、地址來訪問內(nèi)存中的單元,地址有虛擬地址和物理地址之分,如果CPU沒有MMU(Memory Management Unit,內(nèi)存管理單元),或者有MMU但沒有啟用,CPU核在取指令或訪問內(nèi)存時(shí)發(fā)出的地址將直接傳到CPU芯片的外部地址引腳上,直接被內(nèi)存芯片(以下稱為物理內(nèi)存,以便與虛擬內(nèi)存區(qū)分)接收,這稱為物理地址(Physical Address,以下簡稱PA),如下圖所示。圖 1. 物理地址示意圖     如果CPU啟用了MMU,CPU核發(fā)出的地址將被MMU截獲,從CPU到MMU的地址稱為虛擬地址(Virtual Address,以下簡稱VA),而MMU

3、將這個(gè)地址翻譯成另一個(gè)地址發(fā)到CPU芯片的外部地址引腳上,也就是將虛擬地址映射成物理地址,如下圖所示1。圖 2. 虛擬地址示意圖     MMU將虛擬地址映射到物理地址是以頁(Page)為單位的,對(duì)于32位CPU通常一頁為4K。例如,虛擬地址0xb700 10000xb700 1fff是一個(gè)頁,可能被MMU映射到物理地址0x20000x2fff,物理內(nèi)存中的一個(gè)物理頁面也稱為一個(gè)頁框(Page Frame)。虛擬內(nèi)存管理現(xiàn)代操作系統(tǒng)充分利用MMU提供的VA到PA的映射機(jī)制來做內(nèi)存管理,以下稱為虛擬內(nèi)存管理(Virtual Memory Managemen

4、t)。首先看下面的例子:   例 1. 進(jìn)程的地址空間   這是bash進(jìn)程的虛擬地址空間,32位CPU的虛擬地址空間是4GB,也就是0x0000 0000-0xffff ffff,該進(jìn)程占用的地址范圍近似為0x0000 0000-0xbfff ffff,地址范圍0xc000 0000-0xffff ffff由內(nèi)核占用,用戶進(jìn)程不允許訪問。在這個(gè)bash進(jìn)程的地址空間中,從0x0804 8000開始的668K的權(quán)限為r-x-,表示代碼段,從0x080e f000開始的24K的權(quán)限是rw-,表示數(shù)據(jù)段,從0x080f 5000開始的2056K的權(quán)限也是rw

5、-,但是沒有對(duì)應(yīng)任何磁盤文件,而是用 anon (anonymous,匿名)來表示,這是堆所占的空間,從0xb7c6 d000開始是共享庫和資源文件的映射空間,每個(gè)共享庫也分為代碼段和數(shù)據(jù)段,用不同的權(quán)限表示,可以看到,從堆空間到下面的共享庫映射空間之間有很大的地址空洞,最末從0xbfad 4000開始的84K是??臻g。   為什么需要虛擬內(nèi)存管理呢?可以從以下幾個(gè)方面來理解。   第一,讓每個(gè)進(jìn)程有獨(dú)立的地址空間是引入虛擬內(nèi)存管理的最主要目的。所謂獨(dú)立的地址空間是指,不同進(jìn)程中的同一個(gè)VA被MMU映射到不同的PA,并且在某一個(gè)進(jìn)程中訪問任何地址都不可能

6、訪問到另外一個(gè)進(jìn)程的數(shù)據(jù),這樣使得任何一個(gè)進(jìn)程由于程序BUG或惡意代碼所導(dǎo)致的非法內(nèi)存訪問都不會(huì)意外改寫其它進(jìn)程的數(shù)據(jù),不會(huì)影響其它進(jìn)程的運(yùn)行,從而保證了整個(gè)系統(tǒng)的穩(wěn)定性。另一方面,每個(gè)進(jìn)程都認(rèn)為自己獨(dú)占4GB的地址空間,編寫程序會(huì)比較方便,不必為每個(gè)進(jìn)程分配一個(gè)地址范圍,而是每個(gè)進(jìn)程都可以使用一個(gè)完整的地址空間中的任何地址。   我們繼續(xù)用上面的例子來理解,再打開一個(gè)shell窗口,用pmap命令看一下這個(gè)新的bash進(jìn)程的地址空間,可以發(fā)現(xiàn)和剛才的地址空間布局差不多:   該進(jìn)程也占用了0x0000 0000-0xbfff ffff的地址空間,代碼段

7、也是從0x0804 8000開始的668K,數(shù)據(jù)段也是從0x080e f000開始的24K,共享庫的內(nèi)存布局也差不多。這個(gè)進(jìn)程和剛才的例子是同一個(gè)系統(tǒng)中同時(shí)運(yùn)行著的兩個(gè)進(jìn)程,它們都認(rèn)為自己占有0x0000 0000-0xbfff ffff的地址空間,并且它們的數(shù)據(jù)段的地址范圍是重合的,但是兩個(gè)進(jìn)程各自干各自的事情,顯然數(shù)據(jù)段中的數(shù)據(jù)是不同的,正是因?yàn)椴煌M(jìn)程中的同一個(gè)VA被映射到了不同的PA,所以兩個(gè)進(jìn)程的數(shù)據(jù)段其實(shí)是在不同的物理地址上,如下圖所示。圖 4. 進(jìn)程地址空間是獨(dú)立的    從圖中還可以看到,兩個(gè)進(jìn)程都是bash進(jìn)程,代碼段是一樣的,并且代碼段是只讀的

8、,不會(huì)被改寫,因此操作系統(tǒng)會(huì)安排兩個(gè)進(jìn)程的代碼段共享相同的物理內(nèi)存。由于每個(gè)進(jìn)程都有自己的一套VA到PA的映射表,整個(gè)地址空間中的任何VA都在每個(gè)進(jìn)程自己的映射表中查找相應(yīng)的物理地址,因此不可能訪問到其它進(jìn)程的地址,也就沒有可能意外改寫其它進(jìn)程的數(shù)據(jù)。    第二,引入VA到PA的映射也會(huì)給分配和釋放內(nèi)存帶來方便,物理上不連續(xù)的空間可以映射為邏輯上連續(xù)的虛擬地址空間。比如要malloc一塊很大的內(nèi)存空間,而物理內(nèi)存雖然有足夠的空閑內(nèi)存,卻沒有足夠大的連續(xù)空閑內(nèi)存,這時(shí)就可以分配多個(gè)不連續(xù)的物理頁面,而映射為連續(xù)的虛擬地址范圍。如下圖所示。圖 5. 不連續(xù)的PA可以

9、映射為連續(xù)的VA    第三,一個(gè)系統(tǒng)如果同時(shí)運(yùn)行著很多進(jìn)程,為各進(jìn)程分配的內(nèi)存之和可能會(huì)大于實(shí)際可用的物理內(nèi)存,虛擬內(nèi)存管理使得這種情況下各進(jìn)程仍然能夠正常運(yùn)行。因?yàn)楦鬟M(jìn)程分配的只不過是虛擬內(nèi)存的頁,這個(gè)頁的內(nèi)容可以映射到物理內(nèi)存的頁框,也可以臨時(shí)保存到磁盤上而不占用物理內(nèi)存的頁框,磁盤上這一部分稱為交換設(shè)備(Swap Device),可能是一個(gè)磁盤分區(qū),也可能是一個(gè)磁盤文件。當(dāng)物理內(nèi)存不夠時(shí)將物理內(nèi)存中不常用的頁框臨時(shí)保存到磁盤上,而當(dāng)用到這些頁框時(shí)再從磁盤加載回內(nèi)存,這稱為換頁(Paging)因此:     系統(tǒng)中可分配的內(nèi)存總

10、量 = 物理內(nèi)存的大小 + 交換設(shè)備的大小    如下圖所示。第一張圖是換出(Page out),將物理頁面的內(nèi)容保存到磁盤,并解除地址映射,釋放物理頁面。第二張圖是換入(Page in),從空閑的物理頁面中分配一個(gè),將磁盤暫存的頁面加載回內(nèi)存,并建立地址映射。圖 6. 換頁    第四,虛擬內(nèi)存管理可以控制物理頁面的訪問權(quán)限。物理內(nèi)存本身是不限制訪問的,任何地址都可以讀寫,而操作系統(tǒng)要求實(shí)現(xiàn)各種不同的訪問權(quán)限,在先前的例子中我們已經(jīng)看到,代碼段要求是rx的,數(shù)據(jù)段要求是rw的,用戶進(jìn)程不能訪問屬于內(nèi)核的地址空間,這些都是操作系統(tǒng)和M

11、MU配合實(shí)現(xiàn)的。    MMU中還實(shí)現(xiàn)了一種訪問限制是關(guān)于Cache的。Cache(高速緩存)是CPU內(nèi)的一小塊高速RAM,用來緩存最近訪問過的內(nèi)存數(shù)據(jù),CPU訪問Cache的速度是訪問內(nèi)存速度的數(shù)十倍,所以有效地利用Cache可以大大提高計(jì)算機(jī)的整體性能。CPU核要訪問數(shù)據(jù)時(shí)首先發(fā)出VA,Cache利用VA查找相應(yīng)的數(shù)據(jù)有沒有被緩存2,如果有就通知CPU核,如果是讀操作就直接將Cache中的數(shù)據(jù)傳給CPU核中的寄存器,如果是寫操作就直接改寫Cache中的數(shù)據(jù),而不需要訪問物理內(nèi)存。但是,有些VA所對(duì)應(yīng)的PA并不是物理內(nèi)存中的地址而是設(shè)備寄存器的地址,對(duì)這些寄存器

12、進(jìn)行讀寫并不是為了保存數(shù)據(jù),而是對(duì)設(shè)備做特殊操作,這種VA通常是不允許緩存的,因?yàn)槿绻彺媪?,?duì)VA的讀寫將只在Cache中起作用,而不會(huì)傳到設(shè)備寄存器對(duì)設(shè)備進(jìn)行操作。以串口的收發(fā)寄存器為例,如果收發(fā)寄存器地址被緩存了會(huì)出現(xiàn)什么問題呢?如下圖所示。    如果發(fā)送寄存器的地址被緩存起來,CPU核往發(fā)送寄存器的地址做寫操作都寫到Cache中去了,發(fā)送寄存器并沒有及時(shí)得到數(shù)據(jù),也就不能及時(shí)發(fā)送,此外,CPU核先后發(fā)出的1、2、3三個(gè)數(shù)據(jù)都會(huì)寫到Cache中的同一個(gè)地址,最后Cache中只保存了第3個(gè)數(shù)據(jù),如果這時(shí)Cache的數(shù)據(jù)寫回到發(fā)送寄存器去,只能把第3個(gè)數(shù)據(jù)發(fā)送

13、出去,前兩個(gè)數(shù)據(jù)就丟失了。與此類似,如果接收寄存器的地址被緩存起來,CPU核在讀第1個(gè)數(shù)據(jù)時(shí),Cache會(huì)從接收寄存器讀進(jìn)來緩存,然而接收寄存器后面收到2、3兩個(gè)數(shù)據(jù)Cache并不知道,因?yàn)镃ache把接收寄存器當(dāng)作內(nèi)存,并且相信內(nèi)存中的數(shù)據(jù)是不會(huì)自己變的,所以以后每次CPU核讀接收寄存器時(shí),Cache都提供給CPU核第1個(gè)數(shù)據(jù)。ARM920T的CP15協(xié)處理器    ARM920T的MMU和Cache都集成在CP15協(xié)處理器中,MMU和Cache的聯(lián)系非常密切,本節(jié)首先從總體上介紹MMU、Cache和CPU核是如何協(xié)同工作的,后面兩節(jié)分別講解MMU和Cache的

14、細(xì)節(jié)。三星公司的S3C2410是一種很常見的采用ARM920T的芯片,涉及到具體的芯片時(shí)我們以S3C2410為例。   以下是CP15協(xié)處理器的寄存器列表(摘自S3C2410用戶手冊(cè)),和CPU核的r0到r15寄存器一樣,協(xié)處理器寄存器也是用0到15來編號(hào),在指令中用4個(gè)bit來表示寄存器編號(hào),有些協(xié)處理器寄存器有影子寄存器,這種情況下對(duì)同一個(gè)編號(hào)的寄存器使用不同的選項(xiàng)讀或者寫實(shí)際上訪問的是不同的寄存器,后文用到某個(gè)寄存器時(shí)會(huì)詳細(xì)說明它的功能。表 1. CP15協(xié)處理器的寄存器列表    對(duì)CP15協(xié)處理器的操作使用mcr和mrc兩條

15、協(xié)處理器指令,這兩條指令的記法是從后往前看:mcr是把r(CPU核寄存器)中的數(shù)據(jù)傳送到c(協(xié)處理器寄存器)中,mrc則是把c(協(xié)處理器寄存器)中的數(shù)據(jù)傳送到r(CPU核寄存器)中。對(duì)CP15協(xié)處理器的所有操作都是通過CPU核寄存器和CP15寄存器之間交換數(shù)據(jù)來完成的。下圖是協(xié)處理器的指令格式(摘自S3C2410用戶手冊(cè))。圖 8. 協(xié)處理器指令格式    和其它ARM指令一樣,Cond是條件碼,bit 20是L位,表示該指令是讀還是寫,如果L=1就表示Load,從外面讀到CPU核中,也就是mrc指令,如果L=0就表示Store,也就是mcr指令。11:8這四個(gè)位

16、是協(xié)處理器編號(hào),CP15的編號(hào)是15,因此是4個(gè)1。CRn是CP15寄存器編號(hào),Rd是CPU核寄存器編號(hào),各占4個(gè)位。對(duì)于CP15協(xié)處理器,規(guī)定opcode1應(yīng)該為0,opcode2和CRm是指令的選項(xiàng),具體含義取決于不同的寄存器。    雖然這里介紹了協(xié)處理器的寄存器編號(hào)和相關(guān)指令,但讀者只需了解對(duì)協(xié)處理器是這樣進(jìn)行操作的就可以了,我們的重點(diǎn)是講解MMU和Cache的基本概念,具體各種操作的指令該怎么寫可以參考S3C2410用戶手冊(cè)。   MMU是如何把VA映射成PA的呢?從圖 4 “進(jìn)程地址空間是獨(dú)立的”來看,好像是有一張VA轉(zhuǎn)PA的表,給

17、一個(gè)VA查表就可以查到PA,實(shí)際上并不是這么簡單,通常要有一個(gè)多級(jí)的查表過程,對(duì)于ARM體系結(jié)構(gòu)是兩級(jí)查表,對(duì)于一些64位體系結(jié)構(gòu)則需要更多級(jí)??聪旅娴膱D示。圖 9. Translation Table Walk    首先將32位的VA3分成三段,前兩段31:20和19:12作為兩次查表的索引,第三段11:0作為頁內(nèi)的偏移。查表的步驟如下:    1 CP15協(xié)處理器的TTB寄存器(看看表 1 “CP15協(xié)處理器的寄存器列表”中這是第幾個(gè)寄存器?C2)中保存著第一級(jí)頁表(Translation Table)的基地址,這個(gè)基地址指的是

18、PA,也就是說頁表是直接按這個(gè)地址存在物理內(nèi)存中的。    2 以TTB中的內(nèi)容為基地址,以VA31:20為索引在表中查出一項(xiàng)(想一下這個(gè)表中一共有多少項(xiàng)?4096項(xiàng)),這個(gè)表項(xiàng)中保存著第二級(jí)頁表(Coarse Page Table)的基地址,同樣是物理地址,也就是說第二級(jí)頁表也是直接按這個(gè)地址存在物理內(nèi)存中的。    3 以VA19:12為索引在第二級(jí)頁表中查出一項(xiàng)(想一下這個(gè)表中一共有多少項(xiàng)?256項(xiàng)),這個(gè)表項(xiàng)中就保存著物理頁面的基地址,先前我們說虛擬內(nèi)存管理是以頁為單位的,一個(gè)虛擬內(nèi)存的頁映射到一個(gè)物理內(nèi)存的頁框,從這里就可以

19、得到印證,因?yàn)椴楸硎且皂摓閱挝粊聿榈摹?#160;   4 有了物理頁面的基地址之后(兩級(jí)總共4096+4096*256=4K+1M個(gè)表項(xiàng)?),加上VA11:0這個(gè)偏移量就可以取出相應(yīng)地址上的數(shù)據(jù)(想一下一個(gè)頁是多少字節(jié)?4K)。   這個(gè)過程稱為Translation Table Walk,Walk這個(gè)詞用得非常形象。從TTB走到一級(jí)頁表,又走到二級(jí)頁表,又走到物理頁面,一次尋址其實(shí)是三次訪問物理內(nèi)存。注意這個(gè)“走”的過程完全是硬件做的,每次CPU尋址時(shí)MMU就自動(dòng)完成以上四步,不需要編寫指令指示MMU去做,前提是操作系統(tǒng)要維護(hù)頁表項(xiàng)的正確性,每次分配

20、內(nèi)存時(shí)填寫相應(yīng)的頁表項(xiàng),每次釋放內(nèi)存時(shí)清除相應(yīng)的頁表項(xiàng),在必要的時(shí)候分配或釋放整個(gè)頁表。    有了以上基本概念,我們來看CPU訪問內(nèi)存時(shí)的硬件操作順序(摘自ARM參考手冊(cè))。圖 10. CPU訪問內(nèi)存時(shí)的硬件操作順序    我們以CPU讀內(nèi)存為例解釋一下圖中的步驟,各步驟在圖中有對(duì)應(yīng)的標(biāo)號(hào)。    1 CPU核(圖中的“ARM”框)發(fā)出VA請(qǐng)求讀數(shù)據(jù),TLB(Translation Lookaside Buffer)接收到該地址。TLB是MMU中的一塊高速緩存(也是一種Cache),它緩存最近查找過的V

21、A對(duì)應(yīng)的頁表項(xiàng),如果TLB里緩存了當(dāng)前VA的頁表項(xiàng)就不必做Translation Table Walk了,否則去物理內(nèi)存中讀出頁表項(xiàng)保存在TLB中,TLB緩存可以減少訪問物理內(nèi)存的次數(shù)。   2 頁表項(xiàng)中不僅保存著物理頁面的基地址,還保存著權(quán)限位和是否允許Cache的標(biāo)志。MMU首先檢查權(quán)限位,如果沒有訪問權(quán)限,就引發(fā)一個(gè)異常給CPU核。然后檢查是否允許Cache,如果允許Cache就啟用Cache和CPU核互操作,圖中的“C, B bits”可以理解為直寫和回寫線,后面再詳細(xì)解釋這兩個(gè)位的作用。   3 如果不允許Cache,則直接發(fā)出PA從物理內(nèi)存中

22、讀取數(shù)據(jù)到CPU核。   4 如果允許Cache,則以VA為索引到Cache中查找是否緩存了要讀取的數(shù)據(jù),如果Cache中已經(jīng)緩存了該數(shù)據(jù)(稱為Cache Hit)則直接返回給CPU核,如果Cache中沒有緩存該數(shù)據(jù)(稱為Cache Miss),則發(fā)出PA從物理內(nèi)存中讀取數(shù)據(jù)并緩存到Cache中,同時(shí)返回給CPU核。然而Cache并不是只取CPU核所要的數(shù)據(jù),而是把相鄰的數(shù)據(jù)都取上來緩存,這稱為一個(gè)Cache Line。ARM920T的Cache Line是32字節(jié),例如CPU核要讀取地址0x134-0x137的4字節(jié)數(shù)據(jù),Cache會(huì)把地址0x120-0x13f

23、(對(duì)齊到32字節(jié)地址邊界)的32字節(jié)都取上來緩存。    MMU     我們已經(jīng)簡單了解了一下查頁表的過程,實(shí)際上ARM920T支持多種尺寸規(guī)格的頁表,圖 9 “Translation Table Walk”所示的只是其中一種情況。下圖示意了所有可能的情況(本節(jié)的圖表均摘自S3C2410用戶手冊(cè))。 圖 11. 查頁表的過程     回顧一下查表的過程,首先從CP15的TTB寄存器找到一級(jí)頁表的基地址,再把VA31:20(共4096項(xiàng))作為索引從表中找出一項(xiàng),這個(gè)表項(xiàng)稱為一級(jí)頁描述符(Level 1 D

24、escriptor),一個(gè)這樣的表項(xiàng)占4個(gè)字節(jié),可以是以下四種格式之一: 圖 12. 一級(jí)頁描述符   如果描述符的最低兩位是00,屬于Fault格式,表示該范圍的VA沒有映射到PA。如果描述符的最低兩位是10,屬于Section格式,這種格式?jīng)]有二級(jí)頁表而是直接映射到物理頁面,一個(gè)Section是1M的大頁面,描述符中31:20位就是這個(gè)頁面的基地址,基地址的19:0低位全為0,對(duì)齊到1M地址邊界,描述符中的Domain和AP位控制訪問權(quán)限,C、B兩位控制緩存,后面再詳細(xì)解釋每個(gè)位的含義。如果描述符的最低兩位是01或11,則分別對(duì)應(yīng)兩種不同規(guī)格的二級(jí)頁表(VA19:12則

25、為256項(xiàng))。根據(jù)地址對(duì)齊的規(guī)律想一下,這兩種頁表分別是多大?從一級(jí)描述符中取出二級(jí)頁表的基地址,再把VA的一部分作為索引去查二級(jí)描述符(Level 2 Descriptor)(如果是Coarse Page Table則VA19:12是索引,如果是Fine Page Table則VA19:10是索引),二級(jí)描述符可以是以下四種格式之一:圖 13. 二級(jí)頁描述符    描述符最低兩位是00屬于Fault格式,其它三種情況分別對(duì)應(yīng)三種不同規(guī)格的物理頁面。Large Page和Small Page有四組AP權(quán)限位,每組兩個(gè)bit,這樣可以為每1/4個(gè)物理頁面分別設(shè)置不同

26、的權(quán)限,也就是說,Large Page可以為每16K設(shè)置不同的權(quán)限,Small Page可以為每1K設(shè)置不同的權(quán)限。    ARM920T提供了多種頁表和頁面規(guī)格,但操作系統(tǒng)只采用其中一種,Linux采用的就是圖 9 “Translation Table Walk”所示的規(guī)格,一級(jí)描述符是Coarse Page Table格式,二級(jí)描述符是Small Page格式,每個(gè)物理頁面4K。我們以此為例,結(jié)合前面的的解釋和頁描述符的格式,再看一下Translation Table Walk的詳細(xì)過程:圖 14. Translation Table Walk的詳細(xì)過程

27、60;   從上到下依次解釋如下:    1 VA被劃分為三段用于地址映射過程,各段的長度取決于頁描述符的格式。    2 TTB寄存器中只有31:14位有效,低14位全為0,因此一級(jí)頁表的基地址對(duì)齊到16K地址邊界,而一級(jí)頁表的大小也是16K。    3 一級(jí)頁表的基地址加上VA31:20左移兩位組裝成一個(gè)物理地址。想一想為什么VA31:20要左移兩位占據(jù)13:2的位置,而空出1:0兩位呢?類型?   4 用這個(gè)組裝的物理地址從物理內(nèi)存中讀取一級(jí)頁描述符,這是一個(gè)

28、Coarse Page Table格式的描述符。   5 通過Domain權(quán)限檢查后,Coarse Page Table的基地址再加上VA19:12左移兩位組裝成一個(gè)物理地址。   6 用這個(gè)組裝的物理地址從物理內(nèi)存中讀取二級(jí)頁描述符,這是一個(gè)Small Page格式的描述符。   7 通過AP權(quán)限檢查后,Small Page的基地址再加上VA11:0就是最終的物理地址。想一想為什么這次不左移兩位了呢?   下面解釋一下Domain和AP位。CP15的Domain訪問控制寄存器(見表 1 “CP15協(xié)處理器的寄存器

29、列表”寄存器3)表示了16個(gè)域(Domain),每兩位表示一個(gè)Domain的訪問權(quán)限,以下是該寄存器的格式:   圖 15. Domain Access Control Register   每個(gè)Domain的兩個(gè)位可以取值為00、01、10或11,如果取值為00或10則表示該Domain不可訪問,如果取值為01則表示訪問該Domain需要進(jìn)一步檢查AP位,如果取值為11則表示可以直接訪問該Domain而無需檢查AP位?;叵胍幌拢患?jí)頁描述符中的Domain字段由4個(gè)位組成,可以有16個(gè)不同的取值,就表示該描述符所描述的二級(jí)頁表或Section屬于這16

30、個(gè)Domain中的哪一個(gè)??焖偕舷挛那袚Q、Domain和多種規(guī)格的頁表是ARM特有的機(jī)制,是針對(duì)嵌入式系統(tǒng)軟件的特點(diǎn)而設(shè)計(jì)的,其它處理器不一定有類似的機(jī)制,例如也許沒有Domain和快速上下文切換的概念,也許只有一種規(guī)格的頁表。為了能夠在多種不同的平臺(tái)上移植,Linux內(nèi)核代碼不會(huì)利用ARM特有的這些機(jī)制。除了這些特例之外,我們?cè)谶@里介紹的其它機(jī)制都具有普遍性,讀者應(yīng)重點(diǎn)把握具有普遍意義的基本原理和基本概念。   CP15的控制寄存器(見表 1 “CP15協(xié)處理器的寄存器列表”寄存器1)中的S和R位與頁描述符的AP位合在一起決定訪問權(quán)限,如下所示:圖 16. AP權(quán)限檢查&

31、#160;   可見,同樣的AP、S、R位對(duì)用戶模式和特權(quán)模式來說具有不同的意義,特權(quán)模式的權(quán)限都不低于用戶模式的權(quán)限。最后將各種由內(nèi)存訪問產(chǎn)生的異常總結(jié)如下:    Alignment Fault以Word為單位的數(shù)據(jù)訪問指令地址未對(duì)齊到4字節(jié)邊界,或者以Half Word為單位的數(shù)據(jù)訪問指令地址未對(duì)齊到2字節(jié)邊界。    Translation Fault頁描述符的1:0為00,屬于Fault格式,無效表項(xiàng)。    Domain Fault一級(jí)頁描述符或Section所屬Domai

32、n的權(quán)限位為00或10。   Permission Fault根據(jù)AP位和CP15寄存器1的S、R位檢查訪問權(quán)限,若所屬Domain的權(quán)限位為11則跳過這一步檢查。    External Abort總線異常,例如此物理地址上沒有掛RAM芯片,或者其它硬件故障。Cache ARM920T有16K的數(shù)據(jù)Cache和16K的指令Cache,這兩個(gè)Cache是基本相同的,數(shù)據(jù)Cache多了一些寫回內(nèi)存的機(jī)制,后面我們以數(shù)據(jù)Cache為例來介紹Cache的基本原理。我們已經(jīng)知道,Cache中的存儲(chǔ)單位是Cache Line,ARM920T的一個(gè)Cach

33、e Line是32字節(jié),因此16K的Cache由512條Cache Line組成。要了解Cache的基本原理,我們從如何設(shè)計(jì)Cache這個(gè)問題入手。   設(shè)計(jì)Cache的一種最樸素的想法是,把VA分成以32字節(jié)為單位,從任何一個(gè)對(duì)齊到32字節(jié)地址邊界的VA開始連續(xù)的32個(gè)字節(jié)(比如0x00-0x1f,0x20-0x3f,0x40-0x5f等等)都可以緩存到512條Cache Line中的任何一條。那么一條Cache Line中的32個(gè)字節(jié)怎么知道是來自哪個(gè)VA的呢?這就需要把VA也保存在Cache中,由于這32字節(jié)的起始地址是對(duì)齊到32字節(jié)地址邊界的,末5位全為0,因此只需

34、要保存VA31:5即可,這稱為VA Tag4,Tag是VA的一部分,是Cache Line中數(shù)據(jù)的標(biāo)識(shí),表明這32字節(jié)數(shù)據(jù)來自哪個(gè)VA。這樣設(shè)計(jì)的Cache稱為全相聯(lián)Cache(Fully Associative Cache),圖示如下: 圖 17. 全相聯(lián)Cache   給定一個(gè)VA,如何在Cache中查找對(duì)應(yīng)的數(shù)據(jù)呢?首先到Cache中比較查找哪一行的Tag等于VA31:5,找到對(duì)應(yīng)的Cache Line后,再根據(jù)VA4:0決定要訪問的是該Cache Line緩存的32個(gè)字節(jié)中的哪一個(gè)字節(jié)。由于有512條Cache Line,如果這個(gè)VA沒有緩存在Cache中則需要比較

35、512次才知道,這是最壞的情況,也是最常見的情況,下面我們要改進(jìn)Cache的設(shè)計(jì)來解決這個(gè)問題。   全相聯(lián)Cache的特點(diǎn)是任何VA都可以緩存到任何一條Cache Line,給定一個(gè)VA做查找時(shí),由于它有可能緩存在512條Cache Line中的任何一條,就只好全部都找一遍了。如果限定某一個(gè)VA只允許緩存在某一條Cache Line中,那么查找的過程就快多了:檢查一下應(yīng)該緩存這個(gè)VA的那條Cache Line,看Tag一致不一致,如果一致就是Cache Hit,如果不一致就是Cache Miss,可以直接訪問物理內(nèi)存而不必再找其它Cache Line了。這種設(shè)計(jì)稱為直接映

36、射Cache(Direct Mapped Cache),如下圖所示:圖 18. 直接映射Cache    地址031應(yīng)該緩存在第1條Cache Line中,地址3263應(yīng)該緩存在第2條Cache Line中,依此類推,地址1635216383應(yīng)該緩存在第512條Cache Line中,下一個(gè)地址應(yīng)該是16384(16K)了,我們又回到開頭,地址16K16K+31應(yīng)該緩存在第1條Cache Line中,地址16K+3216K+63應(yīng)該緩存在第2條Cache Line中,依此類推,再次回到開頭的地址應(yīng)該是32K,32K32K+31應(yīng)該緩存在第1條Cache Line中

37、,32K+3232K+63應(yīng)該緩存在第2條Cache Line中,依此類推。讀者應(yīng)該可以總結(jié)出規(guī)律了:給定一個(gè)VA,將它除以16K得的余數(shù)決定了它應(yīng)該緩存在哪一條Cache Line中,那么除以16K的商數(shù)部分就應(yīng)該是VA Tag,用以區(qū)別Cache Line中緩存的到底是0還是16K還是32K地址上的數(shù)據(jù)。那么除以16K的商數(shù)和余數(shù)怎么表示呢?VA31:14就是除以16K的商數(shù),VA13:0就是余數(shù),所以上圖的Tag處標(biāo)著VA31:14。余數(shù)VA13:0是16K Cache里的一個(gè)字節(jié)偏移量,而Cache是按32字節(jié)一個(gè)Cache Line組織的,所以余數(shù)中的高位VA13:5決定了是第幾條C

38、ache Line,余數(shù)中的低位VA4:0決定了Cache Line內(nèi)的字節(jié)偏移量。驗(yàn)算一下,VA13:5一共是9位,作為Cache Line的編號(hào)可以表示的Cache Line數(shù)目正是512條。    直接映射Cache雖然查找速度很快,但也有缺點(diǎn)。比如,地址031、16K16K+31、32K32K+31都應(yīng)該緩存到第1條Cache Line中,假如我們程序第一次訪問地址30,地址031的數(shù)據(jù)就從內(nèi)存加載到第1條Cache Line,以便下次訪問能更快一些,但是我們程序第二次訪問的卻是地址32770,地址32K32K+31的數(shù)據(jù)就要從內(nèi)存加載到第1條Cache

39、Line,把Cache Line里原來存的地址031的數(shù)據(jù)替換掉,以便下次訪問能更快一些,但是我們程序第三次訪問的卻是地址16392這樣下去,Cache起不到任何加速作用,形同虛設(shè),這種問題稱為Cache抖動(dòng)(Cache Thrash)。全相聯(lián)Cache就不會(huì)有這種問題,因?yàn)槿魏蜼A都可以緩存到任何一條Cache Line,可以把先后幾次訪問的VA緩存到不同的Cache Line,就不會(huì)相互沖突。    全相聯(lián)Cache和直接映射Cache各有優(yōu)缺點(diǎn),全相聯(lián)Cache查找很慢,但沒有抖動(dòng)問題,直接映射Cache則正相反。為了得到更好的性能,實(shí)際CPU的Cache設(shè)

40、計(jì)是取兩者的折衷,把所有Cache Line分成若干個(gè)組,每一組有n條Cache Line,稱為n路組相聯(lián)Cache(n-way Set Associative Cache)。ARM920T采用64路組相聯(lián)Cache,如下圖所示:圖 19. 64路組相聯(lián)Cache    有了前面兩種Cache概念的基礎(chǔ),這種Cache應(yīng)該很好理解,512條Cache Line分成8組,每組64條,地址0-31、256-587、512-543等等可以緩存到第1組64條Cache Line中的任何一條,地址32-63、288-319、544-575等等可以緩存到第2組64條Cache

41、 Line中的任何一條,依此類推。為什么說組相聯(lián)Cache是全相聯(lián)和直接映射Cache的一個(gè)折衷呢?如果把組分得很大,把全部Cache Line都分到一個(gè)組里面去,就變成了全相聯(lián)Cache;如果把組分得很小,每組只有一個(gè)Cache Line,就變成了直接映射Cache。作為練習(xí),請(qǐng)讀者自己計(jì)算一下為什么VA Tag是VA31:8,為什么組的編號(hào)用VA7:5表示。    那么,為什么組相聯(lián)Cache的性能比直接映射Cache要好呢?一方面,組相聯(lián)Cache把一條Cache Line上的沖突分散到了64條Cache Line上,起到了64倍的積極作用。而另一方面,應(yīng)該

42、緩存到同一個(gè)組的VA更多了:對(duì)于直接映射Cache,在同一個(gè)組(也就是同一條Cache Line)互相沖突的VA有4G/512個(gè);對(duì)于組相聯(lián)Cache,在同一個(gè)組(64條Cache Line)互相沖突的VA有4G/8個(gè)。從這個(gè)數(shù)量關(guān)系來看,組相聯(lián)Cache又起到了64倍的消極作用。難道這兩種作用不會(huì)完全抵銷嗎?我不打算從數(shù)學(xué)上嚴(yán)格證明,這不是本節(jié)的重點(diǎn),讀者可以通過一個(gè)生活常識(shí)的例子來理解:層數(shù)一樣多的兩棟樓,其中一棟樓是一部電梯,每層三戶,而另一棟樓是兩部電梯,每層六戶,每戶的平均人數(shù)一樣多,你認(rèn)為在哪個(gè)樓里等電梯的時(shí)間較短呢?   接下來解釋一下有關(guān)Cache寫回內(nèi)存的

43、問題。Cache寫回內(nèi)存有兩種模式:    Write Back:Cache Line中的數(shù)據(jù)被CPU核修改時(shí)并不立刻寫回內(nèi)存,Cache Line和內(nèi)存中的數(shù)據(jù)會(huì)暫時(shí)不一致,在Cache Line中有一個(gè)Dirty位標(biāo)記這一情況。當(dāng)一條Cache Line要被其它VA的數(shù)據(jù)替換時(shí),如果不是Dirty的就直接替換掉,如果是Dirty的就先寫回內(nèi)存再替換。   Write Through:每當(dāng)CPU核修改Cache Line中的數(shù)據(jù)時(shí)就立刻寫回內(nèi)存,Cache Line和內(nèi)存中的數(shù)據(jù)總是一致的。如果有多個(gè)CPU或設(shè)備同時(shí)訪問內(nèi)存,例如采用雙口RA

44、M,那么Cache中的數(shù)據(jù)和內(nèi)存保持一致就非常重要了,這時(shí)相關(guān)的內(nèi)存頁面通常配置為Write Through模式。    通過讀寫CP15的相關(guān)寄存器,可以對(duì)Cache做以下操作:   Clean:將Cache Line中的數(shù)據(jù)寫回內(nèi)存,清除Dirty位。在程序中的某些同步點(diǎn)上用于確保Cache Line和內(nèi)存中的數(shù)據(jù)一致。   Invalidate:在Cache Line中有一個(gè)Invalid位表示無效,將這個(gè)位置1,下次要訪問時(shí)即使VA Tag匹配也重新從內(nèi)存讀取數(shù)據(jù)。例如進(jìn)程切換時(shí)需要聲明前一個(gè)進(jìn)程緩存在Cache中的

45、數(shù)據(jù)無效。     Lock:將某個(gè)地址的數(shù)據(jù)鎖定在Cache中,確保不被替換掉。在實(shí)時(shí)系統(tǒng)中,這樣做可以保證某個(gè)地址的數(shù)據(jù)能在一個(gè)確定的時(shí)間內(nèi)訪問到。    從Cache中查找要訪問的數(shù)據(jù)時(shí)用的是VA,但是Cache寫回內(nèi)存要用PA,如果寫回內(nèi)存時(shí)還需要查一遍頁表就太沒有效率了,所以實(shí)際上每條Cache Line中還保存了PA31:5(PA Tag),完整的Cache構(gòu)造如下圖所示:圖 20. PA Tag     最后解決我們前面遺留的一個(gè)問題:頁描述符中的C、B位具體是什么意思?表 2. 頁描述符中

46、C、B位的含義    C位為1表示允許Cache,這種情況下用B位來表示W(wǎng)rite Through還是Write Back。有些頁面不允許Cache,置C位為0,這種情況下可以用B位來選擇是否允許使用Write Buffer。Write Buffer也是一種簡單的Cache,CPU核執(zhí)行寫指令時(shí)可以把數(shù)據(jù)交給Write Buffer,然后由Write Buffer負(fù)責(zé)寫回內(nèi)存,這時(shí)CPU可以執(zhí)行后續(xù)指令而不必等待寫回內(nèi)存這個(gè)較慢的操作結(jié)束。操作MMU和Cache的內(nèi)核啟動(dòng)代碼    bootloader加載linux內(nèi)核到內(nèi)存并解壓之

47、后,Linux內(nèi)核首先在匯編代碼中讀取CPU的基本信息,對(duì)CPU做一些基本設(shè)置,創(chuàng)建最簡單的臨時(shí)頁表,然后開啟MMU和Cache,啟用虛擬內(nèi)存管理(此后CPU核發(fā)出的地址都是虛擬地址),然后跳到C代碼中完成其它初始化工作,比如創(chuàng)建完整的頁表、初始化各種內(nèi)核子系統(tǒng)、初始化硬件設(shè)備等。本節(jié)以Linux 2.4內(nèi)核的啟動(dòng)代碼為例,了解一下操作MMU和Cache的具體指令是怎么寫的,通過實(shí)例來加深對(duì)前面內(nèi)容的理解。本節(jié)的內(nèi)容改編自ARM Linux演義。    假設(shè)目標(biāo)板的RAM物理地址是從0x0800 0000開始的(也就是說,RAM芯片連接到CPU芯片上從0x0800

48、 0000開始的bank)。經(jīng)過內(nèi)核的若干初始化代碼之后,寄存器的內(nèi)容如下:表 3. 寄存器的初始值    接下來的步驟是:    1 創(chuàng)建簡單的臨時(shí)頁表和臨時(shí)映射    2 配置與MMU和Cache相關(guān)的CP15寄存器    3 啟用MMU和Cache    臨時(shí)頁表存放在物理內(nèi)存地址0x0800 4000開始的16K(回想一下,第一級(jí)頁表是16K,有4096個(gè)頁描述符)。后面將會(huì)把頁描述符填寫成Section格式,也就是直接映射到1M的大頁面

49、,這些都是內(nèi)核初始化階段臨時(shí)用的,為了是寫盡可能少的匯編代碼,盡快啟用MMU并跳到C代碼中做剩下的初始化工作,在完整的兩級(jí)頁表建立之后臨時(shí)頁表就沒有用了。首先將16K的臨時(shí)頁表清零:    下面我們將使用Section格式的頁描述符來填充表項(xiàng),由于是內(nèi)核初始化階段,還沒有用戶進(jìn)程,我們只映射4M的地址空間,覆蓋內(nèi)核本身的代碼和數(shù)據(jù)就可以了。思考一下,為什么首先要把這16K臨時(shí)頁表清零,即使沒用到的表項(xiàng)也要清零?由于Linux內(nèi)核在編譯時(shí)確定的代碼加載地址是0xc000 8000(虛擬地址),而bootloader將內(nèi)核代碼加載到物理地址0x0800 8000,我們

50、需要把物理地址從0x0800 0000開始的4M映射到虛擬地址從0xc000 0000開始的4M。    但是這里有一個(gè)問題:設(shè)置好頁表之后,最終有一條指令是啟用MMU的,假設(shè)該指令的PA是0x0800 810c,根據(jù)我們要做的映射關(guān)系,它的VA應(yīng)該是0xc000 810c,沒有啟用MMU之前CPU核發(fā)出的都是物理地址,從0x0800 810c地址取這條指令來執(zhí)行,然而該指令執(zhí)行之后,CPU核發(fā)出的地址都要被MMU攔截,CPU核就必須用虛擬地址來取指令了,因此下一條指令應(yīng)該從0xc000 8110處取得,然而這時(shí)pc寄存器(也就是r15寄存器)的值并沒有變,CPU

51、核取下一條指令仍然要從0x0800 8110處取得,此時(shí)0x0800 8110已經(jīng)成了非法地址了。如下圖所示。圖 21. 啟用MMU的那條指令導(dǎo)致的問題為了解決這個(gè)問題,要求啟用MMU的那條指令及其附近的指令虛擬地址跟物理地址相同,這樣在啟用MMU前后,附近指令的地址不會(huì)發(fā)生變化,從而實(shí)現(xiàn)平穩(wěn)過渡。因此需要將物理地址從0x0800 0000開始的1M再映射到虛擬地址從0x0800 0000開始的1M,也就是做一個(gè)等價(jià)映射(identity map)5。現(xiàn)在把需要建立的映射項(xiàng)總結(jié)如下:表 4. 需要建立的映射項(xiàng)    以下代碼建立上面所說的等價(jià)映射。 &#

52、160; 回頭看一下表 3 “寄存器的初始值”,r8的值是頁描述符標(biāo)志位,r5的值是RAM起始物理地址0x0800 0000,由于要做的是等價(jià)映射,這里的r5既是PA同時(shí)也是VA,第一條指令將r5當(dāng)作PA,r3=r8+r5=0x0800 0c1e得到完整的頁描述符,比對(duì)一下看看各bit的含義。圖 22. 等價(jià)映射的頁描述符   該描述符所描述的Section屬于第0個(gè)Domain,AP位是11,可讀可寫,C、B位都是1,允許Cache,并且Cache是Write Back方式的。第二條指令,將虛擬地址r5右移18位(對(duì)照?qǐng)D 14 “Translation Table Wal

53、k的詳細(xì)過程”看一下為什么是右移18位(高12位是段基址),加到頁表基地址上,得到該描述符在頁表中的地址,結(jié)果保存在r0中。第三條指令,將第一條指令計(jì)算出的頁描述符的值r3保存在第二條指令計(jì)算出的r0地址處,這樣就填寫好了頁表項(xiàng)。    下面映射物理地址從0x8000 0000開始的4M到虛擬地址0xc000 0000,其中TEXTADDR是Linux內(nèi)核在編譯時(shí)確定的代碼加載地址0xc000 8000,PAGE_OFFSET定義為0xc000 0000。請(qǐng)讀者自己分析以下代碼。add r0, r4, #(TEXTADDR & 0xfff00000) &g

54、t;> 18 start of kernel 注:r0 = r4+ 0x3000 = 0800 4000 + 3000 = 0800 7000str r3, r0, #4 PAGE_OFFSET + 0MB 注:0800 7000地址的內(nèi)容為0800 0c1e add r3, r3, #1 << 20 注:r3=0810 0c1estr r3, r0,#4 PAGE_OFFSET + 1MB 注:0800 7004地址的內(nèi)容為0810 0c1e add r3, r3, #1 << 20 注:r3=0820 0c1e str r3, r0, #4 PAGE_OFFS

55、ET + 2MB 注:0800 7008地址的內(nèi)容為0820 0c1e add r3, r3, #1 << 20 注:r3=0830 0c1estr r3,r0,#4 PAGE_OFFSET + 3MB 注:0800 700c地址的內(nèi)容為0830 0c1e    設(shè)置好了頁表,接下來設(shè)置與MMU和Cache相關(guān)的CP15寄存器:   這一段有很多協(xié)處理器指令,請(qǐng)讀者對(duì)照S3C2410用戶手冊(cè)和代碼中的注釋查看各指令的含義。大體上來說做了以下事情:首先禁用指令和數(shù)據(jù)Cache,等待Write Buffer寫回內(nèi)存,然后用r4寄存器的值

56、設(shè)置CP15的TTB寄存器,然后設(shè)置Domain權(quán)限位,我們先前填寫的頁描述符都屬于第0個(gè)Domain,Domain寄存器中第0個(gè)Domain的權(quán)限位設(shè)置為11,表示訪問不必檢查AP位。接下來讀出CP15的控制寄存器的值來修改,準(zhǔn)備啟用MMU,根據(jù)內(nèi)核配置決定是否啟用數(shù)據(jù)和指令Cache,修改之后一并寫回控制寄存器,使設(shè)置生效:    相關(guān)索引    C     Cache,高速緩存, 虛擬內(nèi)存管理    Cache Hit, ARM920T的CP15協(xié)處理器 &#

57、160;  Cache Line, ARM920T的CP15協(xié)處理器    Cache Miss, ARM920T的CP15協(xié)處理器    Cache Thrash,Cache抖動(dòng), Cache    Direct Mapped Cache,直接映射Cache, Cache    Fully Associative Cache,全相聯(lián)Cache, Cache    n-way Set Associative Cache,n路組相聯(lián)Cache, Cache    M     MMU,Memo

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論