起因背景
我们在使用NVIDIA vGPU切分显卡资源给虚拟机后,这台虚拟机就会存在2个虚拟屏幕,一个是PVE的VNC窗口,一个是NVIDIA VGX虚拟屏幕,当我们在PVE的VNC窗口操作虚拟机的话,部分应用又无法调用到GPU资源,把VNC窗口设置“无”即NONE的话只能借助外部远程工具连接虚拟机,PVE的VNC窗口又不工作。
所以这里参考佛西:为vgpu设备添加mdev gpu类型的补丁给PVE9打上。让VNC窗口直接输出vGPU显卡画面。
支持类型
| 说明 | 版本 |
|---|---|
| 系统 | PVE 9.1.6 |
| 内核 | Linux pve9 6.17.13-2-pve |
| pve-qemu-kvm | 10.0.2-7 |
| 支持的虚拟机 | SeaBIOS/OVMF |
| 正常工作版本 | vGPU16/17/18 |
| 不工作版本 | vGPU19 |
修改QemuServer.pm
可以使用nano命令来编辑QemuServer.pm文件nano /usr/share/perl5/PVE/QemuServer.pm
1)第一处,在这句结尾加入mdev参数
enum => [
- qw(cirrus qxl qxl2 qxl3 qxl4 none serial0 serial1 serial2 serial3 std virtio virtio-gl vmware)
],修改完成后效果:
enum => [
+ qw(cirrus qxl qxl2 qxl3 qxl4 none serial0 serial1 serial2 serial3 std virtio virtio-gl vmware mdev)
],2)第二处,在这句结尾加入'mdev' => 'mdev',参数
my $vga_map = {
'cirrus' => 'cirrus-vga',
'std' => 'VGA',
'vmware' => 'vmware-svga',
'virtio' => 'virtio-vga',
'virtio-gl' => 'virtio-vga-gl',
};修改完成后效果:
my $vga_map = {
'cirrus' => 'cirrus-vga',
'std' => 'VGA',
'vmware' => 'vmware-svga',
'virtio' => 'virtio-vga',
'virtio-gl' => 'virtio-vga-gl',
+ 'mdev' => 'mdev',
};3)第三处,在这句中加入if ($vga->{type} ne 'mdev'){ if判断语句,别忘了后面还有个括号}参数
push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none') {
push @$devices, '-device',
print_vga_device($conf, $vga, $arch, $machine_version, undef, $qxlnum, $bridges);
push @$cmd, '-display', 'egl-headless,gl=core' if $vga->{type} eq 'virtio-gl'; # VIRGL修改完成后效果:
push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none') {
+ if ($vga->{type} ne 'mdev'){
push @$devices, '-device',
print_vga_device($conf, $vga, $arch, $machine_version, undef, $qxlnum, $bridges);
+ }
push @$cmd, '-display', 'egl-headless,gl=core' if $vga->{type} eq 'virtio-gl'; # VIRGL4)第四处,在这句结尾加入|mdev参数,让Mdev显示器支持spcie协议,如果要用SPICE协议云桌面办公的建议加上(可选)
my $spice_port;
assert_clipboard_config($vga);
- my $is_spice = $qxlnum || $vga->{type} =~ /^virtio/;修改完成后效果:
my $spice_port;
assert_clipboard_config($vga);
+ my $is_spice = $qxlnum || $vga->{type} =~ /^(virtio|mdev)/;修改PCI.pm
可以使用nano命令来编辑PCI.pm文件nano /usr/share/perl5/PVE/QemuServer/PCI.pm
1)第一处,在这2句中间加入mdev类型的判断处理
my $mf_addr = $multifunction ? ".$j" : '';
$devicestr .= ",id=${id}${mf_addr}${pciaddr}${mf_addr}";
if ($j == 0) {
$devicestr .= ',rombar=0' if defined($d->{rombar}) && !$d->{rombar};
$devicestr .= "$xvga";修改完成后效果:
my $mf_addr = $multifunction ? ".$j" : '';
$devicestr .= ",id=${id}${mf_addr}${pciaddr}${mf_addr}";
+ my $mdevtype = $d->{mdev} // undef;
+ if ($mdevtype =~ /^(.*?)-/) {
+ $mdevtype = $1;
+ }
if ($j == 0) {
$devicestr .= ',rombar=0' if defined($d->{rombar}) && !$d->{rombar};
$devicestr .= "$xvga";2)第二处,在这2句中间加入mdev类型的判断处理
if ($j == 0) {
$devicestr .= ',rombar=0' if defined($d->{rombar}) && !$d->{rombar};
$devicestr .= "$xvga";
$devicestr .= ",multifunction=on" if $multifunction;
$devicestr .= ",romfile=/usr/share/kvm/$d->{romfile}" if $d->{romfile};
$devicestr .= ",bootindex=$bootorder->{$id}" if $bootorder->{$id};
for my $option (qw(vendor-id device-id sub-vendor-id sub-device-id)) {
$devicestr .= ",x-pci-$option=$d->{$option}" if $d->{$option};
}
}
push @$devices, '-device', $devicestr;
last if $d->{mdev};
}
}修改完成后效果:
if ($j == 0) {
$devicestr .= ',rombar=0' if defined($d->{rombar}) && !$d->{rombar};
$devicestr .= "$xvga";
$devicestr .= ",multifunction=on" if $multifunction;
$devicestr .= ",romfile=/usr/share/kvm/$d->{romfile}" if $d->{romfile};
$devicestr .= ",bootindex=$bootorder->{$id}" if $bootorder->{$id};
for my $option (qw(vendor-id device-id sub-vendor-id sub-device-id)) {
$devicestr .= ",x-pci-$option=$d->{$option}" if $d->{$option};
}
}
+ if ($mdevtype && $vga->{type} eq 'mdev'){
+ $devicestr .= ",display=on,ramfb=on,driver=vfio-pci-nohotplug";
+ }
push @$devices, '-device', $devicestr;
last if $d->{mdev};
}
}修改pvemanagerlib.js
可以使用nano命令来编辑pvemanagerlib.js文件nano /usr/share/pve-manager/js/pvemanagerlib.js
修改前端文件,在这句结尾加入mdev: 'NVIDIA vGPU',参数
std: gettext('Standard VGA'),
vmware: gettext('VMware compatible'),
qxl: 'SPICE',
qxl2: 'SPICE dual monitor',
qxl3: 'SPICE three monitors',
qxl4: 'SPICE four monitors',
serial0: gettext('Serial terminal') + ' 0',
serial1: gettext('Serial terminal') + ' 1',
serial2: gettext('Serial terminal') + ' 2',
serial3: gettext('Serial terminal') + ' 3',
virtio: 'VirtIO-GPU',
'virtio-gl': 'VirGL GPU',
+ mdev: 'NVIDIA vGPU',
none: Proxmox.Utils.noneText,
},重启服务让其生效,重启完记得Ctrl+F5清理下浏览器缓存。
systemctl restart pveproxy
systemctl restart pvedaemon最后就是给虚拟机添加上vGPU设备了,然后在显示那选择NVIDIA vGPU显示就能正常输入vGPU画面了。只测试了vGPU16 17 18的驱动版本可以正常显示,vGPU19 黑屏异常可能驱动版本过高导致。