编者按:SR-IOV 和 PCIe 设备直通属于非常新的技术,且大部分民用设备有非常严重的兼容性问题。在使用前,请务必和你的平台与设备厂商确认兼容性。使用不兼容的设备可能导致虚拟机或物理机失去响应,设备进入未知的状态,电脑起火等诸多后果。编者不对任何尝试提供担保。
先决条件
- Hyper-V 安装并启用(废话)
- 处理器支持 IOMMU (Intel VT-d / AMD-Vi / ARM SMMU) 并启用
- 平台固件启用了 PCIe ACS (Access Control Services)
- 一块不使用 Line Interrupt 的 PCIe 设备,最好能支持 PCIe ACS (Access Control Services)
已知问题
- 直通设备的虚拟机不能被暂停或热迁移,所以自动关机动作必须为 ACPI shutdown 或者硬关机。
- 如果是 Linux 虚拟机,需要 Hyper-V PCI Bus 驱动
hv_pci
。 - 只有 Windows Server Hyper-V 支持设备直通。
测试过的设备
- HPE ProLiant ML30 Gen 10 + Mellanox ConnectX-4 Lx:原生支持 IOMMU 和 ACS,不需要
-Force
。 - Dell R910 + Intel X520-DA2:原生支持 IOMMU;ACS 支持不全,需要加
-Force
。
检查设备信息
从 这里 下载检查脚本并运行。如果需要直通的设备所有报告全绿 (i.e. 不报错),那么复制 PCIe 设备路径备用。它应该长得像 PCIROOT(0)#PCI(1C00)#PCI(0000)
这样。
如果这个脚本告诉你设备存在 Line Interrupt:
All of the interrupts are line-based, no assignment can work.
那么这个设备不受支持。
如果这个脚本告诉你 BIOS 需要设备不离开它控制的内存:
BIOS requires that this device remain attached to BIOS-owned memory. Not assignable.
请跟 OEM 开票以获取正确支持 DDA 的 UEFI/BIOS 固件。
如果这个脚本告诉你其他设备可能可以访问这个设备:
Traffic from this device may be redirected to other devices in the system. Not assignable.
你依然有可能直通网卡(但是不安全)。在确定没有敏感工作负载的情况下,修改脚本如下:
$locationpath = ($pcidev | get-pnpdeviceproperty DEVPKEY_Device_LocationPaths).data[0]
$acsUp = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_AcsCompatibleUpHierarchy).Data
if ($acsUp -eq $devprop_PciDevice_AcsCompatibleUpHierarchy_NotSupported) {
write-host -ForegroundColor Red -BackgroundColor Black "Traffic from this device may be redirected to other devices in the system. Not assignable."
if ($null -ne $locationpath) {
$locationpath
}
continue
}
其他设备(例如传统 PCI 设备)也不受支持。
准备设备和虚拟机
在设备管理器里禁用准备直通的设备。打开 PowerShell,赋变量 $locationpath
为刚刚获得的 PCIe 设备路径。然后运行:
# 如果设备提供了直通用迁移驱动,那么不需要加 -Force
# 有原生 ACS 支持的也不需要
Dismount-VMHostAssignableDevice -LocationPath $locationpath -Force
如果这一步还是失败了,那么你的平台或者设备可能不受支持。如果这一步成功了,请往下继续看。
赋变量 $VmName
为虚拟机名,然后运行:
# 直通设备的虚拟机不能被暂停或热迁移,所以自动关机动作必须为 ACPI shutdown 或者硬关机
Set-VM -Name $VmName -AutomaticStopAction TurnOff
# 设置虚拟机缓存类型和 MMIO 区域。不同的设备对 MMIO 要求可能不同,具体可以参考
# https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/plan/plan-for-deploying-devices-using-discrete-device-assignment
Set-VM -VMName $VmName -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace 3Gb -HighMemoryMappedIoSpace 33280Mb
# 将设备通入虚拟机
Add-VMAssignableDevice -VMName $VmName -LocationPath $locationpath
将设备从虚拟机里移除
关闭虚拟机。赋变量 $locationpath
为刚刚获得的 PCIe 设备路径,赋变量 $VmName
为虚拟机名,然后运行:
# 将设备从虚拟机里移除
Remove-VMAssignableDevice -VMName $VmName -LocationPath $locationpath
# 挂载设备回 Management OS
Mount-VMHostAssignableDevice -LocationPath $locationpath
然后在设备管理器里重新启用设备。
例子: CSR1000v 16.12
UplinkRouter#sh platform software vnic-if database
vNIC Database
eth00_159127288xxxxxxxxxxx
Device Name : Gi1
Driver Name : ixgbe
MAC Address : xxxx.xxxx.xxxx
PCI DBDF : b605:00:00.0
UIO device : yes
Management : no
Status : supported
注意事项
- 同一个设备只需要跑一次
Add-VMAssignableDevice
。这个命令有概率不检查去重,会导致你的虚拟机无法启动。如果遇到这种情况,那么先把设备从虚拟机里移除,然后重新添加一次。