ARM MMU原理


本文描述基於存儲器管理單元的系統結構, 包含以下內容: 

  1. 關於存儲器管理單元的結構  
  2. 存儲器訪問的順序  
  3. 轉換過程
  4. 訪問權限   
  5. 域  
  6. 異常  
  7. CP15寄存器

3.1 關於存儲器管理單元的結構
 
 
    MMU存儲器系統的結構允許對存儲器系統的精細控制。大部分的控制細節由存在存儲器中的轉換表提供。這些表的入口定義了從 1KB到 1MB的各種存儲器區域的屬性。這些屬性包括:

虛擬地址到物理地址映射:
 
    ARM 處理器產生的地址叫虛擬地址,MMU允許把這個虛擬地址映射到一個不同的物理地址去。這個物理地址表示了被訪問的主存儲器的位置。 
它允許用很多方式管理物理存儲器的位置,例如:它可以用具有潛在沖突的地址映射為不同的進程分配存儲器,或允許具有不連續地址的應用把它映射到連續的地址空間。 
    注:如果使用了快速上下文切換擴展(Fast Context Switch Extension),則在本文中的虛擬地址的意思應該是修改過的虛擬地址(Modified virtual address) 

存儲器訪問權限(permissions) :
 
    這些控制對存儲器區域的不可訪問權限、只讀權限、讀寫權限。當訪問不可訪問權限的存儲器時,會有一個存儲器異常通知 ARM處理器。  
允許權限的級別也受程序運行在用戶狀態還是特權狀態影響,還受是否使用了域有關。
 
高速緩存和緩沖位(Cachability and bufferability bits [C and B]):
 
    這些在高速緩存和緩沖一節講系統控制協處理器的寄存器允許對系統的高級控制,如轉換表的位置。他們也用來為 ARM 提供內存異常的狀態信息。 

查找整個轉換表的過程叫轉換表遍歷。它由硬件制動進行,並需要大量的執行時間(至少一個存儲器訪問,通常是兩個)。為了減少存儲器訪問的平均消耗, 轉換表遍歷結果被高速緩存在一個或多個叫作 Translation Lookaside Buffers(TLBs)的結構中。通常在 ARM的實現中每個內存接口有一個 TLB。 
    *有一個存儲器接口的系統通常有一個唯一的 TLB     

    *指令和數據的內存接口分開的系統通常有分開的指令TLB和數據 TLB
 
    如果系統有高速緩存, 高速緩存的數量也通常是由同樣的方法確定的。所以在高速緩存的系統中,每個高速緩存一個 TLB。
 
    當存儲器中的轉換表被改變或選中了不同的轉換表(通過寫 CP15的寄存器2),先前高速緩存的轉換表遍歷結果將不再有效。MMU 結構提供了刷新 TLB的操作。 
 
    MMU結構也允許特定的轉換表遍歷結果被鎖定在一個TLB中,這就保證了對相關的存儲器區域的訪問絕不會導致轉換表遍歷,這也對那些把指令和數據鎖定在高速緩存中的實時代碼有相同的好處。

3.2 存儲器訪問的順序

    當ARM要訪問存儲器時,MMU先查找TLB中的虛擬地址表,如果ARM的結構支持分開的地址TLB和指令TLB,那么它用:

    * 取指令使用指令TLB  

    * 其它的所有訪問類別用數據TLB

    如果 TLB 中沒有虛擬地址的入口,則轉換表遍歷硬件從存在主存儲器中的轉換表中獲取轉換和訪問權限,一旦取到,這些信息將被放在TLB中,它會放在一個沒有使用的入口處或覆蓋一個已有的入口。關於轉換表的信息和轉換表遍歷的實現參見轉換過程一節。

    一旦為存儲器訪問的 TLB的入口被拿到,這些信息將被用於:
 
    1. C(高速緩存)和B(緩沖)位被用來控制高速緩存和寫緩沖,並決定是否高速緩存。(如果系統中沒有高速緩存和寫緩沖,則對應的位將被忽略)
 
    2. 訪問權限和域位用來控制訪問是否被允許。如果不允許,則 MMU將向 ARM處理器發送一個存儲器異常;否則訪問將被允許進行。 訪問權限、域和異常幾節有詳細描述。

    3. 對沒有高速緩存的系統(包括在沒有高速緩存系統中的所有存儲器訪問),物理地址將被用作主存儲器訪問的地址。 對有高速緩存的系統,在高速緩存沒有選中的情況下,物理地址將被用行取(line fetch)的地址。如果選中了高速緩存,則物理地址將被忽略。

 
    3.2.1 允許和禁止 MMU
 
    通過寫系統控制協處理器的寄存器1的第 0位可以允許和禁止MMU。在復位后這位是 0,MMU 被禁止。當 MMU 被禁止時,存儲器訪問將被按如下處理:
 
    1. 由具體的實現確定當 MMU 被禁止時是否能夠允許高速緩存和寫緩沖。

       當 MMU 被禁止時不能允許高速緩存和寫緩沖時,C 和 B 位不起作用。   當 MMU 被禁止時能允許高速緩存和寫緩沖時:
 
       i.  訪問數據時被認為沒有高速緩存和寫緩沖(C==0,B==0) 
      ii.  取指令時: 
 
      a)   當系統只有一個唯一的 TLB 時,認為是沒有高速緩存。(C==0)
      b)   當系統只有獨立的指令 TLB 時,認為是有高速緩存。(C==1) 
 
    2. 沒有存儲器訪問權限的檢查,MMU 也不產生異常信號。 
 
    3. 物理地址與虛擬地址相同(即所謂的平坦地址映射模式)。 

    在允許 MMU之前,必須在內存中建立適當的轉換表,並且所有相關的 CP15寄存器要被初始化正確。 
    注:允許和禁止MMU直接改變了虛擬地址到物理地址的映射(除非轉換表被設定為平坦地址映射模式)。所以很可能在允許 MMU 時所有的高速緩存需要被刷新。另外,如果允許MMU的指令的物理地址和虛擬地址不同,取指令將變得復雜化。所以,強烈建議允許 MMU 的指令具有相同的物理地址和虛擬地址。

3.3 轉換過程

MMU支持基於節或頁的存儲器訪問:
 
    節(Section)       構成 1MB的存儲器塊 
    支持 3中不同的頁尺寸:
    微頁(Tiny page)   構成 1KB的存儲器塊
    小頁(Small page)  構成 4KB 的存儲器塊
    大頁(Large page)  構成 64KB 的存儲器塊
 
節和大頁是支持允許只用一個TLB入口去映射大的存儲器區間。小頁和大頁有附加的訪問控制:小頁分成 1KB 的子頁,和大頁分成16KB的子頁。微頁沒有子頁,對微頁的訪問控制是對整個頁。

存在主存儲器內的轉換表有兩個級別:
 
第一級表  存儲節轉換表和指向第二級表的指針。
第二級表  存儲大頁和小頁的轉換表。一種類型的第二級表存儲微頁轉換表。
 
    MMU把 CPU 產生的虛擬地址轉換成物理地址去訪問外部存儲器,同時繼承並檢查訪問權限。地址轉換有四條路徑。路徑的選取由這個地址是被標記成節映射訪問還是頁映射訪問確定。頁映射訪問可以是大、小和微頁的訪問。  
    然而,轉換過程總是由下面所描述的那樣由第一級表的獲取開始。節映射的訪問只需要讀取第一級表,頁映射的訪問還需要讀取第二級表。

3.3.1 轉換表基址
 
    當片上(on-chip)的 TLB 中不包含被要求的虛擬地址的入口時,轉換過程被啟動。轉換表基址寄存器(CP15的寄存器2)保存着第一級轉換表基址的物理地址。只有 bits[31:14]有效,bits[13:0]應該是零(SBZ)。所以第一級表必須在16KB的邊界。  

3.3.2 取第一級表

    轉換表基址寄存器的 bits[31:14]與虛擬地址的 bits[31:20]和兩個0位連接形成32為物理地址,如圖3-2。這個地址選擇了一個四字節的轉換表入口,它是第一級描述符或是指向第二級頁表的指針。

 

3.3.3 第一級描述符
 
第一級表的每個入口是一個描述它所關聯的1MB虛擬地址是如何映射的描述符。見表 3-1,根據 bits[1:0]的組合,有四種可能:
    如果 bits[1:0]==0b00,所關聯的地址沒有被映射,試圖訪問他們將產生一個轉換錯(fault)。因為他們被硬件忽略,所以軟件可以利用這樣的描述符的 bits[31:2]做自己的用途。推薦為描述符繼續保持正確的訪問權限。  

   * 如果 bits[1:0]==0b10,這個入口是它所關聯地址的節描述符。見節描述符和轉換節參考中的細節。  

   * 如果 bits[0]==1,這個入口給出粗糙第二級表(bit[1]==0),或精細第二級表(bit[1]==1)。每一種類型的表描述了它所關聯的 1MB存儲區域的映射。粗糙第二級表較小,每個表 1KB,每個精細第二級表 4KB。然而粗糙第二級表只能映射大頁和小頁,精細第二級表可以映射大頁、小頁和微頁。

3.3.4 節描述符和轉換節參考 
 
    如果第一級描述符是節描述符,那么各個字段有如下的意義:  
    Bits[1:0]  描述符類型標識(0b10 表示節描述符)
    Bits[3:2]  高速緩存和緩沖位
    Bits[4]    由具體實現定義
    Bits[8:5]  這個描述符控制的節的 16 種域之一
    Bits[9]    現在沒有使用,應該為零
    Bits[11:10] 訪問控制,見表 3-3
    Bits[19:12] 現在沒有使用,應該為零
    Bits[31:20] 節基址,形成物理地址的高 12 位 
    圖 3-3 表示了節轉換的完整過程。
    注:訪問權限必須在物理地址產生之前去檢查,檢查訪問權限的順序見訪問權限一節。

3.3.5 粗糙頁表描述符 
  
    如果第一級描述符是粗糙頁表描述符,那么各個字段有如下的意義: 
    Bits[1:0]  描述符類型標識(0b01 表示粗糙頁表描述符)
    Bits[4:2]  由具體實現定義
    Bits[8:5]  這個描述符控制的頁的 16 種域之一
    Bits[9]    現在沒有使用,應該為零
    Bits[31:10] 頁表基地址是一個指向第二極粗糙頁表的指針,它給出第二級表訪問 的基地址。而第二級粗糙頁表必須在 1KB 邊界對齊。 
 
    如果從第一級讀取到的是二級粗糙頁表描述符,那么會象圖 3-4所示執行第二級描述符讀取。 

3.3.6  精細頁表描述符 
    如果第一級描述符是精細頁表描述符,那么各個字段有如下的意義:
    Bits[1:0]  描述符類型標識(0b11 表示精細頁表描述符)
    Bits[4:2]  由具體實現定義
    Bits[8:5]  這個描述符控制的頁的 16 種域之一
    Bits[11:9]  現在沒有使用,應該為零
    Bits[31:10] 頁表基地址是一個指向第二級精細頁表的指針,它給出第二級表訪問的基地址。而第二級精細頁表必須在 4KB 邊界對齊。 
 
    如果從第一級讀取到的是二級精細頁表描述符,那么會象圖 3-5所示執行第二級描述符讀取。 


3.3.7 第二級描述符
 
每個粗糙第二級表對映着以 4KB為單位的虛擬地址范圍市怎么映射的,每個精細第二級表對映着以1KB為單位的虛擬地址范圍市怎么映射的。那些入口是頁描述符,他們能夠分別描述大於 4KB或1KB的頁。在這種情況下,這個描述符必須被重復足夠次,以保證這個頁始終使用相同的描述符,不論訪問這個頁中的哪個虛擬地址。
 
對於一個第二級描述符,有四種可能,由描述符的 bits[1:0]選擇。見表 3-2:
   * 如果 bits[1:0]==0b00,說關聯的虛擬地址沒有被映射,任何對這些虛擬地址的訪問將會導致轉換錯(fault)。軟件可以利用這樣的描述符的
      bits[31:2]做自己的用途,因為他們被硬件忽略。推薦為描述符繼續保持正確的訪問權限。 
   * 如果 bits[1:0]==0b01,這個入口是大頁描述符,描述 64KB的虛擬地址。
      見轉換大頁參考。
      一個大頁描述符在精細第二級表中必須被重復64次,在粗糙第二級表中必須被重復 16 次以保證所有的虛擬地址都被描述。 

   * 如果 bits[1:0]== 0b10,這個入口是小頁描述符,描述 4KB 的虛擬地址。
     見轉換小頁參考。
     一個小頁描述符在精細第二級表中必須被重復 4次,以保證所有的虛擬地址都被描述。在粗糙第二級表中只有一個實例。

   * 如果 bits[1:0]== 0b11,這個入口是微頁描述符,描述 1KB 的虛擬地址。
      見轉換微頁參考。 
     在精細第二級表中只需要一個微頁描述符的實例。微頁描述符不能在粗糙第二級表中出現,如果出現了,結果不可預測。

 大頁描述符字段
 
大頁描述符的字段有如下意義:
 
bits[1:0]  表示描述符的類型
bits[3:2]  高速緩促和緩沖位
bits[11:4]  訪問權限位。這些為控制對頁的訪問。關於這些位的解釋見表3-3。
大頁被分成 4 各子頁。
AP0  編碼對第一個子頁的訪問權限。
AP1  編碼對第二個子頁的訪問權限。
AP2  編碼對第三個子頁的訪問權限。
AP3  編碼對第四個子頁的訪問權限。

bits[15:12] 現在沒有使用,應該為零。
bits[31:16] 用來形成物理地址的對應位。
 
小頁描述符字段
 
小頁描述符的字段有如下意義:
 
bits[1:0]  表示描述符的類型
bits[3:2]  高速緩促和緩沖位
bits[11:4]  訪問權限位。這些為控制對頁的訪問。關於這些位的解釋見表3-3。
小頁被分成 4 各子頁。
AP0  編碼對第一個子頁的訪問權限。
AP1  編碼對第二個子頁的訪問權限。
AP2  編碼對第三個子頁的訪問權限。
AP3  編碼對第四個子頁的訪問權限。

 
bits[31:12] 用來形成物理地址的對應位。
 
微頁描述符字段
 
微頁描述符的字段有如下意義:
 
bits[1:0]  表示描述符的類型
bits[3:2]  高速緩促和緩沖位
bits[5:4]  訪問權限位。這些為控制對頁的訪問。關於這些位的解釋見表3-3關
於微頁的解釋。
bits[9:6]  現在沒有使用,應該為零。
bits[31:10] 用來形成物理地址的對應位。

3.3.8 轉換大頁參考
 
 
圖 3-6 顯示了在粗糙第二級表中轉換一個 64KB的大頁的完整順序。在精細第二級
表中的轉換順序頁相似,只是第二級描述符的地址如精細頁表描述符一節所決定。
 
 
注:-----------------------------
頁索引的高4位和第二級表的低階 4位重疊,在粗糙頁表中大頁的每個頁表入口必
須被重復 16次。在精細頁表中大頁的每個頁表入口必須被重復 64 次。
-----------------------------------

                                                   圖 3-7 粗糙第二級表中的小頁轉換

3.3.10 轉換微頁索引
 
 
圖 3-8 顯示了在精細第二級表中轉換 1KB 微頁的完整過程。
 
 
注:---------------------------
微頁不能出現在粗糙第二級表中。
---------------------------------

 

3.4  訪問權限 

    在節和頁描述符中的訪問權限位控制對相應的節和頁的訪問。訪問權限由 CP15的寄存器 1 的 System(S)和 ROM(R)位修改。表 3-3描述了訪問權限位和 S、R位相互作用時的意義。如果訪問了沒有訪問權限的存儲器空間,將會產生權限錯(見異常一節)。

 

 
 

3.5 域

    域是節、大頁和小頁的集合。ARM結構支持16個域。對域的訪問由域訪問控制寄存器的兩個位字段控制。因為每個字段對訪問對應的域的使能非常迅速,所以整個存儲器區間能很快地交換進出虛擬存儲器。這里支持 2種域訪問方式:
 
    客戶    域的用戶(執行程序,訪問數據),被形成這個域的節或頁來監督訪問權限。
    管理者  控制域的行為(域中的當前節和頁,對域的訪問),不被形成這個域的節或頁來監督訪問權限。

    一個程序可以是一些域的客戶,也是另外一些域的管理者,同時沒有對其它域的訪問權限。這允許對程序訪問不同存儲器資源的非常靈活的存儲器保護。表 3-4說明了域訪問控制寄存器的位編碼方式。 

 

3.6 異常 

    由於存儲器訪問的約束而導致 ARM處理器停止執行的機制有: 
 
    MMU fault  MMU 檢測到約束並統治處理器
    外部 Abort 外部存儲器系統發出一個非法存儲器訪問信號
 
    MMU fault 和 外部 Abort 都叫異常(ABORT)。
 
    如果導致異常的存儲器操作是取指令,那么當處理器去執行這個非法訪問得到的指令時產生一個預取指令異常。如果導致異常的存儲器操作是存取數據,那么產生一個數據異常。參見 2.6 節。 

3.6.1 MMU fault 
 
    MMU產生 4 種類型的 fault   

    對齊錯 
    轉換錯 

    * 域錯  

    權限錯
 
存儲器系統能終止 3種類型的訪問  

    line fetch  

    存儲器訪問(沒有高速緩存和沒有緩沖的訪問)  

    轉換表訪問
 
    MMU檢測到的異常在任何外部存儲器訪問發生之前被停止。終止導致外部異常的外部訪問是外部系統的職責。 

    系統控制協處理器有 2個寄存器,當外部訪問被終止時更新。指令預取異常不更新這些寄存器,由於程序流程的改變,產生遺產的指令沒有被執行。
 
    錯誤地址寄存器(FAR)和錯誤狀態寄存器(FSR)
 
    數據異常會被 CPU 立即響應。FSR被一個 4位的錯誤狀態(FS[3:0])和域序號更新。虛擬地址被寫入FAR。如果數據訪問連續地產生多個數據異常,則它們的優先級由表 3-5決定。
 
    由取指令產生的異常在指令進入指令流水線時被標記。只有當指令執行時產生預取異常。一個異常導致取指令沒有被執行如果那條指令不被使用(例如跳轉到別處)

    通常當進入預取指令異常服務程序時,fault所關聯的地址被放在R14_abt寄存器中。由具體實現決定當預取指令異常產生時是否更新FSR和 FAR。但是預取指令異常在數據異常產生時(更新 FAR 和 FSR)和進入數據異常項量入口時絕不更新 FSR和 FAR。也就是說數據異常可以使用 FAR和FSR的值,它們不會被預取指令異常給破壞。 

   

    注:Alignment 能寫 0b0001 或 0b0011 到 FSR[3:0]。 在域(Domain[3:0])中的非法值是因為 fault 發生在有效的域被裝入之前。
任何被優先級編碼屏蔽的異常能夠由修改原來的異常(by fixing the primary abort) 並重新執行那條指令產生。 Vector Exception 打破了 FS[0]=0標致着外部異常的模式。

錯誤檢測順序(Fault-checking sequence)
 
MMU檢測訪問錯對節(Section)和頁(Page)有些不同,見圖 3-9

Terminal exception 終端錯
 
這標志着發生一個不可挽回的錯誤。這在(如果至少)是具體實現決定的情況下發生。
 
Vector exception 向量錯
 
當處理器是 32 位配置(PROG32 被激活),在 26 位模式(CPSR[4]==0),數據訪問(不是取指令)通常的向量表(地址0x00-0x1F)導致一個數據異常,這叫向量錯。如果向量錯發生在 MMU被禁止時,由具體實現決定如何實現。詳細信息見 A8-11頁。
 
Alignment fault 對齊錯
 
如果對齊錯被允許,則當訪問一個不在字對齊地址的數據字(虛擬地址位bits[1:0]!=0b00)或訪問一個不在半字對齊地址的數據半字(虛擬地址位
bits[0]!=0)時產生對齊錯。取指令和字節訪問不產生對齊錯。 

---注-----
如果產生對齊錯,訪問將被終止,而不去進行權限檢查。如果對齊錯發生在MMU被禁止時,由具體實現決定如何實現。
----------
 
Translation fault 轉換錯
 
有兩類轉換錯:
節  當第一級描述符被標志為無效時產生。這時候描述符的 bits[1:0]==0b00。
頁  當第二級描述符被標志為無效時產生。這時候描述符的 bits[1:0]==0b00。
 
Domain fault 域錯
 
有兩類域錯:   節   頁 
 

在這兩種情況下,第一級描述符中有 4位域字段用來選擇16個域中的一個。域由域訪問控制寄存器中的 2個位控制,這 2 個位用來檢查訪問權限。見表 3-4。
如果是節,域訪問的檢查在第一級描述符返回時進行。
如果是頁,域訪問的檢查在第二級描述符返回時進行。
如果特定的訪問在域訪問控制寄存器中被標識為不可訪問,則回產生一個節域錯或頁域錯。 

Permission fault 權限錯
 
有節權限錯和子頁權限錯。
 
權限錯與域錯的檢查同時進行。如果那2位的域字段返回的是客戶(client)(01),權限檢查如下進行: 

節:    如果第一級描述符定義了一個節訪問,那么描述符的 AP位定義了訪問是否允許,見表 3-3。如果訪問不允許,那將產生節權限錯。 
子頁:  如果第一級描述符定義了一個頁映射的訪問,那么第二級描述符可以定義一 個微頁,小頁或大頁。如果第二級描述符定義了一個微頁,那它 只有一個AP 位,這個位適用於整個頁。否則第二級描述符有4個AP位(AP3、AP2、AP1 和 AP0),每一個對應 1/4 頁。
小頁: AP3 選擇頂上的 1KB,AP0選擇底下的 1KB。大頁:AP3 選擇頂上的16KB,AP0選擇底下的 16KB。被選擇的 AP位與節完全一樣地解釋,(見表3-3),只是產生的是子頁錯。 

3.6.2 外部異常
 
除了 MMU 錯,ARM 結構還定義了一個外部異常管腳,可以用來標識訪問外部存儲器錯誤。然而不是所有的訪問都能用這種方式終止,所以這個腳必須被仔細使用。以下的訪問可以被外部終止並安全地重啟動:  

    * 讀 
    無緩沖的寫   

    * 取第一級描述符  

    * 取第二級描述符  

    * 在沒有高速緩存和沒有緩沖的存儲器區域的信號(Semaphore)
 
    行取能夠在行傳送的任何一個字上安全地終止。如果異常發生在處理器請求的數據上(而不是在 cache line上取的其它數據),訪問被終止。任何不是立刻訪問的數據傳送(在 cache line 上取的其它數據),只在訪問它們時產生異常。
 
    由具體實現確定 FAR寄存器是指向 cache line的起始地址還是包含產生遺產的地址。 

    緩沖的寫不能被外部終止。所以系統必須配置成不向能夠標識外部異常的存儲器區域進行緩沖的寫,或者用不同的機制去標志異常(例如中斷)。 產生異常后,那個存儲器空間的值是不確定的。 
 

3.7 CP15寄存器

MMU由系統控制寄存器的 2、3、4、5、6、8、10號寄存器和 1號寄存器的一些位控制。
 
3.7.1 寄存器 1 的 MMU 控制位
 

寄存器 1 的如下這些位用來控制 MMU:
M(bit[0])  使能 MMU
    0 = 禁止 MMU
    1 = 允許 MMU
    在沒有 MMU和保護單元的系統上,這個位應該讀出為0,並忽略寫。
A(bit[1])  使能對齊錯檢查
    0 = 禁止
    1 = 允許
S(bit[8])  這是系統保護位,見 3-4節。
R(bit[9])  這是 ROM 保護位,見 3-4節。 
 
3.7.2 寄存器 2:轉換表基地址 
 

 
讀 CP15寄存器 2時,在 bits[31:14]返回當前活動的第一級轉換表的物理地址,bits[13:0]不確定。讀 CP15 寄存器 2 時,CRm 和操作數 2 被忽略,並應該是 0。
 
寫 CP15寄存器 2時,在 bits[31:14]更新當前活動的第一級轉換表的物理地址,bits[13:0]應該寫 0或先前讀回的值。寫 CP15寄存器 2時,CRm和操作數2被忽略,並應該是 0。

3.7.3 寄存器 3:域訪問控制

讀 CP15寄存器 3時,返回域訪問控制寄存器的值。CRm和操作數2被忽略,並應該是 0。
寫 CP15寄存器 3時,更新域訪問控制寄存器的值。CRm和操作數2被忽略,並應該是 0。

域訪問控制寄存器包含 16 個 2 位的字段,它定義了對應域的訪問權限。見 3-5節。
 
3.7.4 寄存器 4:保留
 
    讀寫 CP15 寄存器 4 不可預料結果。
 
3.7.5 寄存器 5:錯誤狀態  FSR

讀 CP15寄存器 5時,返回 FSR 寄存器的值。FSR 包含最近一次數據錯的信息。只有低 9位有效,高 23 位不確定。FSR 指出異常發生時的域和試圖訪問的類型。
 
bit[8]  返回 0
bit[7:4]  指出錯位發生時訪問的域
bit[3:0]  試圖訪問的類型,這些位的編碼見表 3-5
 
FSR在數據錯時更新。由具體實現確定取指令異常是否更新 FSR。見 3.6.1 節的“錯誤地址寄存器(FAR)和錯誤狀態寄存器(FSR)”。CRm和操作數2被忽略,並應該是 0。
 
寫 FSR 將把 FSR設定成寫的值。這對於程序調試器非常有用,可以用來恢復FSR的值。高 24 位應該寫 0 或上次讀到的值。CRm 和操作數 2被忽略,並應該是 0。
 
3.7.6 寄存器 6:錯誤地址  FAR

讀 CP15寄存器 6返回 FAR 的值。FAR 保存着錯誤產生時訪問的虛擬地址。在數據錯時更新 FAR。由具體實現確定取指令異常是否更新FSR。見3.6.1節的“錯誤地址寄存器(FAR)和錯誤狀態寄存器(FSR)”。CRm和操作數2被忽略,並應該是 0。
 
寫 FSR 將把 FAR設定成寫的值。這對於程序調試器非常有用,可以用來恢復FAR的值。高 24 位應該寫 0 或上次讀到的值。CRm 和操作數 2被忽略,並應該是 0。
 
---注------

如果使用了第六章描述的快速上下文切換擴展(FCSE),那么:   當存儲器錯更新 FAR 時,寫入 FAR 的是修改的虛擬地址。   當用 MRC指令讀或用 MCR指令寫FAR時,它的值被當作數據對待,所以沒有
由 FCSE 產生的地址修改。
------------ 
 3.7.7 寄存器 8:TLB 功能
 
當 CP15的寄存器 8 用來控制 TLB 時是只讀寄存器。表 3-6顯示了定義的 TLB功能和在 MCR 指令中用的 CRm和第二個朝操作數<opcode2>的值。使用沒有在表中的CRm和 opcode2 的組合將導致不可預料的結果。
 
如果下面的任何操作被用在單一 TLB的實現中,則在單一TLB中實現相同的功能:   無效的指令 TLB  (Invalidate instruction TLB)   無效的指令單一入口  (Invalidate instruction single entry)   無效的整個數據 TLB  (Invalidate entire data TLB)   無效的數據單一入口  (Invalidate data single entry)
 
否則,如果執行一個與特定實現不相關的功能,會導致不確定的結果。
 
試圖用 MRC指令讀 CP15 寄存器 8 的結果不確定。
 
當只有很少量的存儲器被重新映射時,無效的單一入口操作能被用來在一些實現中改善性能。對每個被重新映射的存儲器區域(節、小頁或大頁),無效的單一入口需要在存儲器區域的虛擬地址上執行。性能的改善來源於不用重新裝載與沒有被重新映射的存儲器區域相關的 TLB 入口。

---注------
無效的單一入口操作的性能改善並不被保證。具體實現可以是單一請求入口無效,
直到使整個 TLB無效。
-----------
 
---小心------
當存儲器被重新映射時必須使與舊的映射相關的TLB入口無效。如果不這樣,可能會進入兩個TLB入口覆蓋虛擬地址范圍的狀態。在最好的情況下訪問這樣的覆蓋虛擬地址范圍會有不可預料的結果;在某些實現中甚至會物理損壞 MMU。
 
強烈建議在重新映射存儲器時要加倍小心使 TLB 適當地失效。
------------

---注------
如果使用了第六章描述的快速上下文切換擴展(FCSE),那么表3-6中的一些功能傳遞給 CP15 的虛擬地址被當作數據。這意味着對它們來說沒有由FCSE產生的地址修改。
------------
 
3.7.8 寄存器 10:TLB 鎖定
 
轉換表遍歷的執行需要一定的時間,特別當訪問慢速的主存儲器時。在實時中斷處理程序中,當 TLB 不包含中斷處理程序的轉換和/或要訪問的數據時,中斷延遲回大量加長。
 
TLB鎖定是一些 ARM存儲器系統的特性,它允許把特定的轉換表遍歷的結果裝載到TLB中。這種方式不會被后來的轉換表遍歷的結果覆蓋。由 CP15寄存器10設定。
 
設 W=LOG2(TLB 入口數),如果需要的話取整(round-up),則 CP15寄存器 10的格式為:

如果具體的實現有分開的指令和數據 TLB,那么有2個不同的寄存器,由訪問寄存器 10 的 MCR或 MRC 指令中的 opcode2 字段選擇:
opcode2 == 0  選擇數據 TLB鎖定寄存器
opcode2 == 1  選擇指令 TLB鎖定寄存器

如果具體的實現只有唯一的 TLB,那么只有 1 個寄存器,opcode2字段應該為 0。
 
訪問寄存器 10 的 MCR 或 MRC 指令中的 CRm總應該為 0。
 
寫寄存器 10有如下結果:
victim字段表示下次 TLB失敗(miss)時,轉換表遍歷的結果替代哪個TLB入口。
Base 字段包含 TLB 替換的策略,只使用從(base)到(TLB入口-1)的 TLB 入口, victim 應該在這個區間。
轉換表遍歷的結果在寫到 TLB入口時,若 P==1則它被保護起來,不能被寄存器8的使整個 TLB 失效操作影響;若 P==0則會被那些操作給失效掉。
 
---注------
如果 TLB 的入口不是 2 的 N 次方,那么寫到大於或等於 TLB入口數的TLB入口的base 或 victim 的值將不確定。
-----------
 
讀寄存器 10將返回它的值。

TLB 鎖定過程
 
通常鎖定 N個 TLB 入口的過程如下:
 
1. 禁止中斷等,來保證當這個過程執行時不會產生異常
 
2. 如果一個指令 TLB 或唯一 TLB 被鎖定,用 base==N、index==N和P==0寫到適當版本的寄存器 10。如果可能,把另指令預取很難理解的分枝預測功能關掉。
 
3. 使要被鎖定的整個 TLB 失效。
 
4. 如果是指令 TLB 鎖定,要確保剩下的鎖定過程所要預取的指令相關的 TLB入口都被裝載。(要注意鎖定是從哪里開始的,通常可能一個TLB入口包含所有這些。這時 TLB被失效后的第一條指令能完成這個功能)
 
   是數據 TLB 鎖定,要確保剩下的鎖定過程所要訪問數據的相關的 TLB入口都被裝載。這包含被代碼用到的嵌入文字(inline literals)(通常最好避免在鎖定過程中使用嵌入文字,並把所有的數據放在由一個 TLB 入口所包含的區域,然后從那里加載一個數據)

   一個唯一 TLB 被鎖定,執行以上所有的過程。
 
5. i 從 0 到 N-1循環
    a. 用 base==i、index==i 和 P==1寫到寄存器 10。
    b. 強迫被鎖定到 TLB入口i處的轉換表遍歷結果的存儲器區域發生轉換
    表遍歷:
    * 如果是數據 TLB 或唯一 TLB被鎖定,從那個區域加載一個數據
    * 如果是指令 TLB 被鎖定,用B5-15頁所描述的指令預取高速緩沖寄
    存器 7 來在那個區域產生指令預取。
 
6. 用 base==N、index==N和 P==0寫到寄存器 10。
 
---注------
    如果你使用 FCSE,要注意第 5b 步,因為:   如果是數據 TLB 鎖定或唯一 TLB 鎖定,加載數據指令的地址是會被FCSE修改的。  

   如果是指令 TLB 鎖定,用在寄存器 7 的地址被當作數據,所以不會被 FCSE修改。
 
    為了減少混淆,建議鎖定過程應該是:   從禁止 FCSE開始(設置 PID 為 0)   把適當的 PID值 OR 到使用的虛擬地址的高 7 位來自己產生修改的虛擬地址。
-----------

TLB 解鎖過程
 
用上面的過程解鎖被鎖定的 TLB 部分:
 
1. 用寄存器 8 的操作使每個被鎖定的單一入口失效
2. 用 base==0、index==0和 P==0寫到寄存器 10。
 
---注------
第一步是為了保證 P==1 的入口在 TLB中不在被剩下。如故它們被剩在TLB中,后續的 TLB 鎖定過程中使整個 TLB 失效(第三步)將不會有預期的結果。

一、MMU的產生

      許多年以前,當人們還在使用DOS或是更古老的操作系統的時候,計算機的內存還非常小,一般都是以K為單位進行計算,相應的,當時的程序規模也不大,所以內存容量雖然小,但還是可以容納當時的程序。但隨着圖形界面的興起還用用戶需求的不斷增大,應用程序的規模也隨之膨脹起來,終於一個難題出現在程序員的面前,那就是應用程序太大以至於內存容納不下該程序,通常解決的辦法是把程序分割成許多稱為覆蓋塊(overlay)的片段。覆蓋塊0首先運行,結束時他將調用另一個覆蓋塊。雖然覆蓋塊的交換是由OS完成的,但是必須先由程序員把程序先進行分割,這是一個費時費力的工作,而且相當枯燥。人們必須找到更好的辦法從根本上解決這個問題。不久人們找到了一個辦法,這就是虛擬存儲器(virtual memory).虛擬存儲器的基本思想是程序,數據,堆棧的總的大小可以超過物理存儲器的大小,操作系統把當前使用的部分保留在內存中,而把其他未被使用的部分保存在磁盤上比如對一個16MB的程序和一個內存只有4MB的機器,OS通過選擇,可以決定各個時刻將哪4M的內容保留在內存中,並在需要時在內存和磁盤間交換程序片段,這樣就可以把這個16M的程序運行在一個只具有4M內存機器上了。而這個16M的程序在運行前不必由程序員進行分割。

任何時候,計算機上都存在一個程序能夠產生的地址集合,我們稱之為地址范圍。這個范圍的大小由CPU的位數決定,例如一個32位的CPU,它的地址范圍是0~0xFFFFFFFF (4G)而對於一個64位的CPU,它的地址范圍為0~0xFFFFFFFFFFFFFFFF (64T),這個范圍就是我們的程序能夠產生的地址范圍,我們把這個地址范圍稱為虛擬地址空間,該空間中的某一個地址我們稱之為虛擬地址。與虛擬地址空間和虛擬地址相對應的則是物理地址空間和物理地址,大多數時候我們的系統所具備的物理地址空間只是虛擬地址空間的一個子集,這里舉一個最簡單的例子直觀地說明這兩者,對於一台內存為256MB的32bit x86主機來說,它的虛擬地址空間范圍是0~0xFFFFFFFF(4G),而物理地址空間范圍是0x000000000~0x0FFFFFFF(256MB).

在沒有使用虛擬存儲器的機器上,虛擬地址被直接送到內存總線上,使具有相同地址的物理存儲器被讀寫。而在使用了虛擬存儲器的情況下,虛擬地址不是被直接送到內存地址總線上,而是送到內存管理單元——MMU(主角終於出現了)。他由一個或一組芯片組成,一般存在與協處理器中,其功能是把虛擬地址映射為物理地址。

 

 

(1)cpu看到的是VA

(2)caches和MMU使用的是MVA,

(3)實際物理設設備使用的是PA。

 

二、MMU工作過程

      大多數使用虛擬存儲器的系統都使用一種稱為分頁(paging)。虛擬地址空間划分成稱為頁(page)的單位,而相應的物理地址空間也被進行划分,單位是頁框(frame).頁和頁框的大小必須相同。接下來配合圖片我以一個例子說明頁與頁框之間在MMU的調度下是如何進行映射的:

 

                         沒圖,自己腦補

 

在這個例子中我們有一台可以生成16位地址的機器,它的虛擬地址范圍從0x0000~0xFFFF(64K),而這台機器只有32K的物理地址,因此他可以運行64K的程序,但該程序不能一次性調入內存運行。這台機器必須有一個達到可以存放64K程序的外部存儲器(例如磁盤或是FLASH)以保證程序片段在需要時可以被調用。在這個例子中,頁的大小為4K,頁框大小與頁相同(這點是必須保證的,內存和外圍存儲器之間的傳輸總是以頁為單位的),對應64K的虛擬地址和32K的物理存儲器,他們分別包含了16個頁和8個頁框。

 我們先根據上圖解釋一下分頁后要用到的幾個術語,在上面我們已經接觸了頁和頁框,上圖中藍色部分是物理空間,其中每一格表示一個物理頁框。橘黃色部分是虛擬空間,每一格表示一個頁,它由兩部分組成,分別是Frame Index(頁框索引)和位p(present 存在位),Frame Index的意義很明顯,它指出本頁是往哪個物理頁框進行映射的,位p的意義則是指出本頁的映射是否有效,如上圖,當某個頁並沒有被映射時(或稱映射無效,Frame Index部分為X),該位為0,映射有效則該位為1。

我們執行下面這些指令(本例子的指令不針對任何特定機型,都是偽指令)
例1:
    MOVE REG,0 //將0號地址的值傳遞進寄存器REG.
    虛擬地址0將被送往MMU,MMU看到該虛地址落在頁0范圍內(頁0范圍是0到4095),從上圖我們看到頁0所對應(映射)的頁框為2(頁框2的地址范圍是8192到12287),因此MMU將該虛擬地址轉化為物理地址8192,並把地址8192送到地址總線上。內存對MMU的映射一無所知,它只看到一個對地址8192的讀請求並執行它。MMU從而把0到4096的虛擬地址映射到8192到12287的物理地址。

 例2:

    MOVE REG,8192
    被轉換為
    MOVE REG,24576 
    因為虛擬地址8192在頁2中,而頁2被映射到頁框6(物理地址從24576到28671)

  例3:

    MOVE REG,20500
    被轉換為
    MOVE REG,12308
    虛擬地址20500在虛頁5(虛擬地址范圍是20480到24575)距開頭20個字節處,虛頁5映射到頁框3(頁框3的地址范圍是 12288到16383),於是被映射到物理地址12288+20=12308。

 例4:

MOV REG,32780

      虛擬地址32780落在頁8的范圍內,從上圖總我們看到頁8沒有被有效的進行映射(該頁被打上X),這是又會發生什么?MMU注意到這個頁沒有被映射,於是通知CPU發生一個缺頁故障(page fault).這種情況下操作系統必須處理這個頁故障,它必須從8個物理頁框中找到1個當前很少被使用的頁框並把該頁框的內容寫入外圍存儲器(這個動作被稱為page copy),隨后把需要引用的頁(例4中是頁8)映射到剛才釋放的頁框中(這個動作稱為修改映射關系),然后從新執行產生故障的指令(MOV REG,32780)。假設操作系統決定釋放頁框1,那么它將把虛頁8裝入物理地址的4-8K,並做兩處修改:首先把標記虛頁1未被映射(原來虛頁1是被影射到頁框1的),以使以后任何對虛擬地址4K到8K的訪問都引起頁故障而使操作系統做出適當的動作(這個動作正是我們現在在討論的),其次他把虛頁8對應的頁框號由X變為1,因此重新執行MOV REG,32780時,MMU將把32780映射為4108。

  

我們已經知道,大多數使用虛擬存儲器的系統都使用一種稱為分頁(paging)的技術,就象我們剛才所舉的例子,虛擬地址空間被分成大小相同的一組頁,每個頁有一個用來標示它的頁號(這個頁號一般是它在該組中的索引,這點和C/C++中的數組相似)。在上面的例子中0~4K的頁號為0,4~8K的頁號為1,8~12K的頁號為2,以此類推。而虛擬地址(注意:是一個確定的地址,不是一個空間)被MMU分為2個部分,第一部分是頁號索引(page Index),第二部分則是相對該頁首地址的偏移量(offset). 。我們還是以剛才那個16位機器結合下圖進行一個實例說明,該實例中,虛擬地址8196被送進MMU,MMU把它映射成物理地址。16位的CPU總共能產生的地址范圍是0~64K,按每頁4K的大小計算,該空間必須被分成16個頁。而我們的虛擬地址第一部分所能夠表達的范圍也必須等於16(這樣才能索引到該頁組中的每一個頁),也就是說這個部分至少需要4個bit。一個頁的大小是4K(4096),也就是說偏移部分必須使用12個bit來表示(2^12=4096,這樣才能訪問到一個頁中的所有地址),8196的二進制碼如下圖所示:

  

該地址的頁號索引為0010(二進制碼),既索引的頁為頁2,第二部分為000000000100(二進制),偏移量為4。頁2中的頁框號為6(頁2映射在頁框6,見上圖),我們看到頁框6的物理地址是24~28K。於是MMU計算出虛擬地址8196應該被映射成物理地址24580(頁框首地址+偏移量=24576+4=24580)。同樣的,若我們對虛擬地址1026進行讀取,1026的二進制碼為0000010000000010,page index="0000"=0,offset=010000000010=1026。頁號為0,該頁映射的頁框號為2,頁框2的物理地址范圍是8192~12287,故MMU將虛擬地址1026映射為物理地址9218(頁框首地址+偏移量=8192+1026=9218)。以上就是MMU的工作過程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM