- 嵌入式系統Linux內核開發實戰指南(ARM平臺)
- 王洪輝編著
- 581字
- 2018-12-27 18:21:37
第4章 ARM處理器內存管理單元(MMU)
4.1 ARM處理器中CP15協處理器的寄存器
本章和第5章的內容都與ARM處理器中CP15協處理器的寄存器有密切關系,所以我們這里先介紹一下CP15寄存器以及訪問CP15寄存器的匯編指令。
4.1.1 訪問CP15寄存器的指令
訪問CP15寄存器指令的編碼格式及語法說明如下:

說明:
<opcode_1>:協處理器行為操作碼,對于CP15來說,<opcode_1>永遠為0b000,否則結果未知。
<rd>:不能是r15/pc,否則,結果未知。
<crn>:作為目標寄存器的協處理器寄存器,編號為C0~C15。
<crm>:附加的目標寄存器或源操作數寄存器,如果不需要設置附加信息,將crm設置為c0,否則結果未知。
<opcode_2>:提供附加信息比如寄存器的版本號或者訪問類型,用于區分同一個編號的不同物理寄存器,可以省略<opcode_2>或者將其設置為0,否則結果未知。

4.1.2 CP15寄存器介紹
CP15的寄存器列表如表4-1所示。
表4-1 ARM處理器中CP15協處理器的寄存器

CP15中寄存器C0對應兩個標識符寄存器,由訪問CP15中的寄存器指令中的<opcode_2>指定要訪問哪個具體物理寄存器,<opcode_2>與兩個標識符寄存器的對應關系如下所示:
● CP15的寄存器C0

1)主標識符寄存器
訪問主標識符寄存器的指令格式如下所示:
mrc p15, 0, r0, c0, c0, 0 ;將主標識符寄存器C0,0的值讀到r0中
ARM不同版本體系處理器中主標識符寄存器的編碼格式說明如下。
ARM7之后處理器的主標識符寄存器編碼格式如下所示:


ARM7處理器的主標識符寄存器編碼格式如下所示:


ARM7之前處理器的主標識符寄存器編碼格式如下所示:


2)cache類型標識符寄存器
訪問cache類型標識符寄存器的指令格式如下所示:
mrc p15, 0, r0, c0, c0, 1 ;將cache類型標識符寄存器C0,1的值讀到r0中
ARM處理器中cache類型標識符寄存器的編碼格式如下所示:


其中控制字段位[28:25]的含義說明如下:
表4-2 cache類型標識符寄存器的控制字段位[28:25]

控制字段位[23:12]和控制字段位[11:0]的編碼格式相同,含義如下所示:

cache容量字段bits[8: 6]的含義如下所示:

cache相聯特性字段bits[5: 3]的含義如下所示:

cache塊大小字段bits[1: 0]的含義如下所示:

● CP15的寄存器C1
訪問主標識符寄存器的指令格式如下所示:
mrc p15, 0, r0, c1, c0{, 0} ;將CP15的寄存器C1的值讀到r0中 mcr p15, 0, r0, c1, c0{, 0} ;將r0的值寫到CP15的寄存器C1中
CP15中的寄存器C1的編碼格式及含義說明如下:


CP15中的寄存器C2保存的是頁表的基地址,即一級映射描述符表的基地址。其編碼格如下所示:
● CP15的寄存器C2

● CP15的寄存器C3
CP15中的寄存器C3定義了ARM處理器的16個域的訪問權限。

● CP15的寄存器C5
CP15中的寄存器C5是失效狀態寄存器,編碼格式如下所示:

其中,域標識bit[7:4]表示存放引起存儲訪問失效的存儲訪問所屬的域。
狀態標識bit[3:0]表示放引起存儲訪問失效的存儲訪問類型,該字段含義如表4-3所示(優先級由上到下遞減)。
表4-3 狀態標識字段含義

● CP15中的寄存器C6
CP15中的寄存器C5是失效地址寄存器,編碼格式如下所示:

● CP15中的寄存器C7
CP15的C7寄存器用來控制cache和寫緩存,它是一個只寫寄存器,讀操作將產生不可預知的后果。
訪問CP15的C7寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c7>, crm, <opcode_2>;<rd>、<crm>和<opcode_2>的不同取值 組合 實現不同功能
● CP15中的寄存器C8
CP15的C8寄存器用來控制清除TLB的內容,是只寫寄存器,讀操作將產生不可預知的后果。
訪問CP15的C8寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c8>, crm, <opcode_2>;<rd>、<crm>和<opcode_2>的不同取值 組合實現不同功能,見第4.2節
● CP15中的寄存器C9
CP15的C9寄存器用于控制cache內容鎖定。
訪問CP15的C9寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c9>, c0, <opcode_2> mrc p15, 0, <rd>, <c9>, c0, <opcode_2>
如果系統中包含獨立的指令cache和數據cache,那么對應于數據cache和指令cache分別有一個獨立的cache內容鎖定寄存器,<opcode_2>用來選擇其中的某個寄存器:
<opcode_2>=1選擇指令cache的內容鎖定寄存器;
<opcode_2>=0選擇數據cache的內容鎖定寄存器。
CP15的C9寄存器有A、B兩種編碼格式。編碼格式A如下所示:

其中index表示當下一次發生cache未命中時,將預取的存儲塊存入cache中該塊對應的組中序號為index的cache塊中。此時序號為0~index-1的cache塊被鎖定,當發生cache替換時,從序號為index到ASSOCIATIVITY的塊中選擇被替換的塊。
編碼格式B如下所示:


● CP15的寄存器C10
CP15的C10寄存器用于控制TLB內容鎖定。
訪問CP15的C10寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c10>, c0, <opcode_2> mrc p15, 0, <rd>, <c10>, c0, <opcode_2>
如果系統中包含獨立的指令TLB和數據TLB,那么對應于數據TLB和指令TLB分別有一個獨立的TLB內容鎖定寄存器,<opcode_2>用來選擇其中的某個寄存器:
<opcode_2>=1選擇指令TLB的內容鎖定寄存器;
<opcode_2>=0選擇數據TLB的內容鎖定寄存器。
C10寄存器的編碼格式如下:


● CP15的寄存器C13
C13寄存器用于快速上下文切換FCSE。
訪問CP15的C13寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c13>, c0, 0 mrc p15, 0, <rd>, <c13>, c0, 0
C13寄存器的編碼格式如下所示:

其中,PID表示當前進程的所在的進程空間塊的編號,即當前進程的進程標識符,取值為0~127。
0:MVA(變換后的虛擬地址)= VA(虛擬地址),禁止FCSE(快速上下文切換技術),系統復位后PID=0;
非0:使能FCSE。
4.2 MMU簡介
MMU是Memory Manage Unit的縮寫,即存儲管理單元的意思。MMU實現以下功能:
1)虛擬存儲地址到物理存儲地址的映射;
2)控制存儲空間訪問權限;
3)設置存儲空間的緩沖特性。
與MMU相關的一些基本概念介紹如下:
■ 頁表(Translate Table)
頁表又叫翻譯表,用來將虛擬地址翻譯成對應的物理地址,它位于內存中,是實現MMU功能的重要組成部分,處理器通過查找頁表中的描述符來獲取虛擬地址對應的物理地址。ARM處理器是按兩級分頁來管理內存的,所以頁表包括一級頁表和二級頁表。一級頁表中的每一項(1個字,4字節)對應于虛擬存儲空間的一段(section),一段的大小為1MB(0x100000字節),該項包含了該虛擬存儲段對應的物理存儲段的基地址或者一段存儲空間內每頁的二級頁表描述符組成的表的基地址、所屬的內存域編號、緩沖特性等,一級頁表的基地址保存在ARM處理器中CP15協處理器的C2寄存器中,該寄存器中保存的是一級頁表的物理基地址,而不是虛擬地址。二級頁表中的每一項(1word,4bytes)對應于虛擬存儲空間的一頁,一頁的大小可以是4KB或1KB,該項包含了該虛擬存儲頁對應的物理存儲頁的基地址、該頁的訪問權限和該頁的緩沖特性等。我們將頁表中的每一項叫做一個地址變換條目(entry),也可以叫一個頁表項。
■ 翻譯援助緩沖區(Translation Lookaside Buffer,TLB)
TLB在硬件上和cache一樣,是處理器內部的一小塊高速SRAM內存,用于緩存,與cache不同的是,它專門緩存存放在內存中的頁表,容量相對比較小,而cache則用于緩存普通內存,容量相對比較大。TLB也分為數據TLB和指令TLB,指令TLB用于取指令時的指令地址翻譯,而數據TLB用于其他存儲訪問操作時的地址翻譯。有的處理器中數據TLB和指令TLB是分開的,有的處理器中這兩者是統一的。TLB是為了提高處理器查詢頁表的速度而設計的,所以TLB又叫快表。當處理器要查詢頁表時首先在TLB中查找,如果要查找的頁表項不在TLB中,那么CPU從位于內存中的頁表中查詢,并把相應的結果添加到TLB中,這樣CPU下次查找該頁表項時就可以從TLB中直接獲取。
4.3 系統訪問存儲空間的過程
系統訪問存儲空間的過程對于使能MMU和禁止MMU兩種情況是不一樣的。ARM處理器中控制MMU功能的開關位是CP15協處理器的C1寄存器的bit[0],當該位為0時禁止MMU功能,當該位為1時使能MMU功能。

4.3.1 使能MMU時的情況
當CPU請求存儲訪問時,首先在TLB中查找虛擬地址,如果該虛擬地址對應的地址變換條目(頁表項)不在TLB中,CPU從位于內存中的頁表中查詢對應于該虛擬地址的頁表項,并把相應的結果添加到TLB中,這樣CPU下次再訪問該頁表項時就可以直接從TLB中獲取。如果TLB已經裝滿,還應該根據一定的淘汰算法進行替換。
在得到了需要的頁表項后,將進行以下操作:
1)得到該虛擬地址對應的物理地址;
2)根據頁表項中的緩沖特性控制位C(Cachable)和B(Bufferable)的值決定是否緩存該存儲訪問的結果;
3)根據存取權限控制位和所屬存儲域的權限設置情況確定該存儲訪問是否被允許;
4)對于不允許緩存(uncached)的存儲訪問,使用上面步驟1)中得到的物理地址訪問存儲空間。對于允許緩存(cached)的存儲訪問,如果cache命中,則忽略物理地址;如果cache沒有命中,則使用上面步驟1)中得到的物理地址訪問存儲空間,并把該數據塊讀到cache中。
4.3.2 禁止MMU時的情況
如果系統禁止MMU功能,那么CPU的存儲訪問規則如下:
1)當禁止MMU時,是否支持cache和Write Buffer由各具體芯片確定。如果芯片規定當禁止MMU的同時也禁止cache和Write Buffer,則存儲訪問不考慮緩沖特性控制位C和B的設置情況;如果芯片規定當禁止MMU時可以使能cache和Write Buffer,則數據訪問時,C=0,B=0,指令讀取時,如果使用數據和指令分開的TLB,則C=1,如果使用統一的TLB,則C=0。
2)存儲訪問不進行權限控制,MMU也不會產生存儲訪問中止信號。
3)所有的物理地址和虛擬地址相同,也就是使用所謂的平板存儲模式。
4.3.3 使能/禁止MMU時應注意的問題
在使能和禁止MMU時要注意以下幾點:
1)在使能MMU前,要在內存中建立好頁表,同時CP15中的各相關寄存器必須完成初始化。
2)如果使用的不是平板存儲模式(物理地址和對應虛擬地址相等),在禁止/使能MMU時,虛擬地址和物理地址的對應關系會發生改變,此時應該清除cache中的當前地址變換條目(TLB)。
3)如果完成禁止/使能MMU的代碼的物理地址和虛擬地址不同,禁止/使能MMU時將造成很大麻煩,因此強烈建議完成禁止/使能MMU的代碼的物理地址和虛擬地址相同(或者與地址無關)。
4.4 ARM處理器地址變換過程
虛擬存儲空間到物理存儲空間的映射是以內存塊為單位進行的,虛擬存儲空間中的一塊連續存儲空間被映射成物理存儲空間中同樣大小的一塊連續存儲空間。每一個地址變換條目(頁表項)記錄了一個虛擬存儲空間的存儲塊的基地址與物理存儲空間相應的一個存儲塊的基地址的對應關系。根據存儲塊大小不同,可以有多種地址變換。
ARM處理器支持的存儲塊大小有以下幾種:
1)段(section):大小為1MB的存儲塊。
2)大頁(Large Page):大小為64KB的存儲塊。
3)小頁(Small Page):大小為4KB的存儲塊。
4)極小頁(Tiny Page):大小為1KB的存儲塊。
通過采用適當的訪問控制機制,還可以將大頁分成大小為16KB的子頁,也可將小頁分成大小為1KB的子頁,但極小頁不能再細分,只能以1KB大小的整頁為單位。
ARM處理器采用兩級頁表實現地址映射:
1)一級頁表中包含以段為單位的地址變換條目或者指向二級頁表的指針,一級頁表實現的地址映射粒度較大。
2)二級頁表中包含以大頁、小頁和極小頁為單位的地址變換條目。
當以二級分頁管理某段存儲空間時,要同時設置一級頁表項和二級頁表項,一個一級頁表項對應一段(1section=1MB)虛擬存儲空間的映射關系,一個一級頁表項對應一張二級頁表,這張二級頁表中的所有頁表項合在一起對應了前面一級頁表項所對應的一段虛擬存儲空間的映射關系。ARM處理器的二級頁表分為粗粒度二級頁表和細粒度二級頁表,一張粗粒度二級頁表的最大容量為1KB,一張細粒度二級頁表的最大容量為4KB,不管是粗粒度還是細粒度頁表,每張頁表都對應一段虛擬存儲空間的映射關系。所以粗粒度二級頁表的頁表項(頁描述符)最小只能描述4KB大小(小頁)虛擬存儲空間的映射關系,如果再小就沒有足夠的頁表空間來存放一段虛擬存儲空間的全部頁表項(因為粗粒度二級頁表的最大容量為1KB),而細粒度二級頁表的頁描述符最小可以描述1KB大小(極小頁)的虛擬存儲空間的映射關系。
綜上所述,我們可以歸納出以下6種ARM處理器的地址變換方法:
1)分段地址變換,這種變換只需要一級地址變換,而下面5種都需要兩級地址變換;
2)粗粒度大頁地址變換;
3)粗粒度小頁地址變換(Linux通常使用的地址變換方法);
4)細粒度大頁地址變換;
5)細粒度小頁地址變換;
6)細粒度極小頁地址變換。
在講解以上各種地址變換方法之前我們先介紹一下一級映射描述符和二級映射描述符的定義。
4.4.1 MMU的一級映射描述符
ARM處理器MMU的一級映射描述符編碼格式如下所示:


表4-4 一級描述符對應的存儲空間的cache和write buffer特性控制位

4.4.2 MMU的二級映射描述符
ARM處理器MMU的二級映射描述符編碼格式如下所示:


表4-5 二級描述符對應的存儲空間的cache和write buffer特性控制位

4.4.3 基于段的地址變換過程(見圖4-1)

圖4-1 分段地址變換過程
4.4.4 粗粒度大頁地址變換過程(見圖4-2)

圖4-2 粗粒度大頁地址變換過程
4.4.5 粗粒度小頁地址變換過程(見圖4-3)

圖4-3 粗粒度小頁地址變換過程
4.4.6 細粒度大頁地址變換過程(見圖4-4)

圖4-4 細粒度大頁地址變換過程
4.4.7 細粒度小頁地址變換過程(見圖4-5)

圖4-5 細粒度小頁地址變換過程
4.4.8 細粒度極小頁地址變換過程(見圖4-6)

圖4-6 細粒度極小頁地址變換過程
4.5 ARM存儲空間訪問權限控制
在ARM處理器中,MMU將整個存儲空間分成最多16個域,記作D0~D15,每個域對應一定的存儲區域,該區域具有相同的訪問控制屬性。
在ARM處理器中,MMU中的每個域的訪問權限分別由CP15的C3寄存器中的兩位來設定,C3寄存器剛好可以設置16個域的訪問權限。C3寄存器的域定義如表4-6所示。
表4-6 CP15的C3寄存器的域定義

C3寄存器的D0~D15各占兩位,它們分別控制D0~D15共16域的訪問類型,具體說明如表4-7所示。
表4-7 域的訪問控制字段編碼及含義

當域訪問權限控制位設置為上面的0b01即客戶類型權限時,用戶模式以及特權模式的訪問權限則由CP15的C1控制寄存器中的R和S位以及頁表中地址變換條目中的訪問權限控制位AP兩位來確定,具體說明如表4-8所示。
表4-8 MMU中存儲訪問權限控制

4.6 TLB操作
對TLB的操作是通過訪問CP15的C8和C10寄存器來完成的,寫CP15的C8/C10寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c8>, crm, <opcode_2> mcr p15, 0, <rd>, <c10>, crm, <opcode_2>
4.6.1 使TLB內容無效
使TLB中的內容無效是通過寫CP15的寄存器C8來實現的,指令如表4-9所示。
表4-9 使TLB內容無效操作指令

4.6.2 鎖定TLB內容
鎖定TLB是通過寫CP15的寄存器C10來實現的。
鎖定TLB中N條地址變換條目的操作步驟說明如下:
1)確保在整個鎖定過程中不會產生異常中斷,可以通過禁止中斷等方法實現;
2)如果鎖定的是指令TLB或者統一的TLB,將base=N、victim=N、P=0寫入C10;
3)使整個將要鎖定的TLB無效;
4)如果想要鎖定的是指令TLB,確保與鎖定過程所涉及的指令相關的地址變換條目已經加載到指令TLB中;如果想要鎖定的是數據TLB,確保與鎖定過程所涉及的數據相關的地址變換條目已經加載到指令TLB中;如果系統使用的是統一的數據TLB和指令TLB,上述兩條都要保證;
5)對于I=0到N-1,重復執行下面操作:
將base=i、victim=i、P=1寫入寄存器C10,將每一條想要鎖定到快表中的地址變換條目讀取到快表中。對于數據TLB和統一TLB可以使用ldr指令讀取一個涉及該地址變換條目的數據,將該地址變換條目讀取到TLB中。對于指令TLB,通過操作寄存器C7,將相應的地址變換條目讀取到指令TLB中;
6)將base=N、victim=N、P=0寫入寄存器C10。
4.6.3 解除TLB中被鎖定的地址變換條目
解除TLB中被鎖定的地址變換條目,可以使用以下操作步驟:
1)通過操作寄存器C8,使無效TLB中被鎖定的地址變換條目;
2)將base=0、victim=0、P=0寫入C10寄存器。
4.7 存儲訪問失效
ARM處理器通過以下兩種機制來檢測存儲訪問失效,進而中止CPU的運行:
1)MMU硬件模塊檢測與內存管理相關的存儲訪問失效,一旦MMU檢測到存儲訪問失效,它向CPU發出通知,并將存儲訪問失效的相關信息保存到寄存器中,具體說就是將失效狀態保存在CP15的C5寄存器中,將導致失效的地址保存在CP15的C6寄存器中,詳見前面CP15的C5、C6寄存器說明。這種存儲訪問失效叫做MMU失效(MMU Fault)。
2)外部存儲系統向CPU報告存儲訪問失效,這種機制叫做外部存儲訪問中止(External Abort)。
以上兩種訪問失效統稱為存儲訪問中止(Abort)。如果存儲訪問中止發生在數據訪問周期,CPU將產生數據訪問中止異常中斷,即Data Abort;如果存儲訪問中止發生在指令預取周期,那么CPU產生指令預取中止異常中斷,即Prefetch Abort。
4.7.1 MMU失效(MMU Fault)
MMU可以產生以下4大類存儲訪問失效:
1)地址對齊失效:地址對齊失效指揮發生在數據訪問周期,比如訪問字單元(4字節)時地址的bit[1:0]不全是0或者訪問半字(雙字節)單元時地址的bit[0]不等于0;訪問字節單元不會產生地址對齊失效,指令預取周期也不會產生地址對齊失效。
2)地址變換失效:當一級地址變換條目的bit[1:0]為0b00時,表示產生了基于段的地址變換失效;當二級地址變換條目的bit[1:0]為0b00時,表示產生了基于頁的地址變換失效。
3)域控制失效:如果所訪問的存儲地址對應的一級地址變換條目中bit[8:5]的值所指的存儲域的兩位控制位被設置為0,就說明產生了域控制失效,域控制失效可能是基于段的也可能是基于頁的。
4)訪問權限控制失效:參見第4.5節“ARM存儲空間訪問權限控制”,如果出現了訪問權限沖突就產生訪問權限控制失效。
以上4大類存儲訪問失效又可細分為15種類型,見前面CP15的C5寄存器說明。
當發生存儲訪問失效時,存儲系統可以中止3種存儲訪問:cache內容預取、非緩沖的存儲器訪問和頁表訪問。
4.7.2 外部存儲訪問失效(External Abort)
由外部存儲系統向CPU報告存儲訪問失效。
外部存儲訪問失效通過一個外部存儲訪問失效引腳實現,下面的存儲訪問操作可以通過這種機制中止和重啟動:
1)讀操作;
2)非緩沖的寫操作;
3)一級描述符的獲取;
4)二級描述符的獲取;
5)非緩沖的存儲區域中的信號量操作。
注意:在系統中標記為可外部終止的存儲區域不要進行可緩存的寫操作。