KVM 內存虛擬化及其實現

概述

KVM(Kernel Virtual Machine) , 作爲開源的內核虛擬機,越來越受到 IBM,Redhat,HP,Intel 等各大公司的大力支持,基於 KVM 的開源虛擬化生態系統也日益完善。而實現 KVM 虛擬化,使客戶機高效地、安全地使用宿主機的內存資源,就必須實現內存的虛擬化。

客戶機物理地址空間

爲 了實現內存虛擬化,讓客戶機使用一個隔離的、從零開始且具有連續的內存空間,KVM 引入一層新的地址空間,即客戶機物理地址空間 (Guest Physical Address, GPA),這個地址空間並不是真正的物理地址空間,它只是宿主機虛擬地址空間在客戶機地址空間的一個映射。對客戶機來說,客戶機物理地址空間都是從零開始 的連續地址空間,但對於宿主機來說,客戶機的物理地址空間並不一定是連續的,客戶機物理地址空間有可能映射在若干個不連續的宿主機地址區間,如下圖 1 所示:

圖 1. 客戶機物理地址到宿主機虛擬地址的轉換

圖 1. 客戶機物理地址到宿主機虛擬地址的轉換

由 於客戶機物理地址不能直接用於宿主機物理 MMU 進行尋址,所以需要把客戶機物理地址轉換成宿主機虛擬地址 (Host Virtual Address, HVA),爲此,KVM 用一個 kvm_memory_slot 數據結構來記錄每一個地址區間的映射關係,此數據結構包含了對應此映射區間的起始客戶機頁幀號 (Guest Frame Number, GFN),映射的內存頁數目以及起始宿主機虛擬地址。於是 KVM 就可以實現對客戶機物理地址到宿主機虛擬地址之間的轉換,也即首先根據客戶機物理地址找到對應的映射區間,然後根據此客戶機物理地址在此映射區間的偏移量 就可以得到其對應的宿主機虛擬地址。進而再通過宿主機的頁表也可實現客戶機物理地址到宿主機物理地址之間的轉換,也即 GPA 到 HPA 的轉換。

實 現內存虛擬化,最主要的是實現客戶機虛擬地址 (Guest Virtual Address, GVA) 到宿主機物理地址之間的轉換。根據上述客戶機物理地址到宿主機物理地址之間的轉換以及客戶機頁表,即可實現客戶機虛擬地址空間到客戶機物理地址空間之間的 映射,也即 GVA 到 HPA 的轉換。顯然通過這種映射方式,客戶機的每次內存訪問都需要 KVM 介入,並由軟件進行多次地址轉換,其效率是非常低的。因此,爲了提高 GVA 到 HPA 轉換的效率,KVM 提供了兩種實現方式來進行客戶機虛擬地址到宿主機物理地址之間的直接轉換。其一是基於純軟件的實現方式,也即通過影子頁表 (Shadow Page Table) 來實現客戶虛擬地址到宿主機物理地址之間的直接轉換。其二是基於硬件對虛擬化的支持,來實現兩者之間的轉換。下面就詳細闡述兩種方法在 KVM 上的具體實現。

影子頁表

由 於宿主機 MMU 不能直接裝載客戶機的頁表來進行內存訪問,所以當客戶機訪問宿主機物理內存時,需要經過多次地址轉換。也即首先根據客戶機頁表把客戶機虛擬地址轉傳成客戶 機物理地址,然後再通過客戶機物理地址到宿主機虛擬地址之間的映射轉換成宿主機虛擬地址,最後再根據宿主機頁表把宿主機虛擬地址轉換成宿主機物理地址。而 通過影子頁表,則可以實現客戶機虛擬地址到宿主機物理地址的直接轉換。如下圖 2 所示:

圖 2. 客戶機物理地址到宿主機物理地址的轉換

圖 2. 客戶機物理地址到宿主機物理地址的轉換

影 子頁表簡化了地址轉換過程,實現了客戶機虛擬地址空間到宿主機物理地址空間的直接映射。但是由於客戶機中每個進程都有自己的虛擬地址空間,所以 KVM 需要爲客戶機中的每個進程頁表都要維護一套相應的影子頁表。在客戶機訪問內存時,真正被裝入宿主機 MMU 的是客戶機當前頁表所對應的影子頁表,從而實現了從客戶機虛擬地址到宿主機物理地址的直接轉換。而且,在 TLB 和 CPU 緩存上緩存的是來自影子頁表中客戶機虛擬地址和宿主機物理地址之間的映射,也因此提高了緩存的效率。

在影子頁表中,每個頁表項指向的都是宿主機的物理地址。這些表項是隨着客戶機操作系統對客戶機頁表的修改而相應地建立的。客戶機中的每一個頁表項都有一個影子頁表項與之相對應。如下圖 3 所示:

圖 3. 客戶機頁表和影子頁表

圖 3. 客戶機頁表和影子頁表

爲 了快速檢索客戶機頁表所對應的的影子頁表,KVM 爲每個客戶機都維護了一個哈希表,影子頁表和客戶機頁表通過此哈希表進行映射。對於每一個客戶機來說,客戶機的頁目錄和頁表都有唯一的客戶機物理地址,通 過頁目錄 / 頁表的客戶機物理地址就可以在哈希鏈表中快速地找到對應的影子頁目錄 / 頁表。在檢索哈希表時,KVM 把客戶機頁目錄 / 頁表的客戶機物理地址低 10 位作爲鍵值進行索引,根據其鍵值定位到對應的鏈表,然後遍歷此鏈表找到對應的影子頁目錄 / 頁表。當然,如果不能發現對應的影子頁目錄 / 頁表,說明 KVM 還沒有爲其建立,於是 KVM 就爲其分配新的物理頁並加入此鏈表,從而建立起客戶機頁目錄 / 頁表和對應的影子頁目錄 / 頁表之間的映射。當客戶機切換進程時,客戶機操作系統會把待切換進程的頁表基址載入 CR3,而 KVM 將會截獲這一特權指令,進行新的處理,也即在哈希表中找到與此頁表基址對應的影子頁表基址,載入客戶機 CR3,使客戶機在恢復運行時 CR3 實際指向的是新切換進程對應的影子頁表。

影子頁表異常處理機制

在通過影子頁表進行尋址的過程中,有兩種原因會引起影子頁表的 缺頁異常,一種是由客戶機本身所引起的缺頁異常,具體來說就是客戶機所訪問的客戶機頁表項存在位 (Present Bit) 爲 0,或者寫一個只讀的客戶機物理頁,再者所訪問的客戶機虛擬地址無效等。另一種異常是由客戶機頁表和影子頁表不一致引起的異常。

當缺頁異常 發生時,KVM 首先截獲該異常,然後對發生異常的客戶機虛擬地址在客戶機頁表中所對應頁表項的訪問權限進行檢查,並根據引起異常的錯誤碼,確定出此異常的原因,進行相應 的處理。如果該異常是由客戶機本身引起的,KVM 則直接把該異常交由客戶機的缺頁異常處理機制來進行處理。如果該異常是由客戶機頁表和影子頁表不一致引起的,KVM 則根據客戶機頁表同步影子頁表。爲此,KVM 要建立起相應的影子頁表數據結構,填充宿主機物理地址到影子頁表的頁表項,還要根據客戶機頁表項的訪問權限修改影子頁表對應頁表項的訪問權限。

由 於影子頁表可被載入物理 MMU 爲客戶機直接尋址使用, 所以客戶機的大多數內存訪問都可以在沒有 KVM 介入的情況下正常執行,沒有額外的地址轉換開銷,也就大大提高了客戶機運行的效率。但是影子頁表的引入也意味着 KVM 需要爲每個客戶機的每個進程的頁表都要維護一套相應的影子頁表,這會帶來較大內存上的額外開銷,此外,客戶機頁表和和影子頁表的同步也比較複雜。因 此,Intel 的 EPT(Extent Page Table) 技術和 AMD 的 NPT(Nest Page Table) 技術都對內存虛擬化提供了硬件支持。這兩種技術原理類似,都是在硬件層面上實現客戶機虛擬地址到宿主機物理地址之間的轉換。下面就以 EPT 爲例分析一下 KVM 基於硬件輔助的內存虛擬化實現。

EPT 頁表

EPT 技術在原有客戶機頁表對客戶機虛擬地址到客戶機物理地址映射的基礎上,又引入了 EPT 頁表來實現客戶機物理地址到宿主機物理地址的另一次映射,這兩次地址映射都是由硬件自動完成。客戶機運行時,客戶機頁表被載入 CR3,而 EPT 頁表被載入專門的 EPT 頁表指針寄存器 EPTP。EPT 頁表對地址的映射機理與客戶機頁表對地址的映射機理相同,下圖 4 出示了一個頁面大小爲 4K 的映射過程:

圖 4.EPT 頁錶轉換

圖 4.EPT 頁錶轉換

在 客戶機物理地址到宿主機物理地址轉換的過程中,由於缺頁、寫權限不足等原因也會導致客戶機退出,產生 EPT 異常。對於 EPT 缺頁異常,KVM 首先根據引起異常的客戶機物理地址,映射到對應的宿主機虛擬地址,然後爲此虛擬地址分配新的物理頁,最後 KVM 再更新 EPT 頁表,建立起引起異常的客戶機物理地址到宿主機物理地址之間的映射。對 EPT 寫權限引起的異常,KVM 則通過更新相應的 EPT 頁表來解決。

由此可以看出,EPT 頁表相對於前述的影子頁表,其實現方式大大簡化。而且,由於客戶機內部的缺頁異常也不會致使客戶機退出,因此提高了客戶機運行的性能。此外,KVM 只需爲每個客戶機維護一套 EPT 頁表,也大大減少了內存的額外開銷。

結束語

本文主要介紹了兩種內存虛擬化方法在 KVM 上的具體實現。隨着虛擬化技術的發展以及硬件對內存虛擬化的進一步支持,新的內存虛擬化方法也會隨之出現,從而使內存虛擬化變的更加簡單、高效。


轉自:https://www.ibm.com/developerworks/community/blogs/5144904d-5d75-45ed-9d2b-cf1754ee936a/entry/kvm-mem?lang=en

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章