KVM虛擬化源代碼詳解.doc_第1頁
KVM虛擬化源代碼詳解.doc_第2頁
KVM虛擬化源代碼詳解.doc_第3頁
KVM虛擬化源代碼詳解.doc_第4頁
KVM虛擬化源代碼詳解.doc_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

KVM虛擬機(jī)源代碼分析1, KVM結(jié)構(gòu)及工作原理1.1 KVM結(jié)構(gòu)KVM基本結(jié)構(gòu)有兩部分組成。一個是KVM Driver ,已經(jīng)成為Linux 內(nèi)核的一個模塊。負(fù)責(zé)虛擬機(jī)的創(chuàng)建,虛擬內(nèi)存的分配,虛擬CPU寄存器的讀寫以及虛擬CPU的運(yùn)行等。另外一個是稍微修改過的Qemu,用于模擬PC硬件的用戶空間組件,提供I/O設(shè)備模型以及訪問外設(shè)的途徑。圖1 KVM基本結(jié)構(gòu)KVM基本結(jié)構(gòu)如圖1所示。其中KVM加入到標(biāo)準(zhǔn)的Linux內(nèi)核中,被組織成Linux中標(biāo)準(zhǔn)的字符設(shè)備(/dev/kvm)。Qemu通KVM提供的LibKvm應(yīng)用程序接口,通過ioctl系統(tǒng)調(diào)用創(chuàng)建和運(yùn)行虛擬機(jī)。KVM Driver使得整個Linux成為一個虛擬機(jī)監(jiān)控器。并且在原有的Linux兩種執(zhí)行模式(內(nèi)核模式和用戶模式)的基礎(chǔ)上,新增加了客戶模式,客戶模式擁有自己的內(nèi)核模式和用戶模式。在虛擬機(jī)運(yùn)行下,三種模式的分工如下:客戶模式:執(zhí)行非I/O的客戶代碼。虛擬機(jī)運(yùn)行在客戶模式下。內(nèi)核模式:實(shí)現(xiàn)到客戶模式的切換。處理因?yàn)镮/O或者其它指令引起的從客戶模式的退出。KVM Driver工作在這種模式下。用戶模式:代表客戶執(zhí)行I/O指令Qemu運(yùn)行在這種模式下。在KVM模型中,每一個Guest OS 都作為一個標(biāo)準(zhǔn)的Linux進(jìn)程,可以使用Linux的進(jìn)程管理指令管理。在圖1中./dev/kvm在內(nèi)核中創(chuàng)建的標(biāo)準(zhǔn)字符設(shè)備,通過ioctl系統(tǒng)調(diào)用來訪問內(nèi)核虛擬機(jī),進(jìn)行虛擬機(jī)的創(chuàng)建和初始化;kvm_vm fd是創(chuàng)建的指向特定虛擬機(jī)實(shí)例的文件描述符,通過這個文件描述符對特定虛擬機(jī)進(jìn)行訪問控制;kvm_vcpu fd指向?yàn)樘摂M機(jī)創(chuàng)建的虛擬處理器的文件描述符,通過該描述符使用ioctl系統(tǒng)調(diào)用設(shè)置和調(diào)度虛擬處理器的運(yùn)行。1.2 KVM工作原理KVM的基本工作原理:用戶模式的Qemu利用接口libkvm通過ioctl系統(tǒng)調(diào)用進(jìn)入內(nèi)核模式。KVM Driver為虛擬機(jī)創(chuàng)建虛擬內(nèi)存和虛擬CPU后執(zhí)行VMLAUCH指令進(jìn)入客戶模式。裝載Guest OS執(zhí)行。如果Guest OS發(fā)生外部中斷或者影子頁表缺頁之類的事件,暫停Guest OS的執(zhí)行,退出客戶模式進(jìn)行一些必要的處理。然后重新進(jìn)入客戶模式,執(zhí)行客戶代碼。如果發(fā)生I/O事件或者信號隊(duì)列中有信號到達(dá),就會進(jìn)入用戶模式處理。KVM采用全虛擬化技術(shù)??蛻魴C(jī)不用修改就可以運(yùn)行。圖2 KVM 工作基本原理2 ,相關(guān)技術(shù)-處理器管理和硬件輔助虛擬化技術(shù)Intel 在2006年發(fā)布了硬件虛擬化技術(shù)。其中支持X86體系結(jié)構(gòu)的稱為Intel VT-x技術(shù)。ADM稱為SVM技術(shù)。VT-x引入了一種新的處理器操作,叫做VMX(Virtual Machine Extension),提供了兩種處理器的工作環(huán)境。VMCS結(jié)構(gòu)實(shí)現(xiàn)兩種環(huán)境之間的切換。VM Entry使虛擬機(jī)進(jìn)去客戶模式,VM Exit使虛擬機(jī)退出客戶模式。2.1 KVM中Guest OS的調(diào)度執(zhí)行VMM調(diào)度Guest OS執(zhí)行時,Qemu通過ioctl系統(tǒng)調(diào)用進(jìn)入內(nèi)核模式,在KVM Driver中通過get_cpu獲得當(dāng)前物理CPU的引用。之后將Guest狀態(tài)從VMCS中讀出。并裝入物理CPU中。執(zhí)行VMLAUCH指令使得物理處理器進(jìn)入非根操作環(huán)境,運(yùn)行客戶代碼。當(dāng)Guest OS執(zhí)行一些特權(quán)指令或者外部事件時,比如I/O訪問,對控制寄存器的操作,MSR的讀寫數(shù)據(jù)包到達(dá)等。都會導(dǎo)致物理CPU發(fā)生VMExit,停止運(yùn)行Guest OS。將Guest OS保存到VMCS中,Host狀態(tài)裝入物理處理器中,處理器進(jìn)入根操作環(huán)境,KVM取得控制權(quán),通過讀取VMCS中VM_EXIT_REASON字段得到引起VM Exit的原因。從而調(diào)用kvm_exit_handler處理函數(shù)。如果由于I/O獲得信號到達(dá),則退出到用戶模式的Qemu處理。處理完畢后,重新進(jìn)入客戶模式運(yùn)行虛擬CPU。如果是因?yàn)橥獠恐袛?,則在Lib KVM中做一些必要的處理,重新進(jìn)入客戶模式執(zhí)行客戶代碼。2.2 KVM中內(nèi)存管理KVM使用影子頁表實(shí)現(xiàn)客戶物理地址到主機(jī)物理地址的轉(zhuǎn)換。初始為空,隨著虛擬機(jī)頁訪問實(shí)效的增加,影子頁表被逐漸建立起來,并隨著客戶機(jī)頁表的更新而更新。在KVM中提供了一個哈希列表和哈希函數(shù),以客戶機(jī)頁表項(xiàng)中的虛擬頁號和該頁表項(xiàng)所在頁表的級別作為鍵值,通過該鍵值查詢,如不為空,則表示該對應(yīng)的影子頁表項(xiàng)中的物理頁號已經(jīng)存在并且所指向的影子頁表已經(jīng)生成。如為空,則需新生成一張影子頁表,KVM將獲取指向該影子頁表的主機(jī)物理頁號填充到相應(yīng)的影子頁表項(xiàng)的內(nèi)容中,同時以客戶機(jī)頁表虛擬頁號和表所在的級別生成鍵值,在代表該鍵值的哈希桶中填入主機(jī)物理頁號,以備查詢。但是一旦Guest OS中出現(xiàn)進(jìn)程切換,會把整個影子頁表全部刪除重建,而剛被刪掉的頁表可能很快又被客戶機(jī)使用,如果只更新相應(yīng)的影子頁表的表項(xiàng),舊的影子頁表就可以重用。因此在KVM中采用將影子頁表中對應(yīng)主機(jī)物理頁的客戶虛擬頁寫保護(hù)并且維護(hù)一張影子頁表的逆向映射表,即從主機(jī)物理地址到客戶虛擬地址之間的轉(zhuǎn)換表,這樣VM對頁表或頁目錄的修改就可以觸發(fā)一個缺頁異常,從而被KVM捕獲,對客戶頁表或頁目錄項(xiàng)的修改就可以同樣作用于影子頁表,通過這種方式實(shí)現(xiàn)影子頁表與客戶機(jī)頁表保持同步。2.3 KVM中設(shè)備管理一個機(jī)器只有一套I/o地址和設(shè)備。設(shè)備的管理和訪問是操作系統(tǒng)中的突出問題、同樣也是虛擬機(jī)實(shí)現(xiàn)的難題,另外還要提供虛擬設(shè)備供各個VM使用。在KVM中通過移植Qemu中的設(shè)備模型(Device Model)進(jìn)行設(shè)備的管理和訪問。操作系統(tǒng)中,軟件使用可編程I/O(PIO)和內(nèi)存映射I/O(MMIO)與硬件交互。而且硬件可以發(fā)出中斷請求,由操作系統(tǒng)處理。在有虛擬機(jī)的情況下,虛擬機(jī)必須要捕獲并且模擬PIO和MMIO的請求,模擬虛擬硬件中斷。捕獲PIO:由硬件直接提供。當(dāng)VM發(fā)出PIO指令時,導(dǎo)致VM Exit然后硬件會將VM Exit原因及對應(yīng)的指令寫入VMCS控制結(jié)構(gòu)中,這樣KVM就會模擬PIO指令。MMIO捕獲:對MMIO頁的訪問導(dǎo)致缺頁異常,被KVM捕獲,通過X86模擬器模擬執(zhí)行MMIO指令。KVM中的I/O虛擬化都是用戶空間的Qemu實(shí)現(xiàn)的。所有PIO和MMIO的訪問都是被轉(zhuǎn)發(fā)到Qemu的。Qemu模擬硬件設(shè)備提供給虛擬機(jī)使用。KVM通過異步通知機(jī)制以及I/O指令的模擬來完成設(shè)備訪問,這些通知包括:虛擬中斷請求,信號驅(qū)動機(jī)制以及VM間的通信。以虛擬機(jī)接收數(shù)據(jù)包來說明虛擬機(jī)和設(shè)備的交互。圖3 I/O分析(1)當(dāng)數(shù)據(jù)包到達(dá)主機(jī)的物理網(wǎng)卡后,調(diào)用物理網(wǎng)卡的驅(qū)動程序,在其中利用Linux內(nèi)核中的軟件網(wǎng)橋,實(shí)現(xiàn)數(shù)據(jù)的轉(zhuǎn)發(fā)。(2)在軟件網(wǎng)撟這一層,會判斷數(shù)據(jù)包是發(fā)往那個設(shè)備的,同時調(diào)用網(wǎng)橋的發(fā)送函數(shù),向?qū)?yīng)的端口發(fā)送數(shù)據(jù)包。(3)若數(shù)據(jù)包是發(fā)往虛擬機(jī)的,則要通過tap設(shè)備進(jìn)行轉(zhuǎn)發(fā),tap設(shè)備由兩部分組成,網(wǎng)絡(luò)設(shè)備和字符設(shè)備。網(wǎng)絡(luò)設(shè)備負(fù)責(zé)接收和發(fā)送數(shù)據(jù)包,字符設(shè)備負(fù)責(zé)將數(shù)據(jù)包往內(nèi)核空間和用戶空間進(jìn)行轉(zhuǎn)發(fā)。Tap網(wǎng)絡(luò)部分收到數(shù)據(jù)包后,將其設(shè)備文件符置位,同時向正在運(yùn)行VM的進(jìn)程發(fā)出I/O可用信號,引起VM Exit,停止VM運(yùn)行,進(jìn)入根操作狀態(tài)。KVM根據(jù)KVM_EXIT_REASON判斷原因,模擬I/O指令的執(zhí)行,將中斷注入到VM的中斷向量表中。(4)返回用戶模式的Qemu中,執(zhí)行設(shè)備模型。返回到kvm_main loop中,執(zhí)行Kvmmainloopwait,之后進(jìn)入main_loop wait中,在這個函數(shù)里收集對應(yīng)設(shè)備的設(shè)備文件描述符的狀態(tài),此時tap設(shè)備文件描述符的狀態(tài)同樣被集到fd set。(5)Kvm mainloop不停地循環(huán),通過select系統(tǒng)調(diào)用判斷哪螋文件描述符的狀態(tài)發(fā)生變化,相應(yīng)的調(diào)用對應(yīng)的處理函數(shù)。對予tap來說,就會通過Qemusend_packet將數(shù)據(jù)發(fā)往rtl8139一doreceiver,在這個函數(shù)中完成相當(dāng)于硬件RTL8139網(wǎng)卡的邏輯操作。KVM通過模擬IO指令操作虛擬RTL8139將數(shù)據(jù)拷貝到用戶地址空間,放在相應(yīng)的IO地址。用戶模式處理完畢后返回內(nèi)核模式,而后進(jìn)入客戶模式,VM被再次執(zhí)行,繼續(xù)收發(fā)數(shù)據(jù)包。3,KVM 源代碼分析-虛擬機(jī)創(chuàng)建和運(yùn)行流程代碼分析3.1 KVM創(chuàng)建和運(yùn)行虛擬機(jī)流程KVM虛擬機(jī)創(chuàng)建和運(yùn)行虛擬機(jī)分為用戶態(tài)和核心態(tài)兩個部分,用戶態(tài)主要提供應(yīng)用程序接口,為虛擬機(jī)創(chuàng)建虛擬機(jī)上下文環(huán)境,在libkvm中提供訪問內(nèi)核字符設(shè)備/dev/kvm的接口;內(nèi)核態(tài)為添加到內(nèi)核中的字符設(shè)備/dev/kvm,模塊加載進(jìn)內(nèi)核后即可進(jìn)行接口用戶空間調(diào)用創(chuàng)建虛擬機(jī)。在創(chuàng)建虛擬機(jī)過程中,kvm字符設(shè)備主要為客戶機(jī)創(chuàng)建kvm數(shù)據(jù)機(jī)構(gòu),創(chuàng)建該虛擬機(jī)的虛擬機(jī)文件描述符及其相應(yīng)的數(shù)據(jù)結(jié)構(gòu)以及創(chuàng)建虛擬處理器及其相應(yīng)的數(shù)據(jù)結(jié)構(gòu)。Kvm創(chuàng)建虛擬機(jī)的流程如圖4所示。首先申明一個kvm_context_t 變量用以描述用戶態(tài)虛擬機(jī)上下文信息,然后調(diào)用kvm_init()函數(shù)初始化虛擬機(jī)上下文信息;函數(shù)kvm_create()創(chuàng)建虛擬機(jī)實(shí)例,該函數(shù)通過ioctl系統(tǒng)調(diào)用創(chuàng)建虛擬機(jī)相關(guān)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)并且返回虛擬機(jī)文件描述符給用戶態(tài)kvm_context_t數(shù)據(jù)結(jié)構(gòu);創(chuàng)建完內(nèi)核虛擬機(jī)數(shù)據(jù)結(jié)構(gòu)后,再創(chuàng)建內(nèi)核pit以及mmio等基本外設(shè)模擬設(shè)備,然后調(diào)用kvm_create_vcpu()函數(shù)來創(chuàng)建虛擬處理器,kvm_create_vcpu()函數(shù)通過ioctl()系統(tǒng)調(diào)用向由vm_fd文件描述符指向的虛擬文件調(diào)用創(chuàng)建虛擬處理器,并將虛擬處理器的文件描述符返回給用戶態(tài)程序,用以以后的調(diào)度使用;創(chuàng)建完虛擬處理器后,由用戶態(tài)的QEMU程序申請客戶機(jī)用戶空間,用以加載和運(yùn)行客戶機(jī)代碼;為了使得客戶虛擬機(jī)正確執(zhí)行,必須要在內(nèi)核中為客戶機(jī)建立正確的內(nèi)存映射關(guān)系,即影子頁表信息。因此,申請客戶機(jī)內(nèi)存地址空間后,調(diào)用函數(shù)kvm_create_phys_mem()創(chuàng)建客戶機(jī)內(nèi)存映射關(guān)系,該函數(shù)主要通過ioctl系統(tǒng)調(diào)用向vm_fd指向的虛擬文件調(diào)用設(shè)置內(nèi)核數(shù)據(jù)結(jié)構(gòu)中客戶機(jī)內(nèi)存域相關(guān)信息,主要建立影子頁表信息;當(dāng)創(chuàng)建好虛擬處理器和影子頁表后,即可讀取客戶機(jī)到指定分配的空間中,然后調(diào)度虛擬處理器運(yùn)行。調(diào)度虛擬機(jī)的函數(shù)為kvm_run(),該函數(shù)通過ioctl系統(tǒng)調(diào)用調(diào)用由虛擬處理器文件描述符指向的虛擬文件調(diào)度處理函數(shù)kvm_run()調(diào)度虛擬處理器的執(zhí)行,該系統(tǒng)調(diào)用將虛擬處理器vcpu信息加載到物理處理器中,通過vm_entry執(zhí)行進(jìn)入客戶機(jī)執(zhí)行。在客戶機(jī)正常運(yùn)行期間kvm_run()函數(shù)不返回,只有發(fā)生以下兩種情況時,函數(shù)返回:1,發(fā)生了I/O事件,如客戶機(jī)發(fā)出讀寫I/O的指令;2,產(chǎn)生了客戶機(jī)和內(nèi)核KVM都無法處理的異常。I/O事件處理完畢后,通過重新調(diào)用KVM_RUN()函數(shù)繼續(xù)調(diào)度客戶機(jī)的執(zhí)行。圖 4 KVM虛擬機(jī)創(chuàng)建流程3.2 虛擬機(jī)創(chuàng)建和運(yùn)行主要函數(shù)分析1,函數(shù)kvm_init():該函數(shù)在用戶態(tài)創(chuàng)建一個虛擬機(jī)上下文,用以在用戶態(tài)保存基本的虛擬機(jī)信息,這個函數(shù)是創(chuàng)建虛擬機(jī)第一個需要調(diào)用的函數(shù),函數(shù)返回一個kvm_context_t結(jié)構(gòu)體。該函數(shù)原型為:Kvm_context_t kvm_init(struct kvm_callbacks *callbacks,void *opaque);參數(shù):callbacks為結(jié)構(gòu)體kvm_callbacks變量,該結(jié)構(gòu)體包含指向函數(shù)的一組指針,用于在客戶機(jī)執(zhí)行過程中因?yàn)镮/O事件退出到用戶態(tài)的時候處理的回調(diào)函數(shù)(后面會分析)。參數(shù)opaque一般未使用。函數(shù)執(zhí)行基本過程:打開字符設(shè)備dev/kvm,申請?zhí)摂M機(jī)上下文變量kvm_context_t空間,初始化上下文的基本信息:設(shè)置fd文件描述符指向/dev/kvm、禁用虛擬機(jī)文件描述符vm_fd(-1)設(shè)置I/O事件回調(diào)函數(shù)結(jié)構(gòu)體,設(shè)置IRQ和PIT的標(biāo)志位以及內(nèi)存頁面記錄的標(biāo)志位。主要相關(guān)數(shù)據(jù)結(jié)構(gòu):虛擬機(jī)上下文structkvm_context_t,用戶態(tài)數(shù)據(jù)結(jié)構(gòu),用以描述虛擬機(jī)實(shí)例的用戶態(tài)上下文信息。Struct kvm_context: 該結(jié)構(gòu)體用于表示一個虛擬機(jī)上下文。主要包含的數(shù)據(jù)域?yàn)椋篒nt fd :指向內(nèi)核標(biāo)準(zhǔn)字符設(shè)備/dev/kvm的文件描述符。Int vm_fd:指向所創(chuàng)建的內(nèi)核虛擬機(jī)數(shù)據(jù)結(jié)構(gòu)相關(guān)文件的文件描述符。Int vcpu_fdMAX_VCPUS:指向虛擬機(jī)所有的虛擬處理器的文件描述符數(shù)組。Struct kvm_run *runMAX_VCPUS:指向虛擬機(jī)運(yùn)行環(huán)境上下文的指針數(shù)組。Struct kvm_callbacks *call_backs: 回調(diào)函數(shù)結(jié)構(gòu)體指針,該結(jié)構(gòu)體用于處理用戶態(tài)I/O事件。Void *opaque:指針(還未弄清楚)Int dirty_page_log_all:設(shè)置是否記錄臟頁面的標(biāo)志。Int no_ira_creation: 用于設(shè)置是否再kernel里設(shè)置irq芯片。Int_irqchip_in_kernel: 內(nèi)核中irqchip的狀態(tài)Int irqchip_inject_ioctl:用于攔截中斷的iotcl系統(tǒng)調(diào)用Int no_pit_creation: 設(shè)置是否再內(nèi)核中設(shè)置陷阱int pit_in_kernel:PIT狀態(tài)int coalesced_mmio:kernel中mmiostruct kvm_irq_routing *irq_routes:KVM中中斷處理的路由結(jié)構(gòu)指針。int nr_allocated_irq_routes:分配給該虛擬機(jī)的中斷路由數(shù)目。int max_used_gsi:使用的最大的gsi(?)。用戶態(tài)I/O處理函數(shù)結(jié)構(gòu)體struct kvm_callbacks,該結(jié)構(gòu)體指向一組函數(shù),主要用于處理客戶機(jī)因?yàn)镮/O事件退出而執(zhí)行的過程。struct kvm_callbacks :該結(jié)構(gòu)體用于在用戶態(tài)中處理I/O事件,在KVM中調(diào)用KVM_QEMU實(shí)現(xiàn)。主要包含的數(shù)據(jù)域?yàn)椋篿nt (*inb)(void *opaque, uint16_t addr, uint8_t *data):用于模擬客戶機(jī)執(zhí)行8位的inb指令。int (*inw)(void *opaque, uint16_t addr, uint16_t *data):用于模擬客戶機(jī)執(zhí)行16位的inw指令。int (*inl)(void *opaque, uint16_t addr, uint32_t *data):用于模擬客戶機(jī)執(zhí)行32位的inl指令。int (*outb)(void *opaque, uint16_t addr, uint8_t data):用于模擬客戶機(jī)執(zhí)行8位的outb指令。int (*outw)(void *opaque, uint16_t addr, uint16_t data):用于模擬客戶機(jī)執(zhí)行16位的outw指令。int (*outl)(void *opaque, uint16_t addr, uint32_t data):用于模擬客戶機(jī)執(zhí)行32位的outl指令。int (*mmio_read)(void *opaque, uint64_t addr, uint8_t *data,int len):用于模擬客戶機(jī)執(zhí)行mmio讀指令。int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data,int len):用于模擬客戶機(jī)執(zhí)行mmio寫指令。int (*debug)(void *opaque, void *env, struct kvm_debug_exit_arch *arch_info):用戶客戶機(jī)調(diào)試的回調(diào)函數(shù)。int (*halt)(void *opaque, int vcpu):用于客戶機(jī)執(zhí)行halt指令的響應(yīng)。int (*shutdown)(void *opaque, void *env):用于客戶機(jī)執(zhí)行shutdown指令的響應(yīng)。int (*io_window)(void *opaque):用于獲得客戶機(jī)io_windows。int (*try_push_interrupts)(void *opaque):用于注入中斷的回調(diào)函數(shù)。void (*push_nmi)(void *opaque):用于注入nmi中斷的函數(shù)。void (*post_kvm_run)(void *opaque, void *env);用戶得到kvm運(yùn)行狀態(tài)函數(shù)。int (*pre_kvm_run)(void *opaque, void *env);用于獲得kvm之前運(yùn)行狀態(tài)的函數(shù)int (*tpr_access)(void *opaque, int vcpu, uint64_t rip, int is_write);獲得tpr訪問處理函數(shù)int (*powerpc_dcr_read)(int vcpu, uint32_t dcrn, uint32_t *data);用于powerpc的dcr讀操作nt (*powerpc_dcr_write)(int vcpu, uint32_t dcrn, uint32_t data);用于powerpc的dcr寫操作int (*s390_handle_intercept)(kvm_context_t context, int vcpu,struct kvm_run *run);用于s390的中斷處理。int (*s390_handle_reset)(kvm_context_t context, int vcpu,struct kvm_run *run);用于s390的重設(shè)處理。當(dāng)客戶機(jī)執(zhí)行I/O事件或者停機(jī)操作等事件時,KVM會交給用戶態(tài)的QEMU模擬外部I/O事件,調(diào)用這個結(jié)構(gòu)體指向的相關(guān)的函數(shù)進(jìn)行處理。Struct kvm_run: 用于KVM運(yùn)行時一些的一些狀態(tài)信息。主要包含的數(shù)據(jù)域?yàn)椋篲u8 request_interrupt_window;_u8 padding17;_u32 exit_reason;_u8 ready_for_interrupt_injection;_u8 if_flag;_u8 padding22;/* in (pre_kvm_run), out (post_kvm_run) */_u64 cr8;_u64 apic_base;union /* KVM_EXIT_UNKNOWN */struct _u64 hardware_exit_reason; 記錄退出原因 hw;/* KVM_EXIT_FAIL_ENTRY */ 客戶機(jī)執(zhí)行過程中執(zhí)行VM_ENTRY失敗。struct _u64 hardware_entry_failure_reason; fail_entry;/* KVM_EXIT_EXCEPTION */ 客戶機(jī)因?yàn)楫惓M顺鰏truct _u32 exception;_u32 error_code; ex;/* KVM_EXIT_IO */ 客戶機(jī)因?yàn)镮O事件退出。struct kvm_io #define KVM_EXIT_IO_IN 0#define KVM_EXIT_IO_OUT 1_u8 direction;_u8 size; /* bytes */_u16 port;_u32 count;_u64 data_offset; /* relative to kvm_run start */ io;struct struct kvm_debug_exit_arch arch; debug;/* KVM_EXIT_MMIO */ 客戶機(jī)因?yàn)镸MIO退出struct _u64 phys_addr;_u8 data8;_u32 len;_u8 is_write; mmio;/* KVM_EXIT_HYPERCALL */ 客戶機(jī)退出的超調(diào)用參數(shù)。struct _u64 nr;_u64 args6;_u64 ret;_u32 longmode;_u32 pad; hypercall;/* KVM_EXIT_TPR_ACCESS */ 客戶機(jī)退出訪問TPR參數(shù)struct _u64 rip;_u32 is_write;_u32 pad; tpr_access;/* KVM_EXIT_S390_SIEIC */ 和S390相關(guān)數(shù)據(jù)struct _u8 icptcode;_u64 mask; /* psw upper half */_u64 addr; /* psw lower half */_u16 ipa;_u32 ipb; s390_sieic;/* KVM_EXIT_S390_RESET */#define KVM_S390_RESET_POR 1#define KVM_S390_RESET_CLEAR 2#define KVM_S390_RESET_SUBSYSTEM 4#define KVM_S390_RESET_CPU_INIT 8#define KVM_S390_RESET_IPL 16_u64 s390_reset_flags;/* KVM_EXIT_DCR */struct _u32 dcrn;_u32 data;_u8 is_write; dcr;/* Fix the size of the union. */char padding256;2, 函數(shù)kvm_create():該函數(shù)主要用于創(chuàng)建一個虛擬機(jī)內(nèi)核環(huán)境。該函數(shù)原型為:int kvm_create(kvm_context_t kvm,unsigned long phys_mem_bytes, void *phys_mem);參數(shù):kvm_context_t 表示傳遞的用戶態(tài)虛擬機(jī)上下文環(huán)境,phys_mem_bytes表示需要創(chuàng)建的物理內(nèi)存的大小,phys_mem表示創(chuàng)建虛擬機(jī)的首地址。這個函數(shù)首先調(diào)用kvm_create_vm()分配IRQ并且初始化為0,設(shè)置vcpu0的值為-1,即不允許調(diào)度虛擬機(jī)執(zhí)行。然后調(diào)用ioctl系統(tǒng)調(diào)用ioctl(fd,KVM_CREATE_VM,0)來創(chuàng)建虛擬機(jī)內(nèi)核數(shù)據(jù)結(jié)構(gòu)struct kvm。3,系統(tǒng)調(diào)用函數(shù)ioctl(fd,KVM_CREATE_VM,0),用于在內(nèi)核中創(chuàng)建和虛擬機(jī)相關(guān)的數(shù)據(jù)結(jié)構(gòu)。該函數(shù)原型為:Static long kvm_dev_ioctl(struct file *filp,unsigned int ioctl, unsigned long arg);其中ioctl表示命令。這個函數(shù)調(diào)用kvm_dev_ioctl_create_vm()創(chuàng)建虛擬機(jī)實(shí)例內(nèi)核相關(guān)數(shù)據(jù)結(jié)構(gòu)。該函數(shù)首先通過內(nèi)核中kvm_create_vm()函數(shù)創(chuàng)建內(nèi)核中kvm上下文struct kvm,然后通過函數(shù)Anno_inode_getfd(“kvm_vm”,&kvm_vm_fops,kvm,0)返回該虛擬機(jī)的文件描述符,返回給用戶調(diào)用函數(shù),由2中描述的函數(shù)賦值給用戶態(tài)虛擬機(jī)上下文變量中的虛擬機(jī)描述符kvm_vm_fd。4,內(nèi)核創(chuàng)建虛擬機(jī)kvm對象后,接著調(diào)用kvm_arch_create函數(shù)用于創(chuàng)建一些體系結(jié)構(gòu)相關(guān)的信息,主要包括kvm_init_tss、kvm_create_pit以及kvm_init_coalsced_mmio等信息。然后調(diào)用kvm_create_phys_mem創(chuàng)建物理內(nèi)存,函數(shù)kvm_create_irqchip用于創(chuàng)建內(nèi)核irq信息,通過系統(tǒng)調(diào)用ioctl(kvm-vm_fd,KVM_CREATE_IRQCHIP)。5,函數(shù)kvm_create_vcpu():用于創(chuàng)建虛擬處理器。該函數(shù)原型為:int kvm_create_vcpu(kvm_context_t kvm, int slot);參數(shù):kvm表示對應(yīng)用戶態(tài)虛擬機(jī)上下文,slot表示需要創(chuàng)建的虛擬處理器的個數(shù)。該函數(shù)通過ioctl系統(tǒng)調(diào)用ioctl(kvm-vm_fd,KVM_CREATE_VCPU,slot)創(chuàng)建屬于該虛擬機(jī)的虛擬處理器。該系統(tǒng)調(diào)用函數(shù):Static init kvm_vm_ioctl_create_vcpu(struct *kvm, n) 參數(shù)kvm為內(nèi)核虛擬機(jī)實(shí)例數(shù)據(jù)結(jié)構(gòu),n為創(chuàng)建的虛擬CPU的數(shù)目。6,函數(shù)kvm_create_phys_mem()用于創(chuàng)建虛擬機(jī)內(nèi)存空間,該函數(shù)原型:Void * kvm_create_phys_mem(kvm_context_t kvm,unsigned long phys_start,unsigned len,int log,int writable);參數(shù):kvm 表示用戶態(tài)虛擬機(jī)上下文信息,phys_start為分配給該虛擬機(jī)的物理起始地址,len表示內(nèi)存大小,log表示是否記錄臟頁面,writable表示該段內(nèi)存對應(yīng)的頁表是否可寫。該函數(shù)首先申請一個結(jié)構(gòu)體kvm_userspace_memory_region 然后通過系統(tǒng)調(diào)用KVM_SET_USER_MEMORY_REGION來設(shè)置內(nèi)核中對應(yīng)的內(nèi)存的屬性。該系統(tǒng)調(diào)用函數(shù)原型:Ioctl(int kvm-vm_fd,KVM_SET_USER_MEMORY_REGION,&memory);參數(shù):第一個參數(shù)vm_fd為指向內(nèi)核虛擬機(jī)實(shí)例對象的文件描述符,第二個參數(shù)KVM_SET_USER_MEMORY_REGION為系統(tǒng)調(diào)用命令參數(shù),表示該系統(tǒng)調(diào)用為創(chuàng)建內(nèi)核客戶機(jī)映射,即影子頁表。第三個參數(shù)memory表示指向該虛擬機(jī)的內(nèi)存空間地址。系統(tǒng)調(diào)用首先通過參數(shù)memory通過函數(shù)copy_from_user從用戶空間復(fù)制struct_user_momory_region 變量,然后通過kvm_vm_ioctl_set_memory_region函數(shù)設(shè)置內(nèi)核中對應(yīng)的內(nèi)存域。該函數(shù)原型:Int kvm_vm_ioctl_set_memory_region(struct *kvm,struct kvm_usersapce_memory_region *mem,int user_alloc);該函數(shù)再調(diào)用函數(shù)kvm_set_memory_resgion()設(shè)置影子頁表。當(dāng)這一切都準(zhǔn)備完畢后,調(diào)用kvm_run()函數(shù)即可調(diào)度執(zhí)行虛擬處理器。7,函數(shù)kvm_run():用于調(diào)度運(yùn)行虛擬處理器。該函數(shù)原型為:Int kvm_run(kvm_context_t kvm,int vcpu, void *env) 該函數(shù)首先得到vcpu的描述符,然后調(diào)用系統(tǒng)調(diào)用ioctl(fd,kvm_run,0)調(diào)度運(yùn)行虛擬處理器。Kvm_run函數(shù)在正常運(yùn)行情況下并不返回,除非發(fā)生以下事件之一:一是發(fā)生了I/O事件,I/O事件由用戶態(tài)的QEMU處理;一個是發(fā)生了客戶機(jī)和KVM都無法處理的異常事件。KVM_RUN()中返回截獲的事件,主要是I/O以及停機(jī)等事件。4, KVM客戶機(jī)異常處理機(jī)制和代碼流程KVM保證客戶機(jī)正確執(zhí)行的基本手段就是當(dāng)客戶機(jī)執(zhí)行I/O指令或者其它特權(quán)指令時,引發(fā)處理器異常,從而陷入到根操作模式,由KVM Driver模擬執(zhí)行,可以說,虛擬化保證客戶機(jī)正確執(zhí)行的基本手段就是異常處理機(jī)制。由于KVM采取了硬件輔助虛擬化技術(shù),因此,和異常處理機(jī)制相關(guān)的一個重要的數(shù)據(jù)結(jié)構(gòu)就是虛擬機(jī)控制結(jié)構(gòu)VMCS。VMCS控制結(jié)構(gòu)分為三個部分,一個是版本信息,一個是中止標(biāo)識符,最后一個是VMCS數(shù)據(jù)域。VMCS數(shù)據(jù)域包含了六類信息:客戶機(jī)狀態(tài)域,宿主機(jī)狀態(tài)域,VM-Entry控制域,VM-Execution控制域VM-Exit控制域以及VM-Exit信息域。其中VM-Execution控制域可以設(shè)置一些可選的標(biāo)志位使得客戶機(jī)可以引發(fā)一定的異常的指令。宿主機(jī)狀態(tài)域,則保持了基本的寄存器信息,其中CS:RIP指向KVM中異常處理程序的地址。是客戶機(jī)異常處理的總?cè)肟?,而異常處理程序則根據(jù)VM-Exit信息域來判斷客戶機(jī)異常的根本原因,選擇正確的處理邏輯來進(jìn)行處理。vmx.c文件是和Intel VT-x體系結(jié)構(gòu)相關(guān)的代碼文件,用于處理內(nèi)核態(tài)相關(guān)的硬件邏輯代碼。在VCPU初始化中(vmx_vcpu_create),將kvm中的對應(yīng)的異常退出處理函數(shù)賦值給CS:EIP中,在客戶機(jī)運(yùn)行過程中,產(chǎn)生客戶機(jī)異常時,CPU根據(jù)VMCS中的客戶機(jī)狀態(tài)域裝載CS:EIP的值,從而退出到內(nèi)核執(zhí)行異常處理。在KVM內(nèi)核中,異常處理函數(shù)的總?cè)肟跒椋簊tatic int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);參數(shù):kvm_run,當(dāng)前虛擬機(jī)實(shí)例的運(yùn)行狀態(tài)信息,vcpu,對應(yīng)的虛擬cpu。這個函數(shù)首先從客戶機(jī)VM-Exit信息域中讀取exit_reason字段信息,然后進(jìn)行一些必要的處理后,調(diào)用對應(yīng)于函數(shù)指針數(shù)組中對應(yīng)退出原因字段的處理函數(shù)進(jìn)行處理。函數(shù)指針數(shù)組定義信息為:static int (*kvm_vmx_exit_handlers)(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) = EXIT_REASON_EXCEPTION_NMI = handle_exception,EXIT_REASON_EXTERNAL_INTERRUPT = handle_external_interrupt,EXIT_REASON_TRIPLE_FAULT = handle_triple_fault,EXIT_REASON_NMI_WINDOW = handle_nmi_window,EXIT_REASON_IO_INSTRUCTION = handle_io,EXIT_REASON_CR_ACCESS = handle_cr,EXIT_REASON_DR_ACCESS = handle_dr,EXIT_REASON_CPUID = handle_cpuid,EXIT_REASON_MSR_READ = handle_rdmsr,EXIT_REASON_MSR_WRITE = handle_wrmsr,EXIT_REASON_PENDING_INTERRUPT = handle_interrupt_window,EXIT_REASON_HLT = handle_halt,EXIT_REASON_INVLPG = handle_invlpg,EXIT_REASON_VMCALL = handle_vmcall,EXIT_REASON_TPR_BELOW_THRESHOLD = handle_tpr_below_threshold,EXIT_REASON_APIC_ACCESS = handle_apic_access,EXIT_REASON_WBINVD = handle_wbinvd,EXIT_REASON_TASK_SWITCH = handle_task_switch,EXIT_REASON_EPT_VIOLATION = handle_ept_violation,;這是一組指針數(shù)組,用于處理客戶機(jī)引發(fā)異常時候,根據(jù)對應(yīng)的退出字段選擇處理函數(shù)進(jìn)行處理。例如EXIT_REASON_EXCEPTION_NMI對應(yīng)的handle_exception處理函數(shù)用于處理NMI引腳異常,而EXIT_REASON_EPT_VIOLATION對應(yīng)的handle_ept_violation處理函數(shù)用于處理缺頁異常。 5, K

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論