国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Linux|Centos|Ubuntu|系統進程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務器之家 - 服務器系統 - Linux - Linux 系統虛擬化模型及障礙

Linux 系統虛擬化模型及障礙

2021-11-26 22:07Linux閱碼場王柏生 謝廣軍 Linux

了滿足GeraldJ. Popek和Robert P. Goldberg提出的滿足虛擬化的3個條件,一個典型的解決方案是Trap andEmulate模型。

Linux 系統虛擬化模型及障礙

x86架構CPU虛擬化

Gerald J. Popek和Robert P. Goldberg在1974年發表的論文“Formal Requirements for Virtualizable[A1] [A2] Third Generation Architectures”中提出了符合虛擬化的3個條件:

(1)等價性,即VMM需要在宿主機上為虛擬機模擬出一個本質上與物理機一致的環境。虛擬機在這個環境上運行與其在物理機上運行別無二致,除了可能因為資源競爭或者VMM的干預導致在虛擬環境中表現上略有差異,比如虛擬機的I/O、網絡等因宿主機的限速或者多個虛擬機共享資源,導致速度可能要比獨占物理機的慢一些。

(2)高效性,即虛擬機指令執行的性能與其在物理機上運行相比并無明顯損耗。該標準要求虛擬機中的絕大部分指令無須VMM干預而直接運行在物理CPU上,比如我們在x86架構上通過Qemu運行的ARM系統并不是虛擬化,而是仿真(Emulator)。

(3)資源控制,即VMM完全控制系統資源。由VMM控制協調宿主機資源給各個虛擬機,而不能由虛擬機控制了宿主機的資源。

陷入和模擬模型

為了滿足GeraldJ. Popek和Robert P. Goldberg提出的滿足虛擬化的3個條件,一個典型的解決方案是Trap andEmulate模型。

一般來說,處理器可以歸結為兩種運行模式:系統模式和用戶模式。相應的,CPU的指令也分為特權指令和非特權指令。特權指令只能在系統模式運行,如果特權指令運行在用戶模式就將觸發處理器異常。操作系統將內核運行在系統模式,因為內核需要管理系統資源,需要運行特權指令,而普通的用戶程序則運行在用戶模式。

在虛擬化場景下,虛擬機的用戶程序仍然運行在用戶模式,但是虛擬機的內核將運行在用戶模式,這種方式稱為Ring Compression。在這種方式下,虛擬機中的非特權指令直接運行在處理器上,滿足了Popek和Goldberg提出的虛擬化標準中高效的要求,即指令的大部分無須VMM干預直接在處理器上運行。但是,當虛擬機執行特權指令時,因為是在用戶模式執行特權指令,將觸發處理器異常,從而陷入到VMM中,由VMM代理虛擬機完成系統資源的訪問,即所謂的模擬(emulate)。如此,又滿足了Popek和Goldberg提出的虛擬化標準中VMM控制系統資源的要求,虛擬機將不會因為可以直接運行特權指令而修改宿主機的資源,從而破壞宿主機的環境。

x86架構虛擬化的障礙

Gerald J. Popek和Robert P. Goldberg指出,修改系統資源的,或者在不同模式下行為有不同表現的,都屬于敏感指令。在虛擬化場景下,VMM需要監測到這些敏感指令。一個支持虛擬化的體系架構的敏感指令都屬于特權指令,即在非特權級別執行這些敏感指令時,CPU會拋出異常,進入VMM的異常處理函數,從而實現了控制VM訪問敏感資源的目的。

但是,x86架構恰恰不能滿足Gerald J. Popek和Robert P. Goldberg定義的這個準則,且并不是所有的敏感指令都是特權指令,有些敏感指令在非特權模式下執行時并不會拋出異常,此時VMM就無法攔截或者處理VM的行為。以修改FLAGS寄存器中的IF(interrupt flag)為例,我們首先使用指令pushfd將寄存器FLAGS的內容壓到棧中,然后將棧頂的IF清0,最后使用popf指令從棧中恢復FLAGS寄存器。如果將虛擬機內核運行在ring 1,x86的CPU并不會拋出異常,而只是默默地忽略指令popfd,因此虛擬機關閉IF的目的并沒有生效。

有人提出半虛擬化的方式,即修改Guest的代碼,但是這不符合虛擬化的透明準則。后來,人們提出了二進制翻譯的方式,包括靜態翻譯和動態翻譯。靜態翻譯就是在運行前,掃描整個可執行文件,對敏感指令進行翻譯,重新形成一個新的文件。靜態翻譯是有其局限性的,必須提前處理,而且有些指令只有在運行時才產生的副作用,無法靜態處理。于是,動態翻譯應運而生,即在運行時以代碼塊為單元動態地修改二進制代碼。動態翻譯在很多VMM中得到應用,而且優化的效果非常不錯。

VMX擴展

雖然程序員們從軟件層面采用了多種方案去解決x86架構在虛擬化方面的問題,但是軟件層的解決方案除了額外的開銷外,也給VMM的實現帶來了巨大的復雜性。于是,Intel嘗試從硬件層面解決這個問題。Intel并沒有將那些非特權的敏感指令修改為特權指令,因為并不是所有的特權指令都需要Trap and Emulate。我們舉個典型的例子,每當操作系統內核切換進程時,都會切換cr3寄存器,使其指向當前運行進程的頁表。當使用影子頁表進行GVA到HPA的映射時,需要捕獲Guest的每一次設置cr3寄存器的操作,VMM模塊使其指向影子頁表。而當啟用了硬件層面的EPT支持后,cr3仍然指向Guest的進程頁表,無須捕捉Guest設置cr3寄存器的操作,也就是說,雖然寫cr3寄存器是特權指令,但是其不需要陷入VMM。

Intel開發了VT技術支持虛擬化,為CPU增加了Virtual-Machine Extensions,簡稱為VMX。一旦啟動了CPU的VMX支持,CPU將提供2種運行模式:VMX Root Mode和VMX non-Root Mode,每一種模式都支持ring0 ~ ring3。VMM運行在VMX RootMode,除了支持VMX外,VMX Root Mode和普通的模式并無本質區別。VM運行在VMX non-Root Mode,Guest無須再采用Ring Compression方式,Guest kernel可以直接運行在VMX non-Root Mode的ring0,如圖1所示。

Linux 系統虛擬化模型及障礙

圖1 VMX運行模式

處在VMX RootMode的VMM可以通過執行CPU提供的虛擬化指令VMLaunch切換到VMX non-Root Mode,因為這個過程相當于進入Guest[3] ,所以通常也被稱為VM entry。當Guest內部執行了敏感指令,比如某些I/O操作后,將觸發CPU發生陷入的動作,從VMX non-Root Mode切換回VMX Root Mode,這個過程相當于退出VM,所以也稱為VM exit。然后VMM將對Guest 的操作進行模擬。相比于Ring Compression方式,即將Guest的內核也運行在用戶模式(ring 1 ~ ring 3)的方式,支持VMX擴展的CPU[4] :

(1)運行于Guest模式時,Guest用戶空間的系統調用直接陷入Guest模式的內核空間,而不是再陷入到Host模式的內核空間。

(2)對于外部中斷,因為需要讓VMM控制系統的資源,所以處于Guest模式的CPU收到外部中斷,則觸發CPU從Guest模式退出到Host模式,由Host內核處理外部中斷。處理完中斷后,再重新切入Guest模式。為了提高I/O效率,Intel支持外設透傳模式,在這種模式下,Guest可以不必產生VM exit,“設備虛擬化”一章將討論這種特殊方式。

(3)不再是所有的特權指令都會導致處于Guest模式的CPU發生VM exit,僅當運行敏感指令時才會導致CPU從Guest模式陷入Host模式,因為有的特權指令并不需要由VMM介入處理。

如同一個CPU可以分時運行多個任務一樣,每個任務有自己的上下文,由調度器在調度時切換上下文,從而實現同一個CPU同時運行多個任務。在VMX擴展下,同一個物理CPU“一人分飾多角”,分時運行著Host及Guest,在不同模式間按需切換,因此,不同模式也需要保存自己的上下文。為此,VMX設計了一個保存上下文的數據結構:VMCS。每一個Guest都有一個VMCS實例,當物理CPU加載了不同的VMCS時,將運行不同的Guest,,如圖2所示。

Linux 系統虛擬化模型及障礙

圖2 多個Guest切換

VMCS中主要保存著兩大類數據,一類是狀態,包括Host的和Guest的,另外一類是控制Guest運行時的行為。

(1)Guest-state area,保存虛擬機狀態的區域。當發生VM exit時,Guest的態保存在這個區域;當VM entry時,這些狀態將被裝載到CPU中。這些都是硬件層面的自動行為,VMM無須編碼干預。

(2)Host-state area,保存宿主機狀態的區域。當發生VM exit時,CPU自動從VMCS裝載這些狀態到物理CPU;當VM entry時,CPU自動將狀態保存到這個區域。

(3)VM-exit information fields。當虛擬機發生VM exit時,VMM需要知道導致VM exit的原因,然后才能對癥下藥,進行相應的模擬操作。為此,CPU會自動將Guest退出的原因保存在這個區域,供VMM使用。

(4)VM-execution control fields。這個區域中的各種字段控制著虛擬機運行時的一些行為,比如設置Guest運行時訪問cr3時是否觸發VM exit;控制VM entry與exit時的行為的VM-entry control fields和VM-exitcontrol fields。我們不再一一列出細節,讀者如有需要可以查閱Intel手冊。

在創建VCPU時,KVM模塊將為每個VCPU申請一個VMCS,每次CPU準備切入Guest模式時,將設置其VMCS指針指向即將切入的Guest對應的VMCS實例:

  1. commit 6aa8b732ca01c3d7a54e93f4d701b8aabbe60fb7
  2. [PATCH] kvm: userspace interface
  3. ?linux.git/drivers/kvm/vmx.c
  4. ?static struct kvm_vcpu *vmx_vcpu_load(structkvm_vcpu *vcpu)
  5. {
  6. u64phys_addr = __pa(vcpu->vmcs);
  7. int cpu;
  8. cpu =get_cpu();
  9. if(per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
  10. per_cpu(current_vmcs, cpu) = vcpu->vmcs;
  11. asmvolatile (ASM_VMX_VMPTRLD_RAX "; setna %0"
  12. : "=g"(error) : "a"(&phys_addr),"m"(phys_addr)
  13. : "cc");
  14. }
  15. }

并不是所有的狀態都由CPU自動保存與恢復,我們還需要考慮效率。以cr2寄存器為例,大多數時候,從Guest退出到Host再次進入Guest期間,Host并不會改變cr2寄存器的值,而且寫cr2的開銷不小,如果每次VM entry都更新一次cr2,除了浪費CPU指令周期,毫無意義。因此,將這些狀態交給VMM由軟件自行控制更合適。

VCPU生命周期

對于每個虛擬處理器(VCPU),VMM使用一個線程代表VCPU這個實體。在Guest運轉過程中,每個VCPU基本都在如圖1-3所示的狀態中不斷地轉換。

Linux 系統虛擬化模型及障礙

圖3 VCPU生命周期

在用戶空間準備好后,VCPU所在線程向內核中KVM模塊向發起一個ioctl請求KVM_RUN,告知內核中的KVM模塊,用戶空間的操作已經完成,可以切入Guest模式運行Guest了。

在進入內核態后,KVM模塊將調用CPU提供的虛擬化指令切入Guest模式。如果是首次運行Guest,則使用VMLaunch指令,否則使用VMResume指令。在這個切換過程中,首先,CPU的狀態,也就是Host的狀態,將會被保存到VMCS中存儲Host狀態的區域,非CPU自動保存的狀態由KVM自行保存。然后,加載存儲在VMCS中的Guest的狀態到物理CPU,非CPU自動恢復的狀態則由KVM自行恢復。

物理CPU切入Guest模式,運行Guest指令。當執行Guest指令遇到敏感指令時,CPU將從Guest模式切回到Host模式的ring0,進入Host內核的KVM模塊。在這個切換過程中,首先,CPU的狀態,也就是Guest的狀態,將會被保存到VMCS中存儲Guest狀態的區域,然后,加載存儲在VMCS中的Host的狀態到物理CPU。同樣的,非CPU自動保存的狀態,由KVM模塊自行保存。

處于內核態的KVM模塊從VMCS中讀取虛擬機退出原因,嘗試在內核中處理。如果內核中可以處理,那么虛擬機就不必再切換到Host模式的用戶態了,處理完后,直接快速切回Guest。這種退出也稱為輕量級虛擬機退出。

如果內核態的KVM模塊不能處理虛擬機退出,那么VCPU將再進行一次上下文切換,從Host的內核態切換到Host的用戶態,由VMM的用戶空間部分進行處理。VMM用戶空間處理完畢后,再次發起切入Guest模式的指令。在整個虛擬機運行過程中,這個過程循環往復。

下面是內核空間切入、切出Guest的代碼:

  1. commit 6aa8b732ca01c3d7a54e93f4d701b8aabbe60fb7
  2. [PATCH] kvm: userspace interface
  3. ?linux.git/drivers/kvm/vmx.c
  4. ?static int vmx_vcpu_run(struct kvm_vcpu *vcpu, …)
  5. {
  6. ? u8 fail;
  7. u16fs_sel, gs_sel, ldt_sel;
  8. intfs_gs_ldt_reload_needed;
  9. again:
  10. ? /*Enter guest mode */
  11. "jne launched \n\t"
  12. ASM_VMX_VMLAUNCH "\n\t"
  13. "jmp kvm_vmx_return \n\t"
  14. "launched: " ASM_VMX_VMRESUME "\n\t"
  15. ".globl kvm_vmx_return \n\t"
  16. "kvm_vmx_return: "
  17. /*Save guest registers, load host registers, keep flags */
  18. ? if(kvm_handle_exit(kvm_run, vcpu)) {
  19. goto again;
  20. }
  21. }
  22. return 0;
  23. }

在從Guest退出時,KVM模塊首先調用函數kvm_handle_exit嘗試在內核空間處理Guest退出。函數kvm_handle_exit有個約定,如果在內核空間可以成功處理虛擬機退出,或者是因為其他干擾比如外部中斷導致虛擬機退出等無須切換到Host的用戶空間,則返回1;否則返回0,表示需要求助KVM的用戶空間部分處理虛擬機退出,比如需要KVM用戶空間的模擬設備處理外設請求。

如果內核空間成功處理了虛擬機的退出,則函數kvm_handle_exit返回1,我們看到上述代碼直接跳轉到標簽again處,然后程序流程會再次切入Guest。這種虛擬機退出被稱為輕量級虛擬機退出。如果函數kvm_handle_exit返回0,則函數vmx_vcpu_run結束執行,CPU從內核空間返回到用戶空間,以kvmtool為例,其相關代碼片段如下:

  1. ?commit 8d20223edc81c6b199842b36fcd5b0aa1b8d3456
  2. Dump KVM_EXIT_IO details
  3. ?kvmtool.git/kvm.c
  4. ?int main(int argc, char *argv[])
  5. {
  6. ? for (;;){
  7. kvm__run(kvm);
  8. ? switch (kvm->kvm_run->exit_reason) {
  9. caseKVM_EXIT_IO:
  10. }
  11. }

根據代碼可見,kvmtool發起進入Guest的代碼處于一個無限的for循環中。當從KVM內核空間返回用戶空間后,kvmtool在用戶空間處理Guest的請求,比如調用模擬設備處理I/O請求。在處理完Guest的請求后,重新進入下一輪for循環,kvmtool再次請求KVM模塊切入Guest。

王柏生 資深技術專家,先后就職于中科院軟件所、紅旗Linux和百度,現任百度主任架構師。在操作系統、虛擬化技術、分布式系統、云計算、自動駕駛等相關領域耕耘多年,有著豐富的實踐經驗。著有暢銷書《深度探索Linux操作系統》(2013年出版)。

謝廣軍 計算機專業博士,畢業于南開大學計算機系。資深技術專家,多年的IT行業工作經驗。現擔任百度智能云副總經理,負責云計算相關產品的研發。多年來一直從事操作系統、虛擬化技術、分布式系統、大數據、云計算等相關領域的研發工作,實踐經驗豐富。

本文內容節選自《深度探索Linux虛擬化技術》,已獲得機械工業出版社華章公司授權。

原文鏈接:https://mp.weixin.qq.com/s/HnERI0V-_YnQZFtN_L5psQ

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美成人免费在线视频 | 久久成人国产精品 | 久久久久久久久久久美女 | 性农村人freesex| 综合久久网 | 成人欧美一区二区三区在线观看 | 日韩精品一区二区在线观看 | 中文字幕在线免费看 | 欧美激情一区二区三区 | 午夜激情视频网站 | 久色 | 国产麻豆乱码精品一区二区三区 | 91精品久久久久久综合五月天 | 伊人99| 久久精品国产一区二区三区不卡 | 欧美不卡视频 | 国产色秀视频在线观看 | 国产精品免费久久久久久久久 | 欧美精品在线一区二区三区 | 欧美大片免费在线观看 | 欧美精品一区视频 | 中文字幕在线视频观看 | 欧美 日韩 国产 一区 | 国产有码| 一区二区三区视频免费在线观看 | 免费国产一区二区 | 日韩欧美国产一区二区 | 国产精品美女久久久免费 | 中文av一区二区 | 日韩欧美视频 | 日韩激情一区二区 | 久久一日本道色综合久久 | 最色网 | 欧美日韩中文在线 | 色香阁99久久精品久久久 | 欧美狠狠干| 一区二区三区在线看 | 久久黄色网 | 国产精品久久国产精品 | 亚洲xxxxx| 狠狠爱天天操 |