KVM 原理簡介

一、 概述

KVM 的全稱是 Kernel-based Virtual Machine,其是一種基於 linux 內核的採用硬件輔助虛擬化技術的全虛擬化解決方案。它最初由以色列的初創公司 Qumranet 開發,並在 linux-2.6.20 中開始被納入在 linux 內核,成爲內核源碼的一部分。KVM 自誕生之初就定位於基於硬件輔助的虛擬化來提供全虛擬化的支持,其以內核模塊的形式被加載。加載 KVM 模塊的 linux 內核相當於變成了一個 Hypervisor,同時依賴 linux 內核提供的各種功能來實現硬件管理,擁有極高的兼容性及可擴展性。

上面提到 KVM 是作爲一個內核模塊出現的,所以它還得藉助用戶空間的程序來和用戶進行交互,這就不得不提到大名鼎鼎的 QEMU 了。QEMU 是一套由法布里斯 · 貝拉 (Fabrice Bellard) 所編寫的以 GPL 許可證分發源碼的模擬處理器,在 GNU/Linux 平臺上使用廣泛。其本身是一個純軟件的支持 CPU 虛擬化、內存虛擬化及 I/O 虛擬化等功能的用戶空間程序。其藉助 KVM 提供的虛擬化支持可以將 CPU、內存等虛擬化工作交由 KVM 處理,自己則處理大多數 I/O 虛擬化的功能,可以實現極高的虛擬化效率。KVM 及 QEMU 配合使用的整體接口如圖 1 所示。

QEMU 儘管非常的強大,但也正是應爲它的強大導致其對初學者非常的不友好。這裏推薦大家剛開始學習 KVM 時可以先學習 kvm tool,這是一個基於 C 語言開發的 KVM 虛擬化工具,其代碼非常精簡易懂,同時也可以支持完整的 linux 虛擬化,非常適合初學者入門使用。其項目地址爲 https://github.com/kvmtool/kvmtool。

二、 ARM64 虛擬化支持

arm 最早在 armv7-a 引入硬件虛擬化支持。到了 armv8 中,arm 拋棄了 armv7 時代的特權級,引入了全新的 Exception Level(EL),其如圖 2 所示 (armv8.4-A 引入了對安全世界虛擬化的支持)。

圖 2

其中 4 個異常等級中的 EL2 留給 Hypervisor 用於各種虛擬化功能的訪問及配置,如:stage 2 轉換、EL1/EL0 指令和寄存器訪問、注入虛擬異常等。

三、 CPU 虛擬化

CPU 被稱爲計算機的大腦,是計算機系統中最核心的模塊。在沒有 CPU 硬件虛擬化技術之前都是使用二進制指令動態翻譯技術來實現對客戶機操作系統中執行的執行(例如 qemu 的軟件虛擬化),其不僅實現複雜而且效率非常低下。因此硬件虛擬化技術應運而生,爲 KVM 的誕生創造了必要的條件。

有時 Hypervisor 需要模擬一些操作,例如 VM 裏運行的軟件試圖配置處理器的一些屬性,如電源管理或是緩存一致性時。通常你不會允許 VM 直接配置這些屬性,因爲這會打破隔離性,從而影響其他 VMs。這就需要通過以陷入的方式產生異常,在異常處理程序中做相應的模擬。armv8 包含一些陷入控制來幫助實現陷入 (trapping) – 模擬 (emulating)。如果對相應操作配置了陷入,則這種操作發生時會陷入到更高的異常級別。

例如,正常我們在執行 WFI 指令時會使 CPU 進入一個低功耗的狀態,但是對於 HOST OS 來說,如果讓 CPU 真正進入低功耗狀態,顯然會影響其他 VM 的運行。如果我們配置了 HCR_EL2.TWI==1 時,那麼 Guest OS 在執行 WFI 時就會觸發 EL2 的異常,然後陷入 Hypervisor,那麼此時 Hypervisor 就可以將對應 VCPU 所處的線程調出出去,將 CPU 讓給其他的 VCPU 線程使用。

圖 3

四、 內存虛擬化

內存虛擬化的目的是給虛擬客戶機操作系統提供一個從 0 開始的連續的地址空間,同時在多個客戶機之間實現隔離與調度。

arm 主要通過 Stage 2 轉換來提供對內存虛擬化的支持,其允許 Hypervisor 控制虛擬機的內存視圖,而在這之前則是使用及其複雜的影子頁表技術來實現。Stage 2 轉換可以控制虛擬機是否可以訪問特定的某一塊物理內存,以及該內存塊出現在虛擬機內存空間的位置。這種能力對於虛擬機的隔離和沙箱功能來說至關重要。這使得虛擬機只能看到分配給它自己的物理內存。爲了支持 Stage 2 轉換, 需要增加一個頁表,我們稱之爲 Stage 2 頁表。操作系統控制的頁錶轉換稱之爲 stage 1 轉換,負責將虛擬機視角的虛擬地址轉換爲虛擬機視角的物理地址。而 stage 2 頁表由 Hypervisor 控制,負責將虛擬機視角的物理地址轉換爲真實的物理地址。虛擬機視角的物理地址在 Armv8 中有特定的詞描述,叫中間物理地址 (intermediate Physical Address, IPA)。

stage 2 轉換表的格式和 stage 1 的類似,但也有些屬性的處理不太一樣,例如, 判斷內存類型 是 normal 還是 device 的信息被直接編碼進了表裏,而不是通過查詢 MAIR_ELx 寄存器。

圖 4

五、 I/O 虛擬化

I/O 設備作爲一種外部設備,其虛擬化的實現相較於前面的 CPU 虛擬化及內存虛擬化有些不同,其目前主要有以下四種虛擬化方案。

1、 設備模擬:

在虛擬機監控器中模擬具體的 I/O 設備的特性,例如 qemu。在 KVM 和 qemu 的組合中通過 Hypervisor 捕獲 Guest OS 的 I/O 請求交給用戶空間的 qemu 進行模擬,然後將結果再通過 Hypervisor 傳遞給 Guest OS。這種方式能夠提供非常好的兼容性但是性能太差,同時模擬設備的功能特性支持不夠多。

2、 前後端驅動接口

在 Hypervisor 和 Guest OS 之間定義一種權限的適用於虛擬機的交互接口,比如 virtio 技術。這個方案相較於設備模擬在性能上有所提高,但是兼容性較差,而且在高 I/O 負載場景,後端驅動的 CPU 佔用較高。

3、 設備直接分配

將一個物理設備直接分配給 Guest OS 使用。此方式的性能顯而易見,要比上面兩種好很多,但是需要硬件設備支持,且無法共享和動態遷移。

4、 設備共享分配

此方式是設備直接分配的一個擴展,其主要就是讓一個物理設備可以支持多個虛擬機功能接口,將不同的接口地址獨立分配給不同的 Guest OS 使用。如 SR-IOV 協議。

參考文獻:

1、《KVM 實戰:原理、進階與性能調優》

2、https://segmentfault.com/a/1190000022797518

3、https://www.cnblogs.com/LoyenWang/

內核工匠微信

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/50cGK-z9zZZAI9FR1BNDYQ