1. 程式人生 > >KVM CPU虛擬化

KVM CPU虛擬化


3.1 基本原理

CPU虛擬化是VMM中最核心的部分,由於記憶體和IO訪問的指令都是敏感指令,所以記憶體和IO虛擬化都依賴於CPU虛擬化的實現。CPU虛擬化的目標是讓虛擬機器中執行的所有敏感指令都能產生異常而“陷入”,並由VMM進行模擬。VMM的陷入是通過CPU的保護機制、中斷或異常來完成的。通常,VMM的陷入方式有如下3種:

1、CPU的保護機制觸發。CPU在執行敏感指令之前,會檢查執行條件是否滿足,執行條件主要包括:當前特權級別、執行模式、記憶體對映關係等,只要有任一條件不滿足,就會VM-Exit陷入到VMM進行進一步處理。

2、非同步中斷。包括處理器內部的中斷源和外設的中斷源,當中斷訊號到達

CPU時,CPU會強行中斷Guest OS當前執行的指令,然後VM-ExitVMM註冊的中斷服務程式進行進一步處理。

3、虛擬機器主動觸發的異常,也就是通常所說的陷阱。虛擬機器可以通過陷阱指令主動VM-ExitVMM中。

KVM虛擬化解決方案中,利用了硬體的虛擬化特性(比如Intel VT-xAMD SVM)實現CPU的虛擬化。如之前介紹,VT-x提供了一套稱作VMX的新的工作模式,工作在該模式下的處理器又具有兩類操作模式:VMX root operationVMX non-root operation。對作業系統來說,VMX non-root operation模式與傳統的

x86處理器相容,最大的差別在於當虛擬機器執行一些訪問全域性資源的指令時將導致虛擬機器退出操作(VM-Exit),從而使虛擬機器監控器獲得控制權,以便對訪問全域性資源的指令進行模擬。以後,虛擬機器監控器可以通過虛擬機器進入操作(VM-Entry)使虛擬機器重新獲得控制權。

其次,VT-x為系統程式設計介面狀態的切換提供硬體支援。VT-x為每個虛擬機器維護至少一個VMCSVirtual Machine Control Structure)結構,其中儲存了虛擬機器和虛擬機器監控器的系統程式設計介面狀態。當執行VM exitVM entry操作時,VT-x自動根據VMCS中的內容完成虛擬機器和虛擬機器監控器間的系統程式設計介面狀態切換。另外,

VT-x還提供了一組指令,使得虛擬機器監控器通過一條指令就可以完成虛擬機器間的切換。

3.2 VCPU

硬體虛擬化使用VCPU(Virtual CPU)描述符來描述虛擬CPUVCPU描述符與OS中程序描述符類似,本質是一個結構體,其中包含如下資訊:

üVCPU標識資訊,如VCPUID號,VCPU屬於哪個Guest等。

ü虛擬暫存器資訊,在VT-x的環境中,這些資訊包含在VMCS中。

üVCPU狀態資訊,標識白VCPU當前所處的狀態(睡眠、執行等),主要供排程器使用。

ü額外的暫存器/部件資訊,主要指未包含在VMCS中的暫存器或CPU部件,比如:浮點暫存器和虛擬的LAPIC等。

ü其他資訊:使用者VMM進行優化或儲存額外資訊的欄位,如:存放該VCPU私有資料的指標。

總體來說,VCPU可以劃分為兩部分:

1、VMCS為主,由硬體來使用和更新的部分,主要是虛擬暫存器。

2、VMCS之外,由VMM來使用和更新的部分。如VCPU標識、狀態資訊等。

VMM建立虛擬機器時,首先要為虛擬機器建立VCPU,整個虛擬機器的執行實際上可以看做VMM排程不同的VCPU執行。

3.3 中斷虛擬化

在物理平臺上,中斷架構和外部中斷處理流程如下圖所示:

大致處理過程為:

üIO裝置通過中斷控制器(IO APICPIC)CPU傳送中斷請求

üIO APIC將中斷轉發至目標CPULocal APIC

ü目標APIC對該中斷進行處理

在虛擬化環境中,VMMGuest OS虛擬了一個與物理中斷架構類似的虛擬中斷架構,如下圖所示:
                                     

每個VCPU對應一個虛擬Local APIC,用於接收中斷,同時還模擬了虛擬IO APIC(或虛擬PIC)用於接收外設(虛擬裝置)發出的中斷請求並進行轉發。虛擬Local APIC、虛擬IO APIC、虛擬PIC等都是VMM中的軟體實體(對應於相應的資料結構)。主要處理流程如下:

ü當虛擬裝置需要傳送中斷時,虛擬裝置會呼叫虛擬IO APIC的介面傳送中斷;

ü而虛擬IO APIC根據中斷請求,選出適合的虛擬Local APIC,並呼叫其介面傳送中斷請求;

ü虛擬Local APIC進一步利用CPU硬體虛擬化功能(Intel VT-xAMD SVM)的事件注入機制,將中斷注入到相應的VCPU

ü當相應VCPU得到排程時,即處理相應的中斷。

3.4 排程

KVM虛擬化環境中,KVM虛擬機器作為一個系統程序執行,因此虛擬機器的的排程,實際上就是利用了Linux自身的排程器完成。本文不做詳述。