1. 程式人生 > >CPU的三種虛擬化機制

CPU的三種虛擬化機制

事實上,不同型別的虛擬化技術是從不同的地方開始引導虛擬機器系統的:

  • 從模擬的 BIOS 開始引導的,支援 MBR、EFI、PXE 等啟動方式,如 QEMU、VMWare;
  • 從核心開始引導的,虛擬機器映象內不包含核心,如 KVM、Xen;
  • 從 init 程序開始引導的,虛擬機器是一個與主機共享核心的容器,會按照作業系統的引導過程啟動各種系統服務,如 LXC、OpenVZ;
  • 只執行一個特定的應用程式或服務的,也是基於容器,如 Docker。

/dev/kvm提供的操作包括: 
• 建立一個新的虛擬機器 
• 向一個虛擬機器中分配記憶體 
• 讀寫虛擬cpu暫存器 
• 向一個虛擬cpu中注入中斷 
• 執行一個虛擬cpu 

目前主要有Intel的VT-x和AMD的AMD-V這兩種技術。其核心思想都是通過引入新的指令和執行模式,使VMM和Guest OS分別執行在不同模式(ROOT模式和非ROOT模式)下,且Guest OS執行在Ring 0下。通常情況下,Guest OS的核心指令可以直接下達到計算機系統硬體執行,而不需要經過VMM。當Guest OS執行到特殊指令的時候,系統會切換到VMM,讓VMM來處理特殊指令。

1、Intel VT-x技術

為彌補x86處理器的虛擬化缺陷,市場的驅動催生了VT-x,Intel推出了基於x86架構的硬體輔助虛擬化技術Intel VT(Intel Virtualization Technology)。

目前,Intel VT技術包含CPU、記憶體和I/O三方面的虛擬化技術。

  • CPU硬體輔助虛擬化技術,分為對應安騰架構的VT-i(Intel Virtualization Technology for ltanium)和對應x86架構的VT-x(Intel Virtualization Technology for x86)。
  • 記憶體硬體輔助虛擬化技術包括EPT(Extended Page Table)技術。
  • I/O硬體輔助虛擬化技術的代表VT-d(Intel Virtualization Technology for Directed I/O)。

Intel VT-x技術解決了早期x86架構在虛擬化方面存在的缺陷,可使未經修改的Guest OS執行在特權級0,同時減少VMM對Guest OS的干預。Intel VT-d技術通過使VMM將特定I/O裝置直接分配給特定的Guest OS,減少VMM對I/O處理的管理,不但加速資料傳輸,且消除了大部分效能開銷。如下圖所示。CPU硬體輔助虛擬化技術簡要說明流程圖:

wKioL1afGVfxeUomAAAz5_tFJmI638.png

效法IBM 大型機,VT-x提供了2 個執行環境:根(Root)環境和非根(Non-root)環境。根環境專門為VMM準備,很像原來沒有VT-x 的x86,只是多了對VT-x 支援的幾條指令。非根環境作為一個受限環境用來執行多個虛擬機器。

wKiom1afGTSh8RorAABRoN9MaUU781.png

如上圖所示,根操作模式與非根操作模式都有相應的特權級0至特權級3。VMM執行在根模式的特權級0,GuestOS的核心執行在非根模式的特權級0,GuestOS的應用程式執行在非根模式的特權級3。執行環境之間相互轉化,從根環境到非根環境叫VMEntry;從非根環境到根環境叫VMExit。VT-x定義了VMEntry操作,使CPU由根模式切換到非根模式,執行客戶機作業系統指令。若在非根模式執行了敏感指令或發生了中斷等,會執行VMExit操作,切換回根模式執行VMM。

根模式與非根模式之問的相互轉換是通過VMX操作實現的。VMM 可以通過VMXON 和VMXOFF開啟或關閉VT-x。如下圖所示:

wKiom1afGVDjubB0AAA3uBxIztk294.png

VMX操作模式流程:

1)、VMM執行VMXON指令進入VMX操作模式。

2)、VMM可執行VMLAUNCH指令或VMRESUME指令產生VM Entry操作,進入到Guest OS,此時CPU處於非根模式。

3)、Guest OS執行特權指令等情況導致VMExit的發生,此時將陷入VMM,CPU切換為根模式。VMM根據VMExit的原因作出相應處理,處理完成後將轉到2),繼續執行GuestOS。

4)、VMM可決定是否退出VMX操作模式,通過執行VMXOFF指令來完成。

為更好地支援CPU虛擬化,VMX新定義了虛擬機器控制結構VMCS(Virtual Machine ControlStructure)。VMCS是儲存在記憶體中的資料結構,其包括虛擬CPU的相關暫存器的內容及相關的控制資訊。CPU在發生VM Entry或VMExit時,都會查詢和更新VMCS。VMM也可通過指令來配置VMCS,達到對虛擬處理器的管理。VMCS架構圖如下圖所示:

wKiom1afGaLTpUkXAAA7ZB52HHU125.png

每個虛擬處理器都需將VMCS與記憶體中的一塊區域聯合起來,此區域稱為VMCS區域。對VMCS區域的操縱是通過VMCS指標來實現的,這個指標是一個指向VMCS的64位的地址值。VMCS區域是一個最大不超過4KB的記憶體塊,且需4KB對齊。

VMCS區域分為三個部分:

  • 偏移0起是VMCS版本標識,通過不同的版本號,CPU可維護不同的VMCS資料格式;
  • 偏移4起是VMX中止指示器,在VMX中止發生時,CPU會在此處存入中止的原因;
  • 偏移8起是VMCS資料區,這一部分控制VMX非根操作及VMX切換。

VMCS 的資料區包含了VMX配置資訊:VMM在啟動虛擬機器前配置其哪些操作會觸發VMExit。VMExit 產生後,處理器把執行權交給VMM 以完成控制,然後VMM 通過指令觸發VMEntry 返回原來的虛擬機器或排程到另一個虛擬機器。

VMCS 的資料結構中,每個虛擬機器一個,加上虛擬機器的各種狀態資訊,共由3個部分組成,如之前的VMCS架構圖所示:

1) Gueststate:該區域儲存了虛擬機器執行時的狀態,在VMEntry 時由處理器裝載;在VMExit時由處理器儲存。它又由兩部分組成:

  • Guest OS暫存器狀態。它包括控制暫存器、除錯暫存器、段暫存器等各類暫存器的值。

  • Guest OS非暫存器狀態。用它可以記錄當前處理器所處狀態,是活躍、停機(HLT)、關機(Shutdown)還是等待啟動處理器間中斷(Startup-IPI)。

2) Hoststate:該區域儲存了VMM 執行時的狀態,主要是一些暫存器值,在VMExit 時由處理器裝載。

3) Control data:該區域包含幾部分資料資訊,分別是:

  • 虛擬機器執行控制域(VM-Execution control fields)。VMM 主要通過配置該區域來控制虛擬機器在非根環境中的執行行為。基於針腳的虛擬機器執行控制。它決定在發生外部中斷或不可遮蔽中斷(NMI)要不要發生VMExit。基於處理器的虛擬機器執行控制。它決定虛擬機器執行RDTSC、HLT、INVLPG 等指令時要不要發生VMExit。

  • VMExit 控制域(VMExit control fields)。該區域控制VMExit 時的行為。當VMExit 發生後處理器是否處於64 位模式;當因為外部中斷髮生VMExit 時,處理器是否響應中斷控制器並且獲得中斷向量號。VMM 可以用它來定製當VMExit 發生時要儲存哪些MSR 並且裝載哪些MSR。MSR是CPU的模式暫存器,設定CPU的工作環境和標識cpu的工作狀態。

  • VMEntry 控制域(VMEntry control fields)。該區域控制VMEntry 時的行為。它決定處理器VMEntry 後是否處於IA-32e 模式。與VMExit 的MSR控制類似,VMM 用它來定製當VMEntry 發生時要裝載哪些MSR。VMM 可以配置VMEntry 時通過虛擬機器的IDT向其傳送一個事件。在此可以配置將使用IDT 的向量、中斷型別(硬體或軟體中斷)、錯誤碼等。

  • VMExit 資訊域(VMExit information fields)。該只讀區域包括最近一次發生的VMExit 資訊。試圖對該區域執行寫操作將產生錯誤。。此處存放VMExit 的原因以及針對不同原因的更多描述資訊、中斷或異常向量號、中斷型別和錯誤碼、通過 IDT 傳送事件時產生的VMExit 資訊、指令執行時產生的 VMExit 資訊。

有了VMCS結構後,對虛擬機器的控制就是讀寫VMCS結構。後面對vCPU設定中斷,檢查狀態實際上都是在讀寫VMCS資料結構。

2、AMD-V技術

       我們在上面小節介紹了 Intel 的硬體輔助虛擬化技術,那麼 AMD 的硬體輔助虛擬化技術又有什麼特點呢?AMD 從 2006 年便開始致力於硬體輔助虛擬化技術的研究,AMD-V全稱是AMD Virtualization,AMD-V從程式碼的角度分別稱為 AMD和 SVM,AMD開發這項虛擬化技術時的內部專案程式碼為Pacifica,是AMD推出的一種硬體輔助虛擬化技術。

wKioL1afGj7xq-X4AAISdUtYJcE211.png

Intel VT-x 和 AMD-V 提供的特徵大多功能類似,但名稱可能不一樣,如 Intel VT-x 將用於存放虛擬機器狀態和控制資訊的資料結構稱為 VMCS, 而 AMD-V 稱之為VMCB; Intel VT-x 將 TLB 記錄中用於標記 VM 地址空間的欄位為 VPID, 而AMD-V 稱之為 ASID; Intel VT-x 將二級地址翻譯稱之為 EPT, AMD 則稱為 NPT,等等一些區別。儘管其相似性,Intel VT-x 和 AMD-V 在實現上對 VMM 而言是不相容的。

AMD-V 在 AMD 傳統的x86-64 基礎上引入了“guest”操作模式。“guest”操作模式就是 CPU 在進入客作業系統執行時所處的模式。 “guest”操作模式為客作業系統設定了一個不同於 VMM 的執行環境而不需要改變客作業系統已有的 4 個特權級機制,也就是說在“guest”模式下,客作業系統的核心仍然執行在 Ring 0, 使用者程式仍然在 Ring 3。 裸機上的作業系統和 VMM 所在的操作模式依然和傳統的 x86 中一樣,且稱之為“host”操作模式。 VMM 通過執行 VMRUN 指令使CPU 進入“guest”操作模式而執行客作業系統的程式碼; 客作業系統在執行時,遇到敏感指令或事件,硬體就執行 VMEXIT 行為,使 CPU 回到“host”模式而執行 VMM 的程式碼。 VMRUN 指令執行的引數是一個實體地址指標,其指向一個 Virtual Machine Control Block (VMCB) 的記憶體資料結構, 該資料結構包含了啟動和控制一個虛擬機器的全部資訊。

wKiom1afGimzbOjaAABAsxMi2CI065.png

“guest”模式的意義在於其讓客作業系統處於完全不同的執行環境,而不需要改變客作業系統的程式碼。“guest”模式的設立在系統中建立了一個比 Ring 0 更強的特權控制,即客作業系統的 Ring 0 特權必須讓位於 VMM 的 Ring 0 特權。客作業系統上執行的那些特權指令,即便是在 Ring 0 上也變的可以被 VMM 擷取的了,“Ring Deprivileging”由硬體自動搞定。此外,VMM 還可以通過 VMCB 中的各種擷取控制欄位選擇性的對指令和事情進行擷取,或設定有條件的擷取,所有的敏感的特權或非特權指令都在其控制之中。

wKioL1afGpTiDMn-AABqRRMT8Wk023.jpg

VMCB 資料結構主要包含如下內容 :

1. 用於描述需要擷取的指令或事件的欄位列表。其中 :

  • 2 個 16 位的欄位用於控制對 CR 類控制暫存器讀寫的擷取

  • 2 個 16 位的欄位用於控制對 DR 類除錯暫存器的讀寫的擷取

  • 一個 32 位的欄位用於控制 exceptions 的擷取

  • 一個 64 位的欄位用於控制各種引起系統狀態變化的事件或指令的擷取,如 INTR, NMI, SMI 等事 件, HLT, CPUID,INVD/WBINVD,INVLPG/INVLPGA,MWAIT 等指令, 還包括兩位分別標誌是否對 IO 指令和 MSR 暫存器的讀寫進行控制

  • 指向IO埠訪問控制點陣圖和MSR讀寫控制點陣圖的實體地址指標欄位。該點陣圖用於差別性地控制虛擬機器對不同的 IO 埠和 MSR 暫存器進行讀寫訪問。

  • 描述虛擬機器CPU狀態的資訊。包含除通用暫存器外的大部分控制暫存器,段暫存器,描述符表暫存器,程式碼指標等。 RAX 暫存器也在其中,因為 RAX 在 VMM 執行 VMRUN 時是用來存放VMCB 實體地址的。 對於段暫存器,該資訊中還包含段暫存器對應的段描述符,也就那些傳統 x86 上對軟體隱藏的資訊。

  • 對虛擬機器的執行進行控制的欄位。主要是控制虛擬機器中斷和 NPT 的欄位。

  • 指示虛擬機器進入“guest”模式後要執行的行動的欄位。包括用來描述 VMM 向虛擬機器注入的中斷或異常的資訊的欄位。 注入的中斷或異常在 VMRUN 進入“guest”模式後立即執行,就象完全發生在虛擬機器內一樣。

  • 提供VMEXIT資訊的欄位。包括導致 VMEXIT 的事件的程式碼,異常或中斷的號碼,page fault 的線性地址,被截獲的指令的編碼等。

wKiom1afGuOSVGDWAACiyrhiMUI787.png

VMCB 以及其涉及的控制點陣圖,完全通過實體地址進行指向,這就避免了“guest”和“host”模式切換的過程依賴於“guest”空間的線性地址 ( 傳統作業系統內使用者空間到核心的切換確實依賴於 IDT 中提供的目標的線性地址 ),使得 VMM 可以採用和客作業系統完全不同的地址空間。

VMCB 的內容在物理上被分成了倆部分,其中用於儲存虛擬機器 CPU 狀態的資訊佔據 2048 位元組的後半部分,我們可稱之為 VMCB.SAVE; 其他資訊,佔據前 1024 位元組範圍,我們可稱之為 VMCB.CONTROL。

VMRUN 命令以 VMCB 為引數,使CPU 進入“guest”狀態, 按 VMCB.SAVE 的內容恢復虛擬機器的 CPU 暫存器狀態,並按 VMCB.SAVE 中 CS:RIP 欄位指示的地址開始執行虛擬機器 的程式碼, 並將之前 VMM 的 CPU 狀態儲存在MSR_VM_HSAVE_PA 暫存器所指向的實體記憶體區域中。VMRUN 所儲存的 VMM 的 CPU狀態的 CS:RIP 實際上就是 VMM 的程式碼中 VMCB 的下一個指令,當虛擬機器因某種原因而導致 #VMEXIT 時,VMM 會從 VMRUN 後的一條指令開始執行。CPU 執行 #VMEXIT 行為時,會自動將虛擬機器的狀態儲存到 VMCB.SAVE 區,並從 MSR_VM_HSAVE_PA 指定的區域載入 VMM 的 CPU 狀態。

VMLOAD 和 VMSAVE 指令是對 VMRUN 的補充,他們用來載入和恢復一些並不需要經常使用的 CPU 狀態,如 FS, GS, TR, LDTR 暫存器以及其相關的隱含的描述符暫存器的內容,VMLOAD 和 VMSAVE 可以讓 VMM 的實現對“guest”進入和退出的過程進行優化,讓多數情況下只使用 VMRUN 進行最少的狀態儲存和恢復。

VMMCALL 指令是 AMD-V 為客作業系統核心提供的明確的功能呼叫介面,類似於 syscall 指令 ( 從 Ring3 到 Ring 0), VMMCALL 讓客作業系統直接執行 #VMEXIT 而進入 VMM,請求VMM 的服務。

3、總結

回顧一下CPU虛擬化技術的實現,純軟體的CPU虛擬化使用了陷入-模擬的模式來模擬特權指令,而在x86架構中由於只能模擬特權指令,無法模擬某些敏感指令而無法實現完全的虛擬化。(在x86架構中,特權指令一定是敏感指令,但是敏感指令位元權指令多,造成某系敏感指令不是特權指令而無法模擬,使得CPU虛擬化異常),而硬體輔助虛擬化引入了根模式(root operation)和非根模式(none-root operation),每種模式都有ring0-3的四級特權級別。所以,在硬體輔助虛擬化中,陷入的概念實際上被VM-EXIT操作取代了,它代表從非根模式退出到根模式,而從根模式切換到非根模式是VM-Entry操作。

在2003年出現的Xen,使用了另外的一種半虛擬化的方案來解決x86架構下CPU的敏感指令問題。主要採用Hypercall技術。Guest OS的部分程式碼被改變,從而使Guest OS會將和特權指令相關的操作都轉換為發給VMM的Hypercall(超級呼叫),由VMM繼續進行處理。而Hypercall支援的批處理和非同步這兩種優化方式,使得通過Hypercall能得到近似於物理機的速度。

wKiom1afF8rRLK3ZAACfLO6bwIA867.png

1、Hypercall技術

  對於x86體系結構CPU,Xen使用超級呼叫來替換被監控的操作,其中包括x86架構下的敏感指令。Xen所採用的超級替換的方法是一種全新的設計理念:它將問題的中心,由VMM移向Guest OS自身,通過主動的方式由Guest OS去處理這些指令,而不是被移交給VMM做處理,在這種設計理念下,修改Guest OS核心。

   能修改Guest OS是半虛擬化的一個技術核心。通過修改Guest OS的核心。使Guest OS明確知道自己是執行在1環上,而不是通常OS的0環,有效的避免了虛擬化的執行衝突問題。Guest OS也清楚VMM給自己提供了一個虛擬的暫存器組,並能通過其他方式去訪問他們,避免了訪問衝突的問題。

    解決了敏感指令問題只是解決了x86架構下的半虛擬化的第一步。執行在1環的作業系統沒有許可權執行的指令,交給0環的VMM來處理,這個很大程度上與應用程式的系統呼叫很類似:系統呼叫的作用是把應用程式無權執行的指令交給作業系統完成。因此,Xen向Guest OS提供了一套“系統呼叫”。以方便Guest OS呼叫,這部分”系統呼叫“就是超級呼叫Hypercall。

超級呼叫Hypercall的機制使用,不僅使x86架構的指令虛擬化得以實現,也為後面的記憶體虛擬化和I/O虛擬化提供了新的思路和方法,超級呼叫和事件通道是整個半虛擬化的基礎。

下面我們來看看半虛擬化情況下整體的訪問流程圖,如圖所示。

wKiom1afF9-BZbZuAAAotW_0zjg092.png

CPU半虛擬化技術

上圖明確的顯示了Hypercall的呼叫位置,在Xen中,各元件通訊方式如下所示,Hypercall的呼叫性質是同步的。其他Xen的通訊方式幾乎都是非同步的。

wKiom1afF_iQ2q87AACww5CfWNE788.png

其中,在虛擬機器和Xen的通訊過程中,如果虛擬機器需要呼叫敏感指令,會主動向虛擬機器監控器發起Hypercall呼叫。Hypercall就如同傳統作業系統下的系統呼叫,監管程式通過它向其上各虛擬機器提供各種服務,如MMU 更新、Domain0 操作請求和虛擬處理器狀態等。

下圖顯示了半虛擬化模式下的特權模式:

wKioL1afGFCTwrrgAADLqoaNu8Q729.png

在x86架構下,原生系統和半虛擬化環境下存在差異。原生環境下,CPU有4個特權級(ring0--ring3),作業系統是處於最高級別的ring0,應用程式處於最低級別的ring3。而在半虛擬化環境下,虛擬機器監視器是處於最高級別的ring0,作業系統是處於中級級別的ring1,應用程式處於最低級別的ring3。

wKiom1afGCqRoKQeAABTEciqbX8993.png

只有特權級別為1 的程式碼(準虛擬化Guest VM 的核心)才能向Xen 傳送Hypercall 請求,以防止應用程式(特權級3)的錯誤呼叫導致對系統可能的破壞。因此,只有執行在特權級1 的虛擬機器作業系統核心才能申請Hypercall。但是,一些Xen 專用的特別程式,如xend 或xe也需要有Hypervisor 的服務來完成特殊的操作,如生成一個新的GuestVM 等,這在Xen Linux 中是通過一個稱為privcmd 的核心驅動程式實現。應用程式通過ioctl 向該驅動程式提出服務請求,執行在虛擬機器核心(特權級1)的privcmd 驅動程式再將服務請求以Hypercall 形式轉向Hypervisor,並由後者真正完成生成新Guest VM 的動作。

wKioL1afGH6wRgTgAAELB5Omcd0071.png

上圖中顯示了Hypercall所在的位置,Hypercall位於圖中右上方,核心向Hypervisor發起呼叫的哪裡。Xen啟用130號中斷向量埠(十六進位制的82H)作為超級呼叫的中斷號。這一個中斷向量的DPL被設定為型別為1,型別為中斷門。這樣,超級呼叫能夠由處於特權級1的客戶機作業系統發起,而不能從使用者態發起。

另外,在x86指令集的指令中,有17 條指令不能有效的在ring 1 特權級上執行,Hypercall 的存在解決了這些指令不能正常執行的問題。

wKioL1afGJeBGHKJAAGdRJhdhPM639.png

Hypercall 機制中,在32 位x86 架構下,Hypercall 通過int0x82陷阱(Trap)指令實現,因為傳統作業系統本身並不使用int0x82 (Linux 使用int 0x80 作為系統呼叫指令,int 0x82 並未使用)。

int0x82包括:

  • 超級呼叫號:xen/include/public/xen.h中定義了45個超級呼叫,其中有7個是平臺相關呼叫。

  • 超級呼叫表:xen/arch/x86/x86_32/entry.S中定義了超級呼叫表,通過超級呼叫號索引就可以方便的找到對應的處理函式。

  • 超級呼叫頁:超級呼叫頁是Xen為Guest OS準備的一個頁,可以做到不同Guest OS有不同的超級呼叫頁內容。

  Hypercall 的具體功能識別號由eax 表明,而其他引數則在ebx, ecx, edx, esi 和edi 中。為了減少虛擬機器和Hypervisor 之間的特權級別(Ring)切換次數,Xen 提供對Hypercall的批處理,即將幾個Hypercall 功能請求放在一個列表中由專門的Hypercall 批處理請求完成。在Xen 中,系統呼叫表與Hypercall 表都在entry.S 檔案中被定義。

2、X86架構特權級

x86 硬體支援 4 個特權級 (Ring),一般核心執行在 Ring 0, 使用者應用執行在 Ring 3, 更小的 Ring 有比更高的 Ring 能訪問更多的系統全域性資源,即更高的特權。有些指令只能在 Ring 0 才能正確執行,如 LGDT、LMSW 指令,我們稱之為特權指令;另外有些指令可以在 Ring 3 正確執行,如 SGDT、 SMSW、PUSHF/POPF,我們稱之為非特權指令。

正常模式和虛擬化兩種情況敘述下,特權模式說明如下:

正常模式:特權級別是針對段來講的,段描述符的最後兩位標識了該段所位於的特權級別,比如,中斷處理程式運行於ring0(),此時的核心程式是具有特權的,即ring0。位於ring3使用者程式可以通過系統呼叫的方式,int80,後特權翻轉入ring0,然後就可以順利執行中斷處理程式(好像是使用者程式呼叫核心程式的唯一途徑)。

虛擬化情況下

特權解除:是指解除正常情況下運行於ring0的段,比如中斷處理程式,為了虛擬化需要,此時解除其特權,將其運行於ring1。當用戶程式通過系統呼叫時,其跳轉到的中斷處理程式運行於ring1。但是,在中斷處理程式中,有部分指令是必須在ring0才能執行的,此時,便會自動陷入,然後模擬。也就是說,使用者程式執行特權指令,會有兩次特權下降,一次是通過系統呼叫進入ring1,第二次是通過特權指令陷入進入ring0。這說明,中斷髮生時的中斷處理程式還是以前的位於核心的程式碼,但是其執行級別為ring1,部分指令還需要再次陷入,才能執行。另外,還有一個重要問題,就是部分敏感非特權指令無法陷入的問題:存在二進位制翻譯、超級呼叫等方式,強迫其陷入,然後模擬。

在傳統的 X86 平臺上支援虛擬化上存在如下問題 :

X86 指令集中存在 17 條敏感的非特權指令,“非特權指令”表明這些指令可以在 x86 的 ring 3 執行, 而“敏感性”說明 VMM 是不可以輕易讓客作業系統執行這些指令的。 這 17 條指令在客作業系統上的執行或者會導致系統全域性狀態的破壞,如 POPF 指令,或者會導致客作業系統邏輯上的問題,如 SMSW 等讀系統狀態或控制暫存器的指令。傳統的 X86 沒法捕獲這些敏感的非特權指令。

除了那 17 條敏感的非特權指令,其他敏感的指令都是敏感的特權指令。在 x86 虛擬化環境,VMM 需要對系統資源進行統一的控制,所以其必然要佔據最高的特權級,即 Ring 0, 所以為了捕獲特權指令,在傳統 x86 上一個直接可行的方法是 “Ring deprivileging”, 如將客作業系統核心的特權級從 Ring 0改為 Ring 1 或 Ring 3, 即 “消除” 客核心的特權,以低於 VMM所在的 Ring 0, 從而讓 VMM 捕獲敏感的特權指令。

3、總結

  半虛擬化的思想就是,讓客戶作業系統知道自己是在虛擬機器上跑的,工作在非ring0狀態,那麼它原先在物理機上執行的一些特權指令,就會修改成其他方式,這種方式是可以和VMM約定好的,這就相當於,通過修改程式碼把作業系統移植到一種新的架構上來,就像是定製化。所以XEN這種半虛擬化技術,客戶機作業系統都是有一個專門的定製核心版本,和x86、mips、arm這些核心版本。這樣以來,就不會有捕獲異常、翻譯、模擬的過程了,效能損耗非常低。這就是XEN這種半虛擬化架構的優勢。這也是為什麼XEN半虛擬化只支援虛擬化Linux,無法虛擬化windows原因,微軟不修改程式碼無法實現半虛擬化。

我們在前面的文章中提到了虛擬化技術的大致分類情況,即分為全虛擬化、半虛擬化和硬體輔助虛擬化3大類。而我們虛擬化技術最主要的虛擬主體就是我們的硬體CPU、記憶體和IO,那麼我們的CPU在全虛擬化模式下如何工作,在半虛擬化下如何工作,在硬體輔助虛擬化模式下如何工作?或著說細分下來,我們又可以分為:

  • CPU的全虛擬化技術、半虛擬化技術和硬體輔助虛擬化技術,
  • 記憶體的全虛擬化技術、半虛擬化技術和硬體輔助虛擬化技術
  • IO裝置的全虛擬化技術、半虛擬化技術和硬體輔助虛擬化技術。

本次我們就來說說CPU的全虛擬化技術、半虛擬化技術和硬體輔助虛擬化技術

不支援硬體輔助虛擬化技術的X86架構下的CPU有4個特權級(ring0~ring3),作業系統是處於最高級別的ring0,應用程式處於最低級別的ring3。

wKioL1afFnSRpxlQAABjQiFvejo026.png

在這種架構下實現CPU的全虛擬化是極其困難的,為什麼困難?

  1. 原先的OS執行在ring0層,擁有對所有硬體的全部特權級;
  2. 虛擬化之後將OS執行在ring1層,OS就沒有許可權執行一些特權指令,怎麼保證這些特權指令執行;
  3. 在保證該OS虛擬機器的特權指令執行的情況下,保證其他執行的OS虛擬機器的安全;

1、模擬模擬技術

最先實現這種CPU全虛擬化技術的是Trap-and-emulation技術,即陷入模式和模擬模擬技術。這種技術通過將OS需求的特權指令通過VMM自動捕獲的方式執行後返回去OS。當OS有特權指令產生時,VMM將其自動捕獲,將OS所請求的特權指令進行截獲,然後通過VMM執行之後將結果返回給OS層。VMM會使用模擬模擬將特權指令模擬模擬的方式執行一遍。

wKiom1afFk-T2kDjAACQyVyCch0212.png

在虛擬化模式下,就存在著2中特殊的指令:特權指令和敏感指令。那麼什麼是特權指令?什麼是敏感指令?

特權指令:系統中有一些操作和管理關鍵系統資源的指令,這些指令只有在最高特權級上能夠正確執行。如果在非最高特權級上執行,特權指令會引發一個異常,處理器會陷入到最高特權級,交由系統軟體處理了。

敏感指令:操作特權資源的指令,包括修改虛擬機器的執行模式或者下面物理機的狀態;讀寫時鐘、中斷等暫存器;訪問儲存保護系統、地址重定位系統及所有的I/O指令。

根據Popek和Goldberg的定義,指令集支援虛擬化的前提是:所有敏感指令都是特權指令。很可惜x86指令集不能滿足這個要求。

虛擬化場景下,要求將GuestOS核心的特權解除,從原來的0降低到1或者3。這部分特權指令在Guest OS中發生的時候,就會產生Trap,被VMM捕獲,從而由VMM完成。這就是虛擬的本質方法,特權解除和陷入模擬(Privilege deprivileging/Trap-and-Emulation)。虛擬化場景中敏感指令必須被VMM捕獲並完成。對於一般 RISC 處理器,如 MIPS,PowerPC 以及SPARC,敏感指令肯定是特權指令,但是x86 例外,x86絕大多數的敏感指令是特權指令,但是由於部分敏感指令不是特權指令,執行這些指令的時候不會自動trap被VMM捕獲。

 

2、二進位制翻譯技術

採用模擬模擬的方式模擬和虛擬化x86架構的CPU,但是由於x86架構的CPU中,不是所有的敏感指令都是特權指令,所以並不能完全的解決掉那些不是特權指令的敏感指令的模擬模擬問題。例如SGDT, SLDT, SIDT …

由於模擬模擬技術固有的缺陷,導致對CPU的虛擬化並不完整。所以也導致了基於x86的虛擬化難以和其他CPU架構一樣實現虛擬化。比如IBM的Power CPU架構就很早具備了虛擬化的技術並使用於實踐。

這個現象在1999年得到改善,VMware通過二進位制翻譯技術完成了對x86 CPU架構的完全虛擬化。

其主要採用優先順序壓縮技術(Ring Compression)二進位制程式碼翻譯技術(Binary Translation)。優先順序壓縮技術讓VMM和Guest執行在不同的特權級下。對x86架構而言,即VMM執行在最高特權級別Ring 0下,Guest OS執行在Ring 1下,使用者應用執行在Ring 3下。因此,Guest OS的核心指令無法直接下達到計算機系統硬體執行,而是需要經過VMM的捕獲和模擬執行(部分難以虛擬化的指令需要通過二進位制翻譯【Binary Translation】技術進行轉換)。如下圖所示。

wKioL1afFsDjjbbTAAAl_Q4fU1I877.png

特權級我想在這裡就不用多說,大家都比較清楚,說說大家可能不清楚的二進位制程式碼翻譯技術。二進位制翻譯技術簡稱BT,是一種直接翻譯可執行二進位制程式的技術,能夠把一種處理器上的二進位制程式翻譯到另外一種處理器上執行。二進位制翻譯技術將機器程式碼從源機器平臺對映(翻譯)至目標機器平臺,包括指令語義與硬體資源的對映,使源機器平臺上的程式碼“適應”目標平臺。因此翻譯後的程式碼更適應目標機器,具有更高的執行時效率。二進位制翻譯系統是位於應用程式和計算機硬體之間的一個軟體層,它很好地降低了應用程式和底層硬體之間的耦合度,使得二者可以相對獨立地發展和變化。二進位制翻譯也是一種編譯技術,它與傳統編譯的差別在於其編譯處理物件不同。傳統編譯處理的物件是某一種高階語言,經過編譯處理生成某種機器的目的碼;二進位制翻譯處理的物件是某種機器的二進位制程式碼,該二進位制程式碼是通過傳統編譯過程生成的,經過二進位制翻譯處理後生成另一種機器的二進位制程式碼。

根據不同的實現方式,二進位制翻譯技術可分為三大類:解釋執行,靜態翻譯和動態翻譯。

  程式碼解釋執行

解釋執行(Interpretation)過程對源機器程式碼中的每條指令實時解釋執行,系統不儲存且不快取解釋過的指令,不需要使用者干涉,也不進行任何優化。直譯器相對容易開發,比較容易與老的體系結構高度相容,但效率很差。

  靜態二進位制翻譯

在靜態二進位制翻譯(SBT,Static BinaryTranslation)中,程式碼在執行之前被離線翻譯,根據目標機器的指令結構生成一個新的程式,然後直接執行這個翻譯後生成的程式。靜態翻譯器的離線翻譯過程不會給程式執行帶來額外開銷,因此可以充分採用各種優化措施生產高質量程式碼,大大提高執行時效率。

  動態二進位制翻譯

動態二進位制翻譯(DBT,Dynamic BinaryTranslation)則在程式執行時對執行到的程式碼片段進行翻譯,克服了靜態翻譯所無法解決的一些困難,如執行時動態資訊收集,程式碼挖掘,自修改程式碼和精確中斷問題。而且動態翻譯器對使用者完全透明,無需使用者干預。雖然動態翻譯有上述諸多優點,翻譯過程卻由於受到動態執行的限制而不能像靜態翻譯那樣進行完全細緻的優化,使得翻譯生成的程式碼效率比靜態翻譯器差。

三種二進位制翻譯技術的比較

wKiom1afFp-iEdF_AACk-KSZCrc149.png

解釋執行是最易實現的一種翻譯技術,但是其繁瑣的實現方式大大降低了翻譯系統的執行效率。靜態翻譯雖然能提供高效的執行時效能,但由於無法在靜態環境下覆蓋所有程式碼,無法脫離對直譯器的依賴。與上述兩種相比,動態翻譯很好的解決了程式碼覆蓋、自修改程式碼和精確中斷等諸多問題,同時也能提供可接受的執行效率。因此VMware基於動態二進位制翻譯技術實現了x86架構的CPU的虛擬化。

wKioL1afFvXSPZvRAAC6ySjX1WQ706.png

典型動態二進位制翻譯系統結構所示,被翻譯的程式碼稱為源機器程式碼,在宿主機上執行的程式碼稱為目標機器程式碼,一個典型的動態二進位制翻譯器主要包括兩個模組:翻譯引擎和執行引擎。其中翻譯器引擎負責將源機器程式碼翻譯程式碼翻譯成目標機器程式碼;執行引擎負責準備目標機器程式碼執行的上下文環境(Execution Context)然後從目標機器程式碼快取中找到源機器程式碼對應的目的碼並執行。

其基本執行流程如下:

  查詢(Lookup)階段

這個階段查詢目的碼塊是否存在於目的碼快取中,如果存在則返回目標塊入口地址,如果不存在則進入翻譯階段。

  上下文切換(Context Switch)階段

當一個目的碼塊被查詢到或者翻譯模組生成的時候,二進位制翻譯系統會執行一次控制權轉移。系統會把控制權交給執行模組去執行該目的碼塊,目的碼塊執行完畢後系統需要恢復執行引擎的控制權。一次控制權轉移需要儲存程式的上下文環境。

  翻譯(Translation)階段

完成從源機器二進位制程式碼到目標機器二進位制程式碼的翻譯。包括解碼、中間程式碼優化、編碼三個子階段。

  執行和連結(Executing & Linking)階段

當基本塊被翻譯生成目的碼塊之後,依照原始碼的控制流完成目的碼塊之間的直接以及間接跳轉的連結,並依次執行目的碼塊。

3、總結

在沒有CPU硬體輔助虛擬化技術之前,對於X86架構的CPU就採用模擬和二進位制翻譯的技術對CPU進行虛擬化實現,但是模擬的方式存在固有缺陷,並不完全虛擬化了x86的CPU架構。而二進位制翻譯技術則採用完全不同的思路實現了x86架構的CPU虛擬化。其實對於x86的CPU虛擬化,其難點就在於對其特權指令和敏感指令的虛擬化實現,當然,在實現了CPU的指令這一難題之後,還有一個難題在等著我們!那就是x86架構的CPU排程問題?

在虛擬化環境下,x86架構的CPU有什麼排程問題?

1、 虛擬CPU和物理CPU之間的對應關係?

2、 虛擬CPU和物理CPU之間的資源分配?

3、 虛擬CPU和虛擬CPU之間的優先順序?

4、 多核虛擬CPU架構vSMP和vNUMA與物理多核CPU架構SMP和NUMA之間的排程和負載均衡?

相關推薦

CPU虛擬化機制

事實上,不同型別的虛擬化技術是從不同的地方開始引導虛擬機器系統的: 從模擬的 BIOS 開始引導的,支援 MBR、EFI、PXE 等啟動方式,如 QEMU、VMWare; 從核心開始引導的,虛擬機器映象內不包含核心,如 KVM、Xen; 從 init 程序開始引導的,虛

Oracle基礎學習2--Oracle登錄與驗證機制

cal log 打開 manage nts 系統管理 user 本地用戶和組 成員 首先,Oracle安裝完畢有三個默認用戶   ? Sys:數據庫對象的擁有者。權限最高。password在安裝的時候(口令管理)能夠改變   ? System:數據庫管

虛擬化技術比較

設備 conf build lin 不能 MF lsp 重復 進行 三種虛擬化技術比較 ESXi 與其它虛擬化底層產品之比較: 序號 虛擬化管理程序屬性 VMware ESXi 5.0 采用 Hyper-V 的 Windows Server 20

gtest 事件機制

sting include 一個 兩個 end 程序 mod scrip rtu 前言:   1.首先說明gtest中事件的結構層次:      測試程序:一個測試程序只有一個main函數,也可以說是一個可執行程序是一個測試程序。該級別的事件機制會在程序的開始和結束

CSS的定位機制。絕對定位是相對誰?設定百分屬性時是相對誰?

直入主題: CSS定位的三種機制: 一.普通流:   position: static 元素框正常生成,預設設定。   position: relative  元素相對於它本來的位置,注意:移動後,在原來的位置會佔用一個相同大小的空間。 二.絕對定位:   position

Spring學習之Spring裝配機制:(二)顯示裝配bean

  今天我們介紹一下Spring三種裝配機制中的另外兩種裝配方式:JavaConfig和XML配置,這兩種方式區別於自動化裝配方式都屬於顯示裝配。 1、Java程式碼裝配bean 首先,我們通過在Config類中使用@Bean註解來宣告bean; @Bean註

WPA/WPA2, WPA-PSK/WPA2-PSK, WEP 安全機制的概念和區別

現在基本家家戶戶都安裝有無線WIFI,而且可能不止一個,不過為了安全,大家都會設定密碼,但是下面會有三種加密方式,而且安全效能和設定也不一樣,可能很多人習慣性的選擇了 WPA-PSK/WPA2-PSK密碼設定,而另外兩種加密方式很少有人考慮,下面裝機之家小編來為大家講講這三種

select,poll,epollIO機制對比介紹

 select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是

java 呼叫機制(同步、回撥、非同步)

java中存在三種呼叫機制 1:同步呼叫:一種阻塞式呼叫,呼叫方要等待對方執行完畢才返回,它是一種單向呼叫 2:回撥:一種雙向呼叫模式,也就是說,被呼叫方在介面被呼叫時也會呼叫對方的介面; 3:非同步呼叫:一種類似訊息或事件的機制,不過它的呼叫方向剛好相反

jpa hibernate的快取機制

快取是介於應用程式和物理資料來源之間,其作用是為了降低應用程式對物理資料來源訪問的頻次,從而提高了應用的執行效能。快取內的資料是對物理資料來源中的資料的複製,應用程式在執行時從快取讀寫資料,在特定的時刻或事件會同步快取和物理資料來源的資料。  快取的介質一般是記憶體,所以讀

CPU工作模式

 一直以來,都搞不清楚這幾個概念。在網上搜了一下,把它晒上,不會再忘記! 有其它的內容,請看到的朋友請補充。      從80386開始,cpu有三種工作方式:真實模式,保護模式和虛擬8086模式。只有在剛剛啟動的時候是real-mode,等到linux作業系統執行 起來以

C++(筆記)繼承機制

在實際程式設計中其實公有繼承佔絕大多數,但其他也是都需要了解的 首先要知道子類繼承了基類的所以資料成員和全部函式成員(除了構造、析構器),但它們的繼承方式不同,訪問許可權也會不一樣

COM元件的呼叫機制

這裡的COM元件可以是一個程序內伺服器(In-Process Server),也可以是一個程序外伺服器(Out-Of-Process Server)。一般情況下,我們在使用這些COM元件的時候,只要保證COM是正確註冊了,根本不用關心DLL是怎麼被load進來的,或者Ex

比較虛擬化技術kvm,xen,vmware

目前常用的虛擬機器技術主要有KVM、xen、vmware。KVM是指基於Linux核心(Kernel-based)的虛擬機器(Virtual Machine)。KVM最大的好處就在於它是與Linux核心整合的,所以速度很快。KVM的宿主作業系統必須是Linux,支援的客戶機作

Spring中bean的裝配機制之——自動裝配

基本介紹   關於各種配置,從來沒搞懂過。但是覺得框架發展這麼快,而且結構這麼巨集大,其實現微觀上來講應該從來沒有一種標準方式、更沒有說是固定的幾種。比如Spring專有的@Component、@Autowired註解,大多數情況下都可以被javax.inje

Openvz/KVM/Xen常見VPS虛擬化技術比較

更多 創建 半虛擬化 war 說明 文件 body 折騰 動態 mjj 剁機器時一般都會關心下超售情況,這裏簡要說明下各虛擬化技術超售能力。 KVM 不可超售資源:內存,硬盤空間 內存:KVM 在分配內存時是完全獨占的,也就是說母雞不能生出內存大於總物理內存的小雞。硬盤:

方式在CentOS 7搭建KVM虛擬化平臺

itl ali 簡單 結構 tar pac path idg so文件 KVM 全稱是基於內核的虛擬機(Kernel-based Virtual Machine),它是一個 Linux的一個內核模塊,該內核模塊使得 Linux變成了一個Hypervisor:它由

java反射機制——獲取class物件的方法

package cn.itcast.reflect.demo; import cn.itcast.bean.demo.Person; /** * * 獲取Class物件的3中方法: * * * */ public class ReflectDemo1 { public st

Libvirt支援的CPU模式與熱遷移(by Joshua)

版權宣告:可以任意轉載,轉載時請務必以超連結形式標明文章原始出處和作者資訊及本版權宣告 (作者:張華 發表於:2018-03-09) 問題 原始的nova配置(cpu_mode=”host-passthrough”)導致無法熱遷移,改成(cpu_mode=”custom”, cp

Python基礎(四)--- Python多執行緒介紹,開啟執行緒的方式,time模組,join,Daemon,Lock、Rlock,事件機制,Timer

一、多執行緒介紹 --------------------------------------------------------- 1.threading用於提供執行緒相關的操作,執行緒是應用程式中工作的最小單元。 2.python當前版本的多執行緒庫沒有實現優先順序、執行緒組,執