第 16 章 虚拟机设备配置
Red Hat Enterprise Linux 7 为客户机虚拟机支持三类设备:
- 模拟设备 纯是模拟实际硬件的虚拟设备,允许未经修改的客户机操作系统使用其标准 in-box 驱动程序来与其配合使用。
- VirtIO 设备 (也称为 半虚拟化)是纯粹的虚拟设备,设计为在虚拟机中最佳工作。VirtIO 设备与模拟设备类似,但默认情况下非 Linux 虚拟机不包含它们所需的驱动程序。虚拟化管理软件,如虚拟机管理器(virt-manager)和 Red Hat Virtualization Hypervisor,为支持的非 Linux 虚拟机操作系统自动安装这些驱动程序。Red Hat Enterprise Linux 7 支持 216 virtio 设备。如需更多信息,请参阅 第 5 章 KVM 半虚拟化(virtio)驱动程序。
- 分配的设备 是公开给虚拟机的物理设备。此方法也称为 passthrough。设备分配允许虚拟机独占访问 PCI 设备以实现一系列任务,并允许 PCI 设备看起来和行为,就像实际附加到客户端操作系统一样。Red Hat Enterprise Linux 7 每台虚拟机支持多达 32 个设备。PCIe 设备支持设备分配,包括 选择图形设备。并行 PCI 设备可能作为分配的设备支持,但由于安全性和系统配置冲突,它们存在严重的限制。
Red Hat Enterprise Linux 7 支持将 PCI 热插拔作为虚拟机单一功能插槽公开的。可以配置单一功能的主机设备以及多功能多主机设备的各个功能来启用此功能。仅建议非热插拔应用程序将设备作为多功能 PCI 插槽公开。
有关具体设备和相关限制的详情请参考 第 23.17 节 “Devices”。
注意
对于中断重新映射的平台支持,需要将客户机与主机中分配的设备进行完全隔离。如果没有这样的支持,主机可能会被受到攻击,以中断恶意客户机的注入攻击。在客户受信任的环境中,管理员可能选择使用
allow_unsafe_interrupts
选项为 vfio_iommu_type1
模块来允许 PCI 设备分配。这可以通过在 /etc/modprobe.d
中添加 .conf 文件(如 local.conf
)来永久完成:
options vfio_iommu_type1 allow_unsafe_interrupts=1或者使用 sysfs 条目动态执行相同的操作:
# echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
16.1. PCI 设备
PCI 设备分配只在支持 Intel VT-d 或 AMD IOMMU 的硬件平台中使用。在主机 BIOS 中必须启用这些 Intel VT-d 或 AMD IOMMU 规格,才能使 PCI 设备分配正常工作。
过程 16.1. 为 PCI 设备分配准备 Intel 系统
启用 Intel VT-d 规格
Intel VT-d 规范提供对直接向虚拟机分配物理设备的硬件支持。在 Red Hat Enterprise Linux 中使用 PCI 设备分配需要这些规格。在 BIOS 中必须启用 Intel VT-d 规格。有些系统制造商默认禁用这些规格。查看这些规格的术语在制造商之间可能会不同;请咨询您的系统制造商文档,了解相关条款。在内核中激活 Intel VT-d
在/etc/sysconfig/grub
文件内添加intel_iommu=on
和iommu=pt
参数,在内核中激活 Intel VT-d。以下示例是启用了 Intel VT-d 的已修改 GRUB 文件。GRUB_CMDLINE_LINUX="rd.lvm.lv=vg_VolGroup00/LogVol01 vconsole.font=latarcyrheb-sun16 rd.lvm.lv=vg_VolGroup_1/root vconsole.keymap=us $([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/ rhcrashkernel-param || :) rhgb quiet intel_iommu=on iommu=pt"
重新生成配置文件
运行以下命令来重新生成 /etc/grub2.cfg:grub2-mkconfig -o /etc/grub2.cfg
请注意,如果您使用基于 UEFI 的主机,则目标文件应当是/etc/grub2-efi.cfg
。随时使用
重启系统以启用更改。您的系统现在可以分配 PCI 设备。
过程 16.2. 为 PCI 设备分配准备 AMD 系统
启用 AMD IOMMU 规格
在 Red Hat Enterprise Linux 中使用 PCI 设备分配需要 AMD IOMMU 规格。在 BIOS 中必须启用这些规格。有些系统制造商默认禁用这些规格。启用 IOMMU 内核支持
在/etc/sysconfig/grub
中的引号内,将iommu=pt
附加到 GRUB_CMDLINX_LINUX 行的末尾,以便在启动时启用 AMD IOMMU 规格。重新生成配置文件
运行以下命令来重新生成 /etc/grub2.cfg:grub2-mkconfig -o /etc/grub2.cfg
请注意,如果您使用基于 UEFI 的主机,则目标文件应当是/etc/grub2-efi.cfg
。随时使用
重启系统以启用更改。您的系统现在可以分配 PCI 设备。
注意
有关 IOMMU 的详情,请参考 附录 E, 使用 IOMMU 组。
16.1.1. 使用 virsh 分配 PCI 设备
这些步骤涵盖了将 PCI 设备分配给 KVM 管理程序上的虚拟机。
本例使用 PCIe 网络控制器和 PCI 标识符代码
pci_0000_01_00_0
,以及一个名为 guest1-rhel7-64 的完全虚拟化客户端机器。
过程 16.3. 使用 virsh 为客户机虚拟机分配 PCI 设备
确定设备
首先,识别为分配给虚拟机的设备分配的 PCI 设备。使用 lspci 命令列出可用的 PCI 设备。您可以使用 grep 重新定义 lspci 的输出。本例使用在以下输出中突出显示的以太网控制器:# lspci | grep Ethernet 00:19.0 Ethernet controller: Intel Corporation 82567LM-2 Gigabit Network Connection 01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01) 01:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
此时会显示这个以太网控制器,其简短标识符00:19.0
。我们需要找到 virsh 使用的完整标识符,以将此 PCI 设备分配给虚拟机。为此,请使用 virsh nodedev-list 命令列出附加到主机机器的特定类型(pci
)的所有设备。然后查看映射到您要使用的设备的简短标识符的字符串的输出。本例显示了使用简短标识符00:19.0
映射到以太网控制器的字符串。请注意,:
和.
字符在完整的标识符中被替换为下划线。# virsh nodedev-list --cap pci pci_0000_00_00_0 pci_0000_00_01_0 pci_0000_00_03_0 pci_0000_00_07_0 pci_0000_00_10_0 pci_0000_00_10_1 pci_0000_00_14_0 pci_0000_00_14_1 pci_0000_00_14_2 pci_0000_00_14_3 pci_0000_00_19_0 pci_0000_00_1a_0 pci_0000_00_1a_1 pci_0000_00_1a_2 pci_0000_00_1a_7 pci_0000_00_1b_0 pci_0000_00_1c_0 pci_0000_00_1c_1 pci_0000_00_1c_4 pci_0000_00_1d_0 pci_0000_00_1d_1 pci_0000_00_1d_2 pci_0000_00_1d_7 pci_0000_00_1e_0 pci_0000_00_1f_0 pci_0000_00_1f_2 pci_0000_00_1f_3 pci_0000_01_00_0 pci_0000_01_00_1 pci_0000_02_00_0 pci_0000_02_00_1 pci_0000_06_00_0 pci_0000_07_02_0 pci_0000_07_03_0
记录映射到您要使用的设备的 PCI 设备号;其他步骤中这是必需的。查看设备信息
有关域、总线和功能的信息可从 virsh nodedev-dumpxml 命令的输出中获得:图 16.1. 转储内容
# virsh nodedev-dumpxml pci_0000_00_19_0 <device> <name>pci_0000_00_19_0</name> <parent>computer</parent> <driver> <name>e1000e</name> </driver> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>25</slot> <function>0</function> <product id='0x1502'>82579LM Gigabit Network Connection</product> <vendor id='0x8086'>Intel Corporation</vendor> <iommuGroup number='7'> <address domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> </iommuGroup> </capability> </device>
注意IOMMU 组根据 IOMMU 的视角的可见性和隔离来确定。每个 IOMMU 组可以包含一个或多个设备。当存在多个设备时,必须声明 IOMMU 组内的所有端点,以便将该组中的所有设备分配给客户机。这也可以通过为客户机分配额外的端点,也可以使用 virsh nodedev-detach 从主机驱动程序中分离它们。单个组中包含的设备可能不在多个客户机间分割,或者在主机和客户机间分割。PCIe 根端口、交换机端口和网桥等非端点设备不应与主机驱动程序分离,而不会干扰分配端点。IOMMU 组中的设备可以使用 virsh nodedev-dumpxml 输出的 iommuGroup 部分确定。组的每个成员都在单独的 "address" 字段中提供。这些信息也可以在 sysfs 中使用以下内容:$ ls /sys/bus/pci/devices/0000:01:00.0/iommu_group/devices/
输出示例如下:0000:01:00.0 0000:01:00.1
要只为客户机分配 0000.01.00.0,在启动客户机前应该从主机分离未使用的端点:$ virsh nodedev-detach pci_0000_01_00_1
确定所需的配置详情
如需配置文件所需的值,请参见 virsh nodedev-dumpxml pci_0000_00_19_0 命令的输出。示例设备具有以下值: bus = 0, 插槽 = 25, function = 0。十进制配置使用这三个值:bus='0' slot='25' function='0'
添加配置详情
运行 virsh edit,指定虚拟机名称,并在<devices>
部分添加一个设备条目,将 PCI 设备分配给客户机虚拟机。例如:# virsh edit guest1-rhel7-64
图 16.2. 添加 PCI 设备
<devices> [...] <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0' bus='0' slot='25' function='0'/> </source> </hostdev> [...] </devices>
或者,运行 virsh attach-device,指定虚拟机名称和客户机 XML 文件:virsh attach-device guest1-rhel7-64
file.xml
注意PCI 设备可以包括 可选的只读内存(ROM)模块 (也称为 ROM 或 扩展 ROM ), 用于提供设备固件或预启动驱动程序(如 PXE)。通常,在使用 PCI 设备分配时,这些选项 ROM 也可在虚拟环境中工作,将物理 PCI 设备附加到虚拟机。但是,在某些情况下,选项 ROM 可能是不必要的。这可能会导致虚拟机引导速度变慢,或者该设备提供的预引导驱动程序与虚拟化不兼容,这可能会导致客户端操作系统引导失败。在这种情况下,红帽建议从虚拟机屏蔽选项 ROM。要做到这一点:- 在主机上,验证要分配的设备是否具有扩展 ROM 基本地址寄存器(BAR)。要做到这一点,将 lspci -v 命令用于该设备,并检查包含以下内容的行:
Expansion ROM at
- 将 <rom bar='off'/> 元素作为客户机 XML 配置中的 <hostdev> 元素的子项添加:
<hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0' bus='0' slot='25' function='0'/> </source> <rom bar='off'/> </hostdev>
启动虚拟机
# virsh start guest1-rhel7-64
PCI 设备现在应该能够成功分配给虚拟机,并可供客户端操作系统访问。
16.1.2. 使用 virt-manager 分配 PCI 设备
PCI 设备可以使用图形 virt-manager 工具添加到客户机虚拟机中。以下流程将千兆位以太网控制器添加到客户机虚拟机中。
过程 16.4. 使用 virt-manager 为客户机虚拟机分配 PCI 设备
打开硬件设置
打开 guest 虚拟机,按钮向虚拟机添加新设备。图 16.3. 虚拟机硬件信息窗口
选择 PCI 设备
从左侧 的硬件 列表中选择 PCI 主机设备。选择未使用的 PCI 设备。请注意,选择存在于其他客户机中的 PCI 设备 会导致错误。本例中使用了备用的音频控制器。单击 Finish 以完成设置。图 16.4. Add new virtual hardware 向导
添加新设备
设置已完成,guest 虚拟机现在可以直接访问 PCI 设备。图 16.5. 虚拟机硬件信息窗口
注意
如果设备分配失败,则同一 IOMMU 组中可能存在其他端点仍然附加到主机。无法使用 virt-manager 检索组信息,但 virsh 命令可用于分析 IOMMU 组的绑定,以及所需的 sequester 设备。
有关 IOMMU 组以及如何分离端点设备的更多信息,请参阅 注意 中的 第 16.1.1 节 “使用 virsh 分配 PCI 设备”。
16.1.3. 使用 virt-install 的 PCI 设备分配
在使用 virt-install 命令安装客户机时,可以分配 PCI 设备。为此,请使用
--host-device
参数。
过程 16.5. 使用 virt-install 为虚拟机分配 PCI 设备
确定设备
识别为分配给客户机虚拟机的设备分配的 PCI 设备。# lspci | grep Ethernet 00:19.0 Ethernet controller: Intel Corporation 82567LM-2 Gigabit Network Connection 01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01) 01:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
virsh nodedev-list 命令列出与系统连接的所有设备,并使用字符串来识别每个 PCI 设备。要只把输出限制为 PCI 设备,请输入以下命令:# virsh nodedev-list --cap pci pci_0000_00_00_0 pci_0000_00_01_0 pci_0000_00_03_0 pci_0000_00_07_0 pci_0000_00_10_0 pci_0000_00_10_1 pci_0000_00_14_0 pci_0000_00_14_1 pci_0000_00_14_2 pci_0000_00_14_3 pci_0000_00_19_0 pci_0000_00_1a_0 pci_0000_00_1a_1 pci_0000_00_1a_2 pci_0000_00_1a_7 pci_0000_00_1b_0 pci_0000_00_1c_0 pci_0000_00_1c_1 pci_0000_00_1c_4 pci_0000_00_1d_0 pci_0000_00_1d_1 pci_0000_00_1d_2 pci_0000_00_1d_7 pci_0000_00_1e_0 pci_0000_00_1f_0 pci_0000_00_1f_2 pci_0000_00_1f_3 pci_0000_01_00_0 pci_0000_01_00_1 pci_0000_02_00_0 pci_0000_02_00_1 pci_0000_06_00_0 pci_0000_07_02_0 pci_0000_07_03_0
记录 PCI 设备编号;其他步骤中需要数字。有关域、总线和功能的信息可从 virsh nodedev-dumpxml 命令的输出中获得:# virsh nodedev-dumpxml pci_0000_01_00_0
图 16.6. PCI 设备文件内容
<device> <name>pci_0000_01_00_0</name> <parent>pci_0000_00_01_0</parent> <driver> <name>igb</name> </driver> <capability type='pci'> <domain>0</domain> <bus>1</bus> <slot>0</slot> <function>0</function> <product id='0x10c9'>82576 Gigabit Network Connection</product> <vendor id='0x8086'>Intel Corporation</vendor> <iommuGroup number='7'> <address domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> </iommuGroup> </capability> </device>
注意如果在 IOMMU 组中有多个端点,且并非所有端点都分配给客户端,则需要在启动客户端前运行以下命令从主机中手动分离其他端点:$ virsh nodedev-detach pci_0000_00_19_1
有关 IOMMU 组的更多信息,请参阅 注意 中的 第 16.1.1 节 “使用 virsh 分配 PCI 设备”。添加设备
使用 virsh nodedev 命令的 PCI 标识符输出作为--host-device
参数的值。virt-install \ --name=guest1-rhel7-64 \ --disk path=/var/lib/libvirt/images/guest1-rhel7-64.img,size=8 \ --vcpus=2 --ram=2048 \ --location=http://example1.com/installation_tree/RHEL7.0-Server-x86_64/os \ --nonetworks \ --os-type=linux \ --os-variant=rhel7 --host-device=pci_0000_01_00_0
完成安装
完成客户机安装。PCI 设备应连接到客户机。
16.1.4. 分离分配的 PCI 设备
当主机 PCI 设备分配给客户机机器时,主机将不再使用该设备。如果 PCI 设备处于
受管
模式(使用 域 XML 文件中的 managed='yes
参数进行配置),它会连接到客户端机器并从客户端机器分离,并根据需要重新连接到主机机器。如果 PCI 设备没有处于 受管
模式,您可以将 PCI 设备从虚拟客户机中分离,并使用 virsh 或 virt-manager 重新连接。
过程 16.6. 使用 virsh 从客户机中分离 PCI 设备
分离设备
使用以下命令,在客户机的 XML 文件中删除 PCI 设备来从客户机中分离 PCI 设备:# virsh detach-device name_of_guest file.xml
重新将设备附加到主机(可选)
如果设备处于受管
模式,则跳过此步骤。该设备将自动返回到主机。如果设备没有使用受管
模式,使用以下命令将 PCI 设备重新关联到主机机器:# virsh nodedev-reattach device
例如,要将pci_0000_01_00_0
设备重新关联到主机:# virsh nodedev-reattach pci_0000_01_00_0
该设备现在可供主机使用。
过程 16.7. 使用 virt-manager 从客户机中分离 PCI 设备
打开虚拟硬件详情屏幕
在 virt-manager 中,双击包含该设备的虚拟机。选择 Show virtual hardware details 按钮,以显示虚拟硬件列表。图 16.7. 虚拟硬件详情按钮
选择并删除该设备
从左侧面板中的虚拟设备列表选择要分离的 PCI 设备。图 16.8. 选择要分离的 PCI 设备
16.1.5. PCI Bridges
外围设备组件互联(PCI)网桥用于附加到网卡、模式和声卡等设备。就像其物理对应设备一样,虚拟设备也可以附加到 PCI 网桥。过去,任何客户机虚拟机只能添加 31 个 PCI 设备。现在,当添加 31st PCI 设备时,PCI 网桥会自动放置在 31st 插槽中,将额外 PCI 设备移到 PCI 网桥。每个 PCI 网桥都有 31 个插槽用于 31 个设备,它们都可以是网桥的。这样,客户机虚拟机可以使用超过 900 个设备。
有关 PCI 网桥的 XML 配置示例,请参阅 PCI Bridge 的 Domain XML 示例。请注意,此配置是自动设置的,我们不推荐手动调整。
16.1.6. PCI 设备分配限制
PCI 设备分配(将 PCI 设备附加到虚拟机)需要主机系统具有 AMD IOMMU 或 Intel VT-d 支持,以启用 PCIe 设备的设备分配。
Red Hat Enterprise Linux 7 通过客户机设备驱动程序访问有限的 PCI 配置空间。这个限制可能会导致扩展 PCI 配置空间中取决于设备功能或功能的驱动程序失败。
每个 Red Hat Enterprise Linux 7 虚拟机有总计 32 个设备。这转换为 32 个 PCI 功能,无论虚拟机中存在 PCI 网桥的数量,或者如何合并这些功能来创建多功能插槽。
对于中断重新映射的平台支持,需要将客户机与主机中分配的设备进行完全隔离。如果没有这样的支持,主机可能会被受到攻击,以中断恶意客户机的注入攻击。在客户机受信任的环境中,管理员可能选择是否允许 PCI 设备分配使用
vfio_iommu_type1
模块的 allow_unsafe_interrupts
选项。这可以通过在 /etc/modprobe.d
中添加 .conf 文件(如 local.conf
)来永久完成:
options vfio_iommu_type1 allow_unsafe_interrupts=1或者使用 sysfs 条目动态执行相同的操作:
# echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts