在OVMF虚拟机中安装NVIDIA Linux驱动

我在完成了 采用OVMF实现passthrough GPU和NVMe存储 配置之后,原本以为在passthough的OVMF虚拟机内部,对NVIDIA GPU的驱动安装会像在物理主机上 安装NVIDIA Linux驱动 一样轻松。毕竟,理论上说,直通进虚拟机的NVIDIA GPU卡不就是虚拟机独占的一块物理GPU卡么。

然而,实践并没有像预想的那么顺利…

备注

由于我之前已经在物理主机安装(演练)过一遍 安装NVIDIA Linux驱动 ,所以采用相同方法在 采用OVMF实现passthrough GPU和NVMe存储 的虚拟机 z-k8s-n-1 安装 NVIDIA CUDA 驱动

安装NVIDIA Linux驱动

在Ubuntu 22.04操作系统添加NVIDIA官方软件仓库配置
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt-get update
  • 安装 NVIDIA CUDA 驱动:

使用NVIDIA官方软件仓库安装CUDA驱动
sudo apt-get -y install cuda-drivers

这里安装过程提示不能支持 Secure Boot:

Building initial module for 5.15.0-57-generic
Can't load /var/lib/shim-signed/mok/.rnd into RNG
40A7F3E73E7F0000:error:12000079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:106:Filename=/var/lib/shim-signed/mok/.rnd
...
Secure Boot not enabled on this system.
Done.
  • 重启操作系统,检查驱动安装:

    nvidia-smi
    

我以为一切顺利结束,然而…

NVIDIA passthrough via ovmf需要Host主机内核参数 pci=realloc

在虚拟机内部 安装NVIDIA Linux驱动 遇到异常,设备没有初始化成功,从 dmesg -T 看到:

虚拟机NVIDIA设备初始化失败,显示PCI I/O region错误
[Wed Jan 11 00:56:18 2023] NVRM: The NVIDIA probe routine failed for 1 device(s).
[Wed Jan 11 00:56:18 2023] NVRM: None of the NVIDIA devices were initialized.
[Wed Jan 11 00:56:18 2023] nvidia-nvlink: Unregistered Nvlink Core, major device number 235
[Wed Jan 11 00:56:18 2023] nvidia-nvlink: Nvlink Core is being initialized, major device number 235
[Wed Jan 11 00:56:18 2023] NVRM: This PCI I/O region assigned to your NVIDIA device is invalid:
                           NVRM: BAR0 is 0M @ 0x0 (PCI:0000:09:00.0)
[Wed Jan 11 00:56:18 2023] nvidia: probe of 0000:09:00.0 failed with error -1
[Wed Jan 11 00:56:18 2023] NVRM: The NVIDIA probe routine failed for 1 device(s).
[Wed Jan 11 00:56:18 2023] NVRM: None of the NVIDIA devices were initialized.

这个问题在 PCI passthrough via OVMF/Examples 找到案例,案例中建议物理主机内核参数需要增加 pci=realloc ,否则就会导致类似错误:

NVRM: This PCI I/O region assigned to your NVIDIA device is invalid: NVRM: BAR1 is 0M @ 0x0 (PCI:0000:0a:00.0)

所以修订 采用OVMF实现passthrough GPU和NVMe存储 物理主机内核参数添加 pci=realloc 并重启物理主机

不过,我在物理主机内核参数配置了 pci=realloc 依然没有解决这个问题,虚拟机内部依然同样错误。

在NVIDIA论坛中 NVRM: This PCI I/O region assigned to your NVIDIA device is invalid #229899 提到如果 pci=realloc 不生效可以尝试 pci=realloc=off

正在迷惘的时候,参考 NVRM: This PCI I/O region assigned to your NVIDIA device is invalid #81645 ,原来这个问题就是我在 HP DL360 Gen9 Large Bar Memory(Tesla P10) 曾经解决过的,当时发现BIOS自检报错:

NVIDIA Tesla P10计算卡安装后启动BIOS自检报错信息
276 Option Card Configuration Error. An option card is requesting more memory
mapped I/O than is available.
Action: Remove the option card to allow the system to boot.

通过 HP DL360 Gen9 BIOS设置 PCI Express 64-Bit BAR Support 解决,所以在物理服务器上 安装NVIDIA Linux驱动 就没有遇到 PCI I/O region assigned to your NVIDIA device is invalid 这样的错误。

这个 PCI I/O region 资源分配问题是常见的,表示pci设备所需的内存窗口大小和区域(BAR)最初是由BIOS分配,但是有时候不正确或不兼容,参数 pci=realloc 使内核能够更改区域。

结合 Nvidia drivers for Tesla V100 PCIe 32Gb failing to load 和上文的几个参考文档,我逐渐想清楚了:

需要注意的是,上述配置都是在物理服务器上完成,但是这样依然不能使得虚拟机正确

备注

虚拟机配置 : 反复尝试后我发现 其实需要同时满足2个条件 (见下文)

执行 virsh edit z-k8s-n-1

找到:

<controller type='pci' index='0' model='pcie-root'/>

修改成:

<controller type='pci' index='0' model='pcie-root'>
    <pcihole64 unit='KiB'>2147483648</pcihole64>
</controller>

然后启动虚拟机后检查 qemu 参数就可以看到 -global q35-pcihost.pci-hole64-size=2147483648K

不过,此时虚拟机内部依然报错 (还需要下面一步)

  • 虚拟机内核还是要添加 pci=realloc 才能彻底解决NVIDIA的 PCI I/O region 错误问题

    • 单纯在虚拟机内核上配置 pci=realloc 是不够的(目前我的物理主机还开启着 pci=realloc ,等有时间我关闭物理主机内核 pci=realloc 验证一下我的猜想)

在虚拟机内部修改 /etc/default/grub 将:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

修改成:

GRUB_CMDLINE_LINUX_DEFAULT="pci=realloc quiet splash"

然后执行:

update-grub

再重启一次虚拟机

WOW,终于虚拟机内部不再出现NVIDIA相关报错,并且执行 nvidia-smi 可以正确看到

虚拟机正确配置NVIDIA后执行nvidia-smi输出信息
Wed Jan 11 20:27:44 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.60.13    Driver Version: 525.60.13    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA Graphics...  On   | 00000000:09:00.0 Off |                    0 |
| N/A   30C    P8     9W / 150W |      0MiB / 23040MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

参考