uboot step 11 內(nèi)存一下子變大了 ----MMU的配置與使用
本文結(jié)構(gòu)如下:
MMU 介紹
MMU 相關(guān)寄存器
MMU 內(nèi)存訪問(wèn)權(quán)限控制
MMU 使能
-
MMU 頁(yè)表描述
- 一級(jí)頁(yè)表描述符地址
- 一級(jí)頁(yè)表描述符格式
- 二級(jí)頁(yè)表描述符格式
- 虛擬地址到物理地址轉(zhuǎn)化 (重要)
- 1M段式
- 16M段式
- 64KB大頁(yè)
- 4KB小頁(yè)
代碼實(shí)現(xiàn):使用虛擬地址去控制LED的例子
參考
http://www.it165.net/embed/html/201408/2633.html
http://comm.chinaaet.com/adi/blogdetail/40052.html
在前面初始化的過(guò)程中,由于MMU與Cache會(huì)影響我們進(jìn)行初始化的工作,因此關(guān)閉了MMU與Cache,在那篇文章中已經(jīng)說(shuō)過(guò)了MMU的作用,這里再重新說(shuō)下:
- 1.完成虛擬地址到物理地址的轉(zhuǎn)換
- 2.對(duì)內(nèi)存的訪問(wèn)權(quán)限進(jìn)行控制
首先還是先來(lái)簡(jiǎn)要說(shuō)下相關(guān)與MMU相關(guān)的寄存器,先有個(gè)大概印象,后面用到了再去詳細(xì)的看:

| 名稱 | 描述 | 簡(jiǎn)寫 |
|---|---|---|
| Translation Table Base Register 0 | 保存一級(jí)轉(zhuǎn)換表的物理地址 | TTBR0 |
| Translation Table Base Register 1 | 保存一級(jí)轉(zhuǎn)換表的物理地址 | TTBR1 |
| Translation Table Base Control Register | 一級(jí)轉(zhuǎn)換表控制相關(guān) | TTBCR |
| Domain Access Control Register | 域訪問(wèn)權(quán)限控制 | |
| C1 Control Register | MMU和cache使能 |
MMU使能

- 1.編程所有相關(guān)的CP15寄存器正確的值
- 2.編程建立所要求的一級(jí)頁(yè)表,二級(jí)頁(yè)表
- 3.關(guān)閉I-cache
- 4.使能MMU
MMU 內(nèi)存訪問(wèn)權(quán)限控制
-
Domains 域控制
一個(gè)域被聯(lián)系到一些內(nèi)存區(qū)域,在頁(yè)表描述符中有個(gè)Domain域來(lái)標(biāo)識(shí)此區(qū)域內(nèi)存屬于哪一個(gè)域Domian來(lái)控制,ARM1176 支持16個(gè)Domains,域訪問(wèn)權(quán)限控制是由C3來(lái)設(shè)定的,如下圖:
c3.png
每個(gè)域由兩位來(lái)控制,32位寄存器,總共16個(gè)域
- 00 無(wú)權(quán)限,任何訪問(wèn)都會(huì)產(chǎn)生domain fault
- 01 Client 檢查TLB頁(yè)表描述符的權(quán)限位是否允許訪問(wèn)
- 10 保留,產(chǎn)生domain fault
- 11 Manager 不檢查訪問(wèn)權(quán)限,不會(huì)產(chǎn)生權(quán)限錯(cuò)誤
-
訪問(wèn)權(quán)限控制
在域控制中,提到會(huì)檢查TLB頁(yè)表描述符的權(quán)限位,這個(gè)權(quán)限位就是APX,AP位,在頁(yè)表描述符中有這幾個(gè)域
ap.png -
可執(zhí)行區(qū)域XN位
XN.png- 如果含有可執(zhí)行區(qū)域,XN=0
- XN=1時(shí),在此內(nèi)存區(qū)域任何試圖去執(zhí)行指令的行為會(huì)產(chǎn)生權(quán)限錯(cuò)誤
MMU 頁(yè)表描述
為了支持段和頁(yè)的映射方式,MMU使用兩級(jí)頁(yè)表描述符,一級(jí)頁(yè)表描述符決定訪問(wèn)的是一個(gè)分段還是一個(gè)分頁(yè)式的表,如果訪問(wèn)的是一個(gè)分頁(yè)式的頁(yè)表,處理器MMU決定頁(yè)表類型是大頁(yè)還是小頁(yè)并找到二級(jí)頁(yè)表。
一級(jí)頁(yè)表描述符地址
ARM1176 包含 兩個(gè)轉(zhuǎn)換表基地址寄存器TTBR0和TTBR1,一個(gè)轉(zhuǎn)換表基地址控制寄存器,當(dāng)一個(gè)TLB未命中時(shí),虛擬地址最高位決定使用的基地址寄存器是哪一個(gè),采用兩個(gè)轉(zhuǎn)換表基地址期望去減少OS上下文切換的花費(fèi),每個(gè)獨(dú)立的任務(wù)或進(jìn)程,有他自己的頁(yè)表而不用消耗大量?jī)?nèi)存。整個(gè)虛擬內(nèi)存空間被分為兩個(gè)部分,用戶空間和內(nèi)核空間
0x0 -> 1<<(32-N) that TTBR0 controls
1<<(32-N) -> 4GB that TTBR1 controls.
N的值在TTBCR寄存器中進(jìn)行設(shè)定,N的大小決定了內(nèi)核空間和用戶空間的分界線,當(dāng)N=0時(shí),表示只使用了TTBR0寄存器


一級(jí)頁(yè)表描述符格式分析

如上圖所示:
- bit[1:0]: 映射類型,分段式還是分頁(yè)式。
- 00 忽略
- 11 無(wú)效,返回Translation fault
- 10 分段式
- 01 分頁(yè)式
- nG : 0 轉(zhuǎn)換表被標(biāo)記為全局的; 1 轉(zhuǎn)換表屬于特定進(jìn)程
- S : 共享位,0 非共享; 1 共享內(nèi)存
- XN: 0 包含可執(zhí)行代碼; 1 不包含可執(zhí)行代碼
- APX,AP位: 權(quán)限訪問(wèn)控制位
- Doman : 域標(biāo)識(shí),屬于哪個(gè)域
- P: ECC校驗(yàn)
- TEX,C,B: 此區(qū)域是否采用緩沖buffer,cache,還是直接訪問(wèn),一般外設(shè)采用無(wú)緩沖,內(nèi)存采用緩沖方式(個(gè)人理解)
- NS:No-Secure 屬性
二級(jí)頁(yè)表描述符格式分析

如上圖所示,和一級(jí)頁(yè)表描述符格式相似,相應(yīng)的位的功能是一樣的。不同的是最后兩位代表了兩種不同的分頁(yè)類型。
- bit[1:0] : 01 時(shí),采用粗粒度大頁(yè)64K進(jìn)行映射 1X時(shí),采用?。?xì))頁(yè)4K進(jìn)行映射
虛擬地址到物理地址的轉(zhuǎn)化
MMU對(duì)于剛接觸的人可能會(huì)感覺(jué)到有些不知所措,因?yàn)樗心敲炊嘞嚓P(guān)的寄存器,還有什么TLB,一級(jí)頁(yè)表,二級(jí)頁(yè)表,粗細(xì)粒度,等等,完全一個(gè)大寫的懵,認(rèn)為MMU的使用是個(gè)很難的過(guò)程,當(dāng)你從了解地址轉(zhuǎn)化流程開(kāi)始入手學(xué)習(xí),慢慢了解了之后,便會(huì)覺(jué)得其實(shí)還是蠻簡(jiǎn)單的,下面來(lái)看下S3c6410中MMU的地址轉(zhuǎn)化流程:
- TLB:Translation Lookaside Buffer,可以稱為快表,當(dāng)要進(jìn)行虛擬地址到物理地址轉(zhuǎn)化的時(shí)候,MMU便會(huì)去查詢這個(gè)表來(lái)確定虛擬地址所對(duì)應(yīng)的物理地址是多少,而這個(gè)表也被我們保存在了內(nèi)存的某個(gè)地址,這個(gè)地址稱為轉(zhuǎn)換表基地址,我們需要將這個(gè)基地址寫到轉(zhuǎn)換表基地址寄存器中。
下面分四種情況對(duì)映射轉(zhuǎn)化過(guò)程作下說(shuō)明:
- 分段式映射,大小1M
- 分段式映射,大小16M
- 分頁(yè)式映射,大小64KB 粗頁(yè)
- 分頁(yè)式映射,大小4KB 細(xì)頁(yè)
1M分段式映射

- 頁(yè)表基地址(TTBRx寄存器中)18bits[31:14]+虛擬地址12bits[31:20] +2[00] 構(gòu)成了一級(jí)頁(yè)表描述符的地址
- 取得了一級(jí)頁(yè)表描述符的地址,訪問(wèn)這個(gè)地址從中可以得到真實(shí)的物理段基地址[31:20]
- 將得到的物理段基地址[31:20]加上虛擬地址中的[19:0]位偏移地址構(gòu)成了真正的物理地址
每個(gè)虛擬地址可以索引 2^12 個(gè)一級(jí)描述符地址,每個(gè)一級(jí)描述符可以包含 2^20 個(gè)物理地址,總共可以索引4G空間
16M分段映射

與1M的段映射相似,只是有些地址線的范圍發(fā)生了改變,另外一級(jí)描述符的第18位為1表示16M的段映射,0表示1M段映射
64KB分頁(yè)映射

- 頁(yè)表基地址+虛擬地址的[31:20]位得到了一級(jí)描述符的地址
- 一級(jí)描述符的[31:10]位為二級(jí)描述符的基地址
- 二級(jí)描述符的基地址+虛擬地址的[19:16]位,最后幾位補(bǔ)0構(gòu)成了二級(jí)頁(yè)表描述符的地址
- 二級(jí)頁(yè)表描述符的第[31:16]位為物理基地址+虛擬地址的[15:0]頁(yè)內(nèi)偏移地址構(gòu)成了真正的物理地址
注:上圖映射是從內(nèi)核手冊(cè)中截取的,有些錯(cuò)誤,二級(jí)頁(yè)表描述符的Second-level tabel index 應(yīng)該為96位,50位應(yīng)為0
4KB分頁(yè)映射

- 頁(yè)表基地址+虛擬地址的[31:20]位得到了一級(jí)描述符的地址
- 一級(jí)描述符的[31:10]位為二級(jí)描述符的基地址
- 二級(jí)描述符的基地址+虛擬地址的[19:12]位,最后幾位補(bǔ)0構(gòu)成了二級(jí)頁(yè)表描述符的地址
- 二級(jí)頁(yè)表描述符的第[31:12]位為物理基地址+虛擬地址的[11:0]頁(yè)內(nèi)偏移地址構(gòu)成了真正的物理地址
代碼實(shí)現(xiàn)-控制led
#define GPKCON (volatile unsigned long*)0xA0008800
#define GPKDAT (volatile unsigned long*)0xA0008808
/*
* 用于段描述符的一些宏定義
*/
#define MMU_FULL_ACCESS (3 << 10) // 訪問(wèn)權(quán)限 AP
#define MMU_DOMAIN (0 << 5) // 屬于哪個(gè)域 Domain
#define MMU_SPECIAL (1 << 4) // 必須是1 XN
#define MMU_CACHEABLE (1 << 3) // cacheable C
#define MMU_BUFFERABLE (1 << 2) // bufferable B
#define MMU_SECTION (2) // 表示這是段描述符 10
#define MMU_SECDESC (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_SECTION)
#define MMU_SECDESC_WB (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION)
void create_page_table(void)
{
unsigned long *ttb = (unsigned long *)0x50000000;
unsigned long vaddr, paddr;
vaddr = 0xA0000000;
paddr = 0x7f000000;
*(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC; //將虛擬地址A000映射到led所對(duì)應(yīng)的物理地址區(qū)間
vaddr = 0x50000000;
paddr = 0x50000000;
while (vaddr < 0x54000000)//64M的區(qū)間地址虛擬地址與物理地址映射相同, 或者說(shuō)相當(dāng)于沒(méi)有進(jìn)行地址轉(zhuǎn)化
{
*(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC_WB;
vaddr += 0x100000;
paddr += 0x100000;
}
}
void mmu_init()
{
__asm__(
/*設(shè)置TTB Base addr*/
"ldr r0, =0x50000000\n"
"mcr p15, 0, r0, c2, c0, 0\n"
/*不進(jìn)行權(quán)限檢查 Domain*/
"mvn r0, #0\n"
"mcr p15, 0, r0, c3, c0, 0\n"
/*使能MMU*/
"mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #0x0001\n"
"mcr p15, 0, r0, c1, c0, 0\n"
:
:
);
}
int main()
{
create_page_table();
mmu_init();
*(GPKCON) = 0x11110000;
*(GPKDAT) = 0xa0;
return 0;
}
此去經(jīng)年
zhaiyk@sina.cn
August 10, 2016


