<超標量處理器概覽> 第 3 章 - 虛擬存儲器
3.2 - 位址轉換 3.2.3 - Page Fault PTE (page table entry) 中包含: valid bit:標記這個 PTE 是否有效,當作業系統設定好 page table 後,就需要將對應 PTE 的 valid bit 設成 1 dirty bit:當一個 page 內容被更新時 (e.g. 執行 store 指令),硬體會自動將 dirty bit 設成 1,代表這個 page 如果被選中要被替換時,需要將 page 的內容 swap 回硬碟 access bit:當一個 page 被訪問 (load/store) 時,硬體會自動將 access bit 設成 1,作業系統則會定期的將 access bit 清為 0 當要替換 page table 時,就可以根據 access bit 來得知最近 page 是否有被訪問過,進而實現近似 LRU (Least Recently Used) 的替換策略 當 page 要被 swapped out 前: 要先將 D-Cache 的內容 flush 進 memory,以確保要被 swapped out 的 page 內容是最新的 將 PTE 的 valid bit 設成 0,以避免其他 CPU 或 MMU 在接下來 swap out 期間誤讀這個 page valid bit 為 0 時,代表該 page 並不存在記憶體中,當 MMU 存取時會觸發 page fault 讓作業系統從硬碟讀取 page 進記憶體 valid bit 是由作業系統在把 page 讀進記憶體後設為 1 的 執行如 RISC-V 的 sfence.vma 指令,確保 TLB 中對應的 entries 被清空,以避免 MMU 錯誤存取到被 swapped out page 的 cache 內容 3.4 - 加入 TLB 和 Cache 3.4.1 - TLB 的設計 TLB entry 中也會包含: valid bit:標記這個 TLB entry 是否有效;當 TLB entry 被 swap in 時,valid bit 會被設為 1 dirty bit:當執行 store 指令時,如果 TLB hit,就不會再訪問 PTE,也就不會更新 PTE 中的 dirty bit;只有當 TLB entry 要被替換時,才會同步至 PTE access bit:當執行 load/store 指令時,如果 TLB hit,就不會再訪問 PTE,也就不會更新 PTE 中的 access bit;只有當 TLB entry 要被替換時,才會同步至 PTE P.S. RISC-V 中,TLB entry 並沒有包含 dirty 和 access bits,作業系統需要自己確保 PTE 的更新 sfence.vma 只會將 TLB 中對應的 entries 給 invalid 而已 (針對 TLB 的部份) 如果 CPU 有支援 Svadu extension,那麼硬體就會自動更新 PTE 中的 dirty 和 access bit 如果硬體支援 access 和 dirty bits 自動更新, 作業系統只需要讀取 PTE 即可獲得最新的 access 和 dirty bits 的狀態 如果硬體不支援 access 和 dirty bits 自動更新,當 access=0 或 dirty=0 時: MMU 會觸發 page fault 作業系統在 page fault handler 中設置 access=1 或 dirty=1 作業系統得先透過設定 PTE 的 valid bit (追蹤 page 是否有被 accessed) 和 disable write permission (追蹤 page 是否有被 stored) 來當 page fault 發生時,在 page fault handler 更新 access 或 dirty bit 重新執行造成 page fault 的那道指令 也就是讓作業系統來自行管理 PTE 中 access 和 dirty bits 的內容,效能較差,但硬體設計較簡單 RISC-V privilege spec: If pte.a=0, or if the original memory access is a store and pte.d=0: If the Svade extension is implemented, stop and raise a page-fault exception corresponding to the original access type. 一般為了減少 TLB miss rate,會使用 fully-associative 來設計 TLB 缺點:TLB 容量不能太大,不然會增加查找的時間 因此,有些架構也會使用 set-associative 來設計容量比較大的 TLB 因為是 fully-associative 或 set-associative,因此 TLB entry 中,還會包含 tag 欄位 (VPN,Virtual Page Number),用來比對 TLB 是否 hit P.S. TLB entry 中的 data 是 PFN (Page Frame Number) 現代處理器架構,通常都使用 2-level TLB 1st level 採用 Harvard 架構,分為 I-TLB (指令) 和 D-TLB (數據),一般採用 fully-associative 設計 2nd level 採用 Von Neumann 架構,指令和數據共用,一般採用 set-associative 設計 現代處理器中因應程式的 size 越來越大,因此還會支持容量更大的 page E.g. 128 entries 的 TLB,只能映射到 128 * 4KB = 512 MB 大小的程式,顯然不夠用 更大的 page: 優點: 降低 TLB miss rate 缺點: 當發生 page fault 的時候,需要花更多的時間才能將更大的 page 內容從硬碟搬至記憶體 如果程式用不到這麼大的 page,那麼空間就被浪費了,且也會造成 page fragment,降低 page 的使用效率 總和以上原因,現代處理器都支持大小可變的 page,由作業系統負責管理,根據程式的特點選用不同大小的 page,最大程度地利用 TLB 有限的空間,並降低 page fragment 在 TLB 中會有相對應的設定可以調整映射的 page 大小 因為記憶體的存取速度相對於 CPU 的執行速度來說非常慢,因此 TLB 通常只會採用 Write-back 的方式設計,且因為 TLB entry 中 tag 和 data 等欄位是不會變動的,因此當發生 TLB miss,需要將 TLB entry swap out 時,只需要將 dirty bit (執行 store 指令時會被更新) 和 access bit (執行 load/store 指令時會被更新) 寫回 PTE 中即可 TLB miss 發生的情況: Page 並不在記憶體中,因此也不在 TLB 中 Page 在記憶體中,page table 中也有對應的 PTE,但這個 PTE 並沒有被 cache 在 TLB 中 Page 在記憶體中,page table 中也有對應的 PTE,這個 PTE 也曾經存在 TLB 中,但是因為先前的 TLB miss,因此被替換出來了 TLB miss 時,TLB entry 的替換策略: LRU (Least Recently Used) Random:如同 cache,使用一個 counter,每個 cycle 都會 + 1,每次 TLB miss 要替換 TLB entry 時,就根據當下 counter 的值決定是哪個 entry 要被替換 LRU 比較難實現,所以通常會採用 Random 的替換策略,實做也比較簡單 如果 TLB 採用 Write-back,TLB entry 中的 dirty 和 access bits 就有可能跟 PTE 的內容不同步,如果 page 要被 swap out 的時候,作業系統會無法即時得知究竟 page 是否 dirty,以及是否有被 accessed 過 直觀解法:每次發生 page fault 要 swap page 的時候,先將 TLB entries flush 至 PTE 缺點:需要耗費額外的時間 flush TLB 另類解法:作業系統可以認為,有在 TLB 中被 cached 對應的 pages 都是正在使用的,因此不能將其 swap out 需要作業系統自行維護一張表,紀錄哪些 PTE 有被 cached 在 TLB 中,且為 valid 的 不過這種設計並不常見 如果系統中有 D-Cache,page 也是 dirt 的,那麼 page 被更動的內容也有可能還存在 D-Cache 中,因此在 page swap out 前也必須先 flush D-Cache 3.4.2 - Cache 的設計 兩種 caches: ...