CPU Virtualization¶
Làm sao để nhiều OS cùng chạy trên một CPU mà mỗi OS vẫn tưởng mình nắm toàn quyền. Trang này nói về phần CPU, bộ nhớ xem Memory Virtualization, thiết bị xem I/O Virtualization.
Vấn đề cần giải quyết¶
Guest OS được viết để chạy ở mức đặc quyền cao nhất (kernel mode). Nhưng hypervisor mới là bên phải giữ quyền cao nhất. Vì vậy các lệnh và thanh ghi "nhạy cảm" (đổi page table, tắt ngắt, truy cập I/O...) của guest phải bị chặn lại và xử lý thay.
Mô hình kinh điển là trap-and-emulate: guest chạy ở mức quyền thấp hơn, khi gặp lệnh nhạy cảm thì CPU trap về hypervisor, hypervisor mô phỏng hiệu ứng rồi cho guest chạy tiếp. Mô hình này chỉ chạy đúng nếu mọi lệnh nhạy cảm đều gây trap, điều mà x86 trước khi có hỗ trợ ảo hóa không đảm bảo.
Ba hướng tiếp cận¶
| Hướng | Cách làm | Ví dụ |
|---|---|---|
| Binary translation (full virtualization bằng phần mềm) | Hypervisor quét và viết lại các lệnh nhạy cảm của guest trước khi chạy | VMware thời kỳ đầu |
| Para-virtualization | Sửa guest OS để gọi thẳng hypervisor qua hypercall thay vì dùng lệnh nhạy cảm | Xen PV, virtio (cho thiết bị) |
| Hardware-assisted | CPU có thêm chế độ chạy guest, các sự kiện nhạy cảm tự chuyển quyền về hypervisor | Intel VT-x, AMD-V, ARM EL2, RISC-V H-extension |
Hardware-assisted là mặc định hiện nay: guest không cần sửa và chạy trực tiếp trên CPU.
Hỗ trợ phần cứng theo kiến trúc¶
| Kiến trúc | Chế độ/mức quyền | Cấu trúc điều khiển | Ghi chú |
|---|---|---|---|
| Intel VT-x | VMX root (hypervisor) và VMX non-root (guest) | VMCS | VM entry bằng VMLAUNCH/VMRESUME, thoát về hypervisor gọi là VM exit |
| AMD-V (SVM) | Host mode và guest mode | VMCB | Vào guest bằng VMRUN |
| ARMv8-A | Hypervisor chạy ở EL2, guest kernel ở EL1, guest app ở EL0 | Các thanh ghi *_EL2 (ví dụ HCR_EL2 chọn sự kiện nào bị trap) |
VHE (từ ARMv8.1) cho phép host kernel chạy thẳng ở EL2, giảm chi phí chuyển ngữ cảnh cho KVM |
| RISC-V | H-extension: HS-mode (hypervisor), VS/VU-mode (guest) | CSR như hstatus, hedeleg |
Xem thêm RISC-V Server SoC Spec |
VM exit và chi phí¶
Mỗi lần guest cần hypervisor can thiệp là một VM exit. Chi phí của một exit gồm lưu trạng thái guest, chạy mã hypervisor, nạp lại trạng thái, nên hiệu năng ảo hóa phụ thuộc chủ yếu vào việc giảm số exit. Các nguyên nhân thường gặp:
- Truy cập I/O hoặc MMIO của thiết bị giả lập.
- Lệnh như
CPUID, truy cập MSR hoặc thanh ghi hệ thống bị cấu hình để trap. - Lỗi bảng trang lồng nhau (xem Memory Virtualization).
- Ngắt ngoài và timer.
- Hypercall do guest chủ động gọi.
Cách giảm exit: dùng thiết bị para-virtual, passthrough, ảo hóa bộ điều khiển ngắt bằng phần cứng (APIC virtualization, posted interrupts, GICv4).
vCPU và lập lịch¶
vCPU là CPU ảo của VM. Với KVM, mỗi vCPU là một thread của host nên lập lịch bởi scheduler của Linux (xem KVM & QEMU). Có hai chế độ cấp CPU:
- Chia sẻ: nhiều vCPU chạy luân phiên trên một core vật lý, tiện nhưng độ trễ khó dự đoán.
- Gán cứng (pinning/partitioning): mỗi vCPU gắn với một core vật lý riêng, bắt buộc với yêu cầu real-time. Với KVM trên server x86, cách làm cụ thể (cô lập core, pin vCPU và emulator thread, đo độ trễ) xem Real-time KVM tuning. Với SoC nhúng cần chia cứng thì xem Partitioning hypervisor.