date: 2017-8-28linux
2011年,ARM推出了第8代架構ARMv8(ARMv4以前的架構已經被廢棄),ARMv8架構是迄今爲止ARM歷史上變革最大的架構。編程
若是知道了架構的歷史背景,以及設計者的設計理念,那麼理解架構的行爲方式便很容易了。爲了方便後續的研究,咱們先來回顧下ARMv8的歷史背景(具體可參考ARMv8白皮書,連接地址爲:http://www.arm.com/zh/files/downloads/ARMv8_white_paper_v5.pdf,感興趣的同窗能夠自行閱讀)。緩存
ARM爲低功耗而生,過去20年,基於RISC指令集的ARM芯片在各個領域得到普遍的成功。除了移動設備領域,ARM芯片也已經悄悄滲透到PC領域(基於ARM的平板能夠給用戶帶來PC級的體驗,尤爲是win10宣佈支持ARM)、企業與服務器領域(這些領域一直是intel的天下)。爲了更精準的響應市場的需求,從ARMv7開始,ARM將其架構分爲三個品類,分別是:安全
2011年10月,ARM推出了Cortex-A7以及大小核架構,再一次振奮了業界,在延遲電池壽命的同時,爲用戶提供優秀智能手機的體驗。Cortex系列迅速成爲ARM新業務中的王牌。服務器
ARM芯片的性能上去了,那些包含複雜運算的大致量程序能夠開心的跑起來了。但問題來了,這些大致量的程序須要更多的地址空間(好比超過4G的地址空間),因而AMR在AMRv7中增長了LAPE(Large Physical Address Extensions),使用48位虛擬地址,並將虛擬內存映射到40位物理內存地址上(支持高達1024G的物理內存)。網絡
利用LAPE,內存空間的問題算是暫時解決了,但這隻能是補救方案。若是你想繼續搞企業級產品,想接着玩服務器,不搞64位操做系統行嗎?不搞虛擬化行嗎?所以ARM在設計v8架構時,它面臨下面幾個「剛需」:架構
因爲基於32位ARMv7架構的Cortex系列大受歡迎,並且已經創建起完善的開發者生態。所以新架構(指ARMv8)不能推倒重來另起爐竈,必須兼容ARMv7架構中的主要特性。app
爲了兼容32位程序,新架構將運行狀態分紅AArch64和AArch32兩種狀態,這兩種狀態的具體情形見下表:dom
AArch64: | 64bit的運行狀態。地址存儲在64bit的寄存器中,使用A64指令集,可使用64bit寄存器 |
提供31個64位的通用寄存器(命名爲X0-X30,能夠經過W0~W30來訪問低32位。X30通常用做程序連接寄存器); | |
一個64位的程序計數器(PC); | |
64位的堆棧指針SP(每一個異常等級一個); | |
以及64位的異常連接寄存器ELR(每一個異常等級一個),存儲了從中斷返回的地址 | |
提供32個128位的NEON浮點寄存器(命令爲V0-V31),支持SIMD的向量運算以及標量浮點的運算 | |
使用A64指令集,A64指令集使用固定長度的指令,指令使用32位編碼 | |
從新定義了異常模型,該模型定義了4個異常等級EL0-EL3,異常等級提供了執行權限的等級制度,層級越高,權限越大。 | |
支持64位的虛擬地址空間 | |
定義了一組Process state寄存器PSTATE(NZCV/DAIF/CurrentEL/SPSel等),用於保存PE當前的狀態信息,A64指令集提供專門的指令來訪問這些PSTATE | |
每一個系統寄存器(System register)名稱後面都帶有一個後綴,該後綴表示能夠訪問該寄存器的最低EL級別 | |
AArch32: | 32bit的運行狀態。地址存儲在32bit的寄存器中,可使用T32或者A32指令,使用32bit的寄存器 |
提供13個32位的通用寄存器(R0-R12); | |
一個32位的程序計數器PC; | |
一個32位的堆棧指針寄存器SP; | |
一個32位的程序連接寄存器LR,LR不只做爲程序連接器也用做異常連接寄存器ELR | |
提供一個ELR,用來保存Hyp模式下異常返回的地址,Hyp模式與虛擬化有關。 | |
提供32個64位的浮點寄存器,支持Advanced SIMD的向量計算以及標量浮點運算 | |
使用A32(使用固定長度指令,指令32位編碼)或者T32(使用變長指令,指令編碼能夠是16位的也能夠是32位的)指令集 | |
支持ARMv7架構中基於PE模式(FIQ/IRQ/Abort/Undefined/Svc)的異常模型。本質上是將PE模式映射到ARMv8架構中基於異常等級的異常模型中來。 | |
支持32位的虛擬地址空間 | |
定義了一組Process state寄存器PSTATE(NZCV/DAIF/CurrentEL/SPSel等),用於保存PE當前的狀態信息,A32/T32指令集提供專門的指令來訪問這些PSTATE。指令能夠經過APSR(Application Program Status Register)或者CPSR(Current Program Status Register)來訪問PSTATE,就像在ARMv7架構中作的那樣。 |
表1:AArch64與AArch32的對比ide
ARMv7及以前的架構,爲PE定義了不少種模式:System/User/FIQ/Svc/Abort/IRQ/Undefined,每種模式都有本身的R13(用做SP)與R14(用做LR),FIQ模式還有本身的R8-R12。應用程序大部分時間跑在User模式下。這種設計,一方面是權限隔離,不一樣的模式有不一樣的資源訪問權限;另外一方面,FIQ/Abort/IRQ/Undefined這幾種模式與異常或者中斷關聯,處理相應的異常時迅速切換到對應的模式提升了處理效率。
到了ARMv8,ARM摒棄了這種多模式的設計,從新定義了一套異常或者說等級模型:
異常等級也能夠理解爲特權級別(Privilege Level)。特權級別劃分出來了,那麼在每一個級別,均可以幹那些事?ARM對這4個等級的設想能夠描述以下:
圖1:四個異常等級的實施例
在實現架構時(ARM只是出設計,具體的芯片由廠商實現),並非全部的EL都要實現,其中EL0-EL1是必需要實現的,EL2主要是爲了支持虛擬化,能夠不用實現,EL3用來支持Security,也能夠不實現。
AArch32運行狀態兼容ARMv7中的多模式PE,是經過將不一樣的PE模式映射到不一樣的EL來實現的。
若是換作你,如何在ARMv8架構的等級模型上構建Linux操做系統呢?Linux操做系統只用到兩個特權級別:用戶空間程序與操做系統內核,用戶空間的程序通常運行在非特權級別,操做系統內核運行在特權級別,用戶空間發起的系統調用,以及觸發的異常與中斷,都須要交給「具備特權」的內核空間來處理。所以,針對ARMv8架構,用戶空間能夠落實到EL0層,內核空間能夠落實到EL1層。
爲了向下兼容,ARM v8a將運行狀態分紅AArch64和AArch32兩種狀態。AArch64就是64位指令集的運行態,而AArch32是兼容Arm-v7a的狀態,全部Arm-v7a以及更早的軟件均可以在這個狀態上正常運行。對於應用程序來講,因爲EL0沒有權限進行AArch64和AArch32狀態切換的,所以只能一條道走到黑地用一種態。這也是AArch64與AArch32使用各自獨立指令集的緣由,兩種狀態下的指令集保持着井水不犯河水的「剋制」。但兩者在同一個系統中能夠共生,不免眉來眼去:
圖2:AArch32狀態的下用到的寄存器是用AArch64中的寄存器來模擬的
地址映射就是把PE發出的虛擬地址映射爲內存的物理地址的過程。將虛擬地址映射爲物理地址,顯然這是一件須要「特權」才能乾的事(出於安全考慮,不能在非特權級去執行,否則,那些壞人想攻破你的系統不要太容易),須要與特權等級也就是異常等級聯繫起來:
異常等級及其支持的地址映射以下圖所示:
圖3:stage1/stage2地址映射與異常等級的關係
安全與非安全是一種「物理隔離」。當PE運行在安全模式下,它能夠訪問那些標記爲安全的內存(表示這些內存只能在安全模式下訪問),也能夠訪問那些標記爲非安全的內存。當PE運行在非安全模式,它只能訪問那些標記爲非安全的內存,而沒法訪問那些標記爲安全的物理內存,從而實現物理隔離。
只有在非安全狀態下,從EL1/EL0提高至EL2等級時,Stage2的地址映射纔會開啓。若是Stage2沒有開啓,那麼Stage1從虛擬地址VA轉換後獲得的地址就是物理地址PA。而若是Stage2開啓,那麼Stage1從虛擬地址VA轉換後獲得的地址被稱爲「中間態」物理地址IPA,Stage2再將IPA轉換爲物理地址PA。
地址映射就是將虛擬地址映射爲物理地址,Stage1就夠了,爲什在EL2層又加上Stage2呢?咱們能夠這樣理解:
在後面的討論中,咱們認爲只進行stage 1的地址映射。
64位系統能夠支持更多的虛擬地址空間了,那麼須要將虛擬地址直接提升到64位嗎?一方面,虛擬地址空間越大,一次地址映射(TTW,translation table walk)就須要更多級(Level)的查找。好比在32位系統中,若是page的尺寸爲4K,可能經過兩級查找(目錄表查找/頁表查找)就能將一個32位的虛擬地址映射爲對應的物理地址;若是虛擬地址提升到64位,則須要超過4級的查找才能完成一次地址映射,致使地址映射的開銷增長。另外一方面,當前也沒有那麼大的物理內存,用40位的物理地址就能覆蓋1024G的物理內存了,已經足能夠應付當前及將來很長一段時間的需求了。
所以,ARMv8的地址映射基於ARMv7的LAPE機制,LAPE的設計之初是要解決在如何在32位系統給程序提供超過4G內存空間的問題。LAPE使用48位虛擬地址,而且能夠將虛擬內存映射到40位物理內存地址上。每一個TTBR(地址映射表基址寄存器)最多可支持48位的虛擬地址空間,具體的位數在運行時設定。在一次TTW過程當中,有多少個級別的查找,取決於使用多少位的虛擬地址。
若是地址映射只支持一個VA區間(TCR_ELx 中若是隻有T0SZ域有效,說明地址映射只支持一個虛擬地址空間),則TTBR_ELx指向轉換表的基址,且L0(第一級)查找必須使用該轉換表。VA區間的虛擬地址位數=64-TTBR_ELx.T0SZE。
若是地址映射支持兩個虛擬地址區間(TCR_ELx 中T0SZ域與T1SZ域都有效),則每一個虛擬地址區間對應一個TTBR_ELx寄存器,其中TTBR0_ELx指向第一VA區域(起始地址爲0x0000000000000000)的轉換表的基址,第一VA區域的虛擬地址位數=64-TCR_ELx.T0SZ;TTBR1_ELx指向第二個VA區域(截止地址爲0xFFFFFFFFFFFFFFFF)的轉換表的基址,第二個VA區域的虛擬地址位數=64-TCR_ELx.T1SZ。
下圖展現了EL1/EL0 Stage1的地址映射,該轉換支持兩個VA區域,虛擬地址位數爲48,各個VA區域的地址空間範圍如圖中所示:
圖4:當地址映射支持兩個VA區域時每一個VA區域的分佈狀況
虛擬地址的位數肯定了爲48位,那麼咱們要爲48位的虛擬地址從新建立一種數據類型嗎?徹底不必,咱們用現成的64位整數來存儲地址,只是在進行地址映射時,從64位中取出「有效地址位」即低48位做爲虛擬地址。高16位徹底能夠拿來「變廢爲寶」,記錄一些額外的信息。
虛擬地址的位數定下來了,那麼地址映射過程當中要通過幾級查找,才能把虛擬地址對應的物理地址找到呢?這與地址映射粒度有關。轉換粒度由兩個含義:一是page的大小,二是查找表的大小即表中包含多少個表項。page大小與查找表之間有什麼關聯呢?爲了提升效率,通常將查找表的尺寸與page對齊,這樣一個page就能容納一張查找表了。查找表的尺寸肯定了,表中每一項的尺寸是固定的(爲64位),那麼整個查找表的大小就能夠肯定了。
ARMv8架構支持3種地址映射粒度,以下表:
4KB granule |
16KB granule |
64KB granule |
|
查找表的大小(最多能夠容納的條目數) |
512 |
2048 |
8192 |
每級查找消耗虛擬地址中的位數 |
9-bit |
11-bit |
13-bit |
頁內偏移offset |
VA[11,0] |
VA[13,0] |
VA[15,0] |
支持幾級查找 |
4級 |
4級 |
3級 |
TCR_ELx.TG0域(共2bit)的取值 |
00b |
10b |
01b |
表2:3種轉換粒度對比表
咱們以4KB的粒度來講明上表中各項的含義。
如無特殊聲明,後文中咱們討論的地址映射是以4KB爲粒度的。4KB轉換粒度下的4級查找,以下圖所示:
圖5:查找粒度爲4K時4級查找過程
咱們歷經4級查找,最終目的是爲了找到容納目標物理內存的物理頁的起始地址。物理內存是以頁爲單位組織起來的,所以,要找物理內存,先找到它所在的頁。這種內存管理方式被稱做頁式內存管理。
如今咱們思考一個問題,爲何要建立這種層級查找結構,爲何不乾脆搞一張超大的頁表,表裏的每一項指向一個頁面的基址。這樣只須要查一次表就能夠完成地址映射了,整個結構更扁平了,以下圖示意。
圖6:一種設想的只須要一級查找的地址映射過程
這種架構至少存在下面幾個問題:
首先,Page Table的大小問題。爲了完成一次就能找到的目標,Page Table確定是個線性表(不能玩hash表那一套),用索引作下標直接能夠找到對應的項,而咱們又是拿虛擬地址去索引這張表,所以虛擬地址覆蓋多少個Page,Page Table中就應該有多少項。所以在32位系統中就有 4G/4K=1M個Page。因此Page Table中要有1048576個表項,每一個表項4byte,則Page Table就要消耗掉4M的空間。若是實際的物理內存只有512M,那Page Table中的不少項就會白白浪費。而在4級查找中,經過4個層級的查找表,咱們創建起了一個查找樹(或者目錄樹),整棵查找樹是動態造成的。一個進程不可能用光全部的虛存空間,虛存空間中確定有不一樣大小級別的空洞,在樹形結構中,對於空洞咱們能夠不建立對應的查找表從而節省空間。下圖展現了AArch64的4級查找表構成的查找樹。L0 Table中的一個表項領銜512G的地址空間,若是進程用不到這塊地址空間,那麼以該表項爲根,衍生的1個L1 Table以及512個L2 Table,以及由512個L2 Table衍生的512*512個L3 Table都不會被建立。一樣,L1 Table的一個表項領銜1G的地址空間,若是該1G空間不會被用到,那麼由該表項衍生的全部查找表都不會被建立。
圖7:4個層級組成的查找樹
其次咱們要考慮cache命中率的問題。因爲那張Page Table太大了,cache每次只能裝載其中的一部分。因爲地址的跳躍,致使Page Table的索引跳躍,致使以前加載到cache中內容失效,須要從新裝載cache。而在4級查找結構中,每一個查找表的size與Page size對齊,提升了cache的命中率。
綜合這兩點,咱們獲得結論:頁式內存管理是綜合考慮空間與效率的結果。
經過前面的介紹,咱們已經看到了,4KB的轉換粒度須要4個級別的查找(因此才用translation table walk來描述地址映射過程,轉換過程就像在一條分叉衆多的路上行走同樣,每到一個路口,就須要拿出你的指南針,去找到前進的方向),這條路徑並不短。有沒有能夠提早結束查找的方法呢?
ARM在內存頁以外,提出內存block,一個block包含多個連續的頁,一個塊能夠覆蓋的空間更大。若是咱們咱們知道物理內存在某個塊中,並且知道了相對於塊基址的偏移,那麼咱們只須要找到這個塊的基址,再加上塊內偏移,即可以獲得物理內存的地址,從而提早就是查找過程。所以查找表中,可能存在在兩種表項:
4KB轉換粒度下的4級查找能夠進化到這種樣子:
圖8:考慮內存block後,4KB轉換粒度下的4級查找
在上圖中咱們也看到,在4KB的轉換粒度下的4級查找中,只有L1 Table以及L2 Table中能夠出現block描述符。L1 Table中的一個block描述符領銜1GB的地址空間(由於剩下的位段爲IA[29:0]共30bit,能夠覆蓋1G的空間),T2 Table中的block描述符領銜2MB的地址空間(由於剩下的位段爲IA[20:0]共21bit,能夠覆蓋2MB的空間)。block描述符與轉換粒度的關係見下表:
轉換粒度 |
block描述符 |
4KB |
L0 不支持block描述符 L1 支持block描述符,一個block領銜1GB的地址空間 L2 支持block描述符,一個block領銜2MB的地址空間 |
16KB |
L0/L1不支持block描述符 L2 支持block描述符,一個block領銜32MB的地址空間 |
64KB |
不支持L0級別的查找(只有三級查找:L1-L3) 若是ARMv8.2-LPA功能沒開啓的話,L1不支持BLOCK L2支持block描述符,一個block領銜512MB的地址空間 |
表3:3種轉換粒度下block描述符對比
請你們思考下,當轉換粒度爲4K時,爲何L0不支持block呢?
由於L0若是支持block的話,一個block領銜512G空間。一方面當前Android手機的內存最大才12G,上哪去找一塊連續的大小爲512G的物理內存呢?另外一方面block太大,也缺乏一些必要的靈活性。
上表中並無說L4是否支持block,要不要支持呢?答案是不須要支持。L4中維護的已是頁表了,在L4這個級別,即便支持block,block的尺寸已經與page一致了,固然就不必畫蛇添足再支持block了。
L0-L3查找表中的描述符格式:
前文說過,L0-L3的轉換表中的描述符可能存在兩種狀況:table描述符與block描述符。下圖列出轉換粒度爲4KB時,L0-L3的描述符格式:
圖9:4KB轉換粒度下的L0-L2對應的描述符格式
咱們拿64位的整數來表示地址,前文提到過,有效的虛擬地址只有48位,所以其餘的位段能夠挪做他用。因爲轉換表的尺寸與page對齊,轉換表的基址與4K對齊,因此48位的基址中低12位確定爲0,這低12位也可拿來作文章。這裏用bit[1:0]來指示該描述符的類型,以下表:
Bit[1:0]取值 |
描述符類型 |
‘x0’ |
無效描述符 |
‘01’ |
block描述符,output address指向一個block的基址 |
‘11’ |
Table描述符,next-level table address指向下一級轉換表的基址 |
表4:L0-L2描述符類型
在block描述符中,bit[63:52]與bit[11:2]這兩個位段用來描述block屬性(後文討論這些屬性)。
在table描述符中,bit[63:59]用來表示與table有關的屬性,詳細以下表:
標誌位 |
描述 |
NSTable |
NS表示Non-Secure,該table描述符指向的下一級的轉換表是否存儲在secure memory之中。 爲0表示存儲在Secutre PA中,不然表示存儲在Non-secure PA中。 當在non-secure狀態下進行地址映射時,該標誌別忽略 |
APTable |
AP表示Access Permission,這兩個標誌爲指明瞭下一級轉換表的訪問權限,有以下4中狀況: ‘00’——不作限制 ‘01’——EL0沒有權限訪問 ‘10’——任何異常等級都不能寫(修改轉換表) ‘11’——任何異常等級都不能寫(修改轉換表);並且EL0不能讀 |
UXNTable /XNTable |
當地址映射支持兩個VA區域時,名稱爲UXNTable,當地址映射只支持一個VA區域時,名稱爲XNTable。 UXN 的含義是「Unprivileged Execute Never」,XN的含義是「Execute Never」。它們用來表示內存的執行權限。好比咱們在加載動態庫時,動態庫的代碼段所在的地址就具備執行(x)權限。若是標誌位爲0表示具備執行權限,不然沒有執行權限。 |
PXNTable |
該標誌只有當地址映射支持兩個VA區域時有效。PXN表示Privileged Execute Never,表示內存是否具備「特權執行」權限,好比內核的代碼便具備「特權執行」的權限。 |
表5:Table描述符中的標誌位
L3頁描述符格式:
L3查找表即頁表,4KB轉換粒度下,頁表的描述符格式以下:
圖10:4KB轉換粒度下的L3頁描述符格式
頁描述符與block描述符中的屬性字段:
從前文可知,block描述符與page描述符都有兩個屬性位段,主要的屬性字段以下:
圖11:block描述符與table描述符中的屬性位段
這些屬性的含義以下表:
屬性位段 |
描述 |
|||||||||||||||
Contiguous |
該表項是否爲連續表項中的一項。即轉換表在該表項先後是連續的,沒有空洞。這樣,這些連續的表項便有可能一次性加載到cache中(好比由一個TLB entry緩存) |
|||||||||||||||
nG |
not Global 若是該表項緩存在TLB中,該標誌位指示TLB entry是全局有效仍是僅僅對當前進程有效 |
|||||||||||||||
AF |
Access Flag 當該標誌爲0,標明對應的內存區域(一個block或者一個page)是第一次訪問 |
|||||||||||||||
SH |
Shareability Field 參考後文 |
|||||||||||||||
AP[2:1] |
Access Permission. control the stage 1 data access permissions, and: AP[2] Selects between read-only and read/write access. AP[1] Selects between Application level (EL0) control and the higher Exception level control. This provides four permission settings for data accesses: • Read-only at all levels. • Read/write at all levels. • Read-only at the higher Exception level, no access by software executing at EL0. • Read/write at the higher Exception level, no access by software executing at EL0. the following talbe shows the meaning of the AP[2:1] field for stage 1 of a translation regime that applies to both EL0 and a higher Exception level. In this table, an entry of None indicates that any access from that Exception level faults.
|
|||||||||||||||
NS |
Non-secure 當從Secure狀態訪問內存時,該標誌指示轉換後的地址在Secure區域仍是在Non-Secure區域 |
|||||||||||||||
AttrIndx |
指向內存區域的類型以及可緩存性。 參考後文 |
表6:block描述符與table描述符中的屬性字段的含義
ARMv8中定義了以下兩種內存類型(在ARM手冊中,類型是從內存模型的角度來描述,這裏摘自網絡定義)
類型 |
特性 |
Normal (普通) |
。讀寫通過Cache 。支持亂序,內存訪問順序同編程順序可能不一致 。支持預讀取 。支持內存非對齊訪問 |
Device (設備) |
。讀寫不通過Cache 。不支持亂序內存訪問 。不支持預讀取 。不支持內存非對齊訪問 Device類型的內存還有三個屬性,分別用G/R/E來表示,它們的定義是:
|
表7:內存類型分爲normal與device
除了類型外,ARM還定義了其餘內存特性,它們的含義以下:
Shareability (可共享性) |
指當前內存頁表項的數據是否能夠同步到其它CPU上,多核CPU調用帶有該屬性頁表項的數據,一旦某個CPU修改了數據,那麼系統將自動更新到其它CPU的數據拷貝,實現內存數據一致性. 對於Normal類型的內存,有3種狀況: • Inner Shareable, meaning it applies across the Inner Shareable shareability domain. • Outer Shareable, meaning it applies across both the Inner Shareable and the Outer Shareable shareability domains. • Non-shareable. |
Cacheability (可緩存性) |
指當前內存頁表項對於的數據是否能夠加載到Cache當中 對於Normal類型的內存,有3種狀況: • Write-Through Cacheable. • Write-Back Cacheable. • Non-cacheable. |
表8:內存的可共享性與可緩存性
本文首先介紹了ARMv8的歷史背景,瞭解了ARMv8主要的發力點:一是爲了支持更大的地址空間,ARMv8被設計成64爲的架構,而且從新設計的指令集T64;二是爲了應對企業級(服務器)的市場,提供對虛擬化的支持;三是對安全的加強。
爲了兼容舊的架構,ARMv8定義了兩種運行狀態:AARch64與AArch32,在AArch64狀態下運行64位指令,在AArch32狀態下運行32位的ARM指令或者16位的Thumb指令。
ARMv7及以前的架構爲處理器設置了7種模式(mode),並在此基礎上搭建了ARM的異常處理架構。ARMv8摒棄了這種設計, 它定義了4個異常等級(簡稱EL),異常等級構成了一個特權的等級制度,ARMv8在此基礎上構建新的異常處理架構。CPU廠家在實現本身的CPU時,只有EL0與EL1是必選項,EL2(主要用來支持虛擬化)與EL3(主要用來支持安全)是可選項。
當EL2存在時,ARM能夠提供兩個stage的地址映射。不過EL2主要用做虛擬化,手機上的CPU能夠不實現。這個時候只須要通過一個stage的地址映射,就能將虛擬地址(VA)轉換成物理地址(PA)。一個stage 的地址映射能夠支持兩個VA區域,好比第一VA區域(起始地址爲0x0000000000000000)給用戶空間使用,第二個VA區域(截止地址爲0xFFFFFFFFFFFFFFFF)給內核使用。
ARMv8虛擬內存架構發展自ARMv7的LAPE機制,支持48位虛擬地址。不過最終虛擬地址的寬度能夠經過TCR_ELx的T0SZ域或者T1SZ域(對於支持兩個VA區域的地址映射來講)來指定。虛擬地址的寬度定好後,虛擬地址的空間大小便肯定下來了。
ARMv8支持3種轉換粒度(經過TCR_ELx寄存器的TG0域來指定):4KB、16KB與64KB。轉換粒度不只定義了page的size,也定義了查找表的尺寸。當轉換粒度爲4KB時,一個stage的地址映射支持4個level的查找(這與linux的4級內存管理暗合),這四個level分別記做L0~L3。這樣,一個虛擬地址便被分紅了5部分:L0 Index、L1 Index、L2 Index、L3 Index與offset。在查找時,拿Lx Index在Lx Table中查表(就是將Lx Index做爲索引,拿Lx Table的基址 + Lx Index),獲得下一級查找表的基址。L0 Table的基址存儲在寄存器TTBR中。L3 Table是一個頁表PT,頁表中每一個表項指向一個物理page的起始地址,當經過4級查找以後,就能夠找到虛擬地址對應的物理地址。
爲了加快地址映射過程,當轉換粒度爲4KB時,能夠在L1 Table或者L2 Table中插入一些block描述符,block表示匹配到一塊連續的物理內存。在地址映射過程當中,若是虛擬地址與一個內存塊匹配,則能夠提早結束查找過程,從而提升地址映射效率。所以,在L0~L2 的Table中,存在兩種描述符:block描述符與table描述符。
咱們拿64位的整數來表示地址,L0~L3 Table中的描述符也是64位的,而有效的虛擬地址只有48位,所以描述符中的其餘的位段能夠挪做他用,好比用做標記或者用來指示轉換表以及內存的相關屬性。