漫談虛擬化之二-虛擬化面臨的挑戰
在談這部分內容之前,讓我們先來了解一下常見的一些有關虛擬化的常用概念。
1. 常用概念
(1)宿主機或主機:即 Host Machine,指物理機資源,如果將一個物理機虛擬成多個虛擬機,則稱該物理機為 Host Machine。
(2)客戶機:即 Guest Machine,指虛擬機資源。
(3)Host OS 和 Guest OS:運行在 Host Machine 上的 OS 則為 Host OS;運行在 Guest Machine 上的 OS 為 Guest OS。
(4)Hypervisor 或 VMM:通過虛擬化層的模擬,虛擬機在上層軟件看來就是一個真實的機器,這個虛擬化層一般稱為虛擬機監控機(Virtual Machine Monitor,VMM)或Hypervisor。是一種運行在基礎物理服務器和操作系統之間的中間軟件層,可允許多個操作系統和應用共享硬件。
進一步理解,可以認為 Hypervisor 是一種在虛擬環境中的“元”操作系統。它可以訪問服務器上包括內存和磁盤在內所有物理設備。Hypervisor 不但協調著這些硬件資源的訪問,同時也在各個虛擬機之間施加防護。當服務器啟動并執行 Hypervisor 時,它會加載所有虛擬機客戶端的操作系統,同時會分配給每一臺虛擬機適量的內存、CPU、網絡和磁盤。
(5)VM:即虛擬機,是指使用虛擬化技術,通過軟件模擬完整的計算機硬件系統功能,構造出的完整虛擬計算機系統。該虛擬機可以獨立運行在一個完全隔離的環境中,就像使用本地計算機一樣,安全可靠。
2. 虛擬化面臨的挑戰
在通過軟件手段設計 VMM 的時候,需要解決很多問題,我們來看一下:
(1)確保 VMM 控制所有的系統資源
x86 處理器有 4 個特權級別,Ring 0 ~ Ring 3,只有運行在 Ring 0 ~ 2 級時,處理器才可以訪問特權資源或執行特權指令;運行在 Ring 0 級時,處理器可以訪問所有的特權狀態。x86 平臺上的操作系統一般只使用 Ring 0 和 Ring 3 這兩個級別,操作系統運行在 Ring 0 級,用戶進程運行在 Ring 3 級。為了滿足上面的第一個充分條件-資源控制,VMM 自己必須運行在 Ring 0 級,同時為了避免 Guest OS 控制系統資源,Guest OS 不得不降低自身的運行級別,運行在 Ring 1 或 Ring 3 級(Ring 2 不使用)。
(2)特權級壓縮(Ring Compression)
VMM 使用分頁或段限制的方式保護物理內存的訪問,但是 64 位模式下段限制不起作用,而分頁又不區分 Ring 0, 1, 2。為了統一和簡化 VMM 的設計,Guest OS 只能和 Guest 進程一樣運行在 Ring 3 級。VMM 必須監視 Guest OS 對 GDT(Global Descriptor Table 全局描述符表)、IDT(Interrupt Descriptor Table,即中斷描述符表)等特權資源的設置,防止 Guest OS 運行在 Ring 0 級,同時又要保護降級后的 Guest OS 不受 Guest 進程的主動攻擊或無意破壞。
(3)特權級別名(Ring Alias)
特權級別名是指 Guest OS 在虛擬機中運行的級別并不是它所期望的。VMM 必須保證 Guest OS 不能獲知正在虛擬機中運行這一事實,否則可能打破等價性條件。例如,x86 處理器的特權級別存放在 CS(Code Segment 代碼段) 代碼段寄存器內,Guest OS 可以使用非特權 push 指令將 CS 寄存器壓棧(棧是存儲的系統,壓棧是寫入數據,用 push 表示,每壓棧一次減 2,出棧是輸出數據,用 pop 表示,每出棧一次加 2;遵循先進后出,后進先出的順序),然后 pop 出來檢查該值。又如,Guest OS 在低特權級別時讀取特權寄存器 GDT、LDT(Local Descriptor Table 局部描述符表)、IDT 和 TR(Task Rigister 任務寄存器),并不發生異常,從而可能發現這些值與自己期望的不一樣。為了解決這個挑戰,VMM 可以使用動態二進制翻譯的技術,例如預先把 “push %%cs” 指令替換,在棧上存放一個影子 CS 寄存器值;又如,可以把讀取 GDT 寄存器的操作“sgdt dest”改為“movl fake_gdt, dest”。
(4)地址空間壓縮(Address Space Compression)
地址空間壓縮是指 VMM 必須在 Guest OS 的地址空間中保留一部分供其使用。例如,中斷描述表寄存器(IDT Register)中存放的是中斷描述表的線性地址,如果 Guest OS 運行過程中來了外部中斷或觸發處理器異常,必須保證運行權馬上轉移到 VMM 中,因此 VMM 需要將 Guest OS 的一部分線性地址空間映射成自己的中斷描述表的主機物理地址。VMM 可以完全運行在 Guest OS 的地址空間中,也可以擁有獨立的地址空間,后者的話,VMM 只占用 Guest OS 很少的地址空間,用于存放中斷描述表和全局描述符表(GDT)等重要的特權狀態。無論如何哪種情況,VMM 應該防止 Guest OS 直接讀取和修改這部分地址空間。
(5)處理 Guest OS 的缺頁異常
內存是一種非常重要的系統資源,VMM 必須全權管理,Guest OS 理解的物理地址只是客戶機物理地址(Guest Physical Address),并不是最終的主機物理地址(Host Physical Address)。當 Guest OS 發生缺頁異常時,VMM 需要知道缺頁異常的原因,是 Guest 進程試圖訪問沒有權限的地址,或是客戶機線性地址(Guest Linear Address)尚未翻譯成 Guest Physical Address,還是客戶機物理地址尚未翻譯成主機物理地址。
一種可行的解決方法是 VMM 為 Guest OS 的每個進程的頁表構造一個影子頁表,維護 Guest Linear Address 到 Host Physical Address 的映射,主機 CR3 寄存器存放這個影子頁表的物理內存地址。VMM 同時維護一個 Guest OS 全局的 Guest Physical Address 到 Host Physical Address 的映射表。發生缺頁異常的地址總是 Guest Linear Address,VMM 先去 Guest OS 中的頁表檢查原因,如果頁表項已經建立,即對應的 Guest Physical Address 存在,說明尚未建立到 Host Physical Address 的映射,那么 VMM 分配一頁物理內存,將影子頁表和映射表更新;否則,VMM 返回到 Guest OS,由 Guest OS 自己處理該異常。
(6)處理 Guest OS 中的系統調用
系統調用是操作系統提供給用戶的服務進程,使用非常頻繁。最新的操作系統一般使用 SYSENTER/SYSEXIT 指令對來實現快速系統調用。SYSENTER 指令通過IA32_SYSENTER_CS,IA32_SYSENTER_EIP 和 IA32_SYSENTER_ESP 這 3 個 MSR(Model Specific Register)寄存器直接轉到 Ring 0 級;而 SYSEXIT 指令不在 Ring 0 級執行的話將觸發異常。因此,如果 VMM 只能采取 Trap-And-Emulate 的方式處理這 2 條指令的話,整體性能將會受到極大損害。
(7)轉發虛擬的中斷和異常
所有的外部中斷和主機處理器的異常直接由 VMM 接管,VMM 構造必需的虛擬中斷和異常,然后轉發給 Guest OS。VMM 需要模擬硬件和操作系統對中斷和異常的完整處理流程,例如 VMM 先要在 Guest OS 當前的內核棧上壓入一些信息,然后找到 Guest OS 相應處理例程的地址,并跳轉過去。VMM 必須對不同的 Guest OS 的內部工作流程比較清楚,這增加了 VMM 的實現難度。同時,Guest OS 可能頻繁地屏蔽中斷和啟用中斷,這兩個操作訪問特權寄存器 EFLAGS,必須由 VMM 模擬完成,性能因此會受到損害。 Guest OS 重新啟用中斷時,VMM 需要及時地獲知這一情況,并將積累的虛擬中斷轉發。
(8)Guest OS 頻繁訪問特權資源
Guest OS 對特權資源的每次訪問都會觸發處理器異常,然后由 VMM 模擬執行,如果訪問過于頻繁,則系統整體性能將會受到極大損害。比如對中斷的屏蔽和啟用,cli(Clear Interrupts)指令在 Pentium 4 處理器上需要花費 60 個時鐘周期(cycle)。又如,處理器本地高級可編程中斷處理器(Local APIC)上有一個操作系統可修改的任務優先級寄存器(Task-Priority Register),IO-APIC 將外部中斷轉發到 TPR 值最低的處理器上(期望該處理器正在執行低優先級的線程),從而優化中斷的處理。TPR 是一個特權寄存器,某些操作系統會頻繁設置(Linux Kernel 只在初始化階段為每個處理器的 TPR 設置相同的值)。
3. 總結
軟件 VMM 所遇到的以上挑戰從本質上來說是因為 Guest OS 無法運行在它所期望的最高特權級,傳統的 Trap-And-Emulate 處理方式雖然以透明的方式基本解決上述挑戰,但是帶來極大的設計復雜性和性能下降。早期比較先進的虛擬化軟件結合使用二進制翻譯和半虛擬化的技術,核心思想是動態或靜態地改變 Guest OS 對特權狀態訪問的操作,盡量減少產生不必要的硬件異常,2005 年隨著硬件輔助虛擬化技術的出現,進一步簡化了 VMM 的設計,VMM 的性能也能得到很大提高。