什么是SR-IOV?

SR-IOV(Single Root I/O Virtualization,单根I/O虚拟化)是PCIe的一项标准扩展,允许单个物理PCIe设备在硬件层面虚拟出多个虚拟设备,每个虚拟设备可以直接分配给不同的虚拟机使用。

为什么需要SR-IOV?

  • 性能提升:虚拟机直接访问硬件,绕过Hypervisor软件层
  • 降低延迟:减少I/O虚拟化带来的额外开销
  • 提高吞吐量:接近物理机的I/O性能
  • 节省资源:多个虚拟机共享一个物理设备

I/O虚拟化技术对比

技术 实现方式 性能 隔离性 适用场景
软件模拟 Hypervisor模拟设备 兼容性测试
Para-virtualization 前端/后端驱动 通用虚拟化
设备直通(PCIe Passthrough) 整个设备分配给VM 单VM独占设备
SR-IOV 硬件虚拟化 多VM共享设备

PF和VF详解

SR-IOV定义了两种Function类型:Physical Function(PF)Virtual Function(VF)

Physical Function (PF)

物理功能

PF是完整的PCIe Function,拥有完整的配置空间和管理能力。

主要能力

  • 完整的配置空间访问
  • VF的创建和配置
  • 设备全局资源管理
  • 错误处理和恢复
  • 支持所有PCIe能力

典型用途

  • Hypervisor/Host管理
  • VF生命周期管理
  • 设备监控和诊断

Virtual Function (VF)

虚拟功能

VF是轻量级的PCIe Function,由PF创建,用于分配给虚拟机。

主要特点

  • 轻量级配置空间
  • 独立的I/O资源
  • 独立的MSI/MSI-X中断
  • 共享物理设备资源
  • 无全局管理能力

典型用途

  • 分配给虚拟机
  • 容器I/O加速
  • 多租户隔离

PF与VF对比

特性 PF VF
配置空间大小 完整(256B/4KB) 精简(部分寄存器)
BAR数量 6个 通常2-4个
VF创建能力 支持 不支持
中断数量 完整 受限
错误处理 完整 仅本地错误
DMA能力 支持 支持(IOMMU隔离)

SR-IOV系统架构

SR-IOV拓扑结构

Host/Hypervisor
PF Driver
SR-IOV Device
PF
VF 1
VF 2
VF 3
VF n
VM 1
VF 1
VM 2
VF 2
VM 3
VF 3

SR-IOV配置空间

SR-IOV扩展了PCIe配置空间,增加了SR-IOV Capability结构。

SR-IOV Capability寄存器

寄存器 偏移 功能
(扩展能力头) 0x00-0x03 Ext Cap ID(0x0010)/ Next Cap / 版本
SR-IOV Capabilities 0x04 SR-IOV能力标志(ARI层次、VF迁移、页大小粒度等)
SR-IOV Control 0x08 VF使能/禁用、Memory Space Enable、ARI Capable Hierarchy
SR-IOV Status 0x0A VF迁移状态
InitialVFs 0x0C 设备支持的VF数量(复位后可立即使能)
TotalVFs 0x0E 可配置的VF总数
NumVFs 0x10 当前配置的VF数量
Function Dependency Link 0x12 Function依赖关系
First VF Offset 0x14 第一个VF的RID偏移(相对PF)
VF Stride 0x16 相邻VF的RID间隔
VF Device ID 0x1A VF的设备ID
Supported / System Page Sizes 0x1C / 0x20 VF BAR 映射的页大小(SR-IOV 1.1 起已废弃,恒 0)
VF BAR0-5 0x24-0x38 VF的基地址寄存器(与PF BAR独立,所有VF共享一份布局)

SR-IOV配置流程

VF创建流程

1
检测SR-IOV能力 读取SR-IOV Capability,获取支持的VF数量
2
配置VF数量 写入NumVFs寄存器,设置要创建的VF数量
3
使能VF 设置VF Enable位,硬件创建VF
4
配置VF资源 为每个VF分配内存、中断等资源
5
分配VF给VM 将VF直通给虚拟机使用

Linux SR-IOV配置示例

# 1. 查看设备是否支持SR-IOV
$ lspci -s 03:00.0 -vvv | grep -i sriov
	Capabilities: [160] Single Root I/O Virtualization (SR-IOV)
		IOVCap: Migration-, Interrupt Message Number: 000
		IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy-
		IOVSta: Migration-
		Initial VFs: 64, Total VFs: 64, Number of VFs: 0

# 2. 查看当前VF数量
$ cat /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
0

# 3. 创建4个VF
$ echo 4 | sudo tee /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs

# 4. 查看创建的VF
$ lspci | grep Virtual
03:00.1 Ethernet controller: Intel Corporation Virtual Function
03:00.2 Ethernet controller: Intel Corporation Virtual Function
03:00.3 Ethernet controller: Intel Corporation Virtual Function
03:00.4 Ethernet controller: Intel Corporation Virtual Function

# 5. 查看VF详细信息
$ lspci -s 03:00.1 -vvv

# 6. 删除VF(设置为0)
$ echo 0 | sudo tee /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
                    

KVM虚拟机使用VF

# 1. 解绑VF from host driver
$ echo 0000:03:00.1 | sudo tee /sys/bus/pci/drivers/ixgbevf/unbind

# 2. 绑定VF to vfio-pci(用于直通)
$ echo vfio-pci | sudo tee /sys/bus/pci/devices/0000:03:00.1/driver_override
$ echo 0000:03:00.1 | sudo tee /sys/bus/pci/drivers/vfio-pci/bind

# 3. 查看VF的IOMMU组
$ readlink /sys/bus/pci/devices/0000:03:00.1/iommu_group
../../../../../../kernel/iommu_groups/16

# 4. 启动虚拟机时附加VF
$ qemu-system-x86_64 \
    -device vfio-pci,host=03:00.1,id=net0 \
    ...

# 或使用libvirt
$ virsh attach-device vm1 vf.xml
                    

ACS与SR-IOV的配合

ACS(Access Control Services)是SR-IOV安全隔离的重要保障,确保VF之间的隔离性。

为什么需要ACS?

安全风险

在没有ACS的情况下,恶意VM可能通过VF:

  • 访问其他VF的内存空间
  • 发起针对其他VM的DMA攻击
  • 通过P2P事务绕过IOMMU

ACS保护机制

Source Validation

验证TLP的源地址,防止伪造源地址攻击

P2P Request Redirect

将P2P请求重定向到RC,由IOMMU进行地址转换

Translation Blocking

阻止未授权的地址转换请求

SR-IOV安全架构

IOMMU
ACS (Switch/RC)
VF 1
VF 2
VF 3
VM 1
VM 2
VM 3

Linux ACS配置

# 查看设备的ACS能力
$ lspci -vvv -s 00:01.0 | grep -A 10 "Access Control Services"

# 强制启用ACS(某些情况下需要)
$ echo 1 | sudo tee /sys/bus/pci/devices/0000:00:01.0/acs_enable

# 检查IOMMU是否启用
$ dmesg | grep -i iommu
[    0.000000] Command line: ... intel_iommu=on iommu=pt ...

# 查看IOMMU组
$ find /sys/kernel/iommu_groups/ -type l
                    

SR-IOV性能优化

中断优化

MSI-X优化

  • 为每个VF分配足够的中断向量
  • 使用多队列网卡(RSS/RPS)
  • 中断亲和性绑定(IRQ affinity)

内存优化

  • 使用大页内存(HugePages)
  • NUMA亲和性配置
  • 避免跨节点内存访问

CPU优化

  • CPU pinning(vCPU绑定物理核)
  • 隔离专用CPU核心
  • 禁用超线程(如有必要)

性能测试

# 测试VF网络性能(使用iperf3)
# Host端
$ iperf3 -s

# VM端(通过VF)
$ iperf3 -c  -t 30 -P 4

# 对比:使用virtio-net
$ iperf3 -c  -t 30 -P 4

# 查看VF统计
$ ethtool -S eth0

# 查看中断分布
$ cat /proc/interrupts | grep eth0
                    

VFIO 内部模型:设备是怎么"交出去"的

VF 直通命令(vfio-pci 绑定、QEMU -device vfio-pci)背后是一套清晰的内核对象模型。理解它,才能回答"为什么分不到设备"、"为什么 IOMMU 组不能拆"这类现场问题。

三层对象:Device → Group → Container

对象职责
Device 经 ioctl 从 group fd 取得 device fd 具体设备(如一个 VF)。用户态通过 VFIO_GROUP_GET_DEVICE_FD 打开,随后 VFIO_DEVICE_GET_INFO 获取设备类型与 region;每个 region 支持 read/write/mmap——PCI 配置空间就是一个 region,BAR 空间是 mmap 的 region
Group /dev/vfio/$GROUP IOMMU 组:IOMMU 保护/映射的最小粒度。组内所有设备要么全部绑定到 VFIO、要么全不绑——因为组内设备之间的 DMA 互通无法被安全隔离,拆分等于给用户态留后门
Container /dev/vfio/vfio 承载一个或多个 group 的地址空间(页表集合)。用户态打开 container 文件、VFIO_SET_IOMMU 选 IOMMU 后端,再 VFIO_IOMMU_MAP_DMA 把用户态内存映射成设备的 IOVA 视图——这就是直通场景"DMA 能落进客户机内存"的机制
/* VFIO 典型用户态序(摘自 Documentation/driver-api/vfio.rst 的骨架) */
container = open("/dev/vfio/vfio", O_RDWR);
ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);

group = open("/dev/vfio/<group id>", O_RDWR);
ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);

/* 把客户机内存段注册为设备可见的 IOVA */
struct vfio_iommu_type1_dma_map dma_map = {
    .vaddr = (uintptr_t)guest_ram, .iova = 0x0,
    .size  = guest_ram_size, .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
};
ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);

/* 取设备 fd,逐一 mmap region(BAR 空间) */
device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:06:0d.0");
ioctl(device, VFIO_DEVICE_GET_INFO, &device_info);
for (i = 0; i < device_info.num_regions; i++) {
    struct vfio_region_info reg = { .argsz = sizeof(reg), .index = i };
    ioctl(device, VFIO_DEVICE_GET_REGION_INFO, ®);
    /* reg.offset/size/flags:mmap 到用户态直接操作 BAR */
}

vfio-pci 与 DMA 重映射

  • vfio-pci 作为 PCI 驱动的"接盘方":绑定设备后内核常规驱动不再 probe;VFIO 核心保存设备的 BAR、配置空间、中断(MSI/MSI-X)等资源清单。
  • 中断注入:VFIO 的 VFIO_DEVICE_SET_IRQS + eventfd 把 MSI/MSI-X 向量映射为文件描述符事件——QEMU 收到 eventfd 后向客户机注入虚拟中断,这是直通中断低开销的关键路径。
  • IOMMU 组为何不能拆:同一 IOMMU 组内的设备共享 IOMMU 页表/上下文;若只放行其中一个设备给用户态,其余设备的 DMA 不受约束即可越权访问。内核因此规定:组内设备必须全部交给同一个 VFIO container(多功能设备/未开 ACS 的 Switch 下游设备常因此被"捆绑")。
  • 新版 iommufdVFIO_SET_IOMMU/VFIO_IOMMU_MAP_DMA 的 IOMMU 逻辑正在向 /dev/iommu(iommufd)迁移——VFIO 只负责设备模型,页表由 iommufd 统一管理,用户态也可不用 VFIO 直接用 iommufd 做 DMA。

现场常用命令

# 查看设备的 IOMMU 组号与组内设备
$ ls /sys/bus/pci/devices/0000:01:00.0/iommu_group/devices/

# 查看系统全部 IOMMU 组
$ for g in /sys/kernel/iommu_groups/*/devices/*; do echo "$g"; done

# 将 VF 绑定到 vfio-pci(驱动_override)
$ echo 8086 154c > /sys/bus/pci/drivers/vfio-pci/new_id
# 或先解绑原驱动再覆盖
$ echo 0000:01:00.1 > /sys/bus/pci/drivers/<orig-driver>/unbind
$ echo vfio-pci > /sys/bus/pci/devices/0000:01:00.1/driver_override
$ echo 0000:01:00.1 > /sys/bus/pci/drivers_probe

SR-IOV应用场景

NFV/电信云

虚拟化网络功能,高性能数据面处理

  • vRouter/vFirewall
  • 虚拟负载均衡
  • DPI/流量分析

云数据库

高性能存储访问,低延迟I/O

  • NVMe SSD虚拟化
  • 高并发数据库
  • 内存数据库

公有云

多租户I/O隔离,性能保障

  • 裸金属服务
  • 高性能计算实例
  • GPU虚拟化

边缘计算

资源受限环境下的高效虚拟化

  • 边缘网关
  • 工业控制
  • 5G MEC

总结

SR-IOV是PCIe虚拟化的核心技术,通过硬件层面的I/O虚拟化,实现了接近物理机的I/O性能。结合ACS和IOMMU,SR-IOV提供了安全、高效的I/O虚拟化解决方案。

关键要点

  • SR-IOV通过PF和VF实现硬件虚拟化
  • PF负责管理,VF分配给虚拟机使用
  • ACS确保VF之间的安全隔离
  • IOMMU提供DMA重映射和保护
  • SR-IOV适用于高性能I/O虚拟化场景

参考资源