很久沒(méi)寫(xiě)了疆拘,很多人非常關(guān)心虛擬化和硬件隔離寝并,其實(shí)這兩個(gè)概念很容易混淆箫措,大部分人也分不清,這篇主要是把之前自己寫(xiě)的各種筆記整理匯總了一下衬潦,幫大家梳理一個(gè)清晰的脈絡(luò)斤蔓,提綱如下:
- 1.計(jì)算單元三種構(gòu)型
- 2.硬件隔離(適用于多核MCU)
- 3.軟件虛擬化Hypervisor(適用于多核MPU)
- 4.Hypervisor的技術(shù)原理
- 4.1處理器特權(quán)模式
- 4.2處理器編程模型
- 4.3系統(tǒng)調(diào)用
- 4.4內(nèi)存虛擬化
- 4.5設(shè)備虛擬化
- 5.車載場(chǎng)景下方案實(shí)現(xiàn)
- 5.1 多核MCU硬件隔離
- 5.2 多核MPU虛擬化
其中第4節(jié)里面涉及比較多的技術(shù)細(xì)節(jié)與代碼,對(duì)非軟件領(lǐng)域的人不太友好镀岛,可以跳過(guò)弦牡。
1.計(jì)算單元三種構(gòu)型
之前的文章中,為大家介紹過(guò)計(jì)算單元的三種構(gòu)建方式漂羊,雖然集中式的計(jì)算機(jī)是一個(gè)趨勢(shì)驾锰,但并不是所有任務(wù)都適合放在中央計(jì)算機(jī)上運(yùn)行,在進(jìn)行多個(gè)ECU合并的過(guò)程中走越,原來(lái)ECU的硬件會(huì)合并為少數(shù)幾個(gè)XCU椭豫,硬件隔離與軟件虛擬化,是保證相互之間功能不相互干擾的重要技術(shù)手段旨指。
分離式是指赏酥,將多個(gè)不同的芯片集成到一個(gè)計(jì)算單元上去,每個(gè)運(yùn)行不同的操作系統(tǒng)谆构,只是在形態(tài)上集中到了一起今缚,各單元依然獨(dú)立的完成各自任務(wù),代表如特斯拉AP低淡,奧迪zFAS等。
硬件隔離式是指瞬项,在統(tǒng)一的計(jì)算平臺(tái)上采用虛擬化方案蔗蹋,同時(shí)運(yùn)行多個(gè)操作系統(tǒng),但是各個(gè)系統(tǒng)依然在硬件上進(jìn)行隔離囱淋,每個(gè)系統(tǒng)都有自己的專屬硬件資源猪杭。
軟件虛擬式是指,在統(tǒng)一的計(jì)算平臺(tái)上采用虛擬化方案妥衣,同時(shí)運(yùn)行多個(gè)操作系統(tǒng)皂吮,每個(gè)操作系統(tǒng)所使用的硬件資源,由Hypervisor層動(dòng)態(tài)調(diào)配税手,每個(gè)系統(tǒng)并沒(méi)有專屬的硬件資源蜂筹。
分離式最大的好處就是功能邊界清晰,相比于傳統(tǒng)的獨(dú)立的BOX芦倒,只需要在電路設(shè)計(jì)上艺挪,把每個(gè)芯片放在不同的PCB板,然后將多塊PCB疊加在一起兵扬。壞處就是麻裳,硬件資源浪費(fèi)口蝠,每個(gè)芯片都需要一個(gè)最小系統(tǒng),并且硬件上還沒(méi)法拓展津坑。
硬件隔離式和軟件虛擬式妙蔗,都采用了虛擬化方案,唯一不同點(diǎn)在于硬件資源是否專屬疆瑰,如果是專屬的眉反,就意味著資源無(wú)法動(dòng)態(tài)調(diào)配,容易產(chǎn)生資源浪費(fèi)乃摹。 虛擬化方案最大的好處是禁漓,硬件上的可拓展性,如果中央計(jì)算單元采用刀片式的設(shè)計(jì)結(jié)構(gòu)孵睬,可以很方便的拓展計(jì)算單元的算力播歼,而不用替換整個(gè)計(jì)算單元。
2.硬件隔離
Hypervisor大家聽(tīng)到的比較多了掰读,一般用在多核MPU上進(jìn)行OS的虛擬化秘狞,很多軟件廠商也在做多核MCU上的Hypervisor方案,但嚴(yán)格意義上講蹈集,這類方案稱為“Hypervisor”并不準(zhǔn)確烁试。所謂的多核MCU上的“虛擬化方案”,其實(shí)就是采用了AMP的架構(gòu)拢肆,核心工作就是劃分內(nèi)存减响、配置CPU運(yùn)行模式等工作。
目前支持多核處理器的體系結(jié)構(gòu)有對(duì)稱多處理SMP(Symmetric Multi-Processing)構(gòu)架和非對(duì)稱多處理AMP(Asymmetric Multi-Processing)構(gòu)架兩種郭怪。
AMP模式支示,各個(gè)CPU上運(yùn)行不同的操作系統(tǒng)實(shí)例,各個(gè)操作系統(tǒng)擁有自己專用的內(nèi)存鄙才,相互之間通過(guò)訪問(wèn)受限的共享內(nèi)存進(jìn)行通信颂鸿。
SMP模式,系統(tǒng)中所有CPU的地位相同攒庵,共同運(yùn)行一個(gè)操作系統(tǒng)實(shí)例嘴纺,所有CPU共享系統(tǒng)內(nèi)存和外設(shè)資源。
在傳統(tǒng)的汽車電子ECU當(dāng)中浓冒,絕大部分使用的計(jì)算單元都稱為“MCU”栽渴,和另外一個(gè)大家經(jīng)常聽(tīng)到“MPU”有很大區(qū)別,估計(jì)很多人也有一些疑問(wèn)吧稳懒,究竟MCU和MPU有什么區(qū)別熔萧?其實(shí)這個(gè)兩個(gè)詞的邊界正越來(lái)越模糊,高性能的MCU與MPU之間的差異也越來(lái)越小,其中一個(gè)比較重要的差異就是佛致,MCU片上只有內(nèi)存保護(hù)單元贮缕,而MPU通常都有MMU( 最新的Cortex-R82也支持MMU)。
多核MCU上只有內(nèi)存保護(hù)單元而沒(méi)有MMU俺榆,是無(wú)法做到真正意義上的虛擬化的感昼,而基于AMP架構(gòu),運(yùn)行多個(gè)操作系統(tǒng)罐脊,本質(zhì)上和采用多個(gè)單核的MCU沒(méi)有太大差異定嗓,所以稱為“硬件隔離”更加準(zhǔn)確。在追求可靠性萍桌、確定性宵溅、低延時(shí)的MCU應(yīng)用場(chǎng)景中,硬件隔離是一種更好的選擇上炎,對(duì)純軟件的虛擬化方案需求并不是很高恃逻。
3.軟件虛擬化Hypervisor
Hypervisor通常被分成Type1與Type2,Type1類型的Hypervisor直接運(yùn)行在硬件之上藕施,Hypervisor需要自己管理所有硬件資源寇损;Type2類型的Hypervisor運(yùn)行在某個(gè)Host系統(tǒng)之上,利用Host系統(tǒng)對(duì)硬件資源進(jìn)行訪問(wèn)裳食。大家在PC上使用的Virtual Box和VMware虛擬機(jī)矛市,就屬于Type2的類型。
全虛擬化時(shí)诲祸,Hypervisor完整模擬了所有硬件資源浊吏,Guest OS不知道正在被虛擬化,它也不需要任何修改就能運(yùn)行救氯,Hypervisor負(fù)責(zé)捕獲并處理所有特權(quán)指令卿捎,如果Guest OS使用的指令集架構(gòu)與物理設(shè)備的相同(例如都是ARM64),那么用戶級(jí)別的指令可以直接在物理設(shè)備上運(yùn)行径密。
在某些場(chǎng)景下,要完全模擬一個(gè)真實(shí)的物理設(shè)備是非常慢的躺孝,因?yàn)樗袑?duì)模擬寄存器的訪問(wèn)都會(huì)產(chǎn)生一個(gè)軟中斷享扔,之后系統(tǒng)需要切換處理器特權(quán)模式,陷入到Hypervisor當(dāng)中進(jìn)行模擬植袍,這樣會(huì)帶來(lái)很多額外的性能開(kāi)銷惧眠。
為了解決這個(gè)問(wèn)題,部分外圍設(shè)備會(huì)采用半虛擬化于个,半虛擬化方式需要修改Guest OS氛魁,使之意識(shí)到自身運(yùn)行在虛擬機(jī)當(dāng)中,通過(guò)Guest OS當(dāng)中的前端驅(qū)動(dòng),與Hypervisor中的后端驅(qū)動(dòng)進(jìn)行直接通信秀存,以此來(lái)?yè)Q取更好得I/O性能捶码,virtio就是一種半虛擬化的方案。
4. Hypervisor的技術(shù)原理
下面將以ARMv8-A架構(gòu)為例介紹一下Hypervisor的實(shí)現(xiàn)原理或链。
4.1處理器特權(quán)模式
幾乎所有的操作系統(tǒng)惫恼、虛擬化方案都是建立在處理器特權(quán)模式的基礎(chǔ)之上的,ARMv8定義了4種特權(quán)級(jí)別:
- EL0:Application
- EL1:OS Kernel
- EL2:Hypervisor
- EL3:Secure Monitor
從EL0-EL3澳盐,特權(quán)級(jí)別依次升高祈纯,應(yīng)用軟件發(fā)起的系統(tǒng)調(diào)用(ARM上是svc,x86上是int)叼耙,或者產(chǎn)生了外部中斷腕窥,會(huì)導(dǎo)致特權(quán)級(jí)別的變更。
從上面這張圖當(dāng)中可以看出筛婉,Application簇爆、OS、Hypervisor 等倾贰,分別運(yùn)行在不同的特權(quán)級(jí)別上冕碟,應(yīng)用程序可以通過(guò)系統(tǒng)調(diào)用陷入到OS或者Hypervisor當(dāng)中,以執(zhí)行不同的特權(quán)指令匆浙。
4.2 處理器編程模型
如果不理解處理器的編程模型安寺,接下里很多概念將無(wú)法理解,所以先簡(jiǎn)短介紹一下首尼,以下以ARMv8 AArch64為例挑庶,解釋了處理器的運(yùn)行過(guò)程。
.section ".text.boot"
.globl _start
.org 0x80000 //制定內(nèi)核入口地址
_start:
ldr x5, =_start // 建立堆棧
mov sp, x5
ldr x5, =__bss_start // 清BSS
ldr w6, =__bss_size
3: cbz w6, 4f
str xzr, [x5], #8
sub w6, w6, #1
cbnz w6, 3b
4: bl kernel_main //跳轉(zhuǎn)到C代碼
b 1b
void kernel_main()
{
init_uart(); //初始化設(shè)備
init_vmm(); //初始化內(nèi)存软能、mmu迎捺、Pagetable
init_irqs(); //初始化中斷向量表
init_timer(); //初始化時(shí)鐘
struct guestVM_s *guest = createVM(0x48000000, 0x20000000); //創(chuàng)建guest實(shí)例
enable_IRQS(); //開(kāi)中斷
schedule(guest);//調(diào)度guest os執(zhí)行
}
沒(méi)有做過(guò)系統(tǒng)軟件或者嵌入式軟件的人,會(huì)覺(jué)得處理器的啟動(dòng)是個(gè)特別復(fù)雜的過(guò)程查排,其實(shí)從軟件角度來(lái)看凳枝,一點(diǎn)也不復(fù)雜,一個(gè)裸機(jī)硬件跋核,只要經(jīng)過(guò)以下步驟就能運(yùn)行起來(lái):
- 通過(guò)匯編初始化CPU岖瑰,建立堆棧。
- 跳轉(zhuǎn)執(zhí)行C函數(shù)砂代。
看不懂匯編沒(méi)關(guān)系蹋订,只要知道,要對(duì)裸機(jī)進(jìn)行編程刻伊,只需要一段匯編建立C語(yǔ)言運(yùn)行必要的堆棧露戒,剩下的就可以全用C解決了椒功,在用C寫(xiě)的kernel_main當(dāng)中,需要做以下幾件事情:
- 初始化設(shè)備
- 初始化內(nèi)存智什、設(shè)置MMU动漾、建立頁(yè)表
- 初始化中斷向量表
- 初始化時(shí)鐘
- 創(chuàng)建任務(wù)(實(shí)例代碼中是創(chuàng)建虛擬機(jī)實(shí)例)
- 開(kāi)啟中斷
- 進(jìn)行任務(wù)調(diào)度
原理上很簡(jiǎn)單,但還有一些基本的事情要做撩鹿,雖然已經(jīng)可以用C寫(xiě)代碼了谦炬,但是大家所熟悉的libc還不能使用,為此节沦,你必須建立自己的syscall和libc键思,之后才能方便的構(gòu)建后續(xù)代碼。
這部分內(nèi)容其實(shí)都是操作系統(tǒng)的基本原理甫贯,雖然電子相關(guān)專業(yè)的學(xué)生都學(xué)過(guò)這門(mén)課程吼鳞,但估計(jì)有90%的人從來(lái)沒(méi)有自己動(dòng)手寫(xiě)過(guò)Kernel。想要了解更多詳細(xì)內(nèi)容叫搁,請(qǐng)參考ARM官網(wǎng)的ARMv8指令集架構(gòu)
介紹這么多赔桌,其實(shí)最核心的是要理解中斷向量表的概念,所有的系統(tǒng)調(diào)用和大家所熟知的驅(qū)動(dòng)程序渴逻,最后都是以某種方式鏈接到這里疾党,因此運(yùn)行在EL1和EL2的OS內(nèi)核與Hypervisor就有機(jī)會(huì)去捕獲這些異常與中斷,該原理是虛擬化實(shí)現(xiàn)的最基本的技術(shù)基礎(chǔ)惨奕。
4.3 系統(tǒng)調(diào)用
上面EL0-EL3層次的劃分雪位,會(huì)讓很多人覺(jué)得各層的軟件是并行運(yùn)行的,其實(shí)在單個(gè)CPU的層面梨撞,代碼的運(yùn)行都是順序執(zhí)行的雹洗,舉個(gè)ARM64匯編的例子:
.text //code section
.globl _start
_start:
mov x0, 0 // stdout has file descriptor 0
ldr x1, =msg // buffer to write
mov x2, len // size of buffer
mov x8, 64 // sys_write() is atHello world in assembly language ARM64 (AArch64, ARMv8)
.text //code section
.globl _start
_start:
mov x0, 0 // stdout has file descriptor 0
ldr x1, =msg // buffer to write
mov x2, len // size of buffer
mov x8, 64 // sys_write() is at index 64 in kernel functions table
svc #0 // generate kernel call sys_write(stdout, msg, len);
mov x0, 123 // exit code
mov x8, 93 // sys_exit() is at index 93 in kernel functions table
svc #0 // generate kernel call sys_exit(123);
.data //data section
msg:
.ascii "Hello, World!\n"
len = . - msg
以上代碼其實(shí)等價(jià)為調(diào)用sys_write與sys_exit兩個(gè)系統(tǒng)調(diào)用,如果調(diào)用libc的函數(shù)卧波,大概效果就是printf("hello world!")时肿。在設(shè)置完參數(shù)寄存器之后,調(diào)用svc指令港粱,cpu就會(huì)去之前設(shè)置的中斷向量表中螃成,查找相關(guān)的中斷子服務(wù)。
4.4 內(nèi)存虛擬化
在整個(gè)Hypervisor的技術(shù)架構(gòu)當(dāng)中查坪,內(nèi)存的虛擬化是基石寸宏,而MMU是實(shí)現(xiàn)內(nèi)存虛擬化的硬件基礎(chǔ),內(nèi)存的虛擬化依賴于MMU的兩級(jí)頁(yè)表轉(zhuǎn)換機(jī)制(Stage1與Stage2)咪惠,它允許Hypervisor控制虛擬機(jī)的內(nèi)存視圖。
Guest OS控制的頁(yè)表轉(zhuǎn)換稱之為stage 1轉(zhuǎn)換淋淀,負(fù)責(zé)將Guest OS視角的虛擬地址(VA)轉(zhuǎn)換為中間物理地址(IPA)遥昧,而stage 2轉(zhuǎn)換由Hypervisor控制覆醇,負(fù)責(zé)將中間地址(IPA)轉(zhuǎn)換為真實(shí)的物理地址(PA)。
4.5 設(shè)備虛擬化
應(yīng)用程序要訪問(wèn)外部設(shè)備炭臭,經(jīng)過(guò)Guest OS的driver處理永脓,其實(shí)就是訪問(wèn)中間物理地址IPA的一塊內(nèi)存區(qū)域,如果將這個(gè)IPA和設(shè)備真實(shí)的物理地址PA映射起來(lái)鞋仍,那么該物理設(shè)備就被Guest OS 獨(dú)占了常摧,這種設(shè)備就叫做直通設(shè)備(Pass-through)。
如果該IPA沒(méi)有和真實(shí)的物理地址映射威创,那么在stage2轉(zhuǎn)換的過(guò)程中就會(huì)產(chǎn)生一個(gè)EL2異常落午,該異常會(huì)被運(yùn)行在EL2的Hypervisor捕捉到,通過(guò)中斷向量表的地址肚豺,就能夠找到處理該異常的子程序溃斋,從而就能夠在當(dāng)中模擬設(shè)備的行為。
5.硬件隔離與軟件虛擬化方案開(kāi)發(fā)
5.1 多核MCU硬件隔離
前面也介紹過(guò)了硬件隔離的方案吸申,本質(zhì)上其不屬于Hypervisor的范疇梗劫,要使用硬件隔離方案,有幾點(diǎn)需要注意:
- 需要支持內(nèi)存保護(hù)單元的多核MCU芯片截碴,這個(gè)條件很好滿足梳侨,英飛凌和NXP的多核MCU基本都支持。
- 需要一家提供硬件隔離方案的軟件供應(yīng)商日丹,雖然硬件隔離的技術(shù)方案主要是依賴硬件特性走哺,自己做的技術(shù)門(mén)檻不高,但一般的玩家也不太能自己搞定聚凹,割坠。
- 需要運(yùn)行在不同核心上的基礎(chǔ)軟件,比如Autosar或者FreeRTOS等妒牙,需要一定的porting和配置工作才能在隔離后的硬件上運(yùn)行起來(lái)彼哼。
- 如果選擇的MCU的芯片支持的IO接口足夠,完全可以把IO資源以獨(dú)占的方式給到某個(gè)核心使用湘今,如果某些接口只有一個(gè)敢朱,比如以太網(wǎng),要在兩個(gè)核心之間共享摩瞎,實(shí)現(xiàn)起來(lái)就比較麻煩拴签。
- 需要一套穩(wěn)定可靠的核間通信機(jī)制,該機(jī)制一般需要基于共享的內(nèi)存區(qū)域去實(shí)現(xiàn)旗们。
5.2 多核MPU虛擬化
為了在多核MPU上使用軟件的虛擬化方案蚓哩,以下條件是必備的:
- 支持虛擬化的多核處理器
- 內(nèi)存管理單元MMU與IOMMU
- Hypervisor Monitor Software(Blackberry的Hypervisor 2.0 或者開(kāi)源的Xen等)
- 運(yùn)行虛擬化的內(nèi)核(Linux或者QNX)
- 穩(wěn)定可靠的虛擬化驅(qū)動(dòng)支持
MPU上的虛擬化方案使用起來(lái)比較復(fù)雜,和所要使用的芯片廠商非常相關(guān)上渴, 市場(chǎng)上有很多家提供Hypervisor Monitor Software軟件的公司岸梨,也可以選擇開(kāi)源的方案喜颁,主要的瓶頸不是在Hypervisor運(yùn)行框架本身,其本質(zhì)上是一個(gè)操作系統(tǒng)中間件曹阔,工作量最大的還是在驅(qū)動(dòng)之上半开,因?yàn)榇笮蚆PU上的設(shè)備和驅(qū)動(dòng)非常復(fù)雜。
像高通這樣的公司赃份,會(huì)基于第三方公司的Hypervisor框架寂拆,把所有Host與Guest系統(tǒng)上的驅(qū)動(dòng)開(kāi)發(fā)整合完畢再提供給客戶,出了問(wèn)題找高通就行了抓韩,一般很少和第三方Hypervisor框架供應(yīng)商有很多交集纠永。
其他的很多芯片廠商,本身并不提供完整的虛擬化解決方案园蝠,客戶必須自己渺蒿,或者找第三方的公司合作,把所有Host與Guest系統(tǒng)上front/backend驅(qū)動(dòng)開(kāi)發(fā)完畢彪薛。
在中央計(jì)算單元所有的外設(shè)當(dāng)中茂装,最復(fù)雜的有這么幾大塊:Graphics、Video善延、 Audio少态、AI Core,而這其中Graphics又是排名第一的易遣。這幾個(gè)都是消耗內(nèi)存和計(jì)算資源的大戶彼妻,幾乎70%的導(dǎo)致系統(tǒng)不穩(wěn)定的問(wèn)題,都出自這幾個(gè)大戶豆茫。
結(jié)語(yǔ)
從這些技術(shù)細(xì)節(jié)也可以看到侨歉,硬件隔離的可靠性其實(shí)是非常高的,軟件的虛擬的Guest OS的確存在一些不穩(wěn)定因素揩魂,但其實(shí)在中央計(jì)算單元中幽邓,只需要兩個(gè)操作系統(tǒng)即可,用于自動(dòng)駕駛火脉、車控牵舵、網(wǎng)關(guān)的RTOS,以及用于娛樂(lè)的普通OS(如Android倦挂、Linux)畸颅。用于娛樂(lè)的OS完全可以通過(guò)虛擬機(jī)的方式運(yùn)行,用于自動(dòng)駕駛方援、車控没炒、網(wǎng)關(guān)的RTOS,可以直接運(yùn)行在Hypervisor層犯戏,這樣在兼顧實(shí)時(shí)計(jì)算的要求的前提下也能獲得豐富的娛樂(lè)系統(tǒng)功能送火。