倪子豪 何照丹, 耿楊 張凱,
(1.清華大學深圳國際研究生院,深圳 518055;2.深圳市阿丹能量信息技術有限公司,深圳 518126)
主題詞:智能交通 i.MX8 嵌入式虛擬化 Xen Linux 雙系統
隨著汽車多元化需求的增加,車載系統向著智能座艙方向發展,成為同時具有交通、娛樂、辦公和通訊等多種功能的綜合平臺。現代化的智能座艙系統在保證車輛安全、穩定的前提下,對信息、娛樂和輔助駕駛的集成提出了新的要求。智能座艙需要集成度更高、感官效果更好的整體系統,因此需要將組合儀表、中控臺等多個工作目的、性能要求不同的系統進行集成。
目前,汽車普遍將2套完全獨立的系統分別安裝于2 個處理器上,分別負責儀表的數據處理與顯示,以及信息娛樂功能。該方法需2套硬件資源,成本較高,且2個系統需要通過總線或以太網協議進行信息交互,系統間交互較為復雜。另一種方法是使用虛擬化系統,即在1套硬件資源上通過虛擬化技術運行2個系統。若沿用類似VMWare的基于軟件的虛擬化方案,會增加系統代碼量,從而影響可靠性。因此,必須尋找新的基于硬件的虛擬化方案,通過采用多核方案實現硬件虛擬化,從而兼顧安全性與成本。
Xen是開源的虛擬化管理軟件,其核心是虛擬機監視器,負責完成CPU 調度和內存資源分配[1],具有高性能和占用資源少的特點,且與操作平臺的結合極為密切,并支持ARMv8 嵌入式架構。相比于其他虛擬化方案,Xen相對成熟,且其ARM架構支持相對前沿。在各種車載嵌入式系統的虛擬化中,Xen 的應用相對較少。在國外:Avanzini等人[2]提出了基于Xen的車載系統虛擬化方案,將Linux 系統和ERIKA 實時系統進行整合;Luca等人[3]的研究表明,Xen和KVM都可以作為實時管理程序,并提供了一些減少延遲的指導機制,有利于提高Xen在車載系統中的實時特性。在國內,主流的方案有:使用ARM和Windows Embedded CE設計車載系統[4];使用嵌入式Linux進行開發,例如結合圖形界面QT設計車載虛擬儀表[5]等;王沖[6]提出了基于Xen的半虛擬化系統設計,討論了Linux 與μC/OS-Ⅱ系統結合的性能,但由于μCOS-Ⅱ目前尚未開源,所以無法定制開發。
基于以上背景,本文使用NXP 公司開發的高配版i.MX8 系列處理器,基于i.MX8 系列ARMv8 架構處理器,使用Xen虛擬化方案實現Linux雙系統的啟動。
在嵌入式Linux 系統常用的引導加載程序(BootLoader)中,通用引導加載程序(Universal Boot Loader,U-Boot)使用頻率最高。其“通用”有兩層含義,一是支持多種不同的嵌入式操作系統,二是支持諸多常用系列的處理器。U-Boot 項目的開發目標與之契合,即支持盡可能多的嵌入式處理器和嵌入式操作系統。本文對U-Boot 進行一些定制化設計,將Xen 引導命令編譯入U-Boot,使其能夠正常啟動虛擬機管理器。
U-Boot目錄分為3類:與處理器架構和板極硬件相關的代碼;通用函數和驅動、檢測程序;參考文檔和工具。修改代碼時只需要修改/arch/arm、/board、/configs、/include目錄下有關開發板和處理器架構等方面的配置文件。
U-Boot啟動過程分為3個階段,其中第3個階段主要任務是加載內核并跳轉到內核啟動。而Xen Hypervisor是類似內核的模塊,因此U-Boot設計與修改的重點在于了解第3個階段如何調用內核并傳遞必要參數。
按照正常的單系統啟動流程,應在內存中將U-Boot、Linux系統內核、根文件系統等啟動相關的鏡像按照圖1的順序加載。

圖1 Linux單系統啟動流程
Xen是一個微內核,作為Linux虛擬機的管理者,需要先于Linux 系統啟動,在Xen 虛擬化方案下的啟動鏡像應按照圖2的順序加載。

圖2 Xen虛擬化方案下Linux雙系統啟動流程
比較圖1和圖2可以明確需對U-Boot進行的修改:將傳遞給Linux 和Xen 的參數全部傳遞給Xen 內核,并加載Xen內核到內存中,最后啟動Xen Hypervisor。
基于上述分析,本文對U-Boot進行了如下修改:
a.在定義環境變量中加入有關Xen啟動的變量:

b.對Xen Hypervisor 使用參數進行定義,包括命令行為串口1、加載地址為0x80280000、啟動介質為SD卡,在此基礎上傳遞Linux 系統Domain-0 啟動所需參數,包括加載地址為0x85000000、分配內存2 048 M 和分配4個虛擬CPU。最后定義指令run xenmmcboot作為U-Boot命令行調用這些代碼加載Xen內核的入口:

通過以上操作,完成了U-Boot的設計與修改,設置了啟動方式和命令,使U-Boot從SD卡啟動,使得U-Boot啟動目標為復制Xen內核到內存中,最后啟動Xen內核,并將控制權交給Xen Hypervisor。經過上述修改,對Xen加入內存前、后的內存空間進行比較,如圖3所示。

圖3 Linux系統和Xen虛擬化方案Linux雙系統內存空間分布
從Linux 3.0 開始,Linux 內核添加了Xen 相關的支持,可以選擇是否作為Domain-0內核使用,給內核編譯帶來不少方便。Domain-0內核修改過程如圖4所示。

圖4 Domain-0內核修改過程
由于i.MX8 系列處理器使用ARMv8 架構,屬于64位處理器,所以需要在內核配置前執行:

上述代碼將架構改為ARM64,并在內核根目錄的/arch/arm64/configs 下對默認配置文件defconfig 進行修改,調整是否為Domain-0的配置,將修改后的配置文件重命名為Dom0_defconfig、DomU_defconfig 并保存,如是便可以在后續修改2 個系統的內核時分別擁有對應的默認配置文件。進而執行:

則make 腳本會讀取Dom0_defconfig 中的代碼,對內核進行配置,并保存文件.config。該文件即內核在進行編譯時參考的最終配置文件。
其中,關于Xen和Domain-0的部分重要配置如下:

以上即以Domain-0 作為特權域必須的配置,能使Domain-0 在啟動時加載特權域相關組件,及組成Xen Hypervisor中分離驅動架構的必要部分——backend驅動。
配置結束后保存,然后對內核進行編譯。本文使用的Linux 內核加入了Yocto Project 的支持,可以使用bitbake linux-imx-C compile 指令一步完成內核編譯和部署,之后會直接將編譯生成的鏡像文件Image 和設備樹.dtb 文件保存于deploy 目錄下,方便查找和使用。
一個Linux 系統的運行包含4 個必需部分:Linux系統內核Image、設備樹.dtb 文件、BootLoader、根文件系統。通過Yocto Project 提供的bibake 編譯指令可在/tmp/deploy 目錄下生成單獨的內核、文件系統等,也有將上述4個部分全部打包的鏡像.sdcard文件,供開發人員制作啟動介質,可以直接使用dd 指令將打包好的完整系統鏡像.sdcard文件燒錄到SD卡中。但是使用這種固定的燒錄鏡像方法時,無論SD卡的存儲空間多大,都會對SD 卡進行固定大小的分區,且僅有2 個分區。這會造成SD卡存儲資源的浪費,且空間大小不可調節,若文件系統中放入大量應用程序,則會造成分區空間不足,但空余空間無法利用的后果。另外,由于使用Xen虛擬化方案啟動2個系統,則需要在一張SD卡上燒錄2個系統,以上方法便不能適應此需求。
對上述結果進行分析,并結合Linux系統啟動過程,本文手動對SD卡進行分區并格式化,根據需求自定義分區大小。此后,按地址前后順序在SD卡上燒錄U-Boot、在第1個分區放置設備樹.dtb文件和系統鏡像,在第2個分區放入根文件系統。后續空間為未分區或格式化的raw存儲空間,仍可在后期增加分區和放置系統文件。
考慮到目前本課題實際需要,暫不涉及多系統的試驗,因此對SD卡分為3個分區,如表1所示。

表1 自定義SD卡分區情況
分區完成后需要進行格式化,第1 個分區格式為vfat,用于存放設備樹文件和內核鏡像,第2、第3個分區格式為ext4,用于存放根文件系統。接下來分別完成單獨燒錄BootLoader、復制根文件系統等操作,即完成了啟動介質的自定義制作。
經試驗驗證,該方法具有可行性,同時解決了無法燒錄多個系統、SD卡空間浪費的問題。為提高SD卡內存使用率,在后續研究中將全部使用該方法。
完成SD卡啟動介質制作后,將SD卡插入開發板卡槽,輸入run xenmmcboot,即從SD卡中啟動Xen Hypervisor。初始化Xen的一些資源后,內核開始啟動Domain-0。
Domain-U內核的配置過程與Domain-0類似,但在設備分配上有所不同。Domain-U的配置主要是內核模塊與硬件設備的分配。Linux 內核從3.x 版本開始引入設備樹的概念,用于實現驅動代碼與設備信息的分離。對于Linux 雙系統,需要編寫2 個系統分別對應的設備樹.dts文件。而NXP公司對于單Linux系統已經編寫了針對該開發板的設備樹文件fsl-imx8qm-mek.dtsi,因此可以在此基礎上進行修改。
設備樹文件的修改原理如圖5 所示。根據Xen Hypervisor 虛擬化方案的原理,Domain-0作為特權域擁有所有硬件資源的訪問權,因此在Domain-0 的設備樹中理應包括所有的設備,但有些需要設置為“xen,passthrough”屬性,傳遞給Domain-U 供其重寫屬性并使用。本文完成了fsl-imx8qm-mek-dom0.dts 和fsl-imx8qm-mek-domu.dts 2個文件的編寫,并在調試中進一步修正。

圖5 Xen資源分配方法
根據Domain-U 的配置要求,對其內核配置make menuconfig時,將XEN_BACKEND設為n,即將與Xen有關的backend 驅動全部關閉。此外,在啟動過程中經常遇到啟動Domain-U時部分模塊啟動異常而出現致命錯誤,導致內核錯誤(kernel panic)的問題。以加密算法模塊(Cryptographic Accelerator and Assurance Module,CAAM)為例,由于其需要直接與硬件通訊,而根據Xen虛擬化方案,只有Xen Hypervisor工作在ring 0時可以直接訪問硬件,其他域的特權級均低于它。非特權域中的操作系統不能直接與硬件通訊,因此,在啟動過程中CAAM模塊會因找不到硬件地址而出現野指針,從而導致內核出現錯誤,無法正常啟動。
根據以上原因,需要把Domain-U中與硬件資源直接相關的配置刪除,重新編譯內核作為Domain-U的Image,以上便完成了Domain-U的內核配置。隨后使用與編譯Domain-0內核相同的方法完成Domain-U內核的編譯。
Xen Hypervisor將策略的制定和實施分離,將管理和配置工作交給Domain-0 進行,而并非給Hypervisor 實施。亦即若將虛擬機的管理工作分為2類,即確定如何管理和實施,則Domain-0 負責第1 類工作,Xen Hypervisor 負責第2類。之后,Domain-U 創建的過程即在Domain-0中對其配置進行設置,繼而通過xl create、xl console等命令行指令進行創建。同理,用戶在Domain-0中可以設置虛擬機的管理參數,而Xen Hypervisor 按照在Domain-0中設置的參數設置并啟動客戶虛擬機。
根據以上分析,對于從Domain-0到Domain-U的啟動,需要經過如圖6所示的操作過程。

圖6 Domain-U的啟動過程
其中重點在于需要編寫/etc/xen/domu-im8qm-mek.cfg 配置文件,對Domain-U 進行配置。domu-im8qmmek.cfg文件的主要內容包括:

該.cfg文件中對Domain-U的內存進行了設置,同時在U-Boot 中也對內存資源進行了預分配。其中.cfg 文件中指定最大內存容量,U-Boot中通過宏分配實際的內存地址空間大小。若U-Boot 中分配的內存大于.cfg 文件中配置的最大內存,則在創建過程中Domain-U 正在使用的內存會超出最大允許范圍,出現野指針導致系統跑飛,進而被Xen Hypervisor強制關閉。根據以上情況,對2處內存設置進行協調,完成Domain-U的創建。
本文使用xl create/etc/xen/domu-im8qm-mek.cfg 的方法將配置要求傳遞給Xen Hypervisor,隨后Xen Hypervisor 進行資源分配,并創建Domain-U。xl create方法流程圖如圖7所示。
將修改好的Domain-U 內核鏡像Image、Domain-U設備樹文件復制到SD 卡中的第1 個分區。隨后在SD卡中的第3 個分區中裝入Domain-U 的根文件系統,將寫好的Domain-U系統配置文件放在/etc/xen目錄下。
Domain-0 系統啟動后,進入到/etc/xen,然后執行xl create domu-imx8qm-mek.cfg,成功創建Domain-U 系統。隨后執行xl console DomU 接入Domain-U 的控制,完成雙系統啟動。

圖7 xl create*.cfg創建客戶虛擬機流程
為了方便區分2 個系統,在用戶名中把Domain-U的root 用戶名設置為guest。登錄Domain-U 后,可以回到特權域Domain-0,通過xl list命令可以看到正在運行的2個虛擬機系統及其相關信息。
雙屏顯示驅動程序的開發過程中需要根據Xen Hypervisor 的驅動結構對一般的顯示驅動進行前、后端分離。Xen的虛擬設備架構采用前、后端分離的設備驅動結構。虛擬設備驅動包含Domain-U中前端設備驅動和Domain-0中后端設備驅動。后端設備驅動可以通過原生設備驅動訪問真實的硬件設備,其架構如圖8所示。

圖8 Xen設備驅動架構
基于Xen的虛擬驅動架構,本文完成了雙屏顯示所需的原生驅動程序、資源配置、設備節點分配、前后端驅動的所有設計與開發,最終完成了雙屏顯示的驅動程序設計,顯示效果如圖9所示。

圖9 雙系統雙屏顯示
本文在NXP 公司開發的基于i.MX8 處理器的i.MX8QuadMax Mek 開發板上完成了虛擬化Xen方案下的Linux雙系統設計,在i.MX8系列處理器上實現了Xen虛擬化方案,驗證了虛擬化方案在車載智能座艙系統上的可行性,是嵌入式虛擬化技術在車載智能座艙系統上使用的新嘗試。在本文研究成果的基礎上,未來可以進行進一步探索,如:開發系統間通訊機制,在2個系統之間提高數據傳遞速度;將Linux 系統升級為Android 系統,并在Android系統中開發更加豐富的中控系統應用,最終真正應用于實際的車載智能座艙系統。