当前位置:网站首页>【Jailhouse 文章】Jailhouse Hypervisor

【Jailhouse 文章】Jailhouse Hypervisor

2022-07-05 05:31:00 Jia ming

作者:Maxim Baryshnikov,布拉格捷克技術大學

本文描述了Jailhouse Hypervisor的主要概念和原理。
本文實現了簡單的演示應用程序(與高精度事件定時器交互)。
本文將一個小型操作系統(L4 Fiasco)移植到Jailhouse cell中。
本文評估了共享內存系統對於Jailhouse中運行程序的實時屬性的影響。benchmark 測試結果錶明,兩個相互交互的CPU,在最壞情况下,由於對於 L3 的共享,導致內存訪問帶寬降低。

1. Jailhouse 特點

Jailhouse 由首席開發人員 Jan Kiszka 負責,專注於與安全相關的示例(工業流程、航空航天、醫學等),其應用場景是特殊的。Jailhouse 的主要特點是:並不是在 GuestOS 間對稱地共享多核處理器資源,而是劃分不同的資源給 GuestOS 獨立使用。

Vitaliy Sinitsyn 這樣評價,Jailhouse 在現有 Linux 設置之上啟用非對稱多處理方式,並將系統拆分成稱為 cell 的獨立分區。每個 cell 運行一個 GuestOS 並擁有一組完全控制的分配資源(CPU、內存區域、PCI設備)。Jailhouse的工作是管理 cell 並保持它們彼此隔離。

假設本文有一個多核系統,本文想用一個物理 CPU 來處理硬實時任務,另一個 core 用於用戶交互(GUI/HMI),其它物理 CPU 用來收集傳感器數據。顯然,GUI 應用程序不能影響第一個物理 CPU 的工作。如何防止不被幹擾,這就是 Jailhouse 的工作。

Jailhouse 的目標是安全關鍵的工業應用。此類應用程序通常需要由獨立機構根據眾多安全標准進行認證,認證的目標是獲得系統足够可靠以安全地執行其預期功能的信心。安全標准根據所需的可靠性程度將安全功能分為多個級別(安全完整性級別),對關鍵性更高的系統提高更嚴格的要求。複雜的系統很難(很昂貴)或無法認證。這就是為什麼 Jailhouse 是一個非常簡約的 Hypervisor,它只包含隔離功能以隔離 GuestOS 所需要的功能。沒有一個 cell 可以訪問不屬於它們的設備,因為 Hypervisor 會阻止它。因此,實時應用程序不會受其它分區中發生的任何事情的影響。

Jailhouse 是在用戶空間通過向 Jailhouse VMM 發出超級調用的設備驅動程序來管理的。Jailhouse不是內核的一部分,它運行在最低級別。內核模塊僅用於將 Jailhouse 的二進制鏡像加載到內核所保留的內存。

請添加圖片描述

2. celll configuration

每個 cell(root cell/non-root cell)必須在啟動之前進行靜態配置,此配置確定 cell 可以訪問哪些硬件資源。Jailhouse 使用 *.c 文件作為配置文件,其中必須將參數分配給特殊的 C 結構的字段,這些字段定義在 hypervisor/include/jailhouse/cell-config.h 中。

non-root cell 字段如圖下,root cell 字段如圖後圖。

請添加圖片描述

對於 root cell,結構體中需要包含(struct jailhouse_system),而不是 struct jailhouse_cell_desc,其餘內容二者沒有區別。

請添加圖片描述

配置 non-root 只能手寫配置文件,而 root cell,存在這樣的工具,分為以下兩個步驟:

1、jailhouse config collect <name-of-arch.tar> 收集目標平臺信息。

2、jailhouse config create -r <name-of-arch.tar> <name-of-conf.c> 需要安裝 python-mako 庫。創建後,配置被編譯為原始二進制文件,Jailhouse 在創建cell 時會使用。

3. Jailhouse enabling

Jailhouse 啟動需要如下步驟:

1、在目標平臺上安裝 Linux>=3.18

2、在目標平臺上編譯安裝 Jailhouse。

3、在 Linux 內核啟動參數中添加對於內存區域的保留選項(如memmap=),該值必須和 .phys_start 和在 root cell 配置中的 .size 字段值一致。

4、加載 jailhouse.ko 內核模塊。這可以創建 /dev/jailhouse 設備,該設備可以通過用戶空間的工具訪問。Jailhouse 用戶空間程序向 /dev/jailhouse 發送JAILHOUSE_ENABLE 請求,該請求指示驅動程序調用 jailhouse_cmd_enable()(driver/main.c)。在此函數中,驅動程序首先進行一些驗證。它檢查 CPU 標志以確定該 CPU 使用哪種虛擬化技術,然後對配置的二進制文件進行基本驗證。之後調用request_firmware()函數在 /lib/firmware 文件夾中搜索 jailhouse-inter.bin 或者 jailhouse-amd.bin。驅動程序將步驟2中保留的內存區域重新映射到內核地址空間內存(使用ioremap_page_range(…)),因此可以從用戶空間訪問Jailhouse,驅動程序在此內存區域的開頭複制該二進制文件,並在其後面複制 cell 的配置。然後,調用 jailhouse_cell_create() 函數。

5、執行 hypervisor 啟動命令:jailhouse enable <path/to/cell/conf.cell>。enable 的最後階段是 CPU 初始化。Jailhouse 為每個 CPU 調用entry_hypervisor()函數來啟動(hypervisor/x86/entry.S中的arch_entry)。Jailhouse 需要成為 cell 和 CPU 之間的接口,因此它會保存系統的狀態,然後在 CPU0 初始化時設置其環境。包括:為 Jailhouse 和 APIC 設置分頁、創建中斷描述符錶、創建配置虛機擴展(VME),它還設置 UART 通信以將調試信息寫入其中,因此可以在 ttyS0 上看到輸出信息。對於所有 CPU,此過程都是一致的:更新 IDT 和 GDT,重置 CR3,設置 VMCS。最後 Hypervisor 發送VMLAUNCH 指令。從此開始,Linux不再在裸機上運行,而是在 Jailhouse 的 cell 中運行。

請添加圖片描述

4. Cell initialization and start process

當用戶執行 jailhouse cell create <path/to/conf.cell> 時,它將配置文件讀入內存,並將 JAILHOUSE_CELL_CREATE 命令發送給驅動程序,調用 jailhouse_cmd_cell_create()(driver/control.c)將上述配置文件從用戶空間內存複制到內核空間,並對cell desc進行檢查。然後,根據配置內容為guest得到image,在 sysfs 中顯示新的cell的信息,並將請求的CPU從Linux root cell中分配出去,從Linux中卸載PCI設備。Jailhouse模擬PCI虛擬驅動程序將其從Linux中删除,因為無法執行真正的拔出。當驅動程序發出 JAILHOUSE_HC_CELL_CREATE 超級調用時,Jailhouse調用 hypervisor/control.c中的cell_create(),發出命令,讓所有新cell的處理器暫停,除了當前的處理器,它可以防止它們之間的競爭。

然後,開始cell初始化過程。cell_init()函數用I/O端口比特圖的值填充cell結構中的cpu_set字段,並調用曆程來保存PCI、IOAPIC和IOMMU等內存映射設備的比特置和處理程序。然後,檢查CPU沒有被分配出去後,跳轉到arch_cell_create()(hypervisor/arch/x86/control.c),開始"shrinking"。這裏的重點是遵循一對一分配的概念:如果root cell有初始的cell需要的東西,那麼Linux cell(root cell)的訪問將被拒絕,而新的cell得到它,在這種情况下,Linux cell將在第一次訪問時停止。在重新分配I/O端口、IOAPIC、IOMMU、PCI等資源後,配置通信區域(這是hypervisor和特定的cell都可以讀取和寫入的每個cell共享內存區域)。它還包含有關PM計時器地址的信息,分配的CPU數量,包含當前cell的狀態(例如,running、running/locked)。

最後,cell 將被提交到cell list,通信區域中的cell 狀態將設置為 JAILHOUSE_CELL_SHUT_DOWN,並且對每個cell的CPU,Jailhouse發出arch_cpu_resume()。

要在新的cell中執行inmate,需要將inmate移動到cell的內存區域:jailhouse cell load <name-of-cell> <inmate.bin> -a <off-in-guest>

所有的inmates都被視為原始二進制文件。此二進制文件的大小必須小於或等於將加載它的guest內存區域。驅動程序將 JAILHOUSE_HC_CELL_SET_LOADABLE發送到hypervisor,並將標記為可加載的 guest 區域重新映射到 root cell 的地址空間。可以看到串口信息:“Cell can be loaded”。驅動程序將二進制文件存儲在給定的地址。

最後,要啟動它,用戶應該調用:jailhouse cell start <name-of-cell>,這會導致HyperCall —— JAILHOUSE_HC_CELL_START,從它的角度來看,它會導致Jailhouse的cell_start()執行從root cell到Guest的取消映射所有可加載區域。cell的狀態變為JAILHOUSE_CELL_RUNNING,並且在cell的每個CPU上調用arch_cpu_reset()。這會向cell中的每個CPU發送虛假的啟動處理器間中斷(SIPI)。在下一個#VMEXIT時,Guest指令指針將設置為0xFFFF0,並且inmate開始執行。

5. Inmate demos

Jailhouse 提供了一個小型的框架,可以輕松地開發簡單的無操作系統的應用程序。所依賴的 library 頭文件定義在 inmate.h 中,其中包含了內存分配和重新映射、APIC 和 IOAPIC 的初始化、中斷處理程序設置、與 PCI 設備的一些交互甚至是一些基本的 SMP 操作(smp_wait_for_all_cpus()、smp_start_cpu())。

inmates 的啟動代碼(header.S for 64-bit、header-32.S for 32-bit)如Listing 2.4所示。Jailhouse 中 inmates 的入口點在 0xFFFF0,這裏需要一個小技巧來跳轉到16比特代碼部分(用於GDT和保護模式標志設置)。inmate二進制文件以偏移量0xF0000加載到GuestOS中。

Listing 2.5中顯示的鏈接描述文件(inmate.lds)確保了以下內容。16比特的startup段綁定在二進制文件的最開頭(0x0000)。boot段緊隨startup段之後,固定在0xFFF0,因此加上偏移地址之後,會給出正確的入口地址。.text、.data、.rodata部分有它們的虛擬內存地址(VMA,運行output file時,該部分的虛擬地址),其中包括加載偏移量。但是它們的加載內存地址(LMA,加載該部分的地址)沒有加載偏移量。

因此,在0xFFF0處的.boot段只有一條指令:ljmp $0xf000, $start16,它使instruction pointer在物理地址0xf0000上移動。之後,當GDT和保護模式標志被設置時,它會跳轉到32比特代碼,在此處進行分頁設置,最後是inmate_main()函數入口。

5.1 APIC demo

APIC-高級可編程中斷控制器。這是一個典型的inmate,通常用於演示Jailhouse功能。它為APIC計時器設置中斷並測量事件發生之間的實際時間。除此之外,它還展示了使用域間通信和 manipulate the cell state。

該 demo 的配置文件如 Listing 2.8 所示,configs/apic-demo.c,定義了兩個內存區域:加載 inmate 的內存區域(1MB),緊挨著的用於通信的區域(4KB),後者有一個額外的標志JAILHOUSE_MEM_CONMM_REGION,讓Jailhouse知道在哪裏讀/寫消息,它會在串口0上打印一個日志。

請添加圖片描述

Launching apic-demo cell:

jailhouse cell create /jailhouse/configs/apic-demo.cell

jailhouse cell load apic-demo /jailhouse/inmates/apic-demo.bin -a 0xf000

jailhouse cell start apic-demo

jailhouse cell shutdown apic-demo

jailhouse cell shutdonw apic-demo

demo開始運行之後,cell state被設置為 JAILHOUSE_CELL_RUNNING_LOCKED,這是通過設置commo_region->cell_state實現的,通常,這意味著Jailhouse無法shrink cell。之後,應用程序校准時間戳計數器(inmates/lib/x86/timing.c),並初始化APIC定時器。然後為定時器的中斷設置處理程序,因此,每次下一個中斷發生時,都會計算抖動。“抖動是預期時間和時間(延遲)之間的差异,就性能而言,越小意味著jailhouse越不感知”。程序在通信區域中等待消息,如果出現關閉請求,則程序發送一條消息,錶明現在無法關閉,如果此請求出現第二次,apic-demo會中斷循環。將apic-demo的cell狀態更改為JAILHOUSE_CELL_SHUT_DOWN,所以Jailhouse知道關閉過程進展順利。

5.2 HPET demo

作者實現的高精度事件定時器。

6. L4 Fiasco.OC launch

在cell中使用裸機程序時,可能有助於解决簡單問題,但是在大多數情况下,當必須實現更複雜的東西(網絡協議棧、自動駕駛等)時,需要運行操作系統,因此,將某些操作系統移植為 inmate 是有必要的。

目前,可以在non-root cell中啟動Linux,並且Documentation/non-root-linux.txt中描述了如何做,必須以特定的方式修改和配置內核,用於引導內核的用戶空間工具也必須創建。但是,面對實時任務,Linux便不能勝任。

選擇Fiasco.OC進行移植就是為了滿足實時要求。

6.1 Overview

Fiasco.OC是德累斯頓大學Fiasco團隊開發的基於微內核的操作系統。它由L4的微內核和與L4運行時環境(L4Re)相關的用戶級程序組成。內核本身非常簡約。它還提供了作為進程間通信(IPC)、創建/删除地址空間(任務)和線程等基本功能。

Fiasco的極簡主義:微內核總共提供了7個系統調用,換句話說,微內核只用了7個系統調用就統治了世界。

可以啟動操作系統的最小配置必須包含Fiasco內核、稱為Sigma0的Root-Pager、Root-Task(Moe)以及至少一個在其之上運行的用戶空間應用程序。Sigma0為用戶空間程序提供了使用內存(重新映射、分配等)的API。Moe在分頁管理器之上運行,是內核首先啟動的任務。它為所有其他用戶空間應用程序提供更抽象的接口。

請添加圖片描述

6.2 Fiasco 啟動過程

為了移植Jailhouse,Fiasco系統配置、啟動過程配置、內核配置。

7. Benchmarks

評估內存系統對不同cell中運行的軟件的性能影響。測試當不同cell同時訪問內存時的影響。

一個普通的多核處理器中,core共享L3緩存,並且內存系統中的其他部分也是共享的。現在假設,每個core執行完全不同的程序,因此,每個程序都需要訪問不同的內存區域,在這種情况下,core之間將相互競爭cache,並且內存訪問時間將增加。此外,當一個core想要訪問內存的同時另一個core也想訪問內存,勢必會有一個core需要等待,在這種core競爭的情况下,某一個core上的內存密集型應用程序會顯著减慢其它core上的應用程序。所有提到的這些問題都會對系統的實時性和安全性產生負面影響。

實現了一個簡單的benchmark,該benchmark可以在cell中、裸機上運行。目的是研究在使用Jailhouse時,內存訪問是否出現减慢的現象。

原网站

版权声明
本文为[Jia ming]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050527567160.html