位址轉譯與 TLB (Address Translation & TLB)
Overview Table
| 主題 | 核心內容 | 書頁 |
|---|---|---|
| 位址轉譯符號 | p.850 | |
| 轉譯機制 | MMU 用 PTBR 找 page table,以 VPN 索引 PTE,PPN 串接 VPO 得 PA;PPO = VPO | p.850-851 |
| Page hit / fault 流程 | hit 純硬體 5 步;fault 需 OS 介入 7 步(victim 換出、新頁換入、重新執行指令) | p.851-852 |
| Cache 與 VM 整合 | 多數系統用 physically addressed cache,先轉譯再查 cache;PTE 本身也可被 cache | p.853 |
| TLB | MMU 內的小型 virtually addressed PTE cache,高關聯度;TLBI = VPN 低 t 位、TLBT = 其餘位 | p.853-855 |
| 多層 page table | 單層表太大(32-bit/4KB/4B PTE → 4MB);k 層階層化,null PTE 的子表可不存在 | p.855-857 |
| End-to-end 範例 | n=14, m=12, P=64;TLB 4-way 16 entries;cache direct-mapped 16 sets、4B block | p.857-860 |
| Core i7 轉譯 | 48-bit VA、52-bit PA;4 層 page table;CR3 存 L1 表基底;36-bit VPN 切成 4 個 9-bit | p.861-864 |
| Linux VM | 以 area (vm_area_struct) 組織;task_struct → mm_struct(pgd, mmap)→ area list | p.864-867 |
| Linux page fault | 三段檢查:位址合法?→ 權限合法?→ 正常 fault(換頁後重跑指令) | p.867-869 |
頁層級保護:PTE 權限位 (p.849)
位址轉譯硬體每次都要讀 PTE,因此在 PTE 加上權限位 (permission bits) 就能以頁為單位控管存取:
- SUP:是否須在 kernel (supervisor) mode 才能存取;user mode 只能存取 SUP=0 的頁。
- READ / WRITE:控制讀/寫權限。
- 違反權限 → CPU 觸發 general protection fault → kernel 例外處理器送 SIGSEGV 給行程;shell 回報為 "segmentation fault"。
9.6 位址轉譯基礎 (p.849-851)
符號整理(Figure 9.11)
| 符號 | 意義 | 符號 | 意義 |
|---|---|---|---|
| virtual address space 位址數 | PPO | physical page offset | |
| physical address space 位址數 | PPN | physical page number | |
| page size(bytes) | CO | cache 內 byte offset | |
| VPO | virtual page offset | CI | cache index |
| VPN | virtual page number | CT | cache tag |
| TLBI | TLB index | TLBT | TLB tag |
形式化定義:位址轉譯是
硬體轉譯流程(Figure 9.12)
- PTBR (page table base register):CPU 控制暫存器,指向目前行程的 page table。
-bit VA = -bit VPN + -bit VPO;VPN 當作 page table 的索引(VPN 0 → PTE 0...)。 - PA = PTE 中的 PPN 串接 VPO;因虛實頁同為
bytes,PPO 恆等於 VPO(不需轉譯)。
n-1 p p-1 0
VA: [ VPN | VPO ]
| |
PTBR ──> Page v |
Table[VPN] ─> PTE |
| (valid=1) | valid=0 → page fault
v v
PA: [ PPN | PPO ]
m-1 p p-1 0
Page hit 流程(純硬體,Figure 9.13a)
- Processor 產生 VA 送給 MMU。
- MMU 產生 PTEA(PTE address)向 cache/main memory 請求。
- Cache/memory 回傳 PTE 給 MMU。
- MMU 組出 PA 送給 cache/memory。
- Cache/memory 回傳資料字給 processor。
Page fault 流程(硬體 + OS,Figure 9.13b)
1-3. 同上。4. PTE 的 valid bit = 0 → MMU 觸發例外,控制權轉給 kernel 的 page fault handler。5. Handler 選出 victim page;若已被修改(dirty)則先寫回磁碟(page out)。6. Handler 將新頁 page in,並更新記憶體中的 PTE。7. Handler 返回原行程,重新執行 faulting instruction;這次變成 page hit。
Page hit: Page fault:
CPU ──VA──> MMU ──PTEA──> Mem CPU ──VA──> MMU ──PTEA──> Mem
MMU <──PTE─── Mem MMU <──PTE──── Mem (valid=0)
MMU ──PA────> Mem MMU ──Exception──> Fault handler
CPU <─Data───────────────Mem handler: victim page ──> Disk
handler: new page <── Disk
return & restart instruction
9.6.1 Cache 與 VM 的整合 (p.853)
- 多數系統選擇 physical addressing 的 SRAM cache:轉譯發生在 cache lookup 之前。
- 好處:多個行程可同時在 cache 中有 block、可共享同一虛擬頁的 block;cache 不必處理保護問題(權限已在轉譯時檢查)。
- PTE 和一般資料一樣可以被 cache(MMU 的 PTEA 請求會先查 L1)。
9.6.2 用 TLB 加速位址轉譯 (p.853-855)
每次 CPU 產生 VA,MMU 都要讀一次 PTE——最壞情況多一次記憶體存取(數十至數百 cycle);即使 PTE 在 L1 也要數個 cycle。解法:在 MMU 內放一個小型 PTE cache,即 TLB (translation lookaside buffer)。
- TLB 是小型、virtually addressed 的 cache,每行存一個 PTE,通常高關聯度 (high associativity)。
- 若 TLB 有
個 set:TLBI = VPN 的最低 t 位,TLBT = VPN 其餘高位。
n-1 p+t p+t-1 p p-1 0
VA: [ TLBT (tag) | TLBI(idx) | VPO ]
└────────── VPN ──────────┘
TLB hit(Figure 9.16a,常見情形):
- CPU 產生 VA → 2-3. MMU 從 TLB 取得 PTE → 4. MMU 組 PA 送 cache/memory → 5. 回傳資料。
全部步驟都在晶片內的 MMU 完成,因此很快。
TLB miss(Figure 9.16b):MMU 必須向 L1 cache/memory 發 PTEA 取 PTE,新取得的 PTE 存入 TLB(可能覆蓋既有 entry),再組 PA 完成存取。
9.6.3 多層 Page Table (p.855-857)
單層表的問題:32-bit 位址空間、4 KB 頁、4-byte PTE → page table 大小 =
兩層範例(32-bit、4KB 頁、4B PTE,Figure 9.17):
- Level 1 每個 PTE 負責 4 MB chunk(= 1,024 個連續頁);1,024 個 L1 PTE 即涵蓋 4 GB。
- 若 chunk i 內全部頁未配置 → L1 PTE i 為 null,對應的 level 2 表根本不必存在。
- 若至少一頁已配置 → L1 PTE i 指向一個 level 2 page table 的基底;L2 PTE 才對映 4-KB 頁。
- 每個 L1/L2 表 = 1,024 × 4 B = 4 KB,恰為一頁大小。
省記憶體的兩個機制:
- null L1 PTE → 子表不存在(典型程式的 4 GB 空間大多未配置)。
- 只有 level 1 表須常駐;level 2 表可由 VM 系統按需建立、換入換出。
k 層一般化(Figure 9.18):VA 切成 k 個 VPN + 一個 VPO;VPN i 索引第 i 層表;第 j 層(
VA: [ VPN 1 | VPN 2 | ... | VPN k | VPO ]
| | | |
v v v |
L1 PT ──> L2 PT ──> ... ──> Lk PT |
(PTBR/CR3) PTE→ PPN |
v v
PA: [ PPN | PPO ]
9.6.4 End-to-End 轉譯範例 (p.857-860)
假設:byte-addressable、1-byte 存取、
推導欄位寬度:
- VPO = PPO =
= 6 bits;VPN = = 8 bits;PPN = = 6 bits。 - TLB:4 sets → TLBI = VPN 低 2 位,TLBT = VPN 高 6 位。
- Cache:block 4 B → CO = 2 bits;16 sets → CI = 4 bits;CT =
= 6 bits。
VA (14 bits): [ TLBT(6) | TLBI(2) | VPO(6) ]
└────── VPN(8) ─────┘
PA (12 bits): [ CT(6) | CI(4) | CO(2) ]
└ PPN(6) ┘└──── PPO(6) ─────┘
手算流程(VA = 0x03D4,Figure 9.20 快照):
| 步驟 | 動作 | 值 |
|---|---|---|
| 1 | 展開位元、切欄位 | VPN=0x0F、VPO=0x14、TLBI=0x3、TLBT=0x03 |
| 2 | 查 TLB set 3、tag 0x03 |
TLB hit,回傳 PPN=0x0D |
| 3 | PA = PPN ‖ VPO | PA = 0x354 |
| 4 | 切 PA 欄位 | CT=0x0D、CI=0x5、CO=0x0 |
| 5 | 查 cache set 5、tag 相符 | Cache hit,回傳 byte 0x36 |
其他可能路徑 (p.860):TLB miss → 到 page table 取 PTE;PTE invalid → page fault,kernel 換頁後重跑指令;PTE valid 但 cache miss → 到 main memory 取 block。
9.7 個案研究:Intel Core i7 / Linux (p.861-865)
記憶體系統概觀(Figure 9.21)
- 支援 48-bit (256 TB) 虛擬位址空間、52-bit (4 PB) 實體位址空間(另有 32-bit 相容模式)。
- 頁大小開機時可設 4 KB 或 4 MB;Linux 用 4 KB。
| 元件 | 規格 |
|---|---|
| L1 d-TLB | 64 entries、4-way |
| L1 i-TLB | 128 entries、4-way |
| L2 unified TLB | 512 entries、4-way |
| L1 d-cache / i-cache | 各 32 KB、8-way、64 B block(physically addressed) |
| L2 unified cache | 256 KB、8-way |
| L3 unified cache | 8 MB、16-way(所有 core 共享) |
TLB 為 virtually addressed;各 cache 為 physically addressed。核心間以 QuickPath 點對點連結通訊。
Core i7 位址轉譯(Figure 9.22, 9.25)
- 四層 page table;每個行程有私有的階層。行程執行時已配置頁的 page table 全部常駐記憶體(架構上允許換出)。
- CR3 控制暫存器存 level 1 表的實體位址;CR3 是行程 context 的一部分,context switch 時還原。
- 36-bit VPN 切成 4 個 9-bit 欄位,各為該層表的 offset;VPO = 12 bits(4 KB 頁)。
- L1 d-cache 端:PA 切成 CT(40)| CI(6)| CO(6)。
VA(48): [ VPN1(9) | VPN2(9) | VPN3(9) | VPN4(9) | VPO(12) ]
| | | | |
CR3 ──> L1 PT ──> L2 PT ──> L3 PT ──> L4 PT |
(page global (page upper (page middle (page |
directory) directory) directory) table) |
512 GB/項 1 GB/項 2 MB/項 4 KB/項 |
PTE → PPN(40)
v v
PA(52): [ PPN(40) | PPO(12) ]
PTE 格式(Figure 9.23, 9.24)
Level 1-3 PTE(每項指向一個 4 KB 子表)與 Level 4 PTE(指向 4 KB 實體頁)欄位:
| 欄位 | 意義 | 層級 |
|---|---|---|
| P | 子表/子頁是否在實體記憶體(Linux 恆為 1) | 全部 |
| R/W | 所有可達頁為 read-only 或 read/write | 全部 |
| U/S | user 或 supervisor mode 才能存取(保護 kernel) | 全部 |
| WT | 子表/子頁 write-through 或 write-back 政策 | 全部 |
| CD | 停用/啟用 cache | 全部 |
| A | reference bit:MMU 讀寫時設定、軟體清除 → 供頁替換演算法 | 全部 |
| PS | 頁大小 4 KB 或 4 MB(僅 level 1 定義) | L1 |
| D | dirty bit:MMU 寫入時設定、軟體清除 → 決定 victim 是否須寫回 | 僅 L4 |
| G | global page:task switch 時不從 TLB 逐出 | 僅 L4 |
| Base addr | 子表/子頁實體基底位址的最高 40 位 → 強制 4 KB 對齊 | 全部 |
| XD | execute disable:禁止從可達頁取指令(64-bit 新增,降低 buffer overflow 攻擊風險) | 全部 |
- P = 0 時,其餘位元可供 OS 使用(例如存放頁在磁碟上的位置)。
- A/D 位由 MMU 硬體設定、由 kernel 以特殊 kernel-mode 指令清除——這是 kernel page fault handler 實作替換策略與寫回判斷的依據。
9.7.2 Linux 虛擬記憶體系統 (p.864-867)
Kernel virtual memory
每個行程的位址空間 = 使用者部分(code、data、heap、shared library、stack)+ user stack 之上的 kernel virtual memory:
- 所有行程共享的區域:kernel 的 code 與全域資料結構;此外 Linux 把一段連續虛擬頁直接映到全部 DRAM 的連續實體頁,讓 kernel 能方便存取任意實體位置(如存取 page table、對映到特定實體位址的裝置做 memory-mapped I/O)。
- 各行程不同的區域:該行程的 page tables、kernel 在此行程 context 執行時用的 kernel stack、記錄位址空間組織的資料結構。
Areas(Figure 9.27)
Linux 把虛擬記憶體組織成 area(又稱 segment) 的集合:一段已配置的連續虛擬記憶體,其頁彼此相關(code、data、heap、shared library、stack 各是一個 area)。
- 每個存在的虛擬頁都屬於某個 area;不屬於任何 area 的頁不存在、不可被參照,也不耗任何 kernel/記憶體/磁碟資源 → 位址空間可以有 gap。
task_struct mm_struct vm_area_struct 串列
+--------+ +--------+ +----------+
| mm ---+------->| pgd ---+--CR3 | vm_end | 對應一個 area
| ... | | mmap --+------->| vm_start | (shared libs / data
+--------+ +--------+ | vm_prot | / text ...)
| vm_flags |
| vm_next -+--> 下一個 area struct
+----------+
| 結構/欄位 | 意義 |
|---|---|
task_struct |
每行程一個;含 PID、user stack 指標、執行檔名、PC 等 |
mm_struct |
描述 VM 現況;pgd 指向 level 1 表(page global directory)基底,mmap 指向 area struct 串列 |
vm_start / vm_end |
area 的起點/終點 |
vm_prot |
area 內所有頁的讀寫權限 |
vm_flags |
頁是共享 (shared) 或私有 (private) 等 |
vm_next |
串列中下一個 area struct |
- 行程執行時,kernel 把
pgd存入 CR3。
Linux Page Fault 處理(Figure 9.28, p.868-869)
MMU 轉譯位址 A 觸發 page fault 後,kernel handler 依序判斷:
page fault on VA = A
|
|-- (1) A 落在某個 area 內嗎?(比對各 vm_start/vm_end)
| 否 --> segmentation fault,終止行程
|
|-- (2) 存取方式合法嗎?(寫唯讀頁?user mode 讀 kernel 記憶體?)
| 否 --> protection exception,終止行程
|
'-- (3) 合法位址 + 合法操作 => 正常 page fault:
選 victim -> dirty 則換出 -> 換入新頁 -> 更新 page table
-> handler 返回,CPU 重跑 faulting instruction(這次正常轉譯)
Exam/Test Patterns
| 情境 / 關鍵字 | 答案 |
|---|---|
| 給 n、m、P,求 VPN/VPO/PPN/PPO 位元數 | VPO = PPO = |
| 為何 PPO 不必轉譯? | 虛擬頁與實體頁大小相同( |
| TLB 有 |
TLBI = VPN 最低 |
| Page hit 誰處理?page fault 誰處理? | hit 全由硬體 (MMU);fault 由硬體觸發例外 + OS kernel handler 換頁後重跑指令 |
| 為何 cache 多用 physical addressing? | 多行程可同時共存/共享 block;保護檢查已併入轉譯,cache 不需處理 |
| TLB miss 之後一定 page fault 嗎? | 否。TLB miss 只是去記憶體讀 PTE;PTE valid 就沒有 fault(也可能接著 cache miss) |
| 單層 page table 太大怎麼辦? | 多層階層:null 上層 PTE → 子表不存在;只有 level 1 表須常駐 |
| 多層表要查 k 次 PTE,不會很慢? | TLB 會 cache 各層 PTE,實務上不明顯變慢 |
| Core i7 幾層 page table?VPN 怎麼切? | 4 層;36-bit VPN 切 4×9 bits,VPO 12 bits;CR3 指向 L1 表(屬行程 context) |
| A bit / D bit 誰設誰清?用途? | MMU 設定、kernel(軟體)清除;A 供頁替換參考,D 決定 victim 是否須先寫回 |
| XD bit 的用途 | 禁止從該 PTE 可達頁取指令,把執行限制在唯讀 code 段以降低 buffer overflow 攻擊風險 |
| 寫入唯讀頁 / user 讀 kernel 頁,Linux 如何處理? | fault handler 第 2 步判定不合法 → protection exception(SIGSEGV),終止行程 |
| 存取不在任何 area 的位址 | fault handler 第 1 步判定 → segmentation fault |
| VPO 同時送 L1 cache 的技巧 | 轉譯與 set 選擇重疊:VPO(12) = CI(6)+CO(6),TLB 回 PPN 後只需比 tag |