MMU的理解
許多年以前,當(dāng)人們還在使用DOS或是更古老的操作系統(tǒng)的時候,計算機(jī)的內(nèi)存還非常小,一般都是以K為單位進(jìn)行計算,相應(yīng)的,當(dāng)時的程序規(guī)模也不大,所以
內(nèi)存容量雖然小,但還是可以容納當(dāng)時的程序。但隨著圖形界面的興起還用用戶需求的不斷增大,應(yīng)用程序的規(guī)模也隨之膨脹起來,終于一個難題出現(xiàn)在程序員的面
前,那就是應(yīng)用程序太大以至于內(nèi)存容納不下該程序,通常解決的辦法是把程序分割成許多稱為覆蓋塊(overlay)的片段。覆蓋塊0首先運(yùn)行,結(jié)束時他將調(diào)用另一個覆蓋塊。雖然覆蓋塊的交換是由OS完成的,但是必須先由程序員把程序先進(jìn)行分割,這是一個費時費力的工作,而且相當(dāng)枯燥。人們必須找到更好的辦法從根本上解決這個問題。不久人們找到了一個辦法,這就是虛擬存儲器(virtual memory).虛擬存儲器的基本思想是程序,數(shù)據(jù),堆棧的總的大小可以超過物理存儲器的大小,操作系統(tǒng)把當(dāng)前使用的部分保留在內(nèi)存中,而把其他未被使用的部分保存在磁盤上。
比如對一個16MB的程序和一個內(nèi)存只有4MB的機(jī)器,OS通過選擇,可以決定各個時刻將哪4M的內(nèi)容保留在內(nèi)存中,并在需要時在內(nèi)存和磁盤間交換程序片
段,這樣就可以把這個16M的程序運(yùn)行在一個只具有4M內(nèi)存機(jī)器上了。而這個16M的程序在運(yùn)行前不必由程序員進(jìn)行分割。
這個范圍的大小由CPU的位數(shù)決定,例如一個32位的CPU,它的地址范圍是0~0xFFFFFFFF
(4G),而對于一個64位的CPU,它的地址范圍為0~0xFFFFFFFFFFFFFFFF
(64T).這個范圍就是我們的程序能夠產(chǎn)生的地址范圍,我們把這個地址范圍稱為虛擬地址空間,該空間中的某一個地址我們稱之為虛擬地址。與虛擬地址空間和虛擬地址相對應(yīng)的則是物理地址空間和物理地址,大多數(shù)時候我們的系統(tǒng)所具備的物理地址空間只是虛擬地址空間的一個子集,這里舉一個最簡單的例子直觀地說明這兩者,對于一臺內(nèi)存為256MB的32bit x86主機(jī)來說,它的虛擬地址空間范圍是0~0xFFFFFFFF(4G),而物理地址空間范圍是0x000000000~0x0FFFFFFF(256MB)。
在沒有使用虛擬存儲器的機(jī)器上,虛擬地址被直接送到內(nèi)存總線上,使具有相同地址的物理存儲器被讀寫。而在使用了虛擬存儲器的情況下,虛擬地址不是被直接送
到內(nèi)存地址總線上,而是送到內(nèi)存管理單元——MMU(主角終于出現(xiàn)了:])。他由一個或一組芯片組成,一般存在與協(xié)處理器中,其功能是把虛擬地址映射為物
理地址。
擬地址0將被送往MMU,MMU看到該虛地址落在頁0范圍內(nèi)(頁0范圍是0到4095),從上圖我們看到頁0所對應(yīng)(映射)的頁框為2(頁框2的地址范圍
是8192到12287),因此MMU將該虛擬地址轉(zhuǎn)化為物理地址8192,并把地址8192送到地址總線上。內(nèi)存對MMU的映射一無所知,它只看到一個
對地址8192的讀請求并執(zhí)行它。MMU從而把0到4096的虛擬地址映射到8192到12287的物理地址。例2:MOVE REG,8192被轉(zhuǎn)換為MOVE REG,24576 因為虛擬地址8192在頁2中,而頁2被映射到頁框6(物理地址從24576到28671)例3:MOVE REG,20500被轉(zhuǎn)換為MOVE REG,12308虛擬地址20500在虛頁5(虛擬地址范圍是20480到24575)距開頭20個字節(jié)處,虛頁5映射到頁框3(頁框3的地址范圍是 12288到16383),于是被映射到物理地址12288+20=12308。
這種情況下操作系統(tǒng)必須處理這個頁故障,它必須從8個物理頁框中找到1個當(dāng)前很少被使用的頁框并把該頁框的內(nèi)容寫入外圍存儲器(這個動作被稱為page
copy),隨后把需要引用的頁(例4中是頁8)映射到剛才釋放的頁框中(這個動作稱為修改映射關(guān)系),然后從新執(zhí)行產(chǎn)生故障的指令(MOV
REG,32780)。假設(shè)操作系統(tǒng)決定釋放頁框1,那么它將把虛頁8裝入物理地址的4-8K,并做兩處修改:首先把標(biāo)記虛頁1未被映射(原來虛頁1是被
影射到頁框1的),以使以后任何對虛擬地址4K到8K的訪問都引起頁故障而使操作系統(tǒng)做出適當(dāng)?shù)膭幼鳎ㄟ@個動作正是我們現(xiàn)在在討論的),其次他把虛頁8對
應(yīng)的頁框號由X變?yōu)?,因此重新執(zhí)行MOV REG,32780時,MMU將把32780映射為4108。我們大致了解了MMU在我們的機(jī)器中扮演了什么角色以及它基本的工作內(nèi)容是什么,下面我們將舉例子說明它究竟是如何工作的(注意,本例中的MMU并無針對某種特定的機(jī)型,它是所有MMU工作的一個抽象)。
頁有一個用來標(biāo)示它的頁號(這個頁號一般是它在該組中的索引,這點和C/C++中的數(shù)組相似)。在上面的例子中0~4K的頁號為0,4~8K的頁號為1,8~12K的頁號為2,以此類推。而虛擬地址(注意:是一個確定的地址,不是一個空間)被MMU分為2個部分,第一部分是頁號索引(page Index),第二部分則是相對該頁首地址的偏移量(offset)。
我們還是以剛才那個16位機(jī)器結(jié)合下圖進(jìn)行一個實例說明,該實例中,虛擬地址8196被送進(jìn)MMU,MMU把它映射成物理地址。16位的CPU總共能產(chǎn)生的地址范圍是0~64K,按每頁4K的大小計算,該空間必須被分成16個頁。而我們的虛擬地址第一部分所能夠表達(dá)的范圍也必須等于16(這樣才能索引到該
頁組中的每一個頁),也就是說這個部分至少需要4個bit。一個頁的大小是4K(4096),也就是說偏移部分必須使用12個bit來表示(2^12=
4096,這樣才能訪問到一個頁中的所有地址),8196的二進(jìn)制碼如下圖所示:
該地址的頁號索引為0010(二進(jìn)制碼),既索引的頁為頁2,第二部分為000000000100(二進(jìn)制),偏移量為4。頁2中的頁框號為6(頁2映射
在頁框6,見上圖),我們看到頁框6的物理地址是24~28K。于是MMU計算出虛擬地址8196應(yīng)該被映射成物理地址24580(頁框首地址+偏移量=
24576+4=24580)。同樣的,若我們對虛擬地址1026進(jìn)行讀取,1026的二進(jìn)制碼為0000010000000010,page
index=0000=0,offset=010000000010=1026。頁號為0,該頁映射的頁框號為2,頁框2的物理地址范圍是
8192~12287,故MMU將虛擬地址1026映射為物理地址9218(頁框首地址+偏移量=8192+1026=9218)
下面我們針對s3c2410的MMU(注1)進(jìn)行講解。
S3c2410總共有4種內(nèi)存映射方式,分別是:
- Fault (無映射)
- Coarse Page (粗表)
- Section (段)
- Fine Page (細(xì)表)
我們以Section(段)進(jìn)行說明。
ARM920T是一個32bit的CPU,它的虛擬地址空間為2^32=4G。而在Section模式,這4G的虛擬空間被分成一個一個稱為段
(Section)的單位(與我們上面講的頁在本質(zhì)上其實是一致的),每個段的長度是1M
(而我們之前所使用的頁的長度是4K)。4G的虛擬內(nèi)存總共可以被分成4096個段(1M*4096=4G),因此我們必須用4096個描述符來對這組段
進(jìn)行描述,每個描述符占用4個Byte,故這組描述符的大小為16KB
(4K*4096),這4096個描述符構(gòu)為一個表格,我們稱其為Tralaton Table.
上圖是描述符的結(jié)構(gòu)
Section base address:段基地址(相當(dāng)于頁框號首地址)
AP: 訪問控制位Access Permission
Domain: 訪問控制寄存器的索引。Domain與AP配合使用,對訪問權(quán)限進(jìn)行檢查
C:當(dāng)C被置1時為write-through (WT)模式
B: 當(dāng)B被置1時為write-back (WB)模式
(C,B兩個位在同一時刻只能有一個被置1)
下面是s3c2410內(nèi)存映射后的一個示意圖:
注1
)
被分為兩部分(這點和我們上面舉的例子是一樣的),這兩部分為 Descriptor Index(相當(dāng)于上面例子的Page Index)和
Offset,descript index長度為12bit(2^12=4096,從這個關(guān)系式你能看出什么?:)
),Offset長度為20bit(2^20=1M,你又能看出什么?:)).觀察一下一個描述符(Descriptor)中的Section
Base Address部分,它長度為12
bit,里面的值是該虛擬段(頁)映射成的物理段(頁框)的物理地址前12bit,由于每一個物理段的長度都是1M,所以物理段首地址的后20bit總是
為0x00000(每個Section都是以1M對齊),確定一個物理地址的方法是 物理頁框基地址+虛擬地址中的偏移部分=Section Base Address
代碼
void mem_mapping_linear(void)
架構(gòu)則把這種異常稱之為通用保護(hù)異常(General Protection),什么情況會引起Permission
fault呢?比如處于User級別的程序要對一個System級別的內(nèi)存區(qū)域進(jìn)行寫操作,這種操作是越權(quán)的,應(yīng)該引起一個Permission
fault,搞過x86架構(gòu)的朋友應(yīng)該聽過保護(hù)模式(Protection Mode),保護(hù)模式就是基于這種思想進(jìn)行工作的,于是我們也可以這么說:s3c2410的訪問控制機(jī)制其實就是一種保護(hù)機(jī)制。那s3c2410的訪問控制機(jī)制到底是由什么元素去參與完成的呢?它們間是怎么協(xié)調(diào)工作的呢?這些元素總共有:
- 協(xié)處理器CP15中Control Register3:DOMAIN ACCESS CONTROL REGISTER
- 段描述符中的AP位和Domain位
- 協(xié)處理器CP15中Control Register1(控制寄存器1)中的S bit和R bit
- 協(xié)處理器CP15中Control Register5(控制寄存器5)
- 協(xié)處理器CP15中Control Register6(控制寄存器6)
DOMAIN ACCESS CONTROL REGISTER 是訪問控制寄存器,該寄存器有效位為32,被分成16個區(qū)域,每個區(qū)域由兩個位組成,他們說明了當(dāng)前內(nèi)存的訪問權(quán)限檢查的級別,如下圖所示:
每區(qū)域可以填寫的值有4個,分別為00,01,10,11(二進(jìn)制),他們的意義如下所示:
00:當(dāng)前級別下,該內(nèi)存區(qū)域不允許被訪問,任何的訪問都會引起一個domain fault
01:當(dāng)前級別下,該內(nèi)存區(qū)域的訪問必須配合該內(nèi)存區(qū)域的段描述符中AP位進(jìn)行權(quán)檢查
10:保留狀態(tài)(我們最好不要填寫該值,以免引起不能確定的問題)
11:當(dāng)前級別下,對該內(nèi)存區(qū)域的訪問都不進(jìn)行權(quán)限檢查。
我們再來看看discriptor中的Domain區(qū)域,該區(qū)域總共有4個bit,里面的值是對DOMAIN ACCESS CONTROL
REGISTER中16個區(qū)域的索引.而AP位配合S bit和A bit對當(dāng)前描述符描述的內(nèi)存區(qū)域被訪問權(quán)限的說明,他們的配合關(guān)系如下圖所示:
AP位也是有四個值,我結(jié)合實例對其進(jìn)行說明.
在下面的例子中,我們的DOMAIN ACCESS CONTROL REGISTER都被初始化成0xFFFF BDCF,如下圖所示:
例1:Discriptor 中的domain=4,AP=10(這種情況下S bit ,A bit 被忽略)
假設(shè)現(xiàn)在我要對該描述符描述的內(nèi)存區(qū)域進(jìn)行訪問:
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系統(tǒng)會對該訪問進(jìn)行訪問權(quán)限的檢查。
假設(shè)當(dāng)前CPU處于Supervisor模式下,則程序可以對該描述符描述的內(nèi)存區(qū)域進(jìn)行讀寫操作。
假設(shè)當(dāng)前CPU處于User模式下,則程序可以對該描述符描述的內(nèi)存進(jìn)行讀訪問,若對其進(jìn)行寫操作則引起一個permission fault.
例2:Discriptor 中的domain=0,AP=10(這種情況下S bit ,A bit 被忽略)
domain=0,而DOMAIN ACCESS CONTROL REGISTER中field 0的值是11,系統(tǒng)對任何內(nèi)存區(qū)域的訪問都不進(jìn)行訪問權(quán)限的檢查。
由于統(tǒng)對任何內(nèi)存區(qū)域的訪問都不進(jìn)行訪問權(quán)限的檢查,所以無論CPU處于合種模式下(Supervisor模式或是User模式),程序?qū)υ撁枋龇枋龅膬?nèi)存都可以順利地進(jìn)行讀寫操作
例3:Discriptor 中的domain=4,AP=11(這種情況下S bit ,A bit 被忽略)
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系統(tǒng)會對該訪問進(jìn)行訪問權(quán)限的檢查。
由于AP=11,所以無論CPU處于合種模式下(Supervisor模式或是User模式),程序?qū)υ撁枋龇枋龅膬?nèi)存都可以順利地進(jìn)行讀寫操作
例4:Discriptor 中的domain=4,AP=00, S bit=0,A bit=0
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系統(tǒng)會對該訪問進(jìn)行訪問權(quán)限的檢查。
由于AP=00,S bit=0,A bit=0,所以無論CPU處于合種模式下(Supervisor模式或是User模式),程序?qū)υ撁枋龇枋龅膬?nèi)存都只能進(jìn)行讀操作,否則引起permission fault.
通過以上4個例子我們得出兩個結(jié)論:
1.對某個內(nèi)存區(qū)域的訪問是否需要進(jìn)行權(quán)限檢查是由該內(nèi)存區(qū)域的描述符中的Domain域決定的。
2.某個內(nèi)存區(qū)域的訪問權(quán)限是由該內(nèi)存區(qū)域的描述符中的AP位和協(xié)處理器CP15中Control Register1(控制寄存器1)中的S bit和R bit所決定的。
關(guān)于訪問控制機(jī)制我們就講到這里.
注1:對于s3c2410來說,送進(jìn)MMU的地址準(zhǔn)確講是一個Modify Visual Address(MVA),這個地址是Virtual Address的一個變換,我將在以后談?wù)摰竭M(jìn)程切換的時候中向大家介紹MVA
評論