x86 CPU虛擬化環境中的地址轉換加速機制
前面講過,在Intel x86 CPU中,為了加快線性地址到實體地址的轉換,引入了各種地址轉換的cache(TLB、PDE cache、PDPTE cache、PML4 cache)和PCID(Processor Context Identifier)機制。不清楚的可以出門左轉檢視上一篇文章。
而在虛擬化環境中,即VMX(Virtual Machine Extension)中,Intel x86 CPU同樣也引入了EPT(Extended Page Table)、地址轉換Cache和VPID(Virtual Processor Identifier)機制用於加快地址的轉換。
1. EPT(Extended Page Table)
在虛擬化環境中,由於VMM(Virtual Machine Monitor)可以同時管理、執行多個虛擬機器,每個虛擬機器看到的硬體資源都由VMM模擬或者分配,所以虛擬機器看到的硬體資源可能不是真實的,比如記憶體,所以在虛擬化環境中就需要將虛擬機器所認為的實體記憶體轉換成實際的實體記憶體。即在虛擬機器內部的客戶機作業系統,它能感受到的是和普通的作業系統一樣,即將虛擬地址轉換為實體地址(客戶機實體地址),而在實際的實現中,還需要在客戶機作業系統無法感知的地方將客戶機實體地址轉換為真實的實體地址,即宿主機實體地址,這個過程即GVA(Guest Virtual Address)-> GPA(Guest Physical Address) -> HPA(Host Physical Address)。
為了實現這個目的,可以通過純軟體的方式,也可以通過硬體輔助的方式。對於純軟體的方式而言,由於硬體上只提供了一個地址轉換頁表的入口點——CR3暫存器。為了讓一個頁表實現兩層的地址轉換(GVA->GPA是虛擬機器作業系統可以見的,GPA->HPA是虛擬機器作業系統不可見的),VMM將採用陷入再模擬的方式,讓虛擬機器作業系統對CR3和頁表的訪問都觸發退出到VMM,然後VMM將兩次地址轉換的頁表結合起來形成一系列的頁表,即影子頁表。虛擬機器作業系統以為自己將GVA->GPA的轉換頁表入口載入到CR3暫存器,而實際上已經被VMM“偷樑換柱”了,載入到CR3的是GVA->HPA的頁表,這也是影子頁表名稱的來源。如下圖所示:
為了實現影子頁表,大部分的CR3暫存器和頁表訪問都需要陷入到VMM中,讓VMM在軟體層面上進行模擬。同時VMM需要為每個虛擬機器作業系統的每個程序維護一張地址轉換頁表,會佔用大量的記憶體資源。為此帶來了兩個問題,一個是地址轉換的效率不高,另一方面則是記憶體資源佔用過多。
為了克服在虛擬化環境中地址轉換的效能和資源問題,Intel x86 CPU的VMX功能集中引入了EPT(Extended Page Table)機制,即在原本基於CR3和地址轉換頁表實現分頁機制的基礎上,再在硬體上引入一層分頁機制,該新的分頁機制就叫做EPT,EPT分頁機制用於將GPA轉化為HPA,如下圖所示:
EPT機制所使用的頁表的入口地址位於VMCS(Virtual Machine Control Structure)結構體中的EPTP(Extended Page Table Pointer),當EPT使能的時候,虛擬機器作業系統內部維護的地址轉換頁表由CR3提供入口,將GVA轉化為GPA,讓後再由虛擬機器作業系統看不到的EPT表將GPA轉化為HPA,HPA HPA的訪問請求傳送給記憶體控制器,實現記憶體的訪問。這兩個轉換過程都由硬體自動完成,軟體需要做的就是在記憶體中設定好地址轉換頁表(由VMM完成),並將頁表的入口地址放到CR3或者EPTP位置。硬體的地址轉換速度就比軟體快多了,解決了效能的問題。
另外,由於EPT的作用是進行GPA->HPA的轉換,每個虛擬機器作業系統只有一份GPA,所以VMM只需要為每個虛擬機器維護一份GPA->HPA的地址轉換頁表,這樣就可以大大減少地址轉換頁表對記憶體的佔用。
2. 地址轉換Cache
在前一篇文正中提到,x86 CPU引入了TLB和Paging-Structure Cache用於加速地址轉換,而在虛擬化環境中,也引入了類似的機制用於加快GVA->GPA->HPA的地址轉換,主要包括:
- Linear mapping
- Linear translations,類似於TLB,用於直接將GVA表示頁表的部分(linear page number)直接轉換為虛擬機器實體記憶體頁框的基地址,即GPA的高位。
- Linear paging-structure-cache entries,類似於前面提到的Paging-Structure Cache,只是它針對的是GVA,可以跳過部分的地址轉換頁表的訪問,達到加速的效果。
- Guest-physical mapping
- Guest-physical translations,類似於TLB,用於直接將前面得到的GPA表示頁表的部分(guest-physical page number)直接轉換為主機實體記憶體頁框的基地址。
- Guest-physical paging-structure-cache entries,類似於之前提到的Paging-Structure Cache,只是它針對的是GPA,可以跳過部分的地址轉換頁表的訪問,達到加速的效果。
- Combined mapping
- Combined translations,類似於TLB,只是它的轉換幅度更大,直接從GVA的高位(linear page number)轉換為主機實體記憶體頁框的基地址,即HPA的高位。
- Combined paging-structure-cache entries,類似於之前提到的Paging Structure Cache,只是它針對的是GVA的高位,並且可以直接轉換到GPA->HPA的部分地址轉換頁表上,省去了中間GVA->GPA和部分GPA->HPA的轉換,達到了加速的效果。
從上面的分類可以看出,在虛擬化環境VMX操作模式中,地址轉換也是引入了TLB和Paging Structure Cache這兩種cache來加速地址轉換,只是因為在虛擬化環境中需要有兩次的地址轉換,所以有對這些地址轉換的cache進行了細分,軟體上維護的邏輯複雜度也跟著相應地增加,但是基本原來都是相同的。
3. VPID (Virtual Processor Identifiers)
由於在VMX虛擬化環境中,一個邏輯CPU可以執行來自不同虛擬機器的多個虛擬CPU,即vCPU,為了防止多個不同的vCPU之間,vCPU和邏輯CPU之間的地址轉換cache(TLB和Paging-Structure Cache)之間相互干擾,在每次進行VM Entry或者VM Exit操作的時候,都需要把這些地址轉換所用到的cache清掉,再重新載入目標CPU/vCPU的地址轉換cache。Cache的清除和重新載入是一個比較耗時的操作,會影響到CPU/vCPU的效能,特別是邏輯CPU一直在執行某個vCPU的時候,其實某些cache完全可以保留,不需要進行特殊的操作。
為了減少這些耗時的Cache清除和載入操作,VMX中引入了VPID(Virtual Processor Identifiers)機制,即在為每個地址轉換的Cache(TLB或者Paging-Structure Cache)打上一個VPID的標誌(VMM為每個vCPU分配一個唯一的VPID(位於VMCS中),邏輯CPU的VPID為0,其他vCPU的VPID大於0),這樣就不用擔心不同的vCPU/CPU所使用到的地址轉換Cache混到一起,CPU硬體在尋找Cache的時候,將會多進行一次比較,即將當前執行的vCPU/CPU的VPID和Cache中所包含的VPID進行匹配,只有相等才會使用該Cache條目。這樣在每次進行VM Entry或者VM Exit的時候就不需要將地址轉換的Cache清除掉,完全可以複用之前保留著的Cache,只在必要的時候進行地址轉換Cache的更新。
和之前非虛擬化環境下地址轉換加速機制進行一下對比會發現,VPID的機制和PCID(Process Context Identifiers)的機制類似,都是在不同的層級上對地址轉換的Cache進行保留,減少地址轉換Cache的清除和載入次數。VPID針對的是虛擬化環境下不同vCPU的層面,而PCID針對的是在作業系統下,不同程序的層面,兩者是可以同時起作用的。
總結
總的來說,對於x86 CPU而言,在虛擬化環境中,主要是通過引入EPT、地址轉換Cache和VPID的機制來對GVA->GPA->HPA的地址轉換進行加速。
歡迎關注同名微信公眾號“河馬虛擬化”第一時間獲取最新文章。