歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

OK6410,MMU,內存管理 雜談

一、MMU學習

  MMU其實就是一個頁表。將虛擬地址通過查表的方式,對應到物理地址去他由一個或一組芯片組成,一般存在與協處理器中。

  1.將虛擬地址轉化為物理地址

  2.訪問權限管理

1.1得出mmu功能

 

  這個圖就說明了MMU的作用:

  有三個任務在運行,運行的地址都是0x400000,如果不進行處理,肯定是不行的。所以加入了MMU,MMU其實就是一個頁表。將虛擬地址通過查表的方式,對應到物理地址去。雖然三個任務的運行地址都是0x400000,但是這個地址是虛擬地址,在頁表中,將每個任務的虛擬地址對應到不同的物理地址,這樣,就實現了各個任務雖然是同一個虛擬地址,但是在不同的物理地址中運行。

1.2映射方式(ARM920T_TRM1_S    57頁)

  映射方式:映射方式有兩種,段映射和頁映射。段映射只用到一級頁表,頁映射用到一級頁表和二級頁表。

  映射粒度:段映射的映射粒度有兩種,1M section和16M supersection;頁映射的映射粒度也有兩種,4K small page和64K large page。

1.3頁表

  MMU要自動進行虛擬地址到物理地址的轉化,首先要找到一級頁表,而一級頁表的基地址(TTB:translation table base)則是保存在CP15的C2寄存器中。因此,當程序員創建好相應的頁表後,需要將頁表基地址寫入該寄存器。

      MMU有一級轉換和二級轉換,其實就是查幾次表。對於一級轉換,就是只查一次頁表,就確定了物理地址。這個在S3C6410中,方式是段映射。對於二級轉換,就要查兩次頁表或者三次,才能確定物理地址,這個在S3C6410中。有兩種方式,一種細頁方式,一種粗頁方式。這兩種的區別就是每一頁對應的大小不一樣而已。

  通過虛擬地址的[31:20],找到對應的轉換描述符,這個轉換描述符其實就是一個存在ram中的32位的一個數據。通過判斷這個描述符的最後兩位,判斷是什麼轉換。

1.3.1一級頁表描述符

  一級頁表描述符後兩位如果是10則表示為段轉換。

  如果是段轉換,就按照段轉換的格式去轉化物理地址

  如果是頁轉換,就在去找第二級的頁表,然後再按照二級頁表的格式去轉化物理地址。

  B:表示是否使能write buffer(使用buffer可以提高cpu運行效率-à當CPU訪問內存數據時但是內存沒准備此時cpu可以將數據暫時存放於buffer)

  C: 表示是否開啟cache(cahce用來保存cpu可能要經常訪問內存區域的數據,以便於快速訪問)

   XN:

  Domain:用來說明該段屬於哪一個域,ARM11共有16個域(由CP15的C3來設置),每個域可以設定不同的權限。將段分配到某個域,就使這段的權限和設定的域權限一樣。   (手冊arm11 P195)   

  P:表示段區間有ECC,ARM11不支持,所以這一位為0.

  AP:訪問權限,這個配合域,說明該段地址的訪問權限。(手冊arm11 P329)

  APX: 提供額外的訪問權限。

   S:表示區域是否共享。0不共享,1共享。這個手冊上說,是為了多核使用的。目前用不到,設置為0.

    nG:

  Section base address:這個就是段的物理地址的高12位。

1.4段轉換

  ARM11是32位的,對於段轉換,每一個段代表物理的1MB地址,一級頁表總共有4096個轉換符,所以夠表示的空間是4G。頁表的首地址就是TTB,這個地址是很重要的,因為有了這個地址才能知道頁表是存在什麼地方的,才能通過偏移找到對應的描述符。所以,是有一個寄存器來保存這個地址的,這個寄存器就在CP15的c2寄存器。

  通過虛擬地址的高12位偏移,找到頁表中的對應描述符,判斷描述符的最後兩位,確定是什麼轉換。10的話就表示是段轉換。

  判斷是段轉換後,將描述符的高12位取出,這個就是物理的基地址,在和虛擬地址的後20位拼接,就得到對應的物理地址。

  對於段轉換,每一個段代表物理的1MB地址。為什麼是1MB了。因為總共是有4096個描述符,而ARM11是32位的,所以能夠表示的空間是4G。

以段的方式進行映射時,虛擬地址MVA到物理地址PA的轉換過程如下:

  ①頁表基址寄存器位[31:14]和MVA[31:20]組成一個低兩位為0的32位地址,MMU利用這個地址找到描述符

  ②取出段描述符的位[31:20](段基址),它和MVA[19:0]組成一個32位的物理地址(這就是MVA對應的PA)

     

     

1.5頁轉換(ARM11  360頁)

  二級轉換

 

1.6程序設計

1.6.1建立頁表

  使用段映射的方式,那麼就要將段映射的描述符寫入到相應的內存中去。

  首先將頁表放在ddr的第一個位置,也就是0x50000000。所以需要將這個地址寫入到TTB中。 

  其次,開啟MMU後,使用的就是虛擬地址了,所以還要建立程序段的頁表,不然一旦開啟MMU,CPU去取指令,這個時候發出的就是虛擬地址,但是又沒有建立虛擬地址到物理地址的映射表。這樣的話,就取不到指令了,程序就崩潰了。所以還需要對代碼區建立映射頁表。代碼區的映射就是將虛擬地址直接轉換為物理地址使用。

  將這個地址給映射到0x7F000000區域去。

  unsigned long *ttb = (unsigned long *)0x50000000;//獲取基地址

      unsigned long vaddr, paddr;

      vaddr = 0xA0000000;

      paddr = 0x7f000000;

      *(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC;

       //獲得一級描述符的地址    並且賦值

  首先申明一個ttb指針,這個指針就指向一級表的基地址,也就是ddr的首地址,0x50000000。然後再申明兩個變量,一個表示虛擬地址,一個表示物理地址。

  根據前面的一級段描述符格式,往對應的內存單元寫入數據即可。段描述符的高12位是物理地址的高12位,所以首先有一個物理地址和0xFFF00000與的操作,將物理地址的高12位寫入到段描述符。

  這裡使用*(ttb + (vaddr >> 20))來對對應的頁描述符進行賦值。在一級頁表中,是通過虛擬地址的高12位來決定偏移是多少。高12位也就是位移20位,所以這裡就是加上虛擬地址右移20位的值,也就是取出高12位的值。注意,這裡是指針操作,假設這個時候虛擬地址的高12位值是5,那麼寫的地址不是0x50000005,而是0x50000014。因為指針的數據類型是long型,4個字節,所以加1,地址就會加4,加5,地址就會加5*4=20。

  後面位的配置:

   

  設置為訪問權限是11,也就是不進行訪問權限的檢查。將域設置為0。CACHE和write BUFFER都給關掉。因為這只是對一個寄存器的操作,沒有必要使用CACHE和write BUFFER。

  這樣,就建立好了GPIO的頁表。訪問虛擬地址0xc7000000,也就是訪問物理地址0x7f000000。整個段空間是1Mb。

1.6.2建立代碼區的頁表

  這個時候,代碼已經是在內存中運行的了。所以,直接將內存的所有地址空間進行映射,空間是64MB大小。

  

  使用的宏

  

  其實就是多一個開啟CACHE和WRITE BUFFER。

  內存映射是映射一片區域,從0x50000000地址開始到0x54000000這64M的虛擬地址給映射到0x50000000地址開始到0x54000000這64M物理地址上去。這樣,即使使用虛擬地址去取ddr中數據,也是能夠取到的。

  因為一個段是映射的1MB空間,所以總共需要64個段,十六進制也就是0x40。所以在while裡面判斷是虛擬地址要小於0x54000000。再者,每一個段表示1MB空間,所以虛擬地址和物理地��都要加1MB。也就是0x100000。

  這樣,就將頁表給建立好了。如果還需要使用其他地址區域,就都得為這些區域建立映射表。

1.6.3開啟mmu

  TTB是很重要的,保存的是一級頁表的首地址。首先就應該先要設置這個TTB。往CP15的C2寄存器裡面寫入這個值就好了,因為這個寄存器就是保存的TTB。

  然後是設置域的權限,將域的權限設置為11,不進行訪問權限檢查。設置CP15的c3寄存器。

  最後打開MMU。設置CP15的c1寄存器組的c0。是對CP15進行操作,用C語言是實現不了的,使用嵌入匯編。

  

  就設置好了MMU,並打開了MMU。之後使用的地址都是虛擬地址了。而且該虛擬地址必須是要在頁表中建立的,不然的話,就會產生異常。

Copyright © Linux教程網 All Rights Reserved