# 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