1、前言
ARM架構(gòu)虛擬化擴(kuò)展(Virtualization Extension)是在2010年作為ARMv7架構(gòu)的一部分引入的,它為虛擬化提供了架構(gòu)支持。在此之前,ARM系統(tǒng)上的虛擬化解決方案都是基于半虛擬化(paravirtualization)的,并沒(méi)有被廣泛使用。
不過(guò)隨著ARM CPU的性能不斷提高,并從智能手機(jī)和平板電腦等移動(dòng)設(shè)備向傳統(tǒng)服務(wù)器進(jìn)軍,人們對(duì)ARM虛擬化的興趣也在增長(zhǎng),因?yàn)閷?duì)ARM來(lái)說(shuō),支持虛擬化對(duì)它的生態(tài)建設(shè)起到很重要的作用。
于是,ARM虛擬化擴(kuò)展就出現(xiàn)了,它的核心設(shè)計(jì)目標(biāo)是構(gòu)建ARM hypervisor,且它可以運(yùn)行未經(jīng)修改的Guest OS,而不增加顯著的硬件復(fù)雜性,同時(shí)保持高水平的性能,而且也符合Popek和Goldberg的定理要求,關(guān)于這個(gè)定理,大家可以看下《一文讀懂虛擬化原理》文章。
2、CPU虛擬化
虛擬化擴(kuò)展側(cè)重于在虛擬化上下文中支持現(xiàn)有的ISA,因此ARM沒(méi)打算改變ISA單個(gè)指令語(yǔ)義,而不單獨(dú)處理架構(gòu)中限制虛擬化的指令。相反,虛擬化擴(kuò)展引入了一種新的更高特權(quán)處理器執(zhí)行的模式,這個(gè)模式在ARMv7架構(gòu)首次引入時(shí)稱為HYP(hypervisor)模式,在ARMv8架構(gòu)以及之后稱為EL2。
ARM架構(gòu)上的CPU模式如圖1所示,包括TrustZone(安全擴(kuò)展)。TrustZone將模式分為安全和非安全兩個(gè)世界,這兩個(gè)世界與CPU模式是正交的。而且在EL3也提供了一種特殊模式:Monitor mode(監(jiān)控器模式),用于在安全和非安全世界之間切換。如果實(shí)現(xiàn)了TrustZone,盡管ARM CPU在安全模式下啟動(dòng),但ARM的引導(dǎo)加載程序(bootloaders)通常在早期階段過(guò)渡到非安全世界。安全世界用于可信計(jì)算場(chǎng)景,如數(shù)字版權(quán)管理。不過(guò)需要注意的是,最新的ARM架構(gòu)已經(jīng)支持secure狀態(tài)下的EL2 Hypervisor了。
圖1 ARM處理器模式
不像以前的ARM架構(gòu)支持多種kernel模式,ARMv8只有一個(gè)kernel模式:EL1。圖1中為支持虛擬機(jī)擴(kuò)展而引入的名為EL2的新CPU特權(quán)級(jí)別(也成為異常級(jí)別,Exception Level, EL),它構(gòu)建于現(xiàn)有的user(EL0)和kernel(EL1)級(jí)別上,是虛擬化拓展的中心。EL2以trap-and-emulate機(jī)制來(lái)支持虛擬化,它是嚴(yán)格地比其它CPU模式(EL0和EL1)擁有更多特權(quán)的CPU模式。
為了支持虛擬機(jī)VM,運(yùn)行在EL2中的軟件可以配置捕獲(Trap)來(lái)自EL0或EL1的各種敏感指令和硬件中斷去EL2,這樣系統(tǒng)使用起來(lái)更靈活了。比如,不支持資源復(fù)用的分區(qū)hypervisor可能不會(huì)捕獲正常hypervisor會(huì)捕獲的某些指令。允許VM支持使用ARM調(diào)試寄存器而不是對(duì)它們進(jìn)行Trap在某些情況下是可取的。如果想要模擬與正在使用的CPU不同的CPU,則有必要捕獲對(duì)CPU標(biāo)識(shí)符寄存器的訪問(wèn),但沒(méi)有必要捕獲運(yùn)行完整hypervisor所需的其它訪問(wèn)。
為了允許VM與物理機(jī)相同的接口進(jìn)行交互,同時(shí)將它們與系統(tǒng)的其余部分隔離,并防止它們獲得對(duì)硬件的完全訪問(wèn)權(quán),hypervisor在切換到VM之前要使能EL2中的虛擬化特性。然后VM將在EL0和EL1中正常執(zhí)行,直到達(dá)到需要hypervisor干預(yù)的某些條件。此時(shí),硬件進(jìn)入EL2,將控制權(quán)交接給hypervisor,然后hypervisor可以管理硬件并提供跨VM所需的隔離。一旦系統(tǒng)hypervisor處理了該條件,CPU就可以切換回EL0和EL1,VM就可以恢復(fù)執(zhí)行了。當(dāng)在EL2中禁用所有虛擬化特性時(shí),在EL1和EL0中運(yùn)行的軟件就像在沒(méi)有虛擬化擴(kuò)展的系統(tǒng)上運(yùn)行一樣,在EL1中運(yùn)行的軟件具有對(duì)硬件的完全訪問(wèn)權(quán)限。
ARM架構(gòu)允許將每個(gè)Trap配置為直接路由給在EL1的VM,而不是EL2的hypervisor。例如,由EL0引起的系統(tǒng)調(diào)用或頁(yè)表錯(cuò)誤的Trap可以配置為直接路由到EL1,以便由Guest OS處理它們,而不需要hypervisor的干預(yù)。它避免在每次系統(tǒng)調(diào)用或頁(yè)表錯(cuò)誤時(shí)轉(zhuǎn)到EL2,從而減少了虛擬化開(kāi)銷。此外,所有進(jìn)入EL2的Trap都可以被禁用,單個(gè)非虛擬化kernel可以在EL1中運(yùn)行并完全控制系統(tǒng)。與EL1相比,EL2中可用的控制寄存器數(shù)量減少了。例如,EL2只有一個(gè)頁(yè)表基寄存器,而EL1可以使用兩個(gè)。可以說(shuō),通過(guò)減少EL2中可用的控制寄存器的數(shù)量,因此也相應(yīng)減少需要操作的狀態(tài)數(shù)量,這樣可以簡(jiǎn)化hypervisor的實(shí)現(xiàn)。
ARM的Virtualization Extensions提供了以下特性:
處理器在任何時(shí)間點(diǎn)都只能處于一種CPU模式,即EL0,EL1或EL2。從一種模式到另一種模式的實(shí)際轉(zhuǎn)換是原子的,但是從一種模式到另一種模式時(shí)根據(jù)需要保存和恢復(fù)狀態(tài)的過(guò)程不是原子的。
CPU模式可以通過(guò)執(zhí)行MRS指令來(lái)確定,MRS指令在任何模式下都可用。最開(kāi)始的期望是無(wú)論有沒(méi)有虛擬機(jī),應(yīng)用程序和操作系統(tǒng)仍然使用相同的CPU模式運(yùn)行。但在這種假設(shè)下,EL2執(zhí)行本身不能被虛擬化,并且不支持遞歸虛擬機(jī),因?yàn)榍短椎膆ypervisor可以確定它不是運(yùn)行在EL2。
EL2被設(shè)計(jì)用于虛擬化,但它只是一種更有特權(quán)的CPU模式,也可以用于其它目的。
每種模式由不同的頁(yè)表定義,都有自己完整線性地址空間。EL2有自己的translation regime,它定義了給定模式中使用的寄存器和頁(yè)表格式。然而,EL1/EL0共享一個(gè)translation regime,因此它們的地址空間和頁(yè)表都可以在EL1和EL0中訪問(wèn)。因?yàn)槊總€(gè)TLB 條目都會(huì)被標(biāo)記上translation regime,因此只有在當(dāng)前活躍地址空間的translation regime匹配上TLB條目的標(biāo)記,才能算作命中了。由于TLB條目標(biāo)記,因此在EL2和其它CPU模式之間轉(zhuǎn)換時(shí)不需要刷新TLB內(nèi)容。
ARM有兩種類型的中斷:正常中斷(IRQ)和快速中斷(FIQ),以及對(duì)應(yīng)處理器當(dāng)前模式的兩個(gè)中斷標(biāo)志。EL1中的軟件可以自由操作每種中斷類型的中斷標(biāo)記而不會(huì)引發(fā)Trap。EL2可以配置每個(gè)中斷類型要么直接傳遞到EL1,要么Trap到EL2。當(dāng)中斷直接傳遞給EL1時(shí),由EL1直接配置的中斷標(biāo)志控制真正的物理中斷。當(dāng)中斷Trap到EL2時(shí),由EL1直接配置的中斷標(biāo)志控制虛擬中斷。
3、內(nèi)存虛擬化
HAPPY NEW YEAR
ARM引入了一組額外的頁(yè)表來(lái)將Guest physical address轉(zhuǎn)換成Host physical address,并將此作為虛擬化支持的一部分。在運(yùn)行VM時(shí),使用ARM的硬件支持使用虛擬化物理內(nèi)存,由VM管理的物理地址實(shí)際上是中間物理地址(Intermediate Physical Addresses, IPAs),也稱為來(lái)賓物理地址(Guest physical addresses, gPAs),需要轉(zhuǎn)換為主機(jī)物理地址(host physical addresses, hPAs)。因此,ARM提供了第二組頁(yè)表,stage-2 tables,用于將guest物理地址(gPAs)和host物理地址(hPAs)。EL2可以完全禁用或啟動(dòng)Stage-2轉(zhuǎn)換。Stage-2頁(yè)表使用ARM新的LPAE(Large Physical Address Extension)頁(yè)表格式,與kernel模式使用的頁(yè)表有細(xì)微的區(qū)別。
圖2為ARM中完整的地址轉(zhuǎn)換機(jī)制。在stage-1階段,從virtual physical address到guest physical address轉(zhuǎn)換使用了三層頁(yè)表;在stage-2階段,從guest physical address到host physical address的轉(zhuǎn)換使用了四層頁(yè)表??梢允褂肏CR(Hyp Configuration Register)中的一個(gè)域段來(lái)啟用或禁用stage-2轉(zhuǎn)換。Stage-2第一層次(L1)頁(yè)表的基寄存器由Virtualization Translation Table Base Register(VTTBR)指定的,這兩個(gè)寄存器只能從EL2配置。
圖2 ARM上使用LPAE內(nèi)存長(zhǎng)格式描述符的stage-1核stage-2頁(yè)表遍歷過(guò)程。虛擬地址(VA)首先轉(zhuǎn)換為guest PA,最后轉(zhuǎn)換為host PA。
4、中斷虛擬化
HAPPY NEW YEAR
ARM定義了通用中斷控制器(Generic Interrupt Controller, GIC)架構(gòu)。GIC分配從設(shè)備到CPU的中斷,CPU查詢GIC來(lái)發(fā)現(xiàn)中斷的來(lái)源。在多核配置中,GIC尤其重要,因?yàn)樗糜谏商幚砥鏖g從一個(gè)CPU內(nèi)核到另一個(gè)CPU內(nèi)核的中斷(Inter-Processor Interrupts, IPIs)。GIC分為兩部分:distributor(分發(fā)器)和CPU interfaces(CPU接口)。系統(tǒng)中只有一個(gè)distributor,但每個(gè)CPU核心都有一個(gè)GIC CPU interface。CPU interface和distributor都通過(guò)Memory-Mapped interface(MMIO)訪問(wèn)GIC。Distributor用于配置GIC,例如,設(shè)置中斷的CPU core affinity、完全啟用或禁用系統(tǒng)上的中斷、或?qū)PI發(fā)送到另一個(gè)CPU核心。CPU interface用于確認(rèn)(ACK)和發(fā)送中斷結(jié)束(End-of-Interrupt, EOI)信號(hào)。例如,當(dāng)一個(gè)CPU內(nèi)核接收到一個(gè)中斷時(shí),它將在GIC CPU接口上讀取一個(gè)特殊寄存器,該寄存器對(duì)中斷進(jìn)行ACK處理并返回中斷的編號(hào)。在CPU將從ACK寄存器中檢索到的值寫(xiě)入CPU接口的EOI寄存器之前,將不會(huì)再次向CPU發(fā)出中斷。
可以將中斷配置為Trap到EL2或EL1。將所有中斷Trap到EL1并讓運(yùn)行在EL1中的操作系統(tǒng)軟件直接處理它們是有效地,但在虛擬機(jī)環(huán)境中不起作用,因?yàn)閔ypervisor失去了對(duì)硬件的控制。將所有中斷Trao到EL2可確保hypervisor保留控制權(quán),但需要在軟件中模擬虛擬中斷以向VM發(fā)送信號(hào)事件。由于中斷和虛擬中斷處理的每個(gè)步驟(如ACK和EOI)都必須經(jīng)過(guò)hypervisor,因此管理起來(lái)很麻煩,而且成本很高。
GIC以虛擬GIC(vGIC)的形式提供硬件虛擬化支持,因此不需要在軟件中由hypervisor模擬接收虛擬中斷。vGIC為每個(gè)CPU引入了一個(gè)vGIC CPU接口以及相應(yīng)的hypervisor控制接口。虛擬機(jī)被配置為vGIC CPU接口,而不是GIC CPU接口。在vGIC hypervisor控制接口上,虛擬中斷是通過(guò)寫(xiě)入特殊寄存器(list registers)來(lái)生成。vGIC CPU接口將虛擬中斷直接送到VM的kernel模式。因?yàn)関GIC CPU接口支持ACK和EOI,這些操作不再需要Trap到hypervisor去用軟件模擬了,從而減少了在CPU上接收中斷的開(kāi)銷。例如,模擬的虛擬設(shè)備通常通過(guò)軟件API向hypervisor發(fā)起虛擬中斷,hypervisor可以通過(guò)將模擬設(shè)備的虛擬中斷號(hào)寫(xiě)入list registers來(lái)利用vGIC。它使vGIC直接將虛擬機(jī)中斷送到kernel模式,并允許Guest OS的ACK和EOI虛擬中斷,而不會(huì)Trap到hypervisor。請(qǐng)注意,distributor仍然需要在軟件中模擬,并且VM對(duì)distributor的所有訪問(wèn)必須Trap到hypervisor。例如,當(dāng)一個(gè)虛擬CPU向另一個(gè)虛擬CPU發(fā)送一個(gè)虛擬IPI時(shí),這個(gè)將Trap到hypervisor,hypervisor在軟件中模擬分發(fā)器的訪問(wèn),并在接收CPU的GIC hypervisor控制接口上編程list registers。
5、計(jì)時(shí)器虛擬化
HAPPY NEW YEAR
ARM定義了通用計(jì)時(shí)器架構(gòu)(Generic Timer Architecture),其中包括對(duì)計(jì)時(shí)器虛擬化的支持。通用計(jì)時(shí)器提供一個(gè)計(jì)數(shù)器來(lái)實(shí)時(shí)測(cè)量時(shí)間的流逝,并為每個(gè)CPU提供一個(gè)計(jì)時(shí)器,它被編程為在一定時(shí)間后向CPU發(fā)起中斷。Hypervisor和Guest OS都可能使用計(jì)時(shí)器,但是為了提供隔離和保持控制,Guest OS不能直接配置和操作hypervisor使用的計(jì)時(shí)器。來(lái)自Guest OS的這種計(jì)時(shí)器訪問(wèn)需要Trap到EL2,對(duì)于某些工作負(fù)載來(lái)說(shuō),相對(duì)頻繁的操作會(huì)帶來(lái)額外的開(kāi)銷。Hypervisor也可能希望虛擬化VM時(shí)間,因?yàn)閂M可以直接訪問(wèn)計(jì)數(shù)器硬件,那就不符合虛擬化要求了。
ARM通過(guò)引入一個(gè)新的計(jì)數(shù)器(虛擬計(jì)數(shù)器)和一個(gè)新的計(jì)時(shí)器(虛擬計(jì)時(shí)器),為計(jì)時(shí)器提供虛擬化支持。可以將hypervisor配置為使用物理計(jì)時(shí)器,而將虛擬機(jī)配置為使用虛擬計(jì)時(shí)器。然后,虛擬機(jī)可以訪問(wèn)、編程和取消虛擬計(jì)時(shí)器,而不會(huì)對(duì)EL2產(chǎn)生Trap。Kernel模式訪問(wèn)物理計(jì)時(shí)器和計(jì)數(shù)器是由EL2控制的,但是在kernel模式下運(yùn)行的軟件總是可以訪問(wèn)虛擬計(jì)時(shí)器和虛擬計(jì)數(shù)器。此外,EL2配置一個(gè)偏移寄存器,它從物理計(jì)數(shù)器中減去,并在讀取虛擬計(jì)數(shù)器時(shí)作為返回值。請(qǐng)注意,在使用通用計(jì)時(shí)器之前,讀取計(jì)數(shù)器時(shí)內(nèi)存映射操作,因此頻繁操作讀取的話,通常會(huì)Trap到EL2并產(chǎn)生額外的開(kāi)銷。