每個異常級别,即EL3、EL2或EL1,都有自己的虛拟位址空間。應用程式都有獨立的虛拟記憶體空間,作為應用程式無需了解系統的硬體記憶體布局。為了能夠使得作業系統同時運作多個任務,現代CPU都設計了MMU(記憶體管理單元),其作用是管理虛拟位址和實體位址的映射關系。應用層的虛拟位址看起來連續,實際映射的時候,實體位址很大可能是碎片化的。
虛拟位址:我們編寫應用程式所使用到的運作位址;
實體位址:應用程式在硬體層面使用的位址。
MMU會使用虛拟位址中比較重要的位來索引映射表中的條目,以确定哪個塊會被通路,進而将虛拟位址轉換為實體位址,這種轉換是硬體自動完成的。
除了完成位址轉換外,MMU還會控制記憶體通路權限、記憶體排序和每個區域記憶體的緩存政策。
下面的圖展示了虛拟位址到實體位址的轉換過程,MMU會根據映射表來查找虛拟位址對應的實體頁表入口,對于使用者态的記憶體映射表,我們使用的映射表TTBR0_EL0,而對于核心态,對應的TTBR1_EL1。差別就是TTBR1_EL1可以映射外設實體位址、ROM和RAM,而TTBR0_EL0隻能映射到RAM。ARMv8架構通過這種方式來分離映射使用者層和核心層的虛拟位址。
TLB(D5.9)
TLB全名是轉址旁路緩存,是一種緩存映射表條目的技術。
為什麼要設計TLB?
在沒有TLB之前,虛拟位址的映射需要從記憶體中取映射表,這就導緻了頻繁的記憶體通路,反而會降低系統映射性能。TLB的設計初衷就是支援将映射表存入緩存區域,大大提高映射效率。在虛拟位址映射時,MMU會檢查映射關系是否已經被緩存在了TLB中,如果已被緩存,那麼就會引起緩存命中,此映射關系立即可用。
如果TLB中不包含我們需要的映射關系怎麼辦?
如果TLB不包含處理器發出的虛拟位址的有效映射,稱為TLB缺失,則執行外部映射表查表。MMU内的專用硬體使其能夠讀取記憶體中的映射表。然後,新加載的映射可以被緩存在TLB中,以便在映射表查表沒有導緻頁面故障的情況下進行重複使用。
TLB中都包含了啥?
每一個TLB條目不僅實體位址和虛拟位址,還包含諸如記憶體類型、緩存政策、通路權限、位址空間ID(ASID)和虛拟機ID(VMID)等屬性。
TLB可以容納固定數量的條目。我們可以通過最大限度地減少由映射表周遊引起的外部記憶體通路數量并獲得高TLB命中率來實作最佳性能。ARMv8-A架構提供了一個稱為連續塊條目的功能,可以有效地使用TLB空間。映射表塊條目每個都包含一個連續的位。當設定時,該位向TLB發出信号,它可以緩存一個涵蓋多個塊的映射的單一條目。一個查找可以索引到一個連續塊所覆寫的位址範圍的任何地方。是以,TLB可以為定義的位址範圍緩存一個條目,使得在TLB中存儲更大範圍的虛拟位址成為可能。
**要使用一個連續的位,連續的塊必須是相鄰的,也就是說它們必須對應于一個連續的虛拟位址範圍。它們必須從一個對齊的邊界開始,具有一緻的屬性,并指向同一級别轉換的連續輸出位址範圍。**要求的對齊方式是,4KB顆粒的VA[20:16]或64KB顆粒的VA[28:21],對所有位址都是一樣的。塊條目需要以下數量:
- 16x4KB相鄰塊
- 32x32MB相鄰塊
- 32x64KB相鄰塊
映射顆粒大小
映射控制寄存器TCR_EL1控制了EL1和EL0的記憶體管理功能。寄存器如下圖所示,中級實體位址大小(IPS)字段控制最大輸出位址大小。如果映射指定了超出此範圍的輸出位址,則通路失敗,000=32位實體位址,101=48位。兩位映射顆粒(TG)TG1和TG0字段分别給出核心或使用者空間的顆粒大小,00=4KB,01=16KB,11=64KB。
完整的映射過程可能需要三到四個級别的映射表。你不需要實作所有級别。第一個級别的查找實際上是由顆粒大小和TCR_ELn.TxSZ字段決定的。
顆粒大小對映射表的影響
AArch64支援映射三種不同的顆粒大小。這些顆粒定義了映射表最低層的塊大小,并控制使用中的映射表的大小。較大的顆粒大小減少了所需的頁表層數,這在使用管理程式提供虛拟化的系統中可能成為一個重要因素。
-
4KB
當你使用4kB的顆粒大小時,硬體可以使用4級查找過程。48位位址每一級有9個位址位被翻譯,即每一級有512個條目,最後的12位在4kB内選擇一個位元組,直接來自原始位址。
虛拟位址的第47:39位索引到512個條目的L0表。每個表項都跨越512GB範圍,并指向一個L1表。在這個512條目的L1表中,第38:30位被用作索引來選擇一個條目,每個條目都指向一個1GB塊或一個L2表。位29:21索引到一個512條目的L2表,每個條目指向一個2MB塊或下一級表。在最後一級,第20:12位索引到一個512條目的L2表,每個條目指向一個4kB的塊。
-
16KB
當你使用16KB的顆粒大小時,硬體可以使用4級查找過程。48位的位址每一級映射有11個位址位,即每一級有2048個條目,最後的14位在4KB内選擇一個位元組,直接來自原始位址。0級表隻包含兩個條目。虛拟位址的第47位從兩個條目的L0表中選擇一個描述符。這些表項中的每一個都跨越了128TB的範圍,并指向一個L1表。在這個2048個條目的L1表内,第46:36位被用作索引來選擇一個條目,每個條目指向一個L2表。第35:25位索引到一個2048個條目的L2表,每個條目指向一個32MB的塊或下一個表層。在最後的映射階段,Bit[24:14]索引到一個2048個條目的L2表,每個條目指向一個16KB的塊。
-
64KB
當你使用64kB的顆粒大小時,硬體可以使用3級查找過程。第1級表隻包含64個條目。
虛拟位址的第47:42位從64個條目的L1表中選擇一個描述符。這些表項中的每一個都跨越了4TB的範圍,并指向一個L2表。在這個8192個條目的L2表内,第41:29位被用作索引來選擇一個條目,每個條目指向一個512MB的塊或一個L2表。在最後的DeepL,第28:16位索引到一個8192條目的L3表,每個條目都指向一個64kB的塊。