目錄
- 什么是虛擬化
- 廣義虛擬化
- 狹義虛擬化
- 虛擬化指令集
- 敏感指令集
- 虛擬化指令集的工作模式
- 監視器對敏感指令的處理過程:
- 虛擬化類型
- 全虛擬化
- 類虛擬化
- 硬件輔助虛擬化
- 虛擬化架構
- 裸金屬架構
- 宿主機模式架構
什么是虛擬化
虛擬化就是通過模仿下層原有的功能模塊創造接口來“欺騙”上層的機制。虛擬化可以通過資源管理技術,將物理存在的實體資源以虛擬機(Virtual Machine,VM)的形式抽象成一種邏輯表示。通常的做法是在整個系統架構中增加一個抽象層,負責分割下層的物理資源,然后組合成邏輯資源供上層使用。
廣義虛擬化
狹義虛擬化
狹義虛擬化特指操作系統虛擬化,它使用虛擬化技術在一臺物理機上模擬出多臺虛擬機,每臺虛擬機都擁有獨立的資源(計算資源、存儲資源、網絡資源)。
虛擬化的具體實現是通過在操作系統與硬件之間加入一個虛擬化層,并通過空間上的分割、時間上的分時及仿真模擬,將服務器物理資源抽象成邏輯資源。虛擬化層可以將單個CPU模擬為多個CPU,并且這些CPU之間相互獨立、互不影響,也就是虛擬化層實現了計算單元的模擬及隔離。它向上層操作系統提供與原先物理服務器一致的環境,使得上層操作系統可以直接運行在虛擬環境中,并允許具有不同操作系統的多臺虛擬機相互隔離,并發地運行在同一臺物理服務器上,這臺物理服務器被稱為“宿主機”。虛擬化層模擬出來的主要邏輯功能為虛擬機,在虛擬機中運行的操作系統被稱為“GuestOS”。
虛擬化場景包括三個部分:硬件資源、虛擬機監視器(VMM)和虛擬機(VM)。系統虛擬化可以將一臺物理機(Host)虛擬化為多臺虛擬機,并通過虛擬化層(即虛擬機監視器)使每臺虛擬機都擁有自己的虛擬硬件,并擁有一個獨立的虛擬機運行環境,進而擁有一個獨立運行的操作系統。
虛擬化指令集
虛擬化指令集指的是將某個硬件平臺的二進制代碼轉換為另一個平臺的二進制代碼,從而實現不同硬件指令集之間的兼容。這種技術也被形象地稱為“二進制翻譯”。
敏感指令集
敏感指令(Sensitive Instruction):在虛擬化場景下,在GuestOS的內核中有一部分非特權指令,它們不一定會改變或者損害整個系統,但是會影響基于虛擬化的整個系統的安全。
敏感指令是操作特權資源的指令,包括修改虛擬機的運行模式,改變宿主機的狀態,讀/寫時鐘、中斷等寄存器,訪問存儲保護系統、地址重定位系統及所有的I/O指令。
例如,GuestOS的內核指令可以讀取宿主機CPU的寄存器內容,從而看到整個系統的狀態,這樣一臺虛擬機就可以看到另一臺虛擬機的內部信息了。在虛擬化場景下,所有會危害到系統安全的指令集被稱為“敏感指令集”。
虛擬化指令集的工作模式
Popek&Goldberg 原理定義了如何設計一個有效的虛擬機監視器。
等價性:任何一個程序,在被管理程序控制時,除時序和資源可用性之外,應該與沒有被管理程序控制時是一樣的,而且預置的特權指令可以自由執行。
管理程序通常指的是虛擬機監視器,也稱為hypervisor。虛擬機監視器是一種軟件,它允許多個操作系統在同一臺物理計算機上運行,并且對它們進行管理和監視。虛擬機監視器負責分配計算機的資源,如處理器時間、內存和輸入/輸出設備,以便多個操作系統之間可以共享這些資源。
時序指的是程序執行的時間順序和時序關系,包括程序的指令執行順序、時鐘周期、中斷處理等。在虛擬機監視器中,被管理程序受到虛擬機監視器的控制,因此其時序可能會受到影響。
資源可用性指的是系統中各種資源的可用性,包括CPU、內存、磁盤、網絡等。在虛擬機監視器中,被管理程序的資源使用受到虛擬機監視器的限制和調度,因此其資源可用性也可能會受到影響。
資源控制:一個程序發出的任何調用系統資源的動作在被執行時,都應先調用控制程序(虛擬機監視器)。
效率性:一個程序產生的所有無害指令都應該由硬件直接執行,控制程序不應該在任何地方產生中斷。
Popek和Goldberg虛擬化原理是一種計算機虛擬化技術的基本原理。該原理由Gerald J. Popek和Robert P. Goldberg于1974年提出。該原理規定了一個處理器架構必須滿足的條件,以便能夠支持虛擬化。這些條件包括特權指令的識別、特權指令的陷阱和仿真、設備I/O的虛擬化等。根據這些條件,Popek和Goldberg提出了一個虛擬機監視器(VMM)的概念,該監視器可以在硬件層面上管理和支持虛擬化環境。這個原理對虛擬化技術的發展產生了深遠的影響,也為后來的虛擬化技術提供了理論基礎。
1、虛擬機GuestOS中的所有非敏感指令都會“穿透”虛擬機監視器,直接運行在CPU上。
2、虛擬機GuestOS中的敏感指令,理想的狀態是通過陷阱機制被虛擬機監視器所捕獲,然后虛擬機監視器通過不同的模擬或虛擬化技術實現在虛擬機上的模擬。
監視器對敏感指令的處理過程:
如果敏感指令都是特權指令,當在虛擬機中執行內核態的特權指令時,則會通過陷阱機制被下層的虛擬機監視器捕獲。虛擬機監視器可以對捕獲的特權指令進行替換操作,從而完整地模擬出某個虛擬機監視器下的特權操作。“陷阱+模擬”機制從本質上保證了可影響虛擬機監視器正常運行的指令由虛擬機監視器模擬執行,而大部分非敏感指令還是照常運行在物理CPU上。
虛擬機監視器用到了優先級壓縮技術,使得虛擬機中的應用運行在Ring 3層,GuestOS運行在Ring 1層(有時也可運行在Ring 3層),虛擬機監視器運行在Ring 0層。
虛擬化將原本的GuestOS內核的特權級別從Ring 0改為Ring 1,即可“消除”GuestOS內核的特權。但這會給GuestOS的內核指令帶來一定的麻煩,原本GuestOS的內核指令是被設計在Ring 0層下執行的,通過優先級壓縮后會造成部分指令在虛擬機中的Ring 1層或Ring 3層下無法執行。
當GuestOS的特權指令無法直接下達到CPU執行時,可以通過虛擬機監視器的“陷阱+模擬”機制執行。具體來說,當虛擬機中的應用需要操作重要資源時,會觸發特權指令,通過陷阱機制被虛擬機監視器捕獲,然后交由對應的GuestOS執行。因為虛擬化之后GuestOS運行在Ring 1層,它沒有權限執行一些特權指令,需要通過其他方式保證這些特權指令的執行。
當虛擬機中的應用使用系統調用時,其跳轉到的GustOS內核中斷處理程序(routine)運行于Ring1層。但是在內核中斷處理程序中有部分指令是必須在Ring 0層才能執行的,此時會再通過陷阱機制將這些指令自動轉入虛擬機監視器后執行。用戶程序運行特權指令時會有兩次特權下降,其中一次是進入Ring 1層的GuestOS;另一次是通過特權指令的陷阱機制進入Ring 0層的虛擬機監視器。
控制權指的是程序執行的控制權,即程序在執行過程中所處的特權級別。假設在虛擬化環境中運行一個操作系統,其中運行了一個虛擬機,虛擬機中運行了一個應用程序。當應用程序需要進行系統調用時,控制權會轉移到虛擬機內的操作系統內核中斷處理程序中,此時操作系統內核的特權級別為Ring 1。如果系統調用需要執行一些特權指令,例如修改頁表或訪問I/O端口,那么操作系統內核就無法直接執行這些指令,因為它的特權級別不夠高。這時,操作系統內核會通過陷阱機制將控制權轉移到虛擬機監視器中,虛擬機監視器的特權級別為Ring 0,可以執行特權指令并與物理硬件交互。執行完特權指令后,虛擬機監視器會將控制權返回給操作系統內核,操作系統內核再將控制權返回給應用程序,應用程序繼續執行。這種特權級別的轉換是虛擬化環境中實現安全隔離和資源管理的重要機制。
Popek&Coldberg原理的前提是,敏感指令必須都是特權指令,即敏感指令集是特權指令集的子集,如圖所示。只有這樣,虛擬機監視器才能通過選用特權指令集的陷阱捕獲方式進行虛擬化。
但是在x86處理器中,只能保證絕大多數的敏感指令是特權指令,還有約17個敏感指令不是特權指令,也就是說,敏感指令的范圍更大。然而,當特權指令集是敏感指令集的真子集時,一部分敏感指令無法被虛擬機監視器捕獲,也就是說虛擬機監視器無法完全控制這些指令的執行。這種情況被稱為“虛擬化漏洞”,因為虛擬機監視器無法完全替代或者控制這些敏感指令的執行,可能會導致安全性問題。
虛擬化類型
虛擬化分為全虛擬化、類虛擬化和硬件輔助虛擬化三類
全虛擬化
從GuestOS看來和在真實的物理機上運行完全一致,GuestOS察覺不到是運行在一個虛擬化平臺上。在這樣的虛擬化平臺上,GuestOS 無須做任何修改即可運行,所抽象的虛擬機具有完全的物理計算機特性,我們稱這種虛擬化平臺為“全虛擬化平臺”。全虛擬化平臺需要正確處理所有的敏感指令,進而正確完成對CPU、內存和I/O的各種操作。
在全虛擬化中,對于特權指令,還是采用先前的“陷阱+模擬”的方式。當虛擬機的內核態需要運行虛擬化漏洞指令時,Ring 0下的虛擬機監視器通過二進制代碼掃描并替換Ring 1下的GuestOS的二進制代碼,將所有虛擬化漏洞指令替換為其他指令。二進制翻譯是一種直接翻譯可執行二進制程序的技術,能夠把一種處理器上的二進制程序翻譯到另一種處理器上執行。在虛擬機監視器中,會動態地把虛擬機中的虛擬化漏洞指令翻譯為其他指令,從而實現虛擬化。
類虛擬化
不同于全虛擬化,類虛化的GuestOS知道自己運行在一個虛擬化環境中。類虛擬化可以通過修改GuestOS的內核代碼來規避虛擬化漏洞的問題。
GuestOS會將與敏感指令相關的操作都轉換為對虛擬機監視器的超級調用(Hypercall),交由虛擬機監視器進行處理,使GuestOS內核完全避免處理那些難以虛擬化的虛擬化漏洞指令。
與全虛擬化不同的是它將問題的中心由虛擬機監視器移向GuestOS自身,通過主動的方式由GuestOS去處理這些指令,而不是移交給虛擬機監視器進行處理,在這種設計理念下就必須得修改GuestOS內核。
但與全虛擬化相同的是,類虛擬化修改過的GuestOS也會運行在Ring 1下。運行在Ring 1下的GuestOS沒有權限執行的指令,會交給運行在Ring 0下的虛擬機監視器來處理。虛擬機監視器向GuestOS提供了一套“系統調用”,以方便GuestOS調用,這套“系統調用”就是超級調用。只有Ring 1下的GuestOS才能向虛擬機監視器發送超級調用請求,以防止Ring 3下的應用調用錯誤導致對系統可能的破壞。
例如,當虛擬機內核需要操作物理資源來分配內存時,虛擬機內核無法直接操作物理資源,而是通過調用與虛擬機監視器內存分配相關的超級調用,由超級調用來實現真正的物理資源操作。
全虛擬化通過Binary Translation在二進制代碼級別上來避免虛擬化漏洞。類虛擬化采取的是另一種思路,即修改操作系統內核的代碼,使得操作系統內核完全避免這些難以虛擬化的指令。
硬件輔助虛擬化
為了更好地解決x86架構下虛擬化漏洞的問題,芯片廠商擴展了其指令集來支持虛擬化。其核心思想是通過引入新的指令和運行模式,使虛擬機監視器和GuestOS分別運行在root模式和no-root模式下,這樣一來,GuestOS還是可以運行在Ring 0下的,GuestOS的內核也不需要修改。
將虛擬機監視器與GuestOS的執行環境完全隔離開,通過指令集的變化實現虛擬機監視器和GuestOS運行環境之間的相互轉換,即上文所述的root模式和no-root模式。啟動或退出root模式和no-root模式通過新添加的VMXON和VMXOFF指令實現。從root模式到no-root模式的轉換通過VMEntry指令實現,從no-root模式到root模式的轉換通過VMExit指令實現。
虛擬化架構
虛擬化架構主要分為裸金屬架構和宿主模式架構兩種
裸金屬架構
虛擬機監視器被直接安裝和運行在物理機上,依賴其自帶的虛擬內核管理,使用底層硬件資源。虛擬機監視器擁有硬件的驅動程序,不依賴特定的操作系統,其管理著宿主機及其他虛擬機。宿主機和虛擬機都安裝有各自的操作系統,即宿主機操作系統和GuestOS。裸金屬架構的代表是Xen。
宿主機模式架構
虛擬機監視器被安裝和運行在操作系統上,依賴操作系統對硬件設備的支持和對物理資源的管理。在這種情況下,雖然虛擬機監視器對硬件資源進行訪問必須經過宿主機操作系統,但虛擬機監視器依然可以充分利用操作系統對硬件設備的支持,以及內存管理進程調度等服務。宿主模式架構的代表是KVM。