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