PCIe【5】PCIe设备透传
1. 概述
1.1 什么是PCIe透传
PCIe设备透传使得虚拟机可以直接访问PCIe设备。
VMM(Virtual Machine Minotor,虚拟监控器),也称为Hypervisor,是负责创建、管理和运行虚拟机的核心软件层。它位于硬件(Host)和虚拟机(Guest)之间,负责虚拟化CPU、内存、I/O设备等资源,使多个虚拟机能够安全、高效地共享同一台物理机的硬件资源。
通常情况下,虚拟机访问Hypervisor上的资源时,QEMU/KVM等虚拟机工具提供以下机制实现:
-
trap and emulate
虚拟机每次访问硬件资源都要进行VMExit退出虚拟机执行相应的设备模拟或者访问设备的操作,完成后再执行VMEnter进入虚拟机。频繁的模式切换导致IO访问的低效。
-
virtio半虚拟化
半虚拟化机制,要求虚拟机中运行的os加载特殊的
virtio前端驱动
,虚拟机通过循环命令队列和Hypervisor上运行的virtio后端驱动
进行通信,后端驱动负责适配不同的物理硬件设备,在收到命令后,后端驱动执行命令。
1.2 PCIE设备透传到底"透"了什么?
透了Host Memory
设备透传让虚拟机中的驱动使用IOVA
访问物理内存,在KVMTOOL
中,它是通过调用VFIO
的VFIO_IOMMU_MAP_DMA
命令来实现的,用来将IOVA
映射到具体的物理页面上(通过HVA
得到HVA
对应的物理页面,再进行映射)。
-
注意:透传的设备访问主存/VCPU访问主存or设备内存
1.1 透传设备的DMA访问(仅需一次映射): 当
PCIe
设备(如网卡、GPU
)透传给虚拟机后,设备可以直接进行DMA
,而无需经过VMM
(如KVM
)的干预。即:1. 设备发起DMA请求(如网卡接收数据包,要写入虚拟机内存) 2. IOMMU使用DMAR机制,将设备的IOVA直接翻译成HPA 3. 数据直接写入HPA,无需虚拟机参与
即全程由IOMMU完成,不涉及EPT(GPA->HPA),绕过VMM,性能高,但需要VFIO或PCIe Passthrough支持,确保设备DMA受控。
1.2. VCPU访问内存(需要两次映射)
-
GVA -> GPA
,由Guest OS的MMU(页表)完成(虚拟机内部); -
GPA -> HPA
,由EPT完成,由VMM管理。
-
1.3 HPA的分配
HPA
的分配并非直接静态分配,而是通过进程的HVA
动态映射而来。
-
无虚拟化情况:
- 进程通过malloc()或mmap()申请内存时,内核分配HVA,实际物理内存HPA由内核页表动态映射,进程无需关心HPA;
-
虚拟化情况:
- 类似无虚拟化。用户态进程(如QEMU)通过mmap()分配HVA,内核页表将HVA映射到HPA。此时,IOMMU/EPT的页表项(PTE)中填写的HPA,实际上是通过查Host的页表(HVA->HPA)得到的。
2. PCIe BAR空间的透传
- BAR空间的作用:
PCIe
设备(如显卡显存、网卡缓冲区)需要将板载存储空间映射到处理器的地址空间(PA
,即HPA或GPA),以便CPU
访问。由于不同设备的存储需求不同,PCI
标准通过BAR
字段让设备自行声明所需地址空间的大小和类型(MMIO
或PIO
),最多支持6
个BAR
区域。BIOS
在初始化时统一分配地址空间。
-
透传机制:
-
主机端:
BIOS
为PCIe
设备分配物理地址(如BAR2映射到0xdf104000)。 -
虚拟机端:透传后,虚拟机看到的BAR空间大小与主机一致,但地址可能不同(如主机
0xdf104000
对应虚拟机0xd2004000
)。 -
映射原理:
-
类似
KVM
添加内存条,将主机用户态MMAP
的BAR
空间(HVA
)映射到虚拟机的一段GPA
。 -
例如,虚拟机访问
0xd2004000
会通过VMM
转换为对主机0xdf104000
的访问。
-
-
-
关键点:
-
地址转换:虚拟机中的
GPA
通过VMM
映射到主机的HPA
,实现透明访问。 -
一致性:透传后,虚拟机内
BAR
空间的大小和功能与主机端完全一致。
-
Guest OS (VM) VMM (KVM) Host
GPA 0xd2004000 → HVA (MMAP BAR) → HPA 0xdf104000
3. SR-IOV BAR空间映射机制
SR-IOV(Single Root I/O Virtualization)是由PCI-SIG组织定义的PCIe规范的扩展规范《Single Root I/O Virtualization and Sharing Specification》,目的是通过提供一种标准规范,为VM(虚拟机)提供独立的内存空间、中断、DMA数据流。
SR-IOV的出现,支持了单个物理PCIe设备虚拟出多个虚拟PCIe设备,然后将虚拟PCIe设备直通到各虚拟机,以实现单个物理PCIe设备支撑多虚拟机的应用场景,如下图所示: