時間:2020-08-31來源:www.farandoo.com作者:電腦系統城
Read the fucking source code!
--By 魯迅A picture is worth a thousand words.
--By 高爾基說明:
Hypervisor
軟件,涵蓋的功能包括:內存管理、設備模擬、設備分配、異常處理、指令捕獲、虛擬異常管理、中斷控制器管理、調度、上下文切換、內存轉換、多個虛擬地址空間管理等;arch/arm64/kvm
下的代碼很重要,脫離硬件去看Architecture-Specific代碼,那是耍流氓;開始旅程!
USR, FIQ, IRQ, SVC, ABT, UND, SYS, HYP, MON
等,各個異常模式所處的特權級不一樣,比如USR
模式的特權級就為PL0
,對應為用戶態程序運行;CPSR
寄存器,也可以被動進行異常模式切換,典型的比如中斷來臨時切換到IRQ模式
;ARMv7處理器的異常模式如下表所示:
然鵝,到了ARMv8,Exception Level(EL)
取代了特權級,其中處理器的異常模式與Exception Level
的映射關系如下圖:
Exception Level
(相當于ARMv7中的處理器模式切換),來處理異常類型;Hypervisor
運行在EL2
,而Guest OS
運行在EL1
,可以通過HVC (Hypervisor Call)
指令向Hypervisor
請求服務,響應虛擬化請求時就涉及到了Exception Level
的切換;Stage 2轉換
與內存虛擬化息息相關,這部分內容不僅包括常規的內存映射訪問,還包含了基于內存映射的I/O(MMIO
)訪問,以及系統內存管理單元(SMMUs
)控制下的內存訪問。
OS在訪問物理內存前,需要先建立頁表來維護虛擬地址到物理地址的映射關系,看過之前內存管理分析的同學應該熟悉下邊這張圖,這個可以認為是Stage 1轉換
:
Guest OS
所認為自己訪問的物理地址,其實是Linux的用戶進程虛擬地址,到最終的物理地址還需要進一步的映射;Hypervisor
可以通過Stage 2轉換
來控制虛擬機的內存視圖,控制虛擬機是否可以訪問某塊物理內存,進而達到隔離的目的;整個地址的映射分成了兩個階段:
Stage 1: VA(Virutal Address) -> IPA(Intermediate Physical Address)
,操作系統控制Stage 1轉換
;Stage 2: IPA(Intermediate Physical Address) -> PA(Physical Address)
,Hypervisor
控制Stage 2轉換
;Stage 2轉換
與Stage 1
轉換機制很類似,不同點在于Stage 2轉換
時判斷內存類型是normal還是device時,是存放進頁表信息里了,而不是通過MAIR_ELx
寄存器來判斷;
每個虛擬機(VM,Virtual Machine)都會分配一個VMID
,用于標識TLB entry
所屬的VM,允許在TLB中同時存在多個不同VM的轉換;
操作系統會給應用程序分配一個ASID(Address Space Identifier)
,也可以用于標識TLB entry
,屬于同一個應用程序的TLB entry
都有相同的ASID
,不同的應用程序可以共享同一塊TLB緩存
。每個VM都有自己的ASID
空間,通常會結合VMID
和ASID
來同時使用;
Stage 1
和Stage 2
的轉換頁表中,都包含了屬性的相關設備,比如訪問權限,存儲類型等,在兩級轉換的過程中,MMU
會整合成一個最終的也有效值,選擇限制更嚴格的屬性,如下圖:
Device
屬性限制更嚴格,則選擇Device
類型;Hypervisor
如果想要改變默認整合行為,可以通過寄存器HCR_EL2(Hypervisor Configuration Register)
來配置,比如設置Non-cacheable
, Write-Back Cacheable
等特性;MMIO(Memory-Mapped Input/Output)
Guest OS
認為的物理地址空間,實際是IPA
地址空間,就像真實物理機中一樣,IPA
的地址空間,也分成內存地址空間和I/O
地址空間:
fault
,Hypervisor
通過軟件來模擬;VTTBR_EL2
:Virtualization Translation Table Base Register
,虛擬轉換表基地址寄存器,存放Stage 2轉換
的頁表;Hypervisor
需要知道訪問的是哪個外設以及訪問的寄存器,讀訪問還是寫訪問,訪問長度是多少,使用哪些寄存器來傳送數據等。Stage 2轉換
有一個專門的Hypervisor IPA Fault Address Register, EL2(HPFAR_EL2)
寄存器,用于捕獲Stage 2轉換
過程中的fault;軟件模擬外設的示例流程如下:
Stage 2轉換
被block住,并觸發abort異常路由到EL2
。異常處理程序查詢ESR_EL2(Exception Syndrome Register)
寄存器關于異常的信息,如訪問長度、目標寄存器,Load/Store操作等,異常處理程序還會查詢HPFAR_EL2
寄存器,獲取abort的IPA地址;Hypervisor
通過ESR_EL2
和HPFAR_EL2
里的相關信息對相關虛擬外圍設備進行模擬,完成后通過ERET
指令返回給vCPU
,從發生異常的下一條指令繼續運行;SMMUs(System Memory Management Units)
訪問內存的另外一種case就是DMA控制器。
非虛擬化下DMA控制器的工作情況如下:
虛擬化下DMA控制器,VM中的驅動直接與DMA控制器交互會出現什么問題呢?如下圖:
Stage 2轉換
的約束,會破壞VM的隔離性;SMMUs
可以用于解決這個問題:
SMMU
也叫IOMMU
,對IO部件提供MMU功能,虛擬化只是SMMU的一個應用;Hypervisor
可以負責對SMMU
進行編程,以便讓上層的控制器和虛擬機VM以同一個視角對待內存,同時也保持了隔離性;Hypervisor
也需要具備捕獲(trap
)和模擬指令的能力,比如當VM中的軟件需要配置底層處理器來進行功耗管理或者緩存一致性操作時,為了不破壞隔離性,Hypervisor
就需要捕獲操作并進行模擬,以便不影響其他的VM。如果設置了捕獲某個操作時,當該操作被執行時會向更高一級的Exception Level
觸發異常(比如Hypervisor
為EL2),從而在相應的異常處理中完成模擬。
例子來了:
WFI(wait for interrupt)
命令,可以讓CPU處于一個低功耗的狀態;HCR_EL2(Hypervisor Control Register)
,當該寄存器的TWI==1
時,vCPU執行WFI
指令會觸發EL2異常,從而Hypervisor
可以對其進行模擬,將任務調度到另外一個vCPU即可;捕獲(traps
)的另一個作用是可以用于向Guest OS呈現寄存器的虛擬值,如下:
ID_AA64MMFR0_EL1
寄存器用于查詢處理器對內存系統相關特性的支持,系統可能在啟動階段會讀取該寄存器,Hypervisor
可以向Guest OS呈現一個不同的虛擬值;Hypervisor
在trap_handler
中進行處理,設置一個虛擬值,并最終返回給vCPU;trap
來虛擬化一個操作需要大量的計算,包括觸發異常、捕獲,模擬、返回等一系列操作,像ID_AA64MMFR0_EL1
寄存器訪問并不頻繁,這種方式問題不大。但是當需要頻繁訪問的寄存器,比如MIDR_EL1
和MPIDR_EL1
等,出于性能的考慮,應該避免陷入到Hypervisor
中進行模擬處理,可以通過其他機制,比如提供VPIDR_EL2
和VMIDR_EL2
寄存器,在進入VM前就設置好該值,當讀取MIDR_EL1
和MPIDR_EL1
時,硬件就返回VPIDR_EL2
和VMIDR_EL2
的值,避免了陷入處理;Hypervisor
對虛擬中斷的處理比較復雜,Hypervisor
本身需要機制來在EL2處理中斷,還需要機制來將外設的中斷信號發送到目標虛擬機VM(或vCPU)上,為了使能這些機制,ARM體系架構包含了對虛擬中斷的支持(vIRQs,vFIQs,vSErrors);Hypervisor
通過設置HCR_EL2
寄存器來控制向EL0/EL1發送虛擬中斷,比如為了使能vIRQ,需要設置HCR_EL2.IMO
,設置后便會將物理中斷發送至EL2,然后使能將虛擬中斷發送至EL1;有兩種方式可以產生虛擬中斷:1)在處理器內部控制HCR_EL2
寄存器;2)通過GIC中斷控制器(v2版本以上);其中方式一使用比較簡單,但是它只提供了產生中斷的方式,需要Hypervisor
來模擬VM中的中斷控制器,通過捕獲然后模擬的方式,會帶來overhead,當然不是一個最優解。
讓我們來看看GIC
吧,看過之前中斷子系統系列文章的同學,應該見過下圖:
Hypervisor
可以將GIC中的Virtual CPU Interface
映射到VM中,從而允許VM中的軟件直接與GIC進行通信,Hypervisor
只需要進行配置即可,這樣可以減少虛擬中斷的overhead;來個虛擬中斷的例子吧:
IRQ
或者FIQ
信號,如果設置了HCR_EL2.IMO/FMO
,中斷信號將被路由到Hypervisor
,Hypervisor
會檢查中斷信號轉發給哪個vCPU
;Hypervisor
設置GIC,將該物理中斷信號以虛擬中斷的形式發送給某個vCPU
,如果此時處理器運行在EL2,中斷信號會被忽略;Hypervisor
將控制權返回給vCPU
;PSTATE
中的比特位來控制(比如PSTATE.I
),虛擬化時比特位的作用有些不一樣,比如設置HCR_EL2.IMO
時,表明物理IRQ路由到EL2,并且對EL0/EL1開啟vIRQs
,因此,當運行在EL0/EL1時,PSTATE.I
比特位針對的是虛擬vIRQs
而不是物理的pIRQs
。先來看一下SoC的內部:
簡化之后是這樣的:
Comparators
和Counter Module
,當Comparators
的值小于等于系統的count值時便會產生中斷,我們都知道在操作系統中timer
的中斷就是系統的脈搏了;下圖展示虛擬化系統中運行的vCPU
的時序:
vCPU
運行2ms,如果設置vCPU0
在T=0
之后的3ms后產生中斷,那希望是物理時間的3ms后(也就是vCPU0
的虛擬時間2ms)產生中斷,還是虛擬時間3ms后產生中斷?ARM體系結構支持這兩種設置;vCPU
上的軟件可以同時訪問兩種時鐘:EL1物理時鐘
和EL1虛擬時鐘
;EL1物理時鐘
和EL1虛擬時鐘
:
EL1物理時鐘
與系統計數器模塊直接比較,使用的是wall-clock
時間;EL1虛擬時鐘
與虛擬計數器比較,而虛擬計數器是在物理計數器上減去一個偏移;Hypervisor
負責為當前調度運行的vCPU
指定對應的偏移,這種方式使得虛擬時間只會覆蓋vCPU
實際運行的那部分時間;來一張示例圖:
vCPU
運行3ms,Hypervisor
可以使用偏移寄存器來將vCPU
的時間調整為其實際的運行時間;Host OS
的內核都運行在EL1,而控制虛擬化的代碼運行在EL2,這就意味著傳統的上下文切換,這個顯然是比較低效的;VHE
用于支持type-2
的Hypervisor
,這種擴展可以讓內核直接跑在EL2,減少host和guest之間共享的系統寄存器數量,同時也減少虛擬化的overhead;VHE
由系統寄存器HCR_EL2
的E2H
和TGE
兩個比特位來控制,如下圖:
VHE
的引入,需要考慮虛擬地址空間的問題,如下圖:
EL0
)和內核地址空間(EL1
),兩者的區域不一致,而在EL2
只有一個虛擬地址空間區域,這是因為Hypervisor
不支持應用程序,因此也就不需要分成內核空間和用戶空間了;EL0/EL1
虛擬地址空間也同時支持ASID(Address Space Identifiers)
,而EL2
不支持,原因也是Hypervisor
不需要支持應用程序;從上兩點可以看出,為了支持Host OS
能運行在EL2
,需要添加一個地址空間區域,以及支持ASID
,設置HCR_EL2.E2H
的寄存器位可以解決這個問題,如下圖:
Host OS
運行在EL2
需要解決的另一個問題就是寄存器訪問重定向,在內核中需要訪問EL1
的寄存器,比如TTBR0_EL1
,而當內核運行在EL2
時,不需要修改內核代碼,可以通過寄存器的設置來控制訪問流,如下圖:
Hypervisor
在某些情況下需要訪問真正的EL1
寄存器,ARM架構引入了一套新的別名機制,以_EL12/_EL02
結尾,如下圖,可以在ECH==1
的EL2
訪問TTBR0_EL1
:Host OS
運行在EL2
還需要考慮異常處理的問題,前邊提到過HCR_EL2.IMO/FMO/AMO
的比特位可以用來控制物理異常路由到EL1/EL2
。當運行在EL0
且TGE==1
時,所有物理異常都會被路由到EL2
(除了SCR_EL3控制的),這是因為Host Apps
運行在EL0
,而Host OS
運行在EL2
。
trap and emulation
等內容;EL2
去處理,如果有硬件支持的則硬件負責處理,否則可以通過軟件進行模擬;《ArmV8-A virtualization.pdf》
《vm-support-ARM-may6-2019.pdf》
《aarch64_virtualization_100942_0100_en.pdf》
《ARM Cortex-A Series Programmer's Guide for ARMv8-A》
2022-04-13
蘋果系統安裝雙系統圖文教程 蘋果系統怎么裝雙系統 ?2022-04-13
遠程登錄Linux CentOS系統方法 怎么遠程登錄Linux CentOS系統?2022-03-21
CentOS7安裝MYSQL8.X的詳解教程很多網友對于linux系統比較陌生,更別說linux系統安裝了。有使用筆記本電腦的網友需要用到linux系統,不過卻不知道怎么安裝,所以下面小編要來跟大家說說linux操作系統安裝步驟詳細,大家一起來看看吧。...
2022-03-07
RedFlag紅旗Linux系統怎么安裝?電腦想要安裝雙系統,該怎么安裝RedFlag紅旗系統呢?下面我們就來看看紅旗Red Flag安裝全程圖解,詳細請看下文介紹...
2022-01-23