MIPS32地址映射和TLB


所有集成了MMU功能的CPU,使能MMU之后,程序地址就是虛擬地址,不能直接訪問存儲器,必須經過MMU轉換成物理地址。

MIPS32虛擬地址空間

MIPS32將虛擬地址空間划分為4個區域:

  • kuseg 0x0000 0000 - 0x7FFF FFFF(低2GB)

這些地址是用戶態可用的地址。對於有MMU的機器,這些地址需要經過MMU(TLB)的轉換后才可以使用;對於沒有MMU的機器,這些地址的行為與具體機器實現相關。

  • kseg0 0x8000 0000 - 0x9FFF FFFF(512MB):

這段地址只需將最高位清零即轉換為物理地址,映射到連續的低端512MB物理地址上,因此在描述其屬性時一般稱為unmapped。另外該段地址訪問時總是需要通過cache,因此描述其屬性時稱為cached。在一般應用上,這段地址映射到的物理地址用於存放程序和數據或者操作系統核心。

  • kseg1 0xA000 0000 - 0xBFFF FFFF(512MB):

與kseg0類似,這段地址同樣映射到了低端512MB物理地址(將高3個bit清零),但其訪問不經過cache,因此其屬性可以稱為 unmapped/uncached。由於unmaped/uncached特性,這段地址無需配置TLB和cache即可使用,是唯一的在系統重啟時能 正常工作的地址空間,因此復位入口點(0xBFC0 0000)被放在這個區域,其物理地址為0x1FC0 0000。

  • kseg2 0xC000 0000 - 0xFFFF FFFF(1GB):

該段地址只能在核心態下使用且需要經過MMU(TLB)轉換。

綜上,以BCM53003芯片為例,虛擬地址與物理地址的映射關系如下:

其中,kseg3段只是對kseg2段進一步細分,沒有本質的區別。

kseg0和kseg1兩個虛擬地址段為unmapped地址段,虛擬地址到物理地址的映射關系是固定的,這是因為它們不是通過TLB轉換的,而是由MIPS CPU內部實現的Fix-Mapped MMU完成地址轉換。這樣設計的初衷,是因為CPU剛上電時,TLB未初始化,unmapped地址段可以將Flash Reset Vector(4MB)、DDR DMA(128MB)、CPU核心控制寄存器組以及關鍵外設寄存器組映射到CPU的虛擬地址空間。

kuseg和kseg2兩個虛擬地址段為mapped地址段,由TLB負責處理地址映射。

MIPS CPU有四種工作模式——User/Supervisor/Kernel/Debug,每種工作模式下的訪問權限不同,如下圖所示:

MIPS32 TLB描述

TLB(Translation Lookside Buffer)介於CPU控制核心和Cache控制器之間,其作用是把程序地址(或稱虛擬地址)轉換成物理地址。

TLB被稱為相聯存儲器或者內容尋址存儲器,因為它不是按照索引來尋址,而是根據內容來選擇TLB表項進行尋址。其邏輯非常復雜,每一個TLB表項都有內建的比較器,復雜度和性能擴展性很差,因此,TLB的表項一般不是很多。

典型的TLB包含16~64個TLB表項,每一個表項包含一個頁的虛擬地址(VPN即虛擬頁號)和一個物理頁地址(PFN即物理頁號),頁大小是可以配置的。

當程序訪問一個虛擬地址時,該地址和所有TLB表項中的VPN進行比較,TLB返回匹配的TLB表項的PFN,完成地址轉換;如果找不到,則觸發TLB miss異常(Linux系統中,因為各進程虛擬地址空間獨立且地址范圍相同,因此會觸發TLB refill重填異常,會涉及TLB表項的更新;但是VxWorks系統中,所有任務共享同一虛擬地址空間,所有TLB表項都是啟動時配置,運行時不動態更新)。有一組標志位和每個PFN一起返回,標志位用來標識地址頁是否緩存、緩存模式、屬於某個ASID還是全局有效地址等。

正所謂“知其然,然后知其所以然”,以BCM53003芯片(包含64個TLB表項)為例,將所有TLB表項導出如下:

BCM5300X>tlb 0 63
 0 : 00 e0000000  64MB -> 0_40000000 C2DVG 0_44000000 C2DVG
 1 : 00 c0000000  64MB -> 0_40000000 C0DVG 0_44000000 C0DVG
 2 : 00 20000000 256MB -> 0_10000000 C0--- 0_20000000 C2DV-
 3 : 00 00000000 256MB -> 0_10000000 C0--- 0_20000000 C0DV-
 4 : 00 60000000 256MB -> 0_80000000 C2DVG 0_90000000 C2DVG
 5 : 00 40000000 256MB -> 0_80000000 C0DVG 0_90000000 C0DVG
 6 : 00 8000c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
 7 : 00 8000e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
 8 : 00 80010000   4KB -> 0_00000000 C0--- 0_00000000 C0---
 9 : 00 80012000   4KB -> 0_00000000 C0--- 0_00000000 C0---
10 : 00 80014000   4KB -> 0_00000000 C0--- 0_00000000 C0---
11 : 00 80016000   4KB -> 0_00000000 C0--- 0_00000000 C0---
12 : 00 80018000   4KB -> 0_00000000 C0--- 0_00000000 C0---
13 : 00 8001a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
14 : 00 8001c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
15 : 00 8001e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
16 : 00 80020000   4KB -> 0_00000000 C0--- 0_00000000 C0---
17 : 00 80022000   4KB -> 0_00000000 C0--- 0_00000000 C0---
18 : 00 80024000   4KB -> 0_00000000 C0--- 0_00000000 C0---
19 : 00 80026000   4KB -> 0_00000000 C0--- 0_00000000 C0---
20 : 00 80028000   4KB -> 0_00000000 C0--- 0_00000000 C0---
21 : 00 8002a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
22 : 00 8002c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
23 : 00 8002e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
24 : 00 80030000   4KB -> 0_00000000 C0--- 0_00000000 C0---
25 : 00 80032000   4KB -> 0_00000000 C0--- 0_00000000 C0---
26 : 00 80034000   4KB -> 0_00000000 C0--- 0_00000000 C0---
27 : 00 80036000   4KB -> 0_00000000 C0--- 0_00000000 C0---
28 : 00 80038000   4KB -> 0_00000000 C0--- 0_00000000 C0---
29 : 00 8003a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
30 : 00 8003c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
31 : 00 8003e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
32 : 00 80040000   4KB -> 0_00000000 C0--- 0_00000000 C0---
33 : 00 80042000   4KB -> 0_00000000 C0--- 0_00000000 C0---
34 : 00 80044000   4KB -> 0_00000000 C0--- 0_00000000 C0---
35 : 00 80046000   4KB -> 0_00000000 C0--- 0_00000000 C0---
36 : 00 80048000   4KB -> 0_00000000 C0--- 0_00000000 C0---
37 : 00 8004a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
38 : 00 8004c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
39 : 00 8004e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
40 : 00 80050000   4KB -> 0_00000000 C0--- 0_00000000 C0---
41 : 00 80052000   4KB -> 0_00000000 C0--- 0_00000000 C0---
42 : 00 80054000   4KB -> 0_00000000 C0--- 0_00000000 C0---
43 : 00 80056000   4KB -> 0_00000000 C0--- 0_00000000 C0---
44 : 00 80058000   4KB -> 0_00000000 C0--- 0_00000000 C0---
45 : 00 8005a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
46 : 00 8005c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
47 : 00 8005e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
48 : 00 80060000   4KB -> 0_00000000 C0--- 0_00000000 C0---
49 : 00 80062000   4KB -> 0_00000000 C0--- 0_00000000 C0---
50 : 00 80064000   4KB -> 0_00000000 C0--- 0_00000000 C0---
51 : 00 80066000   4KB -> 0_00000000 C0--- 0_00000000 C0---
52 : 00 80068000   4KB -> 0_00000000 C0--- 0_00000000 C0---
53 : 00 8006a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
54 : 00 8006c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
55 : 00 8006e000   4KB -> 0_00000000 C0--- 0_00000000 C0---
56 : 00 80070000   4KB -> 0_00000000 C0--- 0_00000000 C0---
57 : 00 80072000   4KB -> 0_00000000 C0--- 0_00000000 C0---
58 : 00 80074000   4KB -> 0_00000000 C0--- 0_00000000 C0---
59 : 00 80076000   4KB -> 0_00000000 C0--- 0_00000000 C0---
60 : 00 80078000   4KB -> 0_00000000 C0--- 0_00000000 C0---
61 : 00 8007a000   4KB -> 0_00000000 C0--- 0_00000000 C0---
62 : 00 8007c000   4KB -> 0_00000000 C0--- 0_00000000 C0---
63 : 00 8007e000   4KB -> 0_00000000 C0--- 0_00000000 C0---

以TLB Entry 0為例說明:

 0 : 00 e0000000  64MB -> 0_40000000 C2DVG 0_44000000 C2DVG

該表項表示將虛擬地址0xe000 0000開始的128MB虛擬地址空間,映射到從0x4000 0000開始的64MB物理地址空間,以及從0x4400 0000開始的64MB物理地址空間,每個物理地址段后面的標志位(C2DVG)表示映射模式。

MIPS CPU一般采用雙相相關聯存儲器實現TLB,即每個TLB表項包含一對相鄰的虛擬地址頁(虛擬地址空間上連續)對應兩個單獨的物理地址(物理地址空間上可以不連續)。

接下來,就是“知其所以然”的階段了,MIPS CPU提供了幾個CP0協處理器寄存器和幾條TLB相關的指令,用來實現TLB的配置。以一個TLB表項為例,它由CP0的EntryHi、PageMask、EntryLo0、EntryLo1四個寄存器的不同字段組成。每次程序代碼訪問mapped虛擬地址時,TLB都通過這幾個寄存器返回TLB表項給CPU,整個地址轉換的過程是CPU邏輯電路實現的,軟件不感知;軟件可以做的事情是配置TLB表項,建立虛擬地址和物理地址的映射表。

 VPN2表示虛擬頁號,ASID用來唯一標識當前進程,如Linux系統中,每個進程的虛擬地址空間都是4GB大小,地址范圍都是0x0000 0000 ~ 0xFFFF FFFF,相同的虛擬地址對不同的進程而言,是映射到不同的物理地址的,因此僅靠VPN2虛擬頁號無法完成地址轉換,還需要ASID。

PageMask用來標識每個TLB表項的虛擬地址段大小,可配置范圍如下:

EntryLo0/1兩個寄存器分別表示一個TLB表項的兩個物理地址頁,稱為even page和odd page。

PFN表示物理頁號;C表示Cache一致性屬性,即是cached還是uncached,是write-through還是write-back;D表示是否為Dirty頁,V表示是否有效;G表示是否為全局地址,如果置1,則不關心ASID(ignore ASID),如果置0,則進行地址轉換時要根據ASID進行地址轉換。另外,一般情況下,EntryLo0和EntryLo1的G位需要配置為相同值,因為TLB的表項中的G屬性是兩位相與的邏輯。

值得一提的是,kseg0和kseg1兩個unmapped虛擬地址段的Cache一致性屬性可以通過CP0相關寄存器配置:

綜上,一個完成的TLB地址映射如下:

地址轉換流程如下:

MIPS32 TLB配置

TLB配置還涉及其他CP0寄存器和TLB相關指令。

 Index表示TLB表項序號,從0~63。P表示Probe Failure標志位(只讀),當發生TLB miss時,則置位。

Random和Wired寄存器一起划定TLB refill重填的范圍,即可以把64個TLB表項划分為靜態表項和動態表項兩個區域,當發生TLB refill異常時,則隨機選取Wired~63之間的任意表項(Random隨機數指向的表項)進行TLB表項更新。

Context寄存器是輔助TLB refill重填的,當發生TLB miss異常需要refill時,在PTE Base指向的區域取匹配的表項進行快速回填。

涉及TLB指令包括:

TLBWI - 寫CP0 Index寄存器設置TLB Entry ID

TLBR - 讀CP0 Index寄存器獲取TLB Entry ID

TLBWR - 寫CP0 Random寄存器設置TLB Entry ID

TLBP - 獲取匹配的TLB Entry ID

 

一個完整的TLB配置過程如下:

Physical address 0x88000000 ~ 0x9FFFFFFF (384M) is mapped to virtual address 0xC8000000 ~ 0xDFFFFFFF.

– 1 Set PageMask register to configure 16M page size. The value should be 0x01ffe000. 384/(16*2) = 12 entries needed.

– 2 Set Index register to configure TLB entry index.

– 3 Set EntryHi register to configure virtual address. ASID fields can be ignored.

– 4 Set EntryLo0 and EntryLo1 registers to configure the even and the odd physical pages. The lower 6 bits, which are status bit, could be set to 0x1f. It means:

• Cacheable, write back
• Allow modify
• The entry is valid.
• Ignore ASID.
– 5 Use TLBWI instruction to write one TLB entry by Index register.
– 6 If more TLB entries needed, jump to 2 


免責聲明!

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



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