实现步骤

环境

OS:

# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
# uname -a
Linux hyhive 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

QEMU版本

Compiled against library: libvirt 2.0.0
Using library: libvirt 2.0.0
Using API: QEMU 2.0.0
Running hypervisor: QEMU 2.6.0

操作步骤

1.查找pci设备的硬件信息

pci passthrough需要pcivendor_idproduct_id以及iommu组编号,通常再知道pci设备的类型或者厂商名称时,可以使用lspci查找,如(这里测试有三块Quadro M2000显卡):

# lspci -nn | grep -i vga
06:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
0a:03.0 VGA compatible controller [0300]: Matrox Electronics Systems Ltd. MGA G200eW WPCM450 [102b:0532] (rev 0a)
82:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
83:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
group:06:00.0       82:00.0          83:00.0
venderid:10de 10de 10de
productid:1430 1430 1430

2.打开iommu

iommu功能需要CPU和系统的支持,硬件上要求CPU支持vt-d技术(不是虚拟化),并在bios中打开(通常在北桥芯片设置中)

软件上,需要操作系统的iommu grub标志,添加rd.driver.pre=vfio-pci intel_opmmu=on

# cat /etc/sysconfig/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet rd.driver.pre=vfio-pci intel_iommu=on"
GRUB_DISABLE_RECOVERY="true"

重新生成grub

EFI

grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

EFI

# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
WARNING: Not using lvmetad because duplicate PVs were found.
WARNING: Use multipath or vgimportclone to resolve duplicate PVs?
WARNING: After duplicates are resolved, run "pvscan --cache" to enable lvmetad.
WARNING: Not using lvmetad because duplicate PVs were found.
WARNING: Use multipath or vgimportclone to resolve duplicate PVs?
WARNING: After duplicates are resolved, run "pvscan --cache" to enable lvmetad.
Found linux image: /boot/vmlinuz-3.10.0-514.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-514.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-43b1cb10c00d48b18061c67e6df40752
Found initrd image: /boot/initramfs-0-rescue-43b1cb10c00d48b18061c67e6df40752.img
WARNING: Not using lvmetad because duplicate PVs were found.
WARNING: Use multipath or vgimportclone to resolve duplicate PVs?
WARNING: After duplicates are resolved, run "pvscan --cache" to enable lvmetad.
WARNING: Not using lvmetad because duplicate PVs were found.
WARNING: Use multipath or vgimportclone to resolve duplicate PVs?
WARNING: After duplicates are resolved, run "pvscan --cache" to enable lvmetad.
done

3.配置vfio模块

  1. 屏蔽宿主机驱动(该步骤验证为非必须步骤,当出现异常时尝试添加)

以nvidia显卡为例:

# cat /etc/modprobe.d/blacklist.conf
blacklist nouveau
blacklist nvidia
  1. 添加vfio所需内核模块
# cat /etc/modules-load.d/vfio.conf
vfio
vfio_iommu_type1
vfio_pci
  1. 配置vfio

将1.1中查询到的vendor_idproduct_idvendor_id:product_id的形式添加到vfio option中,完成vfio配置

检查硬件脚本(可以通过以下脚本检查1.1中得到的id是否有误)

# cat gpu.sh
#!/bin/bash
shopt -s nullglob
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done;

通过检查硬件脚本找到显卡对应的显卡设备和声卡设备,将两个设备id都填入vfio.conf文件中

# ./gpu.sh | grep -i nvidia
IOMMU Group 18 06:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
IOMMU Group 18 06:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fba] (rev a1)
IOMMU Group 38 82:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
IOMMU Group 38 82:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fba] (rev a1)
IOMMU Group 39 83:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM206GL [Quadro M2000] [10de:1430] (rev a1)
IOMMU Group 39 83:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fba] (rev a1)

从上面可以查到的显卡设备为10de:1430声卡设备为10de:0fba

添加到vfio.conf文件中

# cat /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:1430,10de:0fba
  1. 重新生成initramfs
# mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
# dracut -v /boot/initramfs-$(uname -r).img $(uname -r)
Executing: /usr/sbin/dracut -v /boot/initramfs-3.10.0-514.el7.x86_64.img 3.10.0-514.el7.x86_64
dracut module 'busybox' will not be installed, because command 'busybox' could not be found!
dracut module 'dmraid' will not be installed, because command 'dmraid' could not be found!
dracut module 'busybox' will not be installed, because command 'busybox' could not be found!
dracut module 'dmraid' will not be installed, because command 'dmraid' could not be found!
*** Including module: bash ***
*** Including module: nss-softokn ***
*** Including module: i18n ***
*** Including module: network ***
*** Including module: ifcfg ***
*** Including module: drm ***
*** Including module: plymouth ***
*** Inc 大专栏  GPU PassThrough in KVMluding module: dm ***
Skipping udev rule: 64-device-mapper.rules
Skipping udev rule: 60-persistent-storage-dm.rules
Skipping udev rule: 55-dm.rules
*** Including module: kernel-modules ***
*** Including module: lvm ***
Skipping udev rule: 64-device-mapper.rules
Skipping udev rule: 56-lvm.rules
Skipping udev rule: 60-persistent-storage-lvm.rules
*** Including module: resume ***
*** Including module: rootfs-block ***
*** Including module: terminfo ***
*** Including module: udev-rules ***
Skipping udev rule: 91-permissions.rules
*** Including module: biosdevname ***
*** Including module: systemd ***
*** Including module: usrmount ***
*** Including module: base ***
*** Including module: fs-lib ***
*** Including module: shutdown ***
*** Including modules done ***
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
*** Resolving executable dependencies ***
*** Resolving executable dependencies done***
*** Hardlinking files ***
*** Hardlinking files done ***
*** Stripping files ***
*** Stripping files done ***
*** Generating early-microcode cpio image contents ***
*** Constructing GenuineIntel.bin ****
*** Store current command line parameters ***
*** Creating image file ***
*** Creating microcode section ***
*** Created microcode section ***
*** Creating image file done ***
*** Creating initramfs image file '/boot/initramfs-3.10.0-514.el7.x86_64.img' done ***
  1. 重启

验证

重启之后,验证vfio是否生效

# dmesg | grep -i vfio
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet rd.driver.pre=vfio-pci intel_iommu=on
[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet rd.driver.pre=vfio-pci intel_iommu=on
[ 8.362177] VFIO - User Level meta-driver version: 0.3
[ 8.367249] vfio_pci: add [10de:1430[ffff:ffff]] class 0x000000/00000000
[ 8.367314] vfio_pci: add [10de:0fba[ffff:ffff]] class 0x000000/00000000
[ 2144.638305] vfio-pci 0000:06:00.0: enabling device (0000 -> 0003)
[ 2144.638464] vfio_ecap_init: 0000:06:00.0 hiding ecap 0x1e@0x258
[ 2144.638479] vfio_ecap_init: 0000:06:00.0 hiding ecap 0x19@0x900

失败案例:

# dmesg | grep vfio
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet rd.driver.pre=vfio-pci intel_iommu=on
[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet rd.driver.pre=vfio-pci intel_iommu=on
[ 19.034596] vfio-pci: probe of 0000:06:00.0 failed with error -22
[ 19.034636] vfio-pci: probe of 0000:82:00.0 failed with error -22
[ 19.034654] vfio-pci: probe of 0000:83:00.0 failed with error -22
[ 19.034661] vfio_pci: add [10de:1430[ffff:ffff]] class 0x000000/00000000

解决办法:

检查/etc/modprobe.d/vfio.conf 文件,检查主板北桥vt-d设置是否打开

调用GPU

创建虚拟机,并添加pci设备

<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x06' slot='0x00' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</hostdev>

其中address1.106:00:0

通过virsh domain ***.xml孵化出虚拟机即可。

ATI部分显卡及某些其他PCI卡reset问题

ATI部分显卡和其他某些cpi卡存在reset问题,具体表现为:

  1. 虚拟机重启一次或几次后,pci passthrough失效,需要重启宿主机
  2. 虚拟机重启时蓝屏,然后恢复正常

该问题由于pci reset导致,和pci板卡驱动程序相关,对于kvm则无根治手段,可以采用的方式:

https://curtisshoward.com/post/fixing-amd-gpu-passthrough-reset-issues-in-windows/

qemu-kvm代码中关于该问题的解释:

https://github.com/qemu/qemu/blob/master/hw/vfio/pci-quirks.c#L1697

相关资源

pci passthrough当前比较成熟,以下是部分资料:

  1. VGA Passthrough on virtual machines in CentOS 7
  2. PCI passthrough via OVMF
  3. VGAPassthrough
  4. HOW-TO make dual-boot obsolete using kvm VGA passthrough
  5. create-gaming-virtual-machine-using-vfio-pci-passthrough-kvm

pci reset相关

  1. pci-quirks
  2. pass-through gpu to guest, but only once?!
  3. vfio pass through only works once after reboot
  4. Fixing AMD GPU Passthrough Reset Issues in Windows

在线测试结果

KVM GPU PASSTHROUGH RESULT

GPU PassThrough in KVM的更多相关文章

  1. KVM 介绍(4):I/O 设备直接分配和 SR-IOV [KVM PCI/PCIe Pass-Through SR-IOV]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  2. KVM Pass-through 上部署 MiniSMB HurricaneII

    KVM Pass-through 上部署 MiniSMB HurricaneII 免费网络测试,是一款专门用于测试无线控制器, 智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具 ...

  3. 计算机组成原理 — GPU 图形处理器

    目录 文章目录 目录 显卡 GPU GPU 与深度学习 GPU 与 CPU 体系结构的区别 GPU 显存与 CPU 主存的区别 GPU 与 CPU 之间的数据交互方式 GPU 的体系结构 GPU 的工 ...

  4. KVM(四) I/O 设备直接分配和 SR-IOV

    (4):I/O 设备直接分配和 SR-IOV 本文将分析 PCI/PCIe 设备直接分配(Pass-through)和 SR-IOV, 以及三种 I/O 虚拟化方式的比较. 1. PCI/PCI-E ...

  5. kvm详细介绍

    KVM详解,太详细太深入了,经典 2016-07-18 19:56:38 分类: 虚拟化 原文地址:KVM详解,太详细太深入了,经典 作者:zzjlzx KVM 介绍(1):简介及安装 http:// ...

  6. 虚拟化之mdev-vfio笔记

    [root@master mdev]# vi Makefile # SPDX-License-Identifier: GPL-2.0-only mdev-y := mdev_core.o mdev_s ...

  7. kvm libvirt: hostdev passthrough support 解决加密狗冲突问题

    From: "Daniel P. Berrange" <berrange redhat com> To: Guido Günther <agx sigxcpu o ...

  8. OpenStack 企业私有云的若干需求(1):Nova 虚机支持 GPU

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  9. kvm

    硬件,os,内核模块,用户空间工具,命令行具体参数,日志 [root@localhost ~]# yum install pciutils [root@localhost ~]# lscpu;lspc ...

随机推荐

  1. NGINX常用模块(二)

    5.Nginx日志配置 Nginx有非常灵活的日志记录模式.每个级别的配置可以有各自独立的访问日志.日志格式 通过log_format命令定义格式 1.log_format指令 # 配置语法:包括:e ...

  2. 垃圾windows10更新遇到的问题

    缘由 1.win10现在必须更新,不更新不给你用,关闭自动更新的方法都失效了,如果有人知道有效的方法还请私信指教一下.. 一个延迟几天的笨方法:当出现更新并关机或更新并重启时,把电源键设置成关机. 就 ...

  3. 通过OAuth2.0 获取授权访问SF 用户数据

    站长资讯: 创建应用程序 新建应用程序   访问示例(Python+django) 环境准备: index.html 两种方式: 方式一:采用由用户授权,调用者无需知道SF的用户名与密码 方式二:直接 ...

  4. 箭头函数,闭包函数中的this指向

    在javscript中,this 是在函数运行时自动生成的一个内部指针,它指向函数的调用者. 箭头函数有些不同,它的this是继承而来, 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象. ...

  5. Tire树(字典树)

    from:https://www.cnblogs.com/justinh/p/7716421.html Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,P ...

  6. 吴裕雄--天生自然 pythonTensorFlow图形数据处理:多线程队列操作

    import tensorflow as tf #1. 定义队列及其操作. queue = tf.FIFOQueue(100,"float") enqueue_op = queue ...

  7. K3CLOUD日志目录

    业务站点安装目录\K3Cloud\WebSite\App_Data\Log下面找

  8. win下PowerShell的簡單使用

  9. G - 旅行的意义(概率DP) (DAG图的概率与期望)

    为什么有人永远渴望旅行,或许就因为,巧合和温暖会在下一秒蜂拥而至吧. 一直想去旅游的天天决定在即将到来的五一假期中安排一场环游世界的旅行.为此,他已经提前查阅了很多资料,并准备画一张旅游路线图.天天先 ...

  10. servlet打包成war

    1.maven pom文件里指定打包类型 2.jdk工具 进入servlet目录,执行jar -cf war名 *