---
title: KVM 内存与设备虚拟化
url: https://doc.liz6.com/linux-kernel/13-kvm-and-virtualization/02-kvm-memory-and-device-virtualization
locale: zh
area: linux-kernel
tags:
- linux-kernel
- KVM与虚拟化
date: 2026-06-30
modified: 2026-06-30
description: '覆盖: EPT/NPT (stage-2 page table) → MMU 虚拟化 → virtio (半虚拟化) → VFIO (直通) → vhost (内核态加速) → virtio-net/virtio-blk 详解 内核版本: 2.6 ~ 6.x'
---

# KVM 内存与设备虚拟化

> 覆盖: EPT/NPT (stage-2 page table) → MMU 虚拟化 → virtio (半虚拟化) → VFIO (直通) → vhost (内核态加速) → virtio-net/virtio-blk 详解
> 内核版本: 2.6 ~ 6.x

## 内存虚拟化: EPT/NPT

```
三层地址转换:
  GVA (guest virtual address)
    → guest page table (guest OS 管理)
    → GPA (guest physical address)
      → EPT/NPT (KVM 管理, "stage-2 page table")
      → HPA (host physical address)

EPT (Intel Extended Page Tables) / NPT (AMD Nested Page Tables):
  硬件直接执行 GVA→GPA→HPA 的 2D page walk (24 步!)
  → 不需要 KVM 维护影子页表 (shadow page table)
  → 现代 CPU 皆有硬件支持

EPT violation: guest 修改自己的页表 → EPT 页表过期 → VM exit
  → KVM 更新 EPT 映射 → VMRESUME
```

### MMU 虚拟化

```c
// arch/x86/kvm/mmu/mmu.c
// KVM MMU 维护两种页表:
//   1. EPT 页表 (硬件使用): GPN → HPN
//   2. 影子页表 (仅无 EPT 的旧 CPU): GVA → HPA

// TDP (Two-Dimensional Paging) = EPT on Intel, NPT on AMD

// kvm_mmu_page_fault():
//   guest 访问 GPA → EPT violation → handle_ept_violation()
//     → kvm_mmu_map() → 在 EPT 中建立 GPA→HPA 映射
//     → 返回 guest
```

---

## virtio: 半虚拟化 IO

```c
// drivers/virtio/
// 设计原则: guest 知道自己在 VM 中 → 用共享内存(virtqueue)通信
//          不需要模拟真实硬件 → 极高的 IO 性能

// virtio 设备模型:
//   前端 (guest): virtio-blk, virtio-net, virtio-scsi, virtio-gpu
//   后端 (host): 
//     QEMU (软件模拟)
//     vhost (内核态加速: vhost-net, vhost-scsi, vhost-vsock)
//     vDPA (硬件加速: 网卡/smartNIC)
```

### virtqueue: 共享环形缓冲

```c
// virtio 的核心传输机制:
//   1. split virtqueue: 传统格式 (descriptor table + available ring + used ring)
//   2. packed virtqueue (1.1): 更紧凑, cache line 友好

// guest 提交 IO:
//   写 descriptor + available ring → kick (写 doorbell)
// host 消费:
//   取 descriptor → 处理 IO → 写 used ring → interrupt (MSI-X)
// guest complete:
//   中断 → 读 used ring → 释放 buffer
```

### vhost: 内核态加速

```c
// drivers/vhost/net.c
// vhost 把 virtio 数据路径移到内核:
//   guest → virtqueue → vhost (host 内核) → tap device → 协议栈
//   绕过 QEMU 用户态 → 延迟 ~50% 降低

// vhost-net:   网络 (最常用)
// vhost-scsi:  存储
// vhost-vsock: guest↔host 通信 (AF_UNIX 跨 VM 边界)
```

---

## VFIO: 设备直通

```c
// 将物理 PCIe 设备独占分配给 guest:
//   1. 从 host 解绑设备 (echo dev > /sys/bus/pci/drivers/xxx/unbind)
//   2. 绑定到 vfio-pci (echo vendor device > /sys/bus/pci/drivers/vfio-pci/new_id)
//   3. QEMU: -device vfio-pci,host=01:00.0
//   4. IOMMU 隔离: 设备 DMA 只能访问此 VM 的内存

// 性能: 接近裸机 (GPU, NVMe 直通给 guest)
// 限制: 不能在线迁移 (设备状态无法保存/恢复)
```

---

## 参考

- **源码**: `arch/x86/kvm/mmu/`, `drivers/virtio/`, `drivers/vhost/`, `drivers/vfio/`
- **内核文档**: `Documentation/virt/kvm/`, `Documentation/driver-api/virtio/`
- **LWN**: "Virtio without the QEMU middleman (vhost)", "VFIO and device assignment"

*关键词: EPT, NPT, stage-2 page table, virtio, virtqueue, vhost, VFIO, PCI passthrough*
