IO虚拟化——设备直通
## 设备直通和非设备直通
### 流程对比
+ 非直通虚拟网卡
1. 虚拟机驱动准备DMA缓冲区
+ 虚拟机内的网络驱动准备发送数据包,分配一块内存缓冲区,地址为**客户机物理地址(GPA)**(例GPA 0x1000)
2. 驱动触发虚拟设备操作
+ 驱动将GPA 0x1000写入虚拟网卡的DMA地址寄存器(通过MMIO操作)。
+ 虚拟机内的CPU执行MMIO写指令,目标地址为虚拟网卡的寄存器(GPA 0xA000)
3. EPT转换MMIO地址
+ CPU访问MMIO地0xA000时,**EPT(Extended Page Tables)**将其转换为宿主机的物理地址(HPA 0x5000),定位到QEMU模拟的虚拟网卡寄存器。
4. QEMU截获DMA请求
+ QEMU模拟的虚拟网卡接收到DMA配置(目标地址为GPA 0x1000),触发模拟的DMA传输流程。
+ QEMU通过**EPT页表**将GPA 0x1000转换为宿主机的HPA(例HPA 0x8000)。
5. 宿主机驱动发起真实DMA
+ QEMU调用宿主机内核的DMA API(dma_map_single()),使用转换后的HPA 0x8000配置物理网卡的DMA引擎。
+ 物理网卡直接从HPA 0x8000读取数据并发送到网络。
6. 传输完成与中断通知
+ 物理网卡完成数据传输后,通过中断通知宿主机驱动。
+ QEMU模拟虚拟中断,通知虚拟机驱动数据已发送。
+ 直通GPU(PCI Passthrough)
1. 虚拟机驱动准备渲染数据
+ 虚拟机内的GPU驱动分配显存缓冲区,地址为GPA(例GPA 0x2000)。
2. 驱动配置GPU DMA
+ 驱动将GPA 0x2000写入直通GPU的DMA地址寄存器(通过MMIO操作)。
+ CPU执行MMIO写指令,目标地址为GPU的物理寄存器(GPA 0xB000)。
3. EPT转换MMIO地址
+ EPT将GPA 0xB000转换为GPU寄存器的真实HPA(例HPA 0x6000),确保CPU直接操作物理硬件。
4. GPU发起DMA请求
+ GPU根据驱动配置的GPA 0x2000,发起DMA传输请求(例如将渲染数据从内存传输到显存)。
5. IOMMU拦截并转换地址
+ IOMMU拦截DMA请求,查询其页表,将GPA 0x2000转换为宿主机的HPA 0x9000。
+ 若IOMMU与EPT共享页表,可能直接复用EPT的GPA→HPA映射。
6. DMA访问物理显存
+ GPU直接读写HPA 0x9000对应的物理显存,完成数据传输。
7. 渲染完成与中断通知
+ GPU触发中断,宿主机将中断路由到虚拟机(需中断重映射支持),通知驱动渲染完成。