在前幾天,我們時做簡易的 host I/O 模組,並且透過 KVM_CREATE_IRQCHIP + KVM_IRQ_LINE 將 IRQ 傳遞給 Guest。這代表 Guest 可以真正的感受到外部事件觸發。
下一步,我們要進入下一個主題記憶體管理。
Guest 的實體地址 (GPA)如何對應到 Host 的記憶體?
KVM 在軟體層定義了一個結構 KVM Memory Slot。
在 KVM 中,每一段 Guest 的實體記憶體會對應到 Host 的一段 usersapce 虛擬地址。這種映射透過 KVM_SET_USER_MEMORY_REGION ioctl 完成。
struct kvm_userspace_memory_region {
__u32 slot;
__u32 flags;
__u64 guest_phys_addr;
__u64 memory_size; /* bytes */
__u64 userspace_addr; /* start of the userspace allocated memory */
};
/* for kvm_userspace_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
#define KVM_MEM_READONLY (1UL << 1)
KVM 利用這個結構維護記憶體映射關係,它的用途是
GPA → KVM slot 表 → HVA
在 Guest 他會看到自己的 RAM,但實際上這個 RAM 是透過 Host 以 malloc/mmap 等方式建立的 buffer。
以下為欄位的說明
GVA → Guest Page Table → GPA → (查 memory slot) → HVA → Host Page Table → HPA
這樣會導致頻繁的 VM-exit 拖垮執行性能。
現代處理器則提供 EPT (Intel) / NPT (AMD),將 GPA → HPA 的轉換下放給硬體完成。KVM 只需第一次訪問時根據 memory slot 建立 EPT 表,之後所有翻譯都由 CPU 的 page walker 與 TLB 快取直接處理。
僅在訪問未映射或權限錯誤時才會產生 VM-exit。