系列文章目录
XHCI 1.2b 规范摘要(一)
XHCI 1.2b 规范摘要(二)
XHCI 1.2b 规范摘要(三)
XHCI 1.2b 规范摘要(四)
XHCI 1.2b 规范摘要(五)
XHCI 1.2b 规范摘要(六)
XHCI 1.2b 规范摘要(七)
XHCI 1.2b 规范摘要(八)
XHCI 1.2b 规范摘要(九)
XHCI 1.2b 规范摘要(十)
XHCI 1.2b 规范摘要(11)
XHCI 1.2b 规范摘要(12)
XHCI 1.2b 规范摘要(13)
XHCI 1.2b 规范摘要(14)
XHCI 1.2b 规范摘要(15)
文章目录
- 系列文章目录
- 8 虚拟化(Virtualization)
- 8.1 操作(Operation)
- 8.1.1 资源分配(Resource Assignment)
- 8.1.1.1 MMIO 空间(MMIO Space)
- 8.1.1.2 设备插槽(Device Slots)
- 8.1.1.3 中断器(Interrupters)
- 8.1.2 设备枚举和切换(Device Enumeration and Handoff)
- 8.1.2.1 根集线器连接仿真(Root Hub Attach Emulation)
8 虚拟化(Virtualization)
虚拟化允许在一个平台内同时运行多个操作系统实例 (OSI,Operating System Instances)。xHC 向主机系统提供的默认接口(即禁用虚拟化)是单个物理功能(PF 或 PF0,Physical Function)或可扩展主机控制器接口(eXtensible Host Controller Interface,例如,图 3-3)。打开 xHC 虚拟化功能后,将启用多个虚拟功能 (VF,Virtual Functions)。为了最大限度地降低硬件要求,xHC VF 提供的物理接口是 PF 提供的物理接口的子集,虚拟化软件应模拟 VF 接口的某些部分以填补空白。
虚拟化允许多个操作系统实例 (OSI) 在一个平台内同时运行。xHC 向主机系统提供的默认接口(即虚拟化已禁用)是单个物理功能 (PF 或 PF0) 或可扩展主机控制器接口(例如,图 3-3)。当 xHC 虚拟化功能打开时,将启用多个虚拟功能 (VF)。为了最大限度地减少硬件要求,xHC VF 提供的物理接口是 PF 提供的接口的子集,虚拟化软件应模拟 VF 接口的某些部分以填补空白。
只有 PF 应提供 xHC 虚拟化功能,即 SR-IOV 和 xHCI-IOV 功能结构。所有 VF 都显示为不具备虚拟化功能的 xHC 实例。
请注意,本文档中讨论的 xHC 虚拟化功能在很大程度上依赖于 PCIe SR-IOV (Single Root – I/O Virtualization,单根 - I/O 虚拟化) 规范中定义的虚拟化概念和机制。
此规范假设虚拟机架构支持三类主要软件:
- 虚拟机管理器 (VMM,Virtual Machine Manager):VMM 充当主机,完全控制处理器和其他平台硬件。VMM 向客户软件(请参阅下面的虚拟机 (VM) 描述)提供虚拟处理器的抽象,并允许其直接在逻辑处理器上执行。虚拟化环境中只有一个 VMM 实例,它可以保留对平台资源的选择性控制:处理器资源、物理内存、中断管理、I/O 等。VMM 可能拥有物理资源并提供服务以在多个 VM 之间共享该资源。或者,它可以直接将物理资源专门分配给 VM。
- 虚拟机 (VM,Virtual Machine):每个虚拟机 (VM) 都是一个客户软件环境,支持由操作系统 (OS) 和应用软件组成的堆栈。每个 VM 独立于其他 VM 运行,并使用物理平台提供的相同接口来处理处理器、内存、存储、图形和 I/O。VM 软件堆栈(或 OSI)可能表现得像在没有 VMM 的平台上运行一样。在 VM 中执行的软件应以较低的权限运行,以便 VMM 可以保留对平台资源的控制。
- 虚拟机管理程序(Hypervisor):虚拟机管理程序是一种传输机制,它为虚拟机和 VMM 之间提供通信路径。虚拟机管理程序的功能使其能够捕获虚拟机对平台资源的请求并将这些请求转发给 VMM 。
一些虚拟化环境将 VMM 和 Hypervisor 功能合并为一个实体。
为了降低硬件要求,xHC 架构依赖 VMM 来模拟 PCI 配置空间、xHCI 功能(xHCI Capability)和操作寄存器(Operational Registers)以及虚拟功能 (VF,Virtual Function) 的其他几个功能。
为了最大限度地减少与 VF 相关的硬件要求,xHCI 架构将其寄存器划分为 “低接触(low touch)” 和 “高接触(high touch)” 。低接触寄存器很少被引用,即仅在初始化时或枚举 USB 设备时引用。高接触寄存器在 xHC 的正常运行期间定期被引用。
VMM 可以捕获和模拟低接触寄存器,因为 VMM 干预对性能的影响很小。xHCI 功能寄存器和操作寄存器是低接触寄存器。功能寄存器通常仅在初始化时被引用,而操作寄存器在运行时很少被引用,即在初始化期间或连接或断开 USB 设备时引用。
高接触寄存器是 Interrupt(中断)和 Event Ring(事件环)管理寄存器以及 Doorbell(门铃)寄存器。 Interrupt 和 Event Ring 寄存器位于 Runtime Register Space (运行时寄存器空间)中。Runtime (运行时)和 Doorbell (门铃)寄存器由 xHC 物理呈现给每个 VF 。
xHCI 的设计使得 xHC 硬件和 VMM 硬件模拟组合呈现给 VM 的接口可能与 VM 通过 PF 看到的接口(如果 VM 独占 xHC)无法区分。这是通过 VMM 模拟功能和操作寄存器以及 xHC 硬件支持过滤 VF 对物理门铃和运行时寄存器集的访问来实现的。结果允许 VMM 处理与设备枚举和其他非时间关键 xHCI 操作相关的 xHCI 寄存器的模拟,并允许 xHC 向 VM 呈现硬件寄存器以进行时间关键的 USB 设备控制和数据传输管理。
xHCI 在 MMIO 空间中为运行时和门铃寄存器定义了独立的基地址,以便将它们定位在页面边界上,从而轻松映射到 VM。
此外,xHCI 还支持 VMM 将 USB 设备模拟到 VM 的能力。在单个 USB 设备的资源需要在多个 VM 之间共享的情况下,VMM 可以拥有物理设备并将该设备的操作模拟到多个 VM。例如,VMM 将拥有分配给 USB 键盘的设备插槽,并为每个 VM 创建该键盘的模拟版本。VMM 将管理将按键流切换到当前具有用户焦点的 VM。xHCI 的 USB 设备模拟支持还允许 VMM 将外部 USB 集线器模拟到 VM,其重要性将在下文讨论。
8.1 操作(Operation)
为了使 VMM 向 VM 提供 xHCI 功能,它应在 VM 的地址空间中显示 xHC VF。要启用 xHC 虚拟化功能,VMM 应执行以下基本步骤:
- 通过启用和配置 PCIe SR-IOV (Single Root – IO Virtualization,单根 - IO 虚拟化) 功能创建 VF。
- 通过启用和配置 xHCI-IOV (xHCI – IO Virtualization,xHCI - IO 虚拟化) 功能将 xHC 资源分配给 VF(中断器和设备插槽,Interrupters and Device Slots)。
- 在虚拟机地址空间中为 VF 分配 PCI 配置空间和 MMIO (Memory Mapped I/O,内存映射 I/O) 空间。
- 为虚拟机对模拟 VF 寄存器的引用建立虚拟机管理程序陷阱。
这些步骤允许结合使用 xHC 硬件和 VMM 寄存器级模拟,向虚拟机呈现功能齐全的 xHC,而无需硬件支持 VF 的每个功能。 它们还允许 VMM 充当中介,管理许多虚拟机之间的共享 xHC 资源。
8.1.1 资源分配(Resource Assignment)
为了最小化 VMM 开销,Device Slots(设备槽) 和 Interrupters(中断器) 可以 “直接分配” 给 Virtual Functions (虚拟功能)。VMM 应始终拥有 PF0。并且只有 PF0 应提供 SR-IOV 和 xHCI-IOV 扩展功能结构。
8.1.1.1 MMIO 空间(MMIO Space)
PCI 配置空间 BAR0 和 BAR1 字段包含指向 xHC PF0 MMIO 空间基址的 64 位地址。此指针将被称为 PBAR0。
SR-IOV VF Enable 字段应设置为 “1”,以启用 xHC 虚拟化支持。
SR-IOV TotalVFs 字段标识可与 PF 关联的 VF 的最大数量。
SR-IOV NumVFs 字段标识在 NumVFs 都设置为有效值且 VF Enable 设置为 “1” 后,MMIO 空间中可见的 VF 数量。NumVFs 的有效值为 1 到 TotalVFs,SR-IOV VF BAR0 和 VF BAR1 字段包含指向 xHC VF MMIO 空间基址的 64 位地址。此指针将被称为 VFBAR0。这些字段的行为与 PCI 规范第 6.2.5 节中描述的普通 PCI BAR 相同。它们的大小可以通过写入所有 1 并读回 BAR 的内容(如 PCI 规范中所述)来调整,并符合定义 BAR 类型字段的低位。VFBAR0 解码的大小称为 VFBAR0.Size。VFBAR0 解码的地址空间数量应为 SR-IOV System Page Size(系统页面大小)字段的整数倍。VFBAR0 确定单个 VF 的对齐要求和大小(VFBAR0.Size)。xHC 占用的总 MMIO 空间为 V F B A R 0. S i z e ∗ N u m V F s VFBAR0.Size * NumVFs VFBAR0.Size∗NumVFs。与每个 VF 关联的 MMIO 空间从页面边界开始,如 SR-IOV 扩展功能结构的系统页面大小字段所定义。
也就是说,如果 VFBAR0.size = 16 KB 且 NumVFs = 4,那么分配给所有 VF 的 MMIO 空间为 64 KB(16K * 4)字节。
PF0 MMIO 寄存器位置:
- 功能寄存器位于 PBAR0。
- 操作寄存器位于 PBAR0 + CAPLENGTH。
- 运行时寄存器位于 PBAR0 + RTSOFF。
- 门铃寄存器阵列位于 PBAR0 + DBOFF。VFn MMIO 寄存器位置,其中 n = 1 到 NumVFs:
- 功能寄存器位于 VFBAR0 + (VFBAR0.Size * (n-1))。
- 操作寄存器位于 VFBAR0 + (VFBAR0.Size * (n-1)) + CAPLENGTH。
- 运行时寄存器位于 VFBAR0 + (VFBAR0.Size * (n-1)) + RTSOFF。
- 门铃寄存器阵列位于 VFBAR0 + (VFBAR0.Size * (n-1)) + DBOFF。
图 8-1 展示了支持两个 VF 的 xHC 实现。请注意,分配给 VF 的 MMIO 地址空间是一个连续的数组。每个 VFBAR0.Size 空间也可以称为“孔径”。
注意:SR-IOV VF MSE 字段应设置为 “1” ,以便 xHC 响应 VF MMIO 内存空间访问。
8.1.1.2 设备插槽(Device Slots)
VF Device Slot Assignment Registers( VF 设备插槽分配寄存器)允许 VMM 将指定的门铃寄存器从其 (PF0) 门铃阵列映射到 VFs 门铃阵列。
-
未启用虚拟化(默认门铃寄存器寻址):
n = Slot ID,有效值 = 1 到 MaxSlots
门铃地址 n = P B A R 0 + D B O F F + ( n ∗ 4 ) 门铃地址 n = PBAR0 + DBOFF + (n * 4) 门铃地址n=PBAR0+DBOFF+(n∗4) -
如果启用虚拟化:
x = VF Device Slot Assignment Register:设备插槽 VF ID,有效值 = 0 到 NumVFs
n = VF Device Slot Assignment Register 索引,有效值 = 1 到 MaxSlots-
如果 x = 0:
门铃地址 n = P B A R 0 + D B O F F + ( n ∗ 4 ) 门铃地址 n = PBAR0 + DBOFF + (n * 4) 门铃地址n=PBAR0+DBOFF+(n∗4) -
如果 x > 0:
门铃地址 n = V F B A R 0 + ( V F B A R 0. S i z e ∗ ( x − 1 ) ) + D B O F F + ( n ∗ 4 ) 门铃地址 n = VFBAR0 + (VFBAR0.Size * (x-1)) + DBOFF + (n * 4) 门铃地址n=VFBAR0+(VFBAR0.Size∗(x−1))+DBOFF+(n∗4)
-
注意:所有门铃地址都是物理地址。
当设备槽 n 从 PF0 MMIO 空间重新映射到 VF 的 MMIO 空间时,VMM 应无法通过 PF0 门铃阵列访问相关的门铃寄存器。VM 应可通过分配给 VM 的 VF 的门铃寄存器 n 访问设备槽 n。
8.1.1.3 中断器(Interrupters)
VF Interrupter Range Registers(VF 中断器范围寄存器,第 7.7.2 节)允许 VMM 将指定的中断器从其(PF0)运行时寄存器空间映射到 VF 运行时寄存器空间。Primary Interrupter Register Set (主中断器寄存器集,0 ) 始终分配给 PF0。只有 secondary Interrupter Register Sets(次要中断器寄存器集,1 到 MaxIntrs-1)可以分配给 VF。中断器寄存器集分配给 VF 是独占的。
-
虚拟化未启用(默认中断器寄存器集寻址):
n = Physical Interrupter Register Set ID(物理中断器寄存器集 ID,0 到 MaxIntrs-1)中断器寄存器集 n 应位于物理地址: P B A R 0 + R T S O F F + ( n ∗ 32 ) PBAR0 + RTSOFF + (n * 32) PBAR0+RTSOFF+(n∗32),其中 32 是中断器寄存器集的大小。 -
如果启用了虚拟化:
- IRROFF = VF Device Interrupter Range Register (VF 设备中断器范围寄存器):Interrupter Offset (中断器偏移),有效值 = 1 到 MaxIntrs-1
- IRRCNT = VF Device Interrupter Range Register (VF 设备中断器范围寄存器):Interrupter Count (中断器计数),有效值 = 1 到 MaxIntrs-1
-
IRRINDX = VF Device Interrupter Range Register index(VF 设备中断器范围寄存器索引),有效值 = 0 到 TotalVFs
np = Physical Interrupter Register Set ID(物理中断寄存器集 ID),有效值 = 0 至 MaxIntrs
nv = VM Interrupter Register Set ID (VM 中断寄存器集 ID),有效值 = 0 至 IRRCNT-1
Interrupter Register Set(中断寄存器集) np + IRROFF 应位于物理地址:
V F B A R 0 + ( V F B A R 0. S i z e ∗ ( I R R I N D X − 1 ) ) + R T S O F F + ( n v ∗ 32 ) VFBAR0 + (VFBAR0.Size * (IRRINDX -1)) + RTSOFF + (nv * 32) VFBAR0+(VFBAR0.Size∗(IRRINDX−1))+RTSOFF+(nv∗32)
所有 VF 设备中断范围寄存器的 IRRCNT 值总和不得超过 MaxIntrs -1。
8.1.2 设备枚举和切换(Device Enumeration and Handoff)
在虚拟化环境中枚举 USB 设备是一个四步过程:VMM,
- 在检测到连接事件时枚举设备,
- 确定将分配设备到的 VM,
- 模拟同一设备到 VM 的连接事件,
- VM 按照第 4.3 节中描述的步骤枚举设备。
默认情况下,所有设备插槽都分配给 PF0,因此它们都归 VMM 所有。由于 VMM 拥有 PF0,它还可以访问 xHC 的物理根集线器端口。当设备连接到根集线器端口时,VMM 还会遵循第 4.3 节中描述的步骤,直到配置设备为止。VMM 只需从 USB 设备中检索足够的信息来确定应如何管理它。也就是说,设备是否归 VMM 所有并模拟到 VM,直接分配给 VM,或者只是由 VMM 自己拥有和使用。
在后一种情况下,VMM 将像非虚拟化环境中的任何其他 USB 设备一样配置和管理该设备。
在直接分配的情况下,模拟 VM 的 PORTSC 寄存器和命令环的 VMM 应模拟设备到 VM 的连接事件,然后将用于枚举设备的设备槽映射到 VM 拥有的 VF。
如果要将设备模拟到 VM,则 VMM 应加载一个可以在多个 VM 之间共享设备资源的“主”驱动程序,并且对于将与之共享设备的每个 VF,模拟设备到 VM 的连接事件,建立模拟的设备槽,并将该槽映射到相应 VM 拥有的 VF。VF 生成的后续工作项将由 VMM 的设备主驱动程序处理,并转发到 VMM 拥有的物理 USB 设备。
注意:如果 VMM 不能确保没有多个 VM 具有处于默认状态的 USB 设备,则可能会出现未定义的行为。
8.1.2.1 根集线器连接仿真(Root Hub Attach Emulation)
非虚拟化环境的设备枚举过程在第 4.3 节中描述。该过程的大部分内容也适用于虚拟化环境。VMM 拥有物理根集线器,因此当设备连接时,它是接收通知的实体。当设备连接时,VMM 应决定将其分配给哪个 VM。设备分配策略不在本规范的范围内,但是 VMM 需要从设备中检索设备描述符和可能的配置描述符以确定目标 VM。VMM 集线器驱动程序将遵循第 4.3 节中描述的步骤,直到但不包括配置设备(步骤 8)。
一旦确定了目标 VM,应执行以下步骤将设备传递给 VM:
-
VMM 向 VM 生成 Port Status Change Event(端口状态更改事件)。
- 在其命令环上发出 Force Event Command (强制事件命令)。强制事件命令指向 Port Status Change Event TRB (端口状态更改事件 TRB),并标识其事件环将接收 TRB 的 VM。
-
收到 Port Status Change Event TRB (端口状态更改事件 TRB) 后,VM 将开始启动第 4.3 节中描述的步骤。第一步要求 VM 重置设备。
- 通过将 Port Status Change Event (端口状态更改事件)指示的 PORTSC 寄存器中的端口重置 (PR) 位设置为 “1” 来重置 USB2 设备。对于 USB3 设备则不需要,因为它们是隐式重置的。 Port Status Change Event 中 Port ID 指示使用哪个 PORTSC 。
-
VMM 捕获 VM 对其 PORTSC 寄存器的引用。
a. 当 VMM 检测到 VM 引用中对模拟 PORTSC 寄存器的 PR 位设置时,它将断言物理 PORTSC 寄存器中的 PR 位。
请注意,VMM 可能会过滤 VM 对物理 PORTSC 寄存器的引用,例如,在 VM 尝试重置连接到集线器的根集线器端口的情况下,因为连接到该集线器的某些设备由其他 VM 拥有。
- 在适当的超时后,VM 将获得“新”连接的设备的设备槽。
a. 它通过在其命令环上放置启用槽命令并使用主机控制器命令的 DB 目标代码写入主机控制器(VM 设备槽 0)门铃寄存器来实现此目的。
- VM 对门铃寄存器的引用会向 VMM 生成门铃事件。
a. VMM 解析门铃事件并确定命令环已被修改。
b. VMM 从 VM 的命令环中检索命令 TRB,更新 VM 命令 TRB 状态字段并适当推进环索引。
-
VMM 检查检索到的命令 TRB,解码启用槽命令,并为 VM 处理它。
a. VMM 使用适当的 VM 槽分配寄存器将其用于枚举设备的设备槽映射到 VM 拥有的 VF。
b. 释放它用于管理设备的任何数据结构。
c. 通过发出强制事件命令向 VM 生成命令完成事件。强制事件命令指向命令完成事件 TRB。命令完成 TRB 的命令响应字段将包括 VMM 分配给 VM 的设备槽的 ID。 -
收到命令完成事件后,VM 将继续初始化其设备上下文数据结构、设备上下文基址数组等,最后发出寻址设备命令以启用设备的控制端点。
-
当 VMM 检查 VM 的命令环时,它会找到寻址设备命令并为 VM 处理它。寻址设备命令通知 xHC 与设备槽关联的设备上下文数据结构已更改。
a. VMM 通过将相同的命令放在 PF0 命令环上,将寻址设备命令转发给 xHC。
b. 然后使用强制事件命令将 PF0 命令完成事件返回给 VM。 -
收到命令完成事件后,VM 将直接向设备的控制端点发出几个请求,读取设备和配置描述符以确定它要选择的配置。
☆