# 2024-05-23 KVM: Linux 虛擬化基礎建設 [TOC] ## Introduction ### Types of Hypervisor - Type 1: 虛擬機器管理程式 (hypervisor) 直接在硬體上執行,e.g. XEN - Type 2: 虛擬機器管理程式 (hypervisor) 在通用作業系統上執行,e.g. KVM - host OS -> hypervisor (KVM) -> guest OS ### Basic Concepts VMM: virtual machine monitor,和 hypervisor 是同義詞 硬體虛擬化分三個部分: - CPU 虛擬化 - Memory 虛擬化 - Peripheral 虛擬化 guest OS 有存取硬體的要求但又不能直接存取硬體 guest OS 和 guest OS 之間要能夠分享資訊,guest OS 和 host OS 之間也要能夠分享資訊 虛擬化的好處 - 虛擬化可以解決 scalability 問題,稱為 workload consolidation,increase server utilization,reduce capital, hardware, power, space, heat costs - 工作負載變化很大,訂票網站 - legacy OS support - e.g. 任天堂模擬器 - EDA tools 只授權某些平台某些版本,可以在新系統模擬舊系統 - instant provisioning - 客製化,可以 config 硬體配置 (memory, processor, I/O)、系統組態 - migration - live migration:從一台機器移動到另一台機器,服務不會暫停 ### Xen 早在 1990 年代就問世,為 type-1 hypervisor,主要為 AWS 所採用,AWS 的 ex-CTO 就是 Xen 的核心人物,至今還有以 Xen 虛擬化為基礎的虛擬機器服務,在 EC2 的設定當中,但較新的服務都是 KVM 為基礎 Xen 的 Domain-0 (Dom0) 和 Domain-U (DomU) 就是為了解決裝置虛擬化,Dom-0 負責和硬體打交道,Dom-U 來模擬虛擬硬體,Xen 負責彼此之間溝通 需要兩套 device driver: - Dom-0 的 device driver 稱為 backend driver - Dom-U 有 device driver 稱為 frontend driver - 兩者之間可以溝通,像是網路一樣 Xen 有其優勢,但無法 leverage Linux 最新技術,因此有了 KVM ### KVM 以 Linux 為基礎的虛擬機器基礎建設 Virtual Box 很長一段時間都是用自己的虛擬化技術,最近開始支援 KVM,可以有圖形化工具,可以在 guest OS 和 host OS 分享資料、網路、細緻調整組態 2005 年左右開放原始碼 (大約 20000 行),2006 年 Intel 和 AMD 開始加入硬體虛擬化特性 (Intel VT-x 和 AMD-V),需要有相關的系統軟體的支援,因此 KVM 開始聲名大噪,在 2006 年下半收錄於 Linux kernel 當中 與 Xen 的比較: - Xen 是通用的虛擬化技術,就算硬體沒有支援虛擬化,也能使用 - 最新的 Linux 技術,使用 KVM,因為其為 Linux kernel 的一部分 KVM 只實作 HVM (hardware virtual machine),和 QEMU 合作,由 QEMU 負責 userspace,搭配 KVM 可以達到硬體加速 VMWare 和 Vitual Box 出現得都比 KVM 早,但因為 KVM 定位為 Linux kernel 基礎建設,因此很早就被收納到 Linux 中 VMWare 和 Vitual Box 由公司開發,即便後來開放原始碼,也未必能被 Linux kernel 接受,即便其有很多和 Linux 核心有關的技術 ### Cloud-hypervisor scale-up:變大 scale-out:變多 著重在 aarch64 和 x86_64 架構,有很多值得學習的地方,有很多不同公司的協作,一開始來自 Intel,現由 Linux 基金會託管,後來陸續有多家公司加入像是 AMD、Microsoft,並納入很多新的技術像是 Kernel Virtual Machine (KVM) 和 Microsoft Hypervisor (MSHV) 虛擬化有三個層面:CPU 虛擬化、記憶體虛擬化和周邊裝置虛擬化,前兩者可以透過硬體虛擬化提供關鍵操作來得到加速,周邊裝置虛擬化則透過 virtio,只要 guest OS 和 hypervisor 的裝置驅動程式都支援 virtio 規範的介面,兩者之間就能溝通,而且 guest OS 的維護成本可以降低 (不需要 Dom0 和 DomU) Cloud hypervisor 由 Rust 實作,Linux kernel 近期內不太可能用 Rust 重寫,但是有越來越多關鍵的軟體正在以 Rust 重寫,包括 Microsoft 在內,Windows 已經有一部份程式改用 Rust 重寫 Rust 系統層級的程式語言,但又比 C 有更豐富的語言特性,但又不致於像是 C++ 那麼複雜那麼失控,很精緻、很嚴格的控管其語言特徵,且很在意 memory safety,對於 concurrency 有很好的支援 - 以 VirtIO 為基礎的 para-virtualized device (para-:希臘語中「半」的意思),降低開發與維護成本 ### Confidential Computing coco: Linux kernel 中 confidential computing 的技術和基礎建設 SEV (secure encrypted virtualization) 記憶體加密技術 若沒有這項技術,其中一個虛擬機器可以透過找到 VM 和 hypervisor 之間共相的資源,來存取到其他虛擬機器的資料,產生資訊安全問題 ### Other Virtualization Projects - 打造一個輕量化的 type-1 虛擬機器:[xvisor](https://wiki.csie.ncku.edu.tw/embedded/xvisor) (jserv 開發) - 用於歐洲太空任務的虛擬化技術:[bao hypervisor](https://github.com/bao-project/bao-hypervisor) ## Hypervisor 的分類 ### Type-1 要求對於開機速度、反應速度,例如太空任務、火箭 device driver 要全部自己實作,對於開發者有很大的挑戰 ### Type-2 要求既有軟硬體相容性,例如雲端公司 可以不用重寫 device driver type-2 資料傳遞的路徑較長,但不代表會慢,電腦科學衡量「速度」有兩個面向,throughput 和 latency,type-2 hypervisor 的 throughput 不錯,但 latency 不如 type-1 hypervisor 但實際差異還是要看 device driver 的具體實作,參考 [以 sendfile 和 splice 系統呼叫達到 Zero-Copy](https://hackmd.io/@sysprog/linux2020-zerocopy) 的內容: 以一般的 I/O 來說,把檔案內容藉由 socket 傳出會如以下 ```c read(file, buf, len); // 從核心讀取檔案內容 write(socket, buf, len); // 把內容藉由核心寫出 ``` 相當於把資料從 kernel 複製到 userspace,又把資料再複製到 kernel,算上 DMA 的控制,總共會花 3~4 四的複製 但如果用 sendfile ```c sendfile(socket, file, len); ``` 直接叫 kernel 把檔案傳出,還是要做資料複製 (3 次),但都在 kernel 內完成,user-kernel 之間沒有 copy 省下巨大的成本: - TLB flush (確保 page table 內容一致性) - CPU pipeline flush - cache (userspace 和 kernel space 的內容不一樣) - MMU 特權模式設定的成本 ## KVM Philosophy - reuse Linux code as mush as possible KVM 是 Linux kernel 的一部分,本質上就是個 kernel module,只要 Linux 持續更新,KVM 就能利用到 Linux 最新的技術 實際拿實驗室的 server 來觀察: - CPU 有支援硬體虛擬化技術 VT-x (VT 是 virtualization technology,第一代 VT-x 專注在 CPU 層級的虛擬化,第二代則是 VT-d 著重在記憶體的虛擬化,可以參考 [Embedded Virtualization applied in Mobile Devices](https://www.slideshare.net/jserv/mobile-virtualization)) ![image](https://hackmd.io/_uploads/SyYTu6hm0.png) - Linux kernel 有 KVM 模組 `kvm_intel` ![image](https://hackmd.io/_uploads/By_tda3QA.png) - 但 KVM 不可用 ![image](https://hackmd.io/_uploads/SJ0PKah70.png) - 可用的長這樣 ![image](https://hackmd.io/_uploads/By4PFp3XA.png) ### KVM Guest Mode - user mode - kernel mode - guest mode 沿用 Linux kernel 原有的 CPU 排程器,Linux 的排程器專注於 scalability,因此雲端運算幾乎都採用 KVM MMU 做 virtual address 轉 physical address 但有虛擬化時,需要有 IPA (intermediate physical address) ![image](https://hackmd.io/_uploads/rklAo63XA.png) memory translation 本身就有成本,更何況 IPA,因此第二代虛擬化技術 (AMD-Vi 和 Intel VT-d) 就是在解決這方面的問題 ## Linux Kernel Integration 虛擬機在做 live migration 時會發生 page fault,需要有對應的處理,Linux kernel 提供了一個特殊的 system call [Userfaultfd](https://docs.kernel.org/admin-guide/mm/userfaultfd.html) 把 page 做成 fd 的好處就是可以用 epoll 叫 kernel 幫忙監控 page fault 的發生,或是讓 userland 來決定怎麼處理 page fault (signalfd 同理) ## KVM Paravirtualization 周邊裝置虛擬化較 CPU 和記憶體虛擬化麻煩,因為涉及到 hypervisor 自己的特色 (裝置管理方式),且希望避免非必要的 device driver 撰寫,KVM 的做法是定義了一系列 paravirtualization 的介面,讓 guest OS 的 device driver 可以轉發到 host OS 的 device driver 上,而這件事的困難點就在於要怎麼定義這樣的介面,這也是之所以 VirtIO 的規格書需要多達三百頁的原因 ## PCI Passthrough VirtIO 在低延遲、高吞吐量 (例如網路傳輸) 的情境下不夠用,這樣的情況下希望讓 guest OS 直接去操控硬體,稱為 pass through,困難點在於提升效能的同時兼顧安全性的考量,做得好甚至有機會比 type-1 hypervisor 還快! ## QEMU DBT (Dynamic Binary Translation) TCG (Tiny Code Gen) 只需要關注特權指令等特殊指令 SR-IOV 安全的 PCI pass through ## KVM-Host