官方全面叫做Deploy graphics devices using Discrete Device Assignment(使用离散设备分配部署图形设备)简称DDA 。
从 Windows Server 2016 开始,可以使用离散设备分配或DDA将整个PCIe设备传递到Hyper-V。这将允许从Hyper-V内部访问NVMe存储或图形卡等设备,同时能够利用设备本机驱动程序。一开始以为应该也挺简单的,但实际上还是踩了很多坑才最终弄好。
适用于:
Windows Server 2022、Microsoft Hyper-V Server 2016、Windows Server 2016、Windows Server 2019、Microsoft Hyper-V Server 2019 (Windows11应该也支持具体没测试)
步骤注意事项:
使用具有离散设备分配的设备有三个步骤:
为离散设备分配配置Hyper-V
从主机分区卸载设备
将设备分配到Hyper-V
所有命令都可以以管理员身份在 Windows PowerShell 控制台上的主机上执行。
关于Hyper-V方面请手动关闭虚拟机 设置-自动停止操作-强制关闭虚拟机。
如果存在还有检查点请手动全部删除 设置-检查点-关闭启动检查点。
如果你只有一张显卡可以直接跳转到完整示例查看完整代码。
参考文档:https://learn.microsoft.com/zh-cn/windows-server/virtualization/hyper-v/deploy/deploying-graphics-devices-using-dda
嵌套虚拟化
此办法用于虚拟化Hyper-V里面的虚拟机比如Windows11的安卓子系统,前提是需要物理机支持并且已经在bois开启了虚拟化。
参考资料:https://learn.microsoft.com/en-us/windows/wsl/troubleshooting#error-0x80370102-the-virtual-machine-could-not-be-started-because-a-required-feature-is-not-installed
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true
完整示例
在此示例中,我们使用 PowerShell 配置名为“ddatest1”的虚拟机,使制造商NVIDIA提供的第一个GPU并将其分配到VM。
#设置需要直通的虚拟机名称
$vm = "ddatest1"
#将自动停止动作设置为关闭
Set-VM -Name $vm -AutomaticStopAction TurnOff
#在CPU上启用Write-Combining
Set-VM -GuestControlledCacheTypes $true -VMName $vm
#配置32位MMIO空间
Set-VM -LowMemoryMappedIoSpace 3Gb -VMName $vm
#配置大于32位MMIO空间
Set-VM -HighMemoryMappedIoSpace 33280Mb -VMName $vm
#查找位置路径并禁用设备
#枚举系统上的所有设备
$pnpdevs = Get-PnpDevice -presentOnly
#仅选择NVIDIA制造的显示设备
$gpudevs = $pnpdevs |where-object {$_.Class -like "Display" -and $_.Manufacturer -like "NVIDIA"}
#选择主机可以卸载的第一个设备的位置路径
$locationPath = ($gpudevs | Get-PnpDeviceProperty DEVPKEY_Device_LocationPaths).data[0]
#禁用设备
Disable-PnpDevice -InstanceId $gpudevs[0].InstanceId
#从主机上卸载设备
Dismount-VMHostAssignableDevice -force -LocationPath $locationPath
#将设备分配给Hyper-V虚拟机
Add-VMAssignableDevice -LocationPath $locationPath -VMName $vm
步骤一获取设备路径:
设备路径在物理设备直通的过程中相当于设备的唯一描述符。下面的Powershell展示了如何获取名称以NVIDIA开头的设备的设备路径。
#获取所有名称以NVIDIA开头的设备
$pnpdevs = Get-PnpDevice -PresentOnly | Where-Object {$_.FriendlyName -like "NVIDIA*"}
#输出LocationPath
foreach ($pnpdev in $pnpdevs) {
$locationpath = ($pnpdev | get-pnpdeviceproperty DEVPKEY_Device_LocationPaths).data[0]
$pnpdev.FriendlyName + ": " + $locationpath
}
在我的机器上,可以得到下面的输出:
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0800)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(80)#PCI(0200)#PCI(0000)#PCI(0800)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(80)#PCI(0200)#PCI(0000)#PCI(0C00)#PCI(0000)
步骤二:禁用设备
要被直通的物理设备将会被虚拟机独占使用,因此,操作系统需要确保宿主机没有其它应用在使用被直通的设备,因此在直通前禁用设备。
我们可以使用Disable-PnpDevice命令,通过设备的InstanceId来禁用设备。例如,在上文Powershell中获取$pnpdev对象后,继续执行:
disable-pnpdevice -InstanceId $pnpdev.InstanceId -Confirm:$false
步骤三:下线(Dismount)设备
这一步操作会将已经禁用的设备从操作系统中移除,使其变成可分配的状态。这一步只能通过Powershell完成。根据上面获得到的设备路径(Location Path),例如,”PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)”,运行下面的命令:
Dismount-VmHostAssignableDevice -locationpath "PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)" -force
这一步是最可能出现错误的。许多硬件上的不兼容都会在这个步骤报错。
成功执行此步操作后,宿主机上的设备管理器将无法查看到该设备。
步骤四:分配设备
假设前面的步骤都已完成,这个时候就已经可以将下线后的设备分配给虚拟机了。这一步依然只能通过Powershell完成。将GPU分配到名称为Test的虚拟机中的命令如下所示:
Add-VMAssignableDevice -LocationPath "PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)" -VMName Test
如果到这一步依然没有任何错误,那么设备已经成功直通到了虚拟机上。你可以通过下面的Powershell检查:
Get-VMAssignableDevice -VMName Test
在我的机器上,可以得到下面的输出:
InstanceID : PCIP\VEN_10DE&DEV_1DB1&SUBSYS_121210DE&REV_A1\6&3D280D5&0&00600018
LocationPath : PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)
ResourcePoolName : Primordial
Name : 虚拟 PCI Express 端口设置
Id : Microsoft:C3B8CA0E-F6DA-417C-B6D6-DD9D68F7D899\EAEE9BF9-B29B-4D2E-970B-325F02812E83
VMId : c3b8ca0e-f6da-417c-b6d6-dd9d68f7d899
VMName : Test
VMSnapshotId : 00000000-0000-0000-0000-000000000000
VMSnapshotName :
CimSession : CimSession: .
ComputerName : TRAIN
IsDeleted : False
VMCheckpointId : 00000000-0000-0000-0000-000000000000
VMCheckpointName :
GPU额外步骤一:合并缓存写入
对于GPU相比于一般的外部设备速度很快,这使得如果我们允许对CPU合并对GPU显存的写入操作以提升性能。以Test虚拟机为例,运行下面的Powershell:
Set-VM Test -GuestControlledCacheTypes $true
GPU额外步骤二:扩大内存映射IO空间(Memory Mapped IO Space)大小
GPU需要的MMIO空间通常较大,当一个虚拟机分配到的设备所需要的MMIO空间综合超过了Hyper-V为其默认提供的大小时,在虚拟机操作系统中就会提示“没有足够的系统资源”的错误。
你可以在设备管理器右键设备-属性中看到设备所需的MMIO空间,如图所示:

根据内存范围,我们可以算出一张V100所需的MMIO大小为16MB+16384MB+32MB,其中,32位地址空间内需求16MB,64位地址空间内需求16384MB+32MB=16416MB。目前一个新建的Hyper-V虚拟机默认只为32位和64位地址空间分别提供了128MB和512MB的MMIO空间大小,这导致V100直接分配到虚拟机中是无法使用的。
32位和64位地址空间的MMIO大小可以通过下面的Powershell来分别修改,以Test虚拟机为例:
Set-VM Test -LowMemoryMappedIoSpace 3Gb
Set-VM Test -HighMemoryMappedIoSpace 33280Mb
步骤五:驱动下载
以上步骤没问题后在nvidia官网下载对应驱动安装完成后重启就可以看到显卡了,ADM也是同理。
https://www.nvidia.cn/Download/index.aspx?lang=cn
删除设备并将其返回到主机
如果要将设备返回到其原始状态,则需要停止虚拟机并发出以下问题:
#从虚拟机中删除设备
Remove-VMAssignableDevice -LocationPath $locationPath -VMName VMName
#将设备装载回主机
Mount-VMHostAssignableDevice -LocationPath $locationPath




评论(0)