QEMU架構淺析

一、QEMU簡介及與KVM等虛擬化的關係

QEMU是“Quick Emulator”的縮寫,是一個用C語言編寫的開源虛擬化軟件。本文的目的是描述本人所理解的QEMU技術架構的見解,並以此拋磚引玉。衆所周知,QEMU的源代碼開發文檔非常稀少,描述內部結構和工作機理的文檔更是鳳毛麟角,一般的開發人員想要從事QEMU的開發工作,通常只能從源代碼入手。因此,對於技術人員來說,瞭解QEMU是一項艱鉅的任務。

QEMU有幾種虛擬化模式。首先,它可以使用基於內核的虛擬機(KVM)執行x86處理器硬件虛擬化,以幾乎比擬硬件本機的速度執行運算任務。其次,它可以通過機器代碼的實時轉換來模擬其他處理器以用於虛擬機運行不同平臺的操作系統。最後,它可以使用實時轉換爲其他架構運行簡單的程序,類似於Linux中的Wine。因爲QEMU沒有圖形用戶界面(GUI),而其提供的核心能力又是關鍵而重要的,因此通常用作更復雜的虛擬化管理器的一部分。比如,我們經常使用的開源VirtualBoxXen等虛擬化產品,其核心底層的虛擬化部分就有集成和使用QEMU,此外,主流的KVM虛擬化也是集成和使用QEMU的主力虛擬化管理器系統。

KVM的角度來說,KVMKernel Virtual Machine)是Linux的一個內核驅動模塊,它能夠讓Linux主機成爲一個Hypervisor(虛擬機監控器)。在支持VMXVirtual Machine Extension)功能的x86處理器中,Linux在原有的用戶模式和內核模式中新增加了客戶模式,並且客戶模式也擁有自己的內核模式和用戶模式,虛擬機就是運行在客戶模式中。KVM模塊的職責就是打開並初始化VMX功能,提供相應的接口以支持虛擬機的運行。KVM通過調用Linux本身內核功能,實現對CPU的底層虛擬化和內存的虛擬化,使Linux內核成爲虛擬化層。KVM20072月被導入Linux 2.6.20內核中。從存在形式來看,它包括兩個內核模塊:kvm.kokvm_intel.ko(或kvm_amd.ko),本質上,KVM是管理虛擬硬件設備的驅動,該驅動使用字符設備/dev/kvm(由KVM本身創建)作爲管理接口,主要負責vCPU的創建、虛擬內存的分配、vCPU寄存器的讀寫以及vCPU的運行。

QEMU的角度來說,QEMUQuick Emulator)本身並不包含或依賴KVM模塊,而是一套由Fabrice Bellard編寫的模擬計算機的自由軟件。QEMU虛擬機是一個純軟件的實現,可以在沒有KVM模塊的情況下獨立運行,但是性能比較低。QEMU有整套的虛擬機實現,包括處理器虛擬化、內存虛擬化以及I/O設備的虛擬化。在不需要KVM加速的情況下,QEMU通過一個特殊的“重編譯器”對特定的處理器的二進制代碼進行翻譯,從而具有了跨平臺的通用性。QEMU有兩種工作模式:系統模式,可以模擬出整個電腦系統,另一種是用戶模式,可以運行不同與當前硬件平臺的其他平臺上的程序(比如在x86平臺上運行跑在ARM平臺上的程序)。目前最新版本是4.x。從QEMU角度來看,虛擬機運行期間,QEMU通過KVM模塊提供的系統調用接口進行內核設置,由KVM模塊負責將虛擬機置於處理器的VMX模式運行。QEMU使用了KVM模塊的虛擬化功能,爲自己的虛擬機提供硬件虛擬化加速以提高虛擬機的性能。

而現在流行的KVM虛擬化平臺,就是在修改了QEMU代碼,把他模擬CPU、內存的代碼換成KVM,而網卡、顯示器等留着,因此QEMU+KVM就成了一個完整的虛擬化平臺。由於KVM運行在內核空間,只是內核模塊,QEMU運行在用戶空間,實際模擬創建,管理各種虛擬硬件(磁盤,網卡,顯卡等)。從KVM的角度來說,用戶沒法直接跟內核模塊交互,需要藉助用戶空間的管理工具,因此需要藉助QEMU這個運行在用戶空間的工具。KVMQEMU相輔相成,QEMU通過KVM達到了硬件虛擬化的速度,而KVM則通過QEMU來模擬設備並實現和內核空間的KVM的交互,雖然這個交互並不僅僅只有QEMU能夠辦到。此外,由於QEMU模擬IO設備效率不高的原因,現在常常採用半虛擬化的virtio方式來虛擬IO設備。

綜上,理解了QEMUKVM的關係,也就理解了VirtualBoxXen等虛擬化產品集成和使用QEMU的關係了。

二、QEMU架構及組成

QEMU的架構如下圖所示,由幾個基本的組件組成:

image.png

QEMU架構圖

如圖所示,QEMU由以下幾個部分組成:

l  Hypervisor控制仿真

l  Tiny Code GeneratorTCG)在虛擬機器代碼和宿主機代碼之間進行轉換。

l  軟件內存管理單元(MMU)處理內存訪問。

l  磁盤子系統處理不同的磁盤映像格式

l  設備子系統處理網卡和其他硬件設備

下面將對這些組件介紹。

2.1 Hypervisor管理程序

Hypervisor(虛擬機管理程序)是一種創建和運行虛擬機的虛擬機監視器。 QEMU中的Hypervisor(虛擬機管理程序)從磁盤映像加載二進制機器代碼,使用TCG將其轉換爲本機機器代碼,連接到虛擬或實際設備,並啓動軟件MMU,然後開始在磁盤映像中模擬操作系統。其中,TCG和軟件MMU是實現虛擬化CPU和內存的關鍵。

而集成KVM後,QEMU將使用Linux內核的KVM功能以純模式執行虛擬機。KVM基本上是Linux內核中的Hypervisor(虛擬機管理程序)。它可以並行運行多個操作系統。QEMU可以在KVM中啓動一個新線程以執行模擬操作系統,然後KVM控制執行。從這部分來說,KVMHypervisor(虛擬機管理程序)替換掉了QEMUHypervisor(虛擬機管理程序)。

3.2微代碼生成器(TCG

QEMU中,Tiny Code GeneratorTCG)將源處理器機器代碼轉換爲虛擬機運行所需的機器代碼塊(如x86機器代碼塊)。從物理硬件的架構和角度上來說,不可能在一個處理器上運行爲另一個處理器的指令集架構(ISA)編譯的機器代碼,例如,x86處理器上的ARM機器代碼。因此,引入中間環節對不同的處理器指令集架構(ISA)進行翻譯和轉換是實現虛擬化通用性的技術途徑和解決方案。在Tiny Code GeneratorTCG)中,這些已經翻譯的代碼塊放在轉換緩存中,並通過跳轉指令將源處理器的指令集(ISA)和目標處理器的指令集(ISA)鏈接在一起。當Hypervisor(虛擬機管理程序)在執行代碼時,存放於轉換緩存中的鏈接指令可以跳轉到指定的代碼塊,並且執行可以在不同的已翻譯代碼塊上運行,直到需要翻譯新塊爲止。在執行的過程中,如果遇到了需要翻譯的代碼塊,執行動作就會暫停並回會跳回到Hypervisor(虛擬機管理程序),Hypervisor(虛擬機管理程序)就會使用和協調TCG對需要進行二進制翻譯的源處理器指令集(ISA)進行轉換和翻譯並存儲到轉換緩存中。

下圖顯示了QEMUTCG工作原理:

image.png

.微代碼生成器工作原理

TCG在運行的過程中存在一個小缺點,即它無法正確運行自修改代碼,因爲它沒有將修改後的代碼頁進行標記,再次運行時需要重新翻譯。這影響了QEMU的二進制運行效率,從另外一個角度來說,這也增加了一定的安全性。自修改代碼在軟件世界中容易被漏洞利用。特別是緩衝區溢出攻&擊等內存損壞漏洞,這些漏洞利用威脅代理(例如後門)提供的特殊代碼覆蓋易受攻&擊的應用程序代碼,如果已經被覆蓋的代碼已經被運行(並因此被緩存),出了正常運行的會導致漏洞攻&擊利用外,更多的時候則會導致TCG運行和翻譯失敗,從而導致程序復現異常或崩潰。

此外,在翻譯的過程中,如果新處理器使用的寄存器多於x86處理器並且具有許多複雜指令,那麼對TCG進行編程以處理和適應新的CPU仿真就可能需要大量的工作。目前來說,QEMU所支持的大部分處理器都擁有部分相同的指令集。例如,“MOV”指令幾乎存在於所有處理器中,並且可以簡單地複製,除非CPU寄存器中存在一些位大小差異。例如,在32位處理器上模擬64位處理器可能需要許多額外的指令,這也需要更多時間在TCG轉換器中進行編程。

QEMU的源代碼中,有一個名爲'tcg'的子目錄,其中包含將機器指令轉換爲相應的x86機器指令的代碼。此代碼是一個用C編寫的簡單翻譯狀態機。還有用於內存訪問和跳轉的特殊轉換,因爲它們可以生成對軟件內存管理單元的調用。而虛擬化CPU和內存也往往是在一起的,因爲從本質上來說,CPU的工作就是對內存的區域數據進行搬運,CPU是內存的搬運工。在QEMU保護代碼塊之外的其他內存區域。機器代碼中的跳轉和分支也必須到達正確的存儲器地址。

所以通過二進制翻譯技術,針對CPU的仿真和虛擬化就非常簡單了。TCGHypervisor(虛擬機管理程序)能夠實現基於CPU的仿真,其中,其CPU仿真流程如下圖所示:

image.png

從上圖我們可以看到,針對CPU的仿真和虛擬化其實就是將源處理器的指令集(ISA)轉換和翻譯成目標處理器的指令集(ISA)。CPU仿真和虛擬化就是通過中間的轉換和翻譯來實現的,由此,針對CPU的虛擬化的第一種技術就完全實現了。這種二進制翻譯技術是最早的CPU虛擬化技術,誕生了VMware這樣的虛擬化巨頭,也誕生了QEMU這樣的開源虛擬化鼻祖。

 

2.3硬件設備

虛擬機的硬件設備要求可以通過直接連接主機中的實際物理設備或通過QEMU中的硬件設備仿真來實現。與硬件相關的大多數QEMU代碼位於目錄“hw”中。

QEMU中,存在兩種使用硬件設備的方式:直通模式使用主機實際物理設備和QEMU的設備驅動仿真實現的模擬虛擬設備。如果採用直通方式使用實際的物理設備,那麼就會搶佔主機的設備使用權,並且其他虛擬機也將無法使用該物理設備。在直通模式中,虛擬機可以直接訪問USB總線或PCI總線,並可以直接與設備通信。一般情況下,採用直通模式的物理設備都是很難進行QEMU仿真的設備,比如網絡攝像頭、串行和並行端口等。其他設備因爲大部分虛擬機都會使用,而且很難與主機共享,例如網絡設備,因此大都會使用QEMU模擬仿真的虛擬設備。比如在虛擬機的網絡設備中,可通過模擬網卡來解決,從而在網絡堆棧上添加額外的層。此外,QEMU可以選擇連接到Linux內核中的“virtio”半虛擬化驅動程序,這意味着Linux內核處理虛擬機和硬件設備之間的輸入/輸出,而不採用QEMU的模擬設備進行中轉和傳輸(僅用作中介)。

 

2.4磁盤映像

QEMU可以處理幾種不同的磁盤映像格式。首選格式爲rawqcow2Raw是一種非常簡單的格式,它將文件系統中的字節逐字節存儲在文件中。大多數其他仿真器都支持此格式。Qcow2QEMU自己的圖像格式,對小圖像很有用。並且支持磁盤映像壓縮以及捕獲磁盤映像狀態的快照。還支持另外兩種格式:在VirtualBox中使用的vdi和在VMWare中使用的vmdk

QEMU的磁盤映像通過其存儲IO協議棧來進行支持,其存儲協議棧如下圖所示:

image.png

image.png

QEMU存儲協議棧

從QEMU的存儲協議棧來說,應用程序和虛擬機內核的工作類似於裸機。虛擬機通過仿真硬件與QEMU交互,並將IO執行情況的控制流和數據流交互給QEMUQEMU代表虛擬機對磁盤鏡像文件執行I / O操作。而從主機內核層面上,主機內核會將虛擬機I / O視爲一種用戶空間的應用程序IO請求進行正常的執行處理。

2.5軟件MMU

傳統處理器中的內存管理單元(MMU)處理對計算機內存位置的訪問。當處理器想要訪問某個存儲器地址時,MMU獲取該地址的內容。此內容可以來自處理器芯片上的本地快速緩存,來自隨機存取存儲器(RAM)或來自光盤。它甚至可以做出一些關於緩存某些內存位置的控制決定。

QEMU有一個基於軟件的MMU,其工作方式與硬件MMU類似。它使用地址轉換緩存,其中包含訪客地址、主機地址和偏移值,以提高轉換速度。它還允許智能鏈接代碼塊,以便在沒有內存故障的情況下實現更快的執行,其中必須重新加載和重新轉換內存塊。

在尋找在QEMU中運行的虛擬機的漏洞時,軟件MMU是否正在進行翻譯和正確放置塊會是其測試和Fuzz的重點。

三、總結

其實搞清楚QEMU的技術架構和實現細節,我們需要弄明白QEMU的架構和組成,以及每個組件的作用及運行機制。此外,我們還需要了解每個組成組件之間的相互交互關係,從數據流的角度來看,其主要是控制流和數據流;從IO角度來看,其主要是網絡IO和存儲IO,從技術實現機制來看,其主要是虛擬化CPU和內存以及存儲、網絡協議棧的實現。本文有許多的未盡事宜,待請後續補充。


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