全網(wǎng)獨(dú)一無二值得收藏《Linux內(nèi)核虛擬技術(shù)大全》
一、半虛擬化操作
Linux提供了對不同管理程序虛擬化技術(shù)的支持。歷史上,為了支持不同的虛擬機(jī)超級管理器 (hypervisor,下文簡稱超級管理器),需要不同的二進(jìn)制內(nèi)核,這個限制已經(jīng)被pv_ops移 除了。Linux pv_ops是一個虛擬化API,它能夠支持不同的管理程序。它允許每個管理程序 優(yōu)先于關(guān)鍵操作,并允許單一的內(nèi)核二進(jìn)制文件在所有支持的執(zhí)行環(huán)境中運(yùn)行,包括本機(jī)——沒 有任何管理程序。
pv_ops提供了一組函數(shù)指針,代表了與低級關(guān)鍵指令和各領(lǐng)域高級功能相對應(yīng)的操作。 pv-ops允許在運(yùn)行時進(jìn)行優(yōu)化,在啟動時對低級關(guān)鍵操作進(jìn)行二進(jìn)制修補(bǔ)。
pv_ops操作被分為三類:
簡單的間接調(diào)用
這些操作對應(yīng)于高水平的函數(shù),眾所周知,間接調(diào)用的開銷并不十分重要。
間接調(diào)用,允許用二進(jìn)制補(bǔ)丁進(jìn)行優(yōu)化
通常情況下,這些操作對應(yīng)于低級別的關(guān)鍵指令。它們被頻繁地調(diào)用,并且是對性能關(guān) 鍵。開銷是非常重要的。
一套用于手寫匯編代碼的宏程序
手寫的匯編代碼(.S文件)也需要半虛擬化,因為它們包括敏感指令或其中的一些代 碼路徑對性能非常關(guān)鍵。
二、客戶機(jī)停機(jī)輪詢機(jī)制(Guest halt polling)
cpuidle_haltpoll驅(qū)動,與haltpoll管理器一起,允許客戶機(jī)vcpus在停機(jī)前輪詢 一定的時間。
這為物理機(jī)側(cè)的輪詢提供了以下好處:
在執(zhí)行輪詢時,POLL標(biāo)志被設(shè)置,這允許遠(yuǎn)程vCPU在執(zhí)行喚醒時避免發(fā)送 IPI(以及處理IPI的相關(guān)成本)。
可以避免虛擬機(jī)退出的成本。
客戶機(jī)側(cè)輪詢的缺點(diǎn)是,即使在物理機(jī)中的其他可運(yùn)行任務(wù)中也會進(jìn)行輪詢。
其基本邏輯如下。一個全局值,即guest_halt_poll_ns,是由用戶配置的,表示允 許輪詢的最大時間量。這個值是固定的。
每個vcpu都有一個可調(diào)整的guest_halt_poll_ns(”per-cpu guest_halt_poll_ns”), 它由算法響應(yīng)事件進(jìn)行調(diào)整(解釋如下)。
模塊參數(shù) haltpoll管理器有5個可調(diào)整的模塊參數(shù):
1.guest_halt_poll_ns:
輪詢停機(jī)前執(zhí)行的最大時間,以納秒為單位。 默認(rèn)值: 200000
2.guest_halt_poll_shrink:
當(dāng)喚醒事件發(fā)生在全局的guest_halt_poll_ns之后,用于縮減每個CPU的guest_halt_poll_ns 的劃分系數(shù)。 默認(rèn)值: 2
3.guest_halt_poll_grow:
當(dāng)事件發(fā)生在per-cpu guest_halt_poll_ns之后但在global guest_halt_poll_ns之前, 用于增長per-cpu guest_halt_poll_ns的乘法系數(shù)。 默認(rèn)值: 2
4.guest_halt_poll_grow_start:
在系統(tǒng)空閑的情況下,每個cpu guest_halt_poll_ns最終達(dá)到零。這個值設(shè)置了增長時的 初始每cpu guest_halt_poll_ns。這個值可以從10000開始增加,以避免在最初的增長階 段出現(xiàn)失誤。: 10k, 20k, 40k, … (例如,假設(shè)guest_halt_poll_grow=2). 默認(rèn)值: 50000
5.guest_halt_poll_allow_shrink:
允許縮減的Bool參數(shù)。設(shè)置為N以避免它(一旦達(dá)到全局的guest_halt_poll_ns值,每CPU的 guest_halt_poll_ns將保持高位)。 默認(rèn)值: Y 模塊參數(shù)可以從Debugfs文件中設(shè)置,在: /sys/module/haltpoll/parameters/
在設(shè)置guest_halt_poll_ns參數(shù)時應(yīng)該小心,因為一個大的值有可能使幾乎是完全空閑機(jī) 器上的cpu使用率達(dá)到100%。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。∏?00名進(jìn)群領(lǐng)取,額外贈送一份價值699的內(nèi)核資料包(含視頻教程、電子書、實戰(zhàn)項目及代碼)??

三、Nitro Enclaves
Nitro Enclaves(NE)是亞馬遜彈性計算云(EC2)的一項新功能,允許客戶在EC2實 例中劃分出孤立的計算環(huán)境[1]。 例如,一個處理敏感數(shù)據(jù)并在虛擬機(jī)中運(yùn)行的應(yīng)用程序,可以與在同一虛擬機(jī)中運(yùn)行的 其他應(yīng)用程序分開。然后,這個應(yīng)用程序在一個獨(dú)立于主虛擬機(jī)的虛擬機(jī)中運(yùn)行,即 enclave。 一個enclave與催生它的虛擬機(jī)一起運(yùn)行。這種設(shè)置符合低延遲應(yīng)用的需要。為enclave 分配的資源,如內(nèi)存和CPU,是從主虛擬機(jī)中分割出來的。每個enclave都被映射到一 個運(yùn)行在主虛擬機(jī)中的進(jìn)程,該進(jìn)程通過一個ioctl接口與NE驅(qū)動進(jìn)行通信。 在這個意義上,有兩個組成部分。
1. 一個enclave抽象進(jìn)程——一個運(yùn)行在主虛擬機(jī)客體中的用戶空間進(jìn)程,它使用NE驅(qū)動 提供的ioctl接口來生成一個enclave虛擬機(jī)(這就是下面的2)。 有一個NE模擬的PCI設(shè)備暴露給主虛擬機(jī)。這個新的PCI設(shè)備的驅(qū)動被包含在NE驅(qū)動中。 ioctl邏輯被映射到PCI設(shè)備命令,例如,NE_START_ENCLAVE ioctl映射到一個enclave 啟動PCI命令。然后,PCI設(shè)備命令被翻譯成在管理程序方面采取的行動;也就是在運(yùn) 行主虛擬機(jī)的主機(jī)上運(yùn)行的Nitro管理程序。Nitro管理程序是基于KVM核心技術(shù)的。
2. enclave本身——一個運(yùn)行在與催生它的主虛擬機(jī)相同的主機(jī)上的虛擬機(jī)。內(nèi)存和CPU 從主虛擬機(jī)中分割出來,專門用于enclave虛擬機(jī)。enclave沒有連接持久性存儲。 從主虛擬機(jī)中分割出來并給enclave的內(nèi)存區(qū)域需要對齊2 MiB/1 GiB物理連續(xù)的內(nèi)存 區(qū)域(或這個大小的倍數(shù),如8 MiB)。該內(nèi)存可以通過使用hugetlbfs從用戶空間分 配[2][3]。一個enclave的內(nèi)存大小需要至少64 MiB。enclave內(nèi)存和CPU需要來自同 一個NUMA節(jié)點(diǎn)。 一個enclave在專用的核心上運(yùn)行。CPU 0及其同級別的CPU需要保持對主虛擬機(jī)的可用 性。CPU池必須由具有管理能力的用戶為NE目的進(jìn)行設(shè)置。關(guān)于CPU池的格式,請看內(nèi)核 文檔[4]中的cpu list部分。 enclave通過本地通信通道與主虛擬機(jī)進(jìn)行通信,使用virtio-vsock[5]。主虛擬機(jī)有 virtio-pci vsock模擬設(shè)備,而飛地虛擬機(jī)有virtio-mmio vsock模擬設(shè)備。vsock 設(shè)備使用eventfd作為信令。enclave虛擬機(jī)看到通常的接口——本地APIC和IOAPIC——從 virtio-vsock設(shè)備獲得中斷。virtio-mmio設(shè)備被放置在典型的4 GiB以下的內(nèi)存中。 在enclave中運(yùn)行的應(yīng)用程序需要和將在enclave虛擬機(jī)中運(yùn)行的操作系統(tǒng)(如內(nèi)核、 ramdisk、init)一起被打包到enclave鏡像中。enclave虛擬機(jī)有自己的內(nèi)核并遵循標(biāo) 準(zhǔn)的Linux啟動協(xié)議[6]。 內(nèi)核bzImage、內(nèi)核命令行、ramdisk(s)是enclave鏡像格式(EIF)的一部分;另外 還有一個EIF頭,包括元數(shù)據(jù),如magic number、eif版本、鏡像大小和CRC。 哈希值是為整個enclave鏡像(EIF)、內(nèi)核和ramdisk(s)計算的。例如,這被用來檢 查在enclave虛擬機(jī)中加載的enclave鏡像是否是打算運(yùn)行的那個。 這些加密測量包括在由Nitro超級管理器成的簽名證明文件中,并進(jìn)一步用來證明enclave 的身份;KMS是NE集成的服務(wù)的一個例子,它檢查證明文件。 enclave鏡像(EIF)被加載到enclave內(nèi)存中,偏移量為8 MiB。enclave中的初始進(jìn)程 連接到主虛擬機(jī)的vsock CID和一個預(yù)定義的端口–9000,以發(fā)送一個心跳值–0xb7。這 個機(jī)制用于在主虛擬機(jī)中檢查enclave是否已經(jīng)啟動。主虛擬機(jī)的CID是3。 如果enclave虛擬機(jī)崩潰或優(yōu)雅地退出,NE驅(qū)動會收到一個中斷事件。這個事件會通過輪詢 通知機(jī)制進(jìn)一步發(fā)送到運(yùn)行在主虛擬機(jī)中的用戶空間enclave進(jìn)程。然后,用戶空間enclave 進(jìn)程就可以退出了。
四、ACRN超級管理器
1、ACRN超級管理器介紹
ACRN超級管理器是一個第一類超級管理器,直接在裸機(jī)硬件上運(yùn)行。它有一個特權(quán)管理虛擬機(jī),稱為服 務(wù)虛擬機(jī),用于管理用戶虛擬機(jī)和進(jìn)行I/O仿真。
ACRN用戶空間是一個運(yùn)行在服務(wù)虛擬機(jī)中的應(yīng)用程序,它根據(jù)命令行配置為用戶虛擬機(jī)仿真設(shè)備。 ACRN管理程序服務(wù)模塊(HSM)是服務(wù)虛擬機(jī)中的一個內(nèi)核模塊,為ACRN用戶空間提供管理程序服 務(wù)。
下圖展示了該架構(gòu)。

ACRN用戶空間為用戶虛擬機(jī)分配內(nèi)存,配置和初始化用戶虛擬機(jī)使用的設(shè)備,加載虛擬引導(dǎo)程序, 初始化虛擬CPU狀態(tài),處理來自用戶虛擬機(jī)的I/O請求訪問。它使用ioctls來與HSM通信。HSM通過 與ACRN超級管理器的hypercalls進(jìn)行交互來實現(xiàn)管理服務(wù)。HSM向用戶空間輸出一個char設(shè)備接口 (/dev/acrn_hsm)。
2、I/O請求處理
客戶虛擬機(jī)的I/O請求由超級管理器構(gòu)建,由ACRN超級管理器服務(wù)模塊分發(fā)到與I/O請求的地址范 圍相對應(yīng)的I/O客戶端。I/O請求處理的細(xì)節(jié)將在以下章節(jié)描述。
I/O請求 對于每個客戶虛擬機(jī),有一個共享的4KB字節(jié)的內(nèi)存區(qū)域,用于超級管理器和服務(wù)虛擬機(jī)之間的 I/O請求通信。一個I/O請求是一個256字節(jié)的結(jié)構(gòu)體緩沖區(qū),它是 “acrn_io_request” 結(jié)構(gòu) 體,當(dāng)客戶虛擬機(jī)中發(fā)生被困的I/O訪問時,由超級管理器的I/O處理器填充。服務(wù)虛擬機(jī)中的 ACRN用戶空間首先分配一個4KB字節(jié)的頁面,并將緩沖區(qū)的GPA(客戶物理地址)傳遞給管理平 臺。緩沖區(qū)被用作16個I/O請求槽的數(shù)組,每個I/O請求槽為256字節(jié)。這個數(shù)組是按vCPU ID 索引的。
I/O客戶端 一個I/O客戶端負(fù)責(zé)處理客戶虛擬機(jī)的I/O請求,其訪問的GPA在一定范圍內(nèi)。每個客戶虛擬機(jī) 可以關(guān)聯(lián)多個I/O客戶端。每個客戶虛擬機(jī)都有一個特殊的客戶端,稱為默認(rèn)客戶端,負(fù)責(zé)處理 所有不在其他客戶端范圍內(nèi)的I/O請求。ACRN用戶空間充當(dāng)每個客戶虛擬機(jī)的默認(rèn)客戶端。 下面的圖示顯示了I/O請求共享緩沖區(qū)、I/O請求和I/O客戶端之間的關(guān)系。

3. I/O請求狀態(tài)轉(zhuǎn)換
一個ACRN I/O請求的狀態(tài)轉(zhuǎn)換如下。

FREE: 這個I/O請求槽是空的
PENDING: 在這個槽位上有一個有效的I/O請求正在等待
PROCESSING: 正在處理I/O請求
COMPLETE: 該I/O請求已被處理
處于COMPLETE或FREE狀態(tài)的I/O請求是由超級管理器擁有的。HSM和ACRN用戶空間負(fù)責(zé)處理其 他的。
4. I/O請求的處理流程
當(dāng)客戶虛擬機(jī)中發(fā)生被陷入的I/O訪問時,超級管理器的I/O處理程序?qū)袸/O請求填充為 PENDING狀態(tài)。
超級管理器向服務(wù)虛擬機(jī)發(fā)出一個向上調(diào)用,這是一個通知中斷。
upcall處理程序會安排一個工作者來調(diào)度I/O請求。
工作者尋找PENDING I/O請求,根據(jù)I/O訪問的地址將其分配給不同的注冊客戶,將其 狀態(tài)更新為PROCESSING,并通知相應(yīng)的客戶進(jìn)行處理。
被通知的客戶端處理指定的I/O請求。
HSM將I/O請求狀態(tài)更新為COMPLETE,并通過hypercalls通知超級管理器完成。
在ACRN超級管理器上運(yùn)行的客戶虛擬機(jī)可以使用CPUID檢查其一些功能。
ACRN的cpuid函數(shù)是:
函數(shù): 0x40000000
返回:

注意,ebx,ecx和edx中的這個值對應(yīng)于字符串“ACRNACRNACRN”。eax中的值對應(yīng)于這個葉子 中存在的最大cpuid函數(shù),如果將來有更多的函數(shù)加入,將被更新。
函數(shù): define ACRN_CPUID_FEATURES (0x40000001)
返回:

其中flag的定義如下:

函數(shù): 0x40000010
返回:

