物理機(jī)器是由CPU,內(nèi)存和I/O設(shè)備等一組資源構(gòu)成的實(shí)體。虛擬機(jī)也一樣,由虛擬CPU,虛擬內(nèi)存和虛擬I/O設(shè)備等組成。VMM(VM Monitor)按照與傳統(tǒng)OS并發(fā)執(zhí)行用戶進(jìn)程的相似方式,仲裁對所有共享資源的訪問。本文將分別討論CPU虛擬化、內(nèi)存虛擬化和I/O虛擬化技術(shù)的原理和實(shí)現(xiàn)。
在虛擬化的平臺上,虛擬機(jī)(guest VM)所使用的多個虛擬CPU(以下稱vCPU)可能是共享同一個物理CPU(以下稱pCPU)的。VMM負(fù)責(zé)vCPU的調(diào)度,當(dāng)一個vCPU被調(diào)度到獲得pCPU的使用權(quán)后,基于該vCPU運(yùn)行的guest OS又可以調(diào)度OS中的各個線程/進(jìn)程了。也就是說,guest OS中的各個線程/進(jìn)程分時復(fù)用了vCPU,而各個vCPU又分時復(fù)用了pCPU。
為了從硬件上提供對vCPU調(diào)度和切換的支持,Intel推出了被稱為VT-x(Virtualization Technology for x86)的CPU虛擬化擴(kuò)展技術(shù),用戶可通過VMXON/VMXOFF指令打開/關(guān)閉這個功能。和Intel亦敵亦友的AMD也推出了被稱為AMD-V的對應(yīng)技術(shù)。
在Linux中,從用戶空間trap到內(nèi)核空間可以通過system call或者interrupt/exception。以system call基于x86的實(shí)現(xiàn)為例,早期x86提供的trap方法是int 0x80這樣的software interrupt機(jī)制,而后改成了SYSENTER/SYSEXIT的指令對,現(xiàn)在則已經(jīng)被速度更快的SYSCALL/SYSRET取代了。
類似地,在VT-x中,從guest VM進(jìn)入VMM(這個過程被稱為VM exit)通常有三種方式:
1)執(zhí)行VMCALL指令,這種方式被稱為hyper call,跟執(zhí)行SYSCALL指令實(shí)現(xiàn)的system call原理差不多。
2)發(fā)生了硬件中斷或軟件異常。
3)guest VM執(zhí)行了一些敏感指令。有一些敏感指令并不會產(chǎn)生VM exit,比如SYSENTER;有一些敏感指令則可以根據(jù)下面將要介紹的VM executation control fields配置來選擇是否產(chǎn)生VM exit。
進(jìn)入VMM就意味著從non-root mode進(jìn)入了root mode,反之,從VMM返回guest VM(這個過程被稱為VM entry)則是重新回到了non-root mode,mode的切換意味著上下文(context)的保存和恢復(fù)。
上下文其實(shí)是個難以定義的概念,它是從CPU的角度引出的,簡單地說,上下文就是程序(進(jìn)程/中斷)運(yùn)行時所需要的寄存器的最小集合,這些寄存器的后面可能代表著程序運(yùn)行的一類資源。
上下文切換是指程序從一種狀態(tài)切換到另一種狀態(tài)(比如從用戶態(tài)切換到內(nèi)核態(tài)),或者從一個程序切換到另一個程序(比如進(jìn)程切換)時,導(dǎo)致上下文相關(guān)寄存器的值變化的行為。對于上下文切換時不需要改變的寄存器,也可以說它不是該程序的上下文。
VMCS
在Linux中,一個進(jìn)程的相關(guān)信息保存在task_struct中。虛擬機(jī)的上下文比進(jìn)程的上下文更為復(fù)雜,在VT-x中,由VMCS(Virtual-Machine Control data Structures)負(fù)責(zé)保存vCPU需要的相關(guān)狀態(tài)和上下文信息。
VMCS在使用時需要和pCPU綁定。一個pCPU可以對應(yīng)多個vCPU,而一個vCPU對應(yīng)一個VMCS,但在任意給定時刻,一個pCPU上只能運(yùn)行一個vCPU(就像在多線程調(diào)度中,某一時刻,一個CPU上只能運(yùn)行一個線程一樣)。
因此,一個pCPU只能綁定一個VMCS,一個VMCS也只能與一個pCPU綁定,可分別通過VMPTRLD/VMCLEAR指令建立/解除兩者的綁定關(guān)系。VMCS存放在內(nèi)存中,一個VMCS占據(jù)4KB大小,由6個區(qū)域組成:
1)Guest state area,用于保存CPU在non-root mode下運(yùn)行時的狀態(tài)。當(dāng)發(fā)生VM exit的時候,CPU將自己當(dāng)前的狀態(tài)保存到guest state area中,當(dāng)發(fā)生VM entry的時候,guest state area保存的狀態(tài)將被自動加載到CPU中。
其實(shí)也不用一口氣將所有寄存器的值都恢復(fù),反正都是保存在VMCS中的,可以等到該寄存器真正被guest使用到時再恢復(fù),這就是LazySave/Restore,其基本思想是盡量將寄存器的保存/恢復(fù)延遲到最后一刻,減少無用功,提高上下文切換的效率。這種思想在Linux的實(shí)現(xiàn)中也比比皆是,比如copy on write, demand paging等,拖延癥也不見得是件壞事哈。
2)Host state area,用于保存CPU在root mode下運(yùn)行時的狀態(tài)。需要保存的寄存器和guest state area是差不多的,但是保存/恢復(fù)的過程是剛好反過來的。
3)VM executation control fields,用于控制non-root模式下CPU的行為。出于優(yōu)化的目的,VMM可以讓某些敏感指令不產(chǎn)生VM exit,以減少mode切換帶來的上下文開銷,而這就是由VM execution control來實(shí)現(xiàn)的。
比如讀取timestamp的RDTSC指令,在一些延時函數(shù)的實(shí)現(xiàn)中,該指令會被頻繁使用,如果每次guest執(zhí)行該指令的時候都trap到VMM,那系統(tǒng)開銷就太大了,這時VMM可以選擇每隔一段時間讀取物理CPU真實(shí)的 timestamp值,然后填寫guest 的timestamp虛擬寄存器,來達(dá)到模擬RDTSC指令的效果。
4)VM exit control fields,用于規(guī)定VM exit時CPU的行為,比如是否應(yīng)答外部中斷。
5)VM exit information fields。VMM除了通過VM exit control fields來控制VM exit的行為,還需要知道VM exit的相關(guān)信息(比如trap的具體原因),這些信息就是保存在VM exit information fields中的。
6)VM entry control fields,用于控制VM entry的過程,比如后續(xù)的文章要介紹的中斷注入。
VM executation control可理解為what to trap,就是哪些event會引起trap,哪些不會。VM exit control可理解為how to trap,VM exit information則可理解為why to trap。讀寫VMCS這段內(nèi)存空間需要使用專門的VMREAD和VMWRITE指令。
小結(jié)一下,一個完整的VT-x使用流程是這樣的:首先需要通過CPUID指令檢查當(dāng)前CPU是否支持虛擬化擴(kuò)展。如果支持,則通過VMXON使能VT-x,建立VMCS并通過VMPTRLD綁定物理CPU。
-
寄存器
+關(guān)注
關(guān)注
31文章
5294瀏覽量
119816 -
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
590瀏覽量
27317 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
904瀏覽量
28018 -
硬件中斷
+關(guān)注
關(guān)注
0文章
11瀏覽量
6830 -
VMM
+關(guān)注
關(guān)注
0文章
11瀏覽量
10043
發(fā)布評論請先 登錄
相關(guān)推薦
評論