1. 程式人生 > >Armv8-A Memory management

Armv8-A Memory management

本文介紹Armv8-A的記憶體管理。記憶體管理指的是在系統中,記憶體訪問是如何實現的。 使用記憶體管理機制,可以讓每個應用之間的記憶體地址分離,即sandbox application,也可以讓多個在實體記憶體上碎片化的地址形成虛擬地址空間一個連續的地址,同時可以讓程式設計師程式設計更為方便。 ![image-20200802152342377](https://i.loli.net/2020/08/02/h3MYRQjywCZnV8p.png) 虛擬地址到實體地址的轉換通過mapping的方式來進行,其關鍵為Translation tables,儲存在memory中,並且被OS或者hypervisor來管理。 ## Memory Management Unit(MMU) 虛擬地址到實體地址的translation由MMU來執行,其包含兩個部分: 1. The **table walk unit**, which contains logic that reads the translation tables from memory. 2. **Translation Lookaside Buffers (TLBs)**, which **cache** recently used **translations** ,是被對映的地址,而不是地址對應的內容。 當一個虛擬地址來臨的時候,MMU先是查詢TLBs,看是否有cached translation,如果沒有,那麼table walk unit就memory中讀取對應的table entry或者table entries(大塊記憶體可能就需要多個entry) ![image-20200802154658528](https://i.loli.net/2020/08/02/WFjLep83Akfwo2Z.png) ### Table entry translation tabls通過把整個虛擬地址空間劃分為多個大小相同的block/page,然後每個page對應一個entry。 ![image-20200802164144863](https://i.loli.net/2020/08/02/JeEvdSQTMaiFfmq.png) ### Table lookup 對於一個單一層級的查詢來說,當對某個虛擬地址來查詢table的時候,會把虛擬地址分城兩部分,高位的用來定位對應的entry,而低位的則用來表示該地址在查詢到的該block中的偏置大小。 ![image-20200802162320897](https://i.loli.net/2020/08/02/vkpZOWw2i9VnA7c.png) ### Multilevel translation 在實踐使用中,一般使用的是分級table。每一級的訪問都像前面介紹的table lookup一樣訪問。 在armv8中,最多可以分為4級,每級分別被標記為0-3. 這種分級方案支援larger blocks和 smaller blocks: - larger blocks:相比smaller blocks,它只要更少層級的讀取翻譯就可以得到對應的實體地址。同時,在TLB中的快取效率也更高 - small block:可以提供對記憶體分配fine-grain的控制。但是在TLB中的快取效率較低,因為需要更多層級的讀取翻譯才可以得到實體地址 ![image-20200802171131536](https://i.loli.net/2020/08/02/WY12NwCEGpdSlHZ.png) OS必須做好large block和small block之間的平衡,以達到效率和實體記憶體使用靈活上的平衡,從而達到最優的效能。Note:在這種情況下,處理器並不知道此次翻譯對應的block大小,它需要通過table walk的方式來得到。 ## Address spaces in Armv8-A ![image-20200802190815094](https://i.loli.net/2020/08/02/fXDRsJuPeUyY3d5.png) 在arm中,同時存在幾個獨立的虛擬地址空間,比如OS的、Hypervisor的以及Secore Monitor的。每個虛擬地址空間都有他們自己的setting和tables。從這個圖上我們可以看到,OS的虛擬地址其實是經過了兩層translation的,先是由OS翻譯成IPAs,然後再又hypervisor翻譯成真正的實體地址,這兩次翻譯雖然在表的格式方面可能有所差異,但是大體是基本是一致的。如下圖所示: ![image-20200802192245574](https://i.loli.net/2020/08/02/jWq9Oe1CYGNgnMF.png) ### Address sizes 雖然Armv8-A是64位的架構,但是並不是意味著所有的地址都是64位的 #### Size of virtual addresses ![image-20200802193015118](https://i.loli.net/2020/08/02/iXmRPTlOQtb7ne8.png) 從這個圖也可以看出,對於EL0/EL1,kernel space和user space的地址空間是分開的,kernel的位於高地址,user位於低地址。kernel space和user space都有各自的translation table。TCR_ELx registers中表示的TnSZ值用來控制虛擬地址空間: ![image-20200802200714262](https://i.loli.net/2020/08/02/jg2eJFUIiGDNa9t.png) 所有的armv8-a架構都支援48位的虛擬地址,52位的是可選支援。比如上圖的中的0x0000_0000_0000_0000~0x000F_FFFF_FFFF_FFFF表示的就是一個52位的地址空間 #### Size of physical address size of實體地址是有實現決定的,最大支援52bits。如果你在table entry中指定一個 ### Adress Space Identifiers - Tagging translations with the owning process 對於現代作業系統,多個同時執行的程序看起來都是有著相同的虛擬地址的。那麼從MMU的角度來講,它怎麼區分一個相同的虛擬地址是來自哪個程序呢?同時,理想化的來講,我們希望不同的程序所對應的TLB是互不衝突的,這就不會導致TLB的的重新整理以及上下文切換。解決這個問題的手段就是使用Address Space Identifiers (ASIDs) 對於EL0/EL1,即OS,的虛擬地址,translations table entry的屬性欄位中的nG位用來標記global或者non-global。kernel對應的是global,也即意味著對於所有的程序都是共用的,而non-global的ranslation則與對應的程序相關。對於non-global的,則匹配TLB中的ASID和當前translations提供的ASID,會選擇匹配了的來進行處理。 ![image-20200802204452682](https://i.loli.net/2020/08/02/7AVln6QJFdOMwTh.png) ### Virtual Machine Identifiers - Tagging translations with the owning VM 對於不同的VM,和ASID一樣,使用Virtual Machine Identifier (VMID) 來進行tag。這裡講的VM就是EL0 EL1 EL2 EL3這些。 ### Common not Private 有這樣一個問題,現在CPU都是多核的,同一個ASID和VMID在不同的process上有相同的含義嗎? 對Armv8.0-A 版本,答案是否定的。沒有要求對於多個processor之間要求ASID和VMID含義一致,即相同的ASID在不同的processor可能表示不同的程序。也即意味著,一個processor建立的TLB不能被另一個processor使用。 但是,在實際中,我們更傾向於他們是跨processor通用的,因此從Armv8.2-A 開始引入了Common not Private (CnP)bit in the Translation Table Base Register (TTBR) ,如果CnP位被set,那麼就意味著可以通用。 ## Controlling address translation ### Translation table format ![image-20200802210800346](https://i.loli.net/2020/08/02/YgumaiPSMUrV3pL.png) 為什麼對於level3沒有*Next-level Table Address*?因為前面也提到過,最多容許四級地址。也即3就是最後一級了,必須輸出硬體地址了,即*Output Block Address* 為什麼level0沒有*Output Block Address*?因為level0表示的範圍太大了,直接讓其表示blocks沒有意義。 為什麼第一個和第三個的descriptor是一樣的?因為這樣容許*recursive tables*,讓他們相互之間可以point back。This is useful because it makes it easy to calculate the virtual address of a particular page table entry so that it can be updated . ## Translation granule translation granule,即翻譯粒度,指的是最小可described的block memory大小。Armv8-A 支援4KB, 16KB, and 64KB 。具體是由ID_AA64MMFR0_EL1 所指定。 ![image-20200802213039482](https://i.loli.net/2020/08/02/NQBXVIhFTojOvUK.png) There are restrictions on using 52-bit addresses. When the selected granule is 4KB or 16KB, the maximum virtual address region size is 48 bits. Similarly, output physical addresses are limited to 48 bits. It is only when the 64KB granule is used that the full 52 bits can be used 。 ### The starting level of address translation ![image-20200802213502181](https://i.loli.net/2020/08/02/rWzZEpNh3mfekuj.png) 這張表說明的是,當選擇4KB的 granule時,各個entry level所利用的地址bits。假如你設定TCR_ELx.T0SZ為32,那麼虛擬地址空間就只有$64-TOSZ=32$位,那麼對應上表,你就可以發現,已經不需要level0了,直接從level1開始就可以完全表示整個虛擬地址空間了。而如果虛擬地址空間只有30位,那麼只需要從level2開始就可以完整表示整個地址空間了。也即,虛擬地址空間越小,那麼所需的level也就越小。 ### Registers that control address translation 地址翻譯是通過如下這些暫存器來配合控制的: - SCTLR_ELx - M - Enable Memory Management Unit (MMU). - C - Enable for data and unified caches - EE - Endianness of translation table walks. - TTBR0_ELx and TTBR1_ELx - BADDR - Physical address (PA) (or intermediate physical address, IPA, for EL0/EL1) of start of translation table. - ASID - The Address Space Identifier for Non-Global translations. - TCR_ELx - PS/IPS - Size of PA or IPA space, the maximum output addresssize. - TnSZ - Size of address space covered by table. - TGn - Granule size. - SH/IRGN/ORGN - Cacheability and shareability to be used by MMU table walks. - TBIn - Disabling of table walks to a specific table. - MAIR_ELx - Attr - Controls the Type and cacheability in Stage 1 tables. ### MMU disabled 如果MMU被禁用的話,那麼所有地址都是flat-mapped,即輸入等於輸出。 ## Translation Lookaside Buffer maintenance TLB快取的最近使用的translations,以便可以得到translation結果而不用去讀tables。注意:TLB換成的translations,即從虛擬地址到硬體地址的直接對映關係,而不是translation tables。個人認為有三個原因:一是這樣效率最高,直接讀結果;二是entry有多個level,換成entry的話,會需要更多的空間;三是entry可能會隨著配置暫存器的更改而有不同的含義,這也會給快取的重利用造成更多負擔。 這些情況下,TLB不會對其進行快取: • A translation fault (unmapped address). • An address size fault (address outside of range). • An access flag fault. 當你首次mapping一個地址的時候,並不需要issue a TLB invalidate ,而當有下列行為的時候,必須issue a TLB invalidate : - Unmap an address .Take an address that was previously valid or mapped and mark it as faulting. - Change the mapping of an address. Change the output address or any of the attributes. For example, change an address from read-only to read-write permissions. - Change the way the tables are interpreted. This is less common. But, for example, if the granule size was changed, then the interpretation of the tables also changes. Therefore, a TLB invalidate would be necessary. 對應的指令為`TLBI {IS|OS} {, } `。 ## Address translation instructions Address Translation (AT) 可以用來查詢特定地址的translation結果,翻譯結果和地址屬性,儲存在Physical Address Register, PAR_EL1 。同時,`AT`指令可以查詢指定regime的結果,比如EL2可以查詢某個EL1地址的結果,但不能反過來。因為EL2比EL1擁有更高的特權。 ## Check your knowledge - What is the difference between a stage and a level in address translation? stage表示的是從輸入到輸出的兩個階段。第一個階段是從虛擬地址VA到中間實體地址IPA,階段二是從IPA到實體地址PA。只有EL1/EL0的才有兩個stage。 level表示的給定stage中不同級別的tables,從大範圍往小範圍級級縮小。 - What is the maximum size of a physical address? 這是implementation決定的,最大為52bit - Which register field controls the size of the virtual address space? TCR_ELx.TnSZ, or VTCR_EL2.T0SZ for Stage 2 - What is a translation granule, and what are the supported sizes? 表示的是最小的記憶體描敘分割單元,支援4,16,64KB三種 - What does the TLBI ALLE3 do? 重新整理所有EL3的虛擬地址空間對應的TLB entries - How are addresses mapped when the MMU is disabled? 採用flat mapped,即輸出等於輸入 - What is an ASID and when does a TLB entry include an ASID? ASID表示的當前地址對應的哪個application。. Non-Global mappings (nG=1)對應的TLBs使用ASID進行標記。 - MMU和DMA? As well as the Memory Management Unit (MMU) in the processor, it is increasingly common to have MMUs for non-processor masters, such as Direct Memory Access (DMA) engines. These are referred to as SMMUs (System MMUs) in Arm systems, and elsewhere as IOMMU. ## 參考 內容來自[https://developer.arm.com/architectures/learn-the-architecture/memory-management](https://developer.arm.com/architectures/learn-the-architecture/memory-man