轉:https://blog.csdn.net/yueqian_scut/article/details/24816757
mmu頁表也是放在內存中,mmu里有一個寄存器存放頁表首地址,從而找到頁表(地址為物理地址)。當我們執行一個程序時,會把這個進程的mmu頁表地址放到該寄存器中,跳轉找到mmu頁表執行。
TLB是MMU內部的緩存,頁表是每個進程都有的一段保存虛擬地址到物理地址對應映射關系的數組,此數據在內存中
(TLB---Translation Lookaside Buffers,轉譯查找緩存):由於從MVA到PA的轉換需要訪問多次內存,大大降低了CPU的性能,故提出TLB辦法改進。當CPU發出一個虛擬地址時,MMU首先訪問TLB。如果TLB中含有能轉換這個虛擬地址的描述符,則直接利用此描述符進行地址轉換和權限檢查,否則MMU訪問頁表找到描述符后再進行地址轉換和權限檢查,並將這個描述符填入TLB中,下次再使用這個虛擬地址時就直接使用TLB用的描述符。使用TLB需要保證TLB中的內容與頁表一致,在啟動MMU之前,頁表中的內容發生變化后,尤其要注意。一般的做法是在啟動MMU之前使整個TLB無效,改變頁表時,使所涉及的虛擬地址對應的TLB中條目無效。
不同進程切換時,通過CR3(x86時)寄存器 把頁表緩存地址傳遞給MMU模塊,進而時MMU的TLB更新為對應進程的頁表內容
程序的大部分代碼都可以在必要的時候才加載到內存去執行,運行完后可以被直接丟棄或者被其他代碼覆蓋。我們PC上同時跑着很多的應用程序,每個應用程序使用的虛擬地址空間幾乎可以整個線性地址空間(除了部分留給操作系統或者預留它用),可以認為每個應用程序都獨占了整個虛擬地址空間(字長是32的CPU是4G的虛擬地址空間),但我們的物理內存只是1G或者2G。即多個應用程序在同時競爭使用這塊物理內存,其必然會導致某個時刻只存在程序的某個片段在執行,也即是所有程序代碼和數據分時復用物理內存空間—這就是內存管理單元(MMU)工作核心作用所在。
處理器系列的芯片(如X86、ARM7以上、MIPS)一般都會有MMU,跟操作系統一塊實現虛擬內存管理,MMU也是Linux、Wince等操作系統的硬件要求。而控制器系統的芯片(面向低端控制領域,ARM1,2,MIPS M系列,80251等)一般都沒有MMU,或者其只有單一的線性映射機制。
本文要談的是控制器領域SoC的內存管理單元的硬件設計,其重要的理念同樣是代碼和數據分時復用物理內存空間,在保障系統功能和性能的基礎上最大限度地節省物理內存的目的。相關的文章包括:SoC軟件架構設計之一:系統內存需求評估和節省內存的軟件設計技巧。
一、內存管理單元(MMU)的工作機制
在闡述控制器領域的內存管理之前,還是要先介紹處理器領域的虛擬內存管理機制,前者很大程度上是對后者核心機制精髓的借鑒。實現虛擬內存管理有幾個模塊是協調工作的:CPU、MMU、操作系統、物理內存,如圖示(假設該芯片系列沒有cache):
我們根據上圖來分析一下CPU訪問內存的過程,假設尋址是0x10000008,一頁大小為4K(12比特)。則虛擬地址會分成兩個部分:頁映射部分(20bit,0x10000)+頁內偏移(12bit, 0x8)。CPU通過總線把地址信號(0x10000008)送給MMU,MMU會把該地址的頁映射部分(20bit)拿到TLB中匹配。
TLB是什么東西?Translation Lookaside Buffer,網上有稱為“翻譯后備緩沖器”。這個翻譯都不知道它干什么。它的作用就是頁表的緩沖,我喜歡叫它為頁表cache。其結構圖如下:
可以想象,TLB就是索引地址數組,數組的每個元素就是一個索引結構,包含虛擬頁地址和物理頁地址。其在芯片內部表現為寄存器形式,一般寄存器都是32位,實際上TLB中的頁地址也是32位寄存器,只不過索引比較時是比較前20bit,后12bit其實也是有用的,例如可以設置某個bit是表示常駐的,即該索引是永遠有效的,不能更換,這種場景一般是為適合一些性能要求特別高的編解碼算法而設計的。非常駐內存的一般在某個時刻(如TLB填滿時訪問一個新的頁地址)就會發生置換。
1) 假如0x10000008的前20bit在TLB中第M個索引中命中,這時就表示該虛擬頁在物理內存中已經給它分配好對應的物理內存,頁表中也已經做好記錄。至於虛擬地址對應的代碼頁是否從外存儲(flash,card,硬盤)的程序中加載到內存中還需要要另外的標記,怎么標記呢?就是利用上面所講的TLB低12位的某一bit(我們稱為K)來標識,1標識代碼數據已經加載到內存,0表示還沒加載到內存。假如是1,那就會用M中的物理地址作為高20bit,以頁內偏移0x8作為低12bit,形成一個物理地址,送到內存去訪問。此時該次訪問就會完成。
2) 假如K是0,那意味着代碼數據尚未加載到內存,這時MMU會向中斷管理模塊輸出信號,觸發一個中斷進行內核態,由操作系統負責將對應的代碼頁加載到內存。並修改對應頁表項的K比特和TLB對應項的K比特為1.
3) 假如0x10000008的前20bit在TLB所有索引中都沒有命中,則MMU也會向中斷管理模塊輸出一個信號觸發中斷進入內核態,由操作系統將0x10000008右移12位(即除以4K)到頁表中去取得對應的物理頁值,假如物理頁值非0有效,說明代碼已經加載到內存了,這時將頁表項的值填入到某一個空閑的TLB項中;假如物理頁值為0,說明尚未給這個虛擬頁分配實際的物理內存空間,這時會給它分配實際的物理內存,並寫好頁表的對應項(這時K是0),最后將這索引項寫入TLB的其中一條。
2)和3)其實都是在中斷內核態中完成的,為什么不一塊做了呢?主要是因為一次中斷不應該做太多事情,以加大中斷延時,影響系統性能。當然如果有芯片將兩者做成一個中斷也是可以理解的。我們再來看看頁表的結構。頁表當然也可以按TLB那樣做成索引數組,但是這樣有兩個不好的地方:
1)頁表是要映射所有的虛擬頁面的,其維護在內存中也需要不小的空間。頁大小是4K時,那映射全部就是4G/4K=1M條索引,每條索引4*2=8個字節,就是8M內存。
2)假如按TLB那種結構,那匹配索引的過程就是一個for循環匹配電路,效率很低,要知道我們做這個都是在中斷態完成的。
所以一般的頁表都是設計成一維數組,即以整個線性虛擬地址空間按頁為單位依次作為數組的下標,即頁表的第一個字(4字節)就映射虛擬地址空間的最低4K,第二個字映射虛擬地址最低的第二個4K,以此類推,頁表的第N個字就映射虛擬地址空間的第N個4K空間,即(N-1)*4K~4KN的地址空間。這樣頁表的大小就是1M*4=4M字節,而且匹配索引的時候只是一個偏移計算,非常快。
承前啟后,在引出第二部分之前先明確兩個概念:
1. Bank表示代碼分塊的意思,類似於上面提到的頁的概念。
2.不同代碼分時復用內存:不同代碼即意味着不同的虛擬地址對應的代碼,(程序鏈接后的地址都是虛擬地址),內存即物理內存,即一定大小的不同虛擬地址的代碼在不同的時刻都跑在同一塊一定大小的物理內存空間上。每一塊不同的代碼塊即是不同的代碼Bank。
二、控制器領域SoC內存管理單元的硬件設計
這里專指沒有內存管理單元的SoC設計,一般為了降低成本,在性能足夠時,如果16位或者24位字長CPU能夠解決問題,一般都不會去選32位字長的CPU,除非是計算性能考慮,或者32位CPU的license更便宜(一般很少見)。只要能夠達到高效地進行內存管理,實現物理內存分時復用的目的,那都可以稱為是成功或者有效的。在介紹真正的內存管理單元硬件設計之前,我們先簡單介紹一種利用工具鏈來實現內存分時復用的機制,然后再結合MMU和這個工具鏈實現的分塊處理方法去設計我們新的內存管理單元,包括其硬件工作機制和軟件設計和關鍵機制。
由於以下內容涉及到在審專利,經過考慮,暫時將以下內容隱藏,適當時候再公開,抱歉!
×××××××
后記補充
在集成沒有MMU的CPU時,SoC要實現內存管理,需要另外設計一個內存管理模塊,實現MMU的核心功能,即代碼分頁(塊)映射的功能,而且需要簡化設計以達到最高的效率,同時代碼分塊需要直接地體現在鏈接腳本上。為了追求效率,編譯鏈接后的可執行性文件還會被離線解析組織成一個更簡化的執行文件,把不需要的段都刪除,並將分塊代碼按邏輯順序放好,以便於操作系統在必要時更快地加載。當然,操作系統的代碼內存管理也需要配合內存管理硬件電路,並能夠解析重新打包后的執行程序文件。因此內存管理的實現是需要架構師從軟件和硬件上全面考慮,盡可能地在實現核心功能的基礎上簡化電路和設計,涉及的模塊包括:硬件機制設計、物理內存分配、代碼分塊原則、linker腳本定義、打包執行文件、操作系統定制等等。后續闡述的架構設計將會包括以上內容。
---------------------
本文來自 吳躍前 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/yueqian_scut/article/details/24816757?utm_source=copy
