MMU
這幾天一直在看MMU部分,現在有了基本的認識,還不深入,解決了初級問題,并且仿照vivi完成了一個測試實例,對深入理解和驗證推論的結果很有幫助。在學習的過程中,體會到幾種方法還是比較實用的:
· 從歷史的角度去了解技術,梳理清楚發展主線,效率更高。 · 采用軟硬件結合的方法分析,理解更為深入。 · 與同一愛好的朋友交流,可以發現認識的盲區,認識更為全面。 · 應該閱讀英文的Datasheet,中文翻譯往往有錯誤,有時候是致命的,以前在c8051F020的SPI的設計中就因為這個問題研究了一周,最后才發現中文翻譯有問題,這也足以說明還是原版更具有可信度。但是呢,不要絕對化,原版也可能有錯誤。在閱讀學習的過程中,如果理解到設計的巧妙,那么很好,拿來使用。如果暫時不能理解,或者認為原版有錯誤,那么不妨持懷疑的態度進行學習,即使錯了,也能學到很多東西,甚至從錯誤中學到的東西更多。 · 充分利用網絡資源。站在巨人的肩上可以更高更遠!但是,你必須訓練讓自己具備找到巨人的能力! 下面開始MMU的探討。因為還只是處于初級階段,本文僅就MMU的基礎方面和應用作一下探討,其中還有沒有明確的地方,待解決。 一、MMU是什么? MMU,英文名稱為Memory Manage Unit, 中文可以為“內存管理單元”,或者“存儲器管理單元”。MMU是硬件設備,它與virtual memory是緊密聯系在一起的。 看一下s3c2410 datasheet Appendix 1中關于ARM920T的介紹(因為s3c2410采用的是ARM920T的處理器)。對ARM9系列處理器有如下幾種: --ARM9TDMI(ARM9TDMI Core)
--ARM940T(ARM9TDMI core plus cache and protection unit)
--ARM920T(ARM9TDMI core plus cache and MMU)
伴隨著這種技術的出現,“virtual address,即VA”和“physical address, 即PA”也就出現了。一般來說,CPU看到的地址是VA,VA是由地址線來決定的。比如,s3c2410是32位的SoC,那么它的尋址空間為2^32=4GB,那么VA空間也就是4GB。但是在嵌入式系統中,物理存儲器是不會有這么大的。現在這塊s3c2410的實際內存SDRAM也就64MB,遠遠小于4GB。也就是說,VA是4GB,PA是64MB,PA的地址空間是VA地址空間的子集。既然PA沒有VA那么大,而且CPU只能看到VA,那么CPU如何找到PA呢?這也正是MMU的基本作用之一,就是提供VA到PA的轉換機制,除了硬件的支持外,軟件上實際就是維護一張表,表中的內容是VA到PA的轉換法則。由于有了MMU,那么就可以實現利用VA找到實際物理內存區域。 現在討論為什么要實現VA到PA的映射。就ARM而言,系統上電后,CPU的PC指向0x00000000(低端模式)或者0xffff0000(高端模式),這是由CPU的設計者決定的。在這個位置,一般安排非易失性存儲器地址空間,比如rom,flash等。但是flash等響應速度慢,這就稱為提高系統性能的一個瓶頸。而sdram則具有很高的響應速度,為了提高系統運行速度,可以把flash中的應用程序下載到sdram中執行,也就是一個簡單的loader的功能實現。這樣就出現一個問題,ARM響應exception時,程序指針指向固定的VA,比如,假設發生了IRQ中斷,那么PC執行0x00000018(如果是高端啟動,則指向0xffff0018處。)但是此處仍然為非易失性存儲器,也就是說,程序的一部分仍然在flash或者rom中執行。這時可以利用MMU,把sdram的地址映射到0x00000000起始的一片連續地址空間,而把原來flash映射到其他不相沖突的存儲空間位置。例如,flash的地址范圍0x00000000-0x00ffffff,sdram的地址范圍0x30000000-0x31ffffff。那么可以把sdram映射到0x00000000-0x1fffffff(此處地址空間未被占用)。映射完成后,如果處理器異常,假設依然為IRQ中斷,pc指向0x00000018,但是pc實際上是從物理地址0x30000018處讀取指令。通過mmu的映射,可以實現系統運行的加速。這個地方也可以說明bootloader中常見的中斷向量表的設置,為什么有些使用b,有些使用ldr了。【b的跳轉空間只能是+-32M,而ldr可以大的多了。】 在實際的應用過程中,還可能會把兩片不連續的物理地址空間分配給sdram,而在os中,習慣上把sdram的空間連續起來,方便實現動態內存管理。通過mmu可以實現不連續的物理地址空間映射為連續的虛擬地址空間。 另外一個需求就是,實現不同的運行級別,那么一些關鍵的代碼可以設定不被普通應用程序訪問。這也是通過mmu控制訪問權限來實現的。 綜上三個階段所述,可見MMU的作用主要就是兩個: · 實現VA到PA的映射(可以因此實現方便的動態內存管理) · 實現不同的訪問權限。 三、結合s3c2410來分析MMU的幾處硬件特點 首先看看ARM920T的框圖:
可以驗證前面的幾個概念:
·位于中心的ARM9TDMI Processor Core發出的地址有兩種,IVA和DVA,都是VA。其中I代表Instruction, D代表Data。也就是說,CPU核心看到的都是32bits的VA。
·Dcache、Icache、Dmmu、Immu看到的都是對應的MVA(modified virtual address),這個是比較復雜的地方,下面專門拿出這個來講解。
·MMU處理后的輸出地址都是對應的PA,通過AMBA Bus Interface連接到ASB總線上面。
這樣,從硬件上對地址的概念就比較清晰了。也可以很明顯的看出MMU的功能:將VA轉換成PA。但是現在存在的一個問題是,MVA是什么,為什么要用到MVA?
可以看CP15協處理器的register 13。這個寄存器是進程識別寄存器,主要的操作如下:
Reading from CP15 register 13 returns the value of the process identifier. Writing CP15register 13 updates the process identifier to the value in bits [31:25]. Bits [24:0] should be zero.
很清晰,ProcID為7bits,剩下的25bits should be zero,也就是可以實現2^25=32M的地址對齊。從這個道理上講,每個進程擁有32M的MVA地址空間,而最多支持的進程數為2^7=128個。這樣,128*32M=4GB,正是全部的虛擬地址空間。但是,英文的datasheet上卻并非如此,寫的記錄數字為64個進程,同樣每個進程32M,怎么可能達到4GB?參看下圖:
我覺得上圖中的63應該改為127。因為這個63處不可能對應4GB,而應該對應2GB。判斷此處屬于datasheet的錯誤。
還有,這個procID是何時,有誰寫入的?有誰來維護?根據推斷,在bootloader階段,只需要一個進程就可以了,所以,procID一直都是復位后默認的0,不需要改變。但是后面有了OS后,要想實現多進程,那么就需要對此維護了。所以procID的維護者是系統軟件OS。在創建一個新進程的時候,要把進程號寫入procID。
另外,關于MVA部分的轉換公式,實際上還是有疑問的。
Addresses issued by the ARM9TDMI core in the range 0 to 32MB are translated by CP15register 13, the ProcID register. Address A becomes A + (ProcID x 32MB). It is thistranslated address that is seen by both the Caches and MMU. Addresses above 32MB undergo no translation.
if VA < 32M then
MVA = VA | (ProcID << 25)
else
MVA = VA
