巢狀分頁表(nested page table)
巢狀分頁表(nested page table)是針對影子分頁表用軟體解決的那同一個「兩層位址問題」所提出的硬體解法。問題再說一次:一台虛擬機器有兩層位址轉譯——客體把客體虛擬轉成客體實體,而超管理器必須把客體實體轉成真實機器實體。影子分頁用軟體把這兩層合併,代價是不斷地陷入。巢狀分頁則改為教會 CPU 自己走完兩層,因此不必再靠陷入來合併。
在機制上,CPU 現在同時持有兩組分頁表:客體自己的(客體虛擬到客體實體),以及超管理器提供的第二組(客體實體到機器實體)。一次記憶體存取時,硬體的分頁表走訪器先走過客體分頁表得到一個客體實體位址,再把它餵進超管理器的分頁表以抵達真實機器位址——全在硬體中完成,結果也像一般轉譯那樣快取在 TLB 裡。Intel 把這行銷為延伸分頁表(EPT),AMD 稱巢狀分頁表(NPT 或 RVI);通稱為第二層位址轉譯(SLAT)。
最大的勝利是:客體可以自由編輯自己的分頁表而完全不必陷入超管理器,這消除了影子分頁最沉重的成本,讓記憶體密集的工作負載快得多。誠實的告誡是:在 TLB 失誤時,一次完整的兩層走訪所觸碰的記憶體比單層走訪多,所以一次失誤更昂貴——這使 TLB 與大型頁在虛擬化下更為重要。即便如此,對幾乎所有現代工作負載而言,巢狀分頁表都明顯勝過影子分頁。
一個客體程式讀取一個變數。在 TLB 失誤時,CPU 硬體走訪客體的分頁表,找到客體實體位址 0x4000,再走訪超管理器的分頁表,發現客體實體 0x4000 其實位於機器實體 0x91000——並把合併後的結果快取起來,使下一次存取瞬間完成。
CPU 在硬體中走訪兩層轉譯,所以客體無須陷入去修正對應。
巢狀分頁消除了影子分頁「每次編輯都陷入」的代價,但一次 TLB 失誤現在要付出更長的二維分頁走訪,所以在虛擬機器裡 TLB 命中與大型頁更為要緊。它平均更快,但並非免費。