配置空间寻址中的 DOMAIN/SEGMENT(Domain 往往是 Linux 术语,Segment 是 Windows 和 PCISIG 术语)主要是 PLATFORM 级别的构造。DOMAIN 和 SEGMENT 在此答案中可互换使用。从逻辑上讲,SEGMENT 是 PCI 系列配置空间寻址机制的 DOMAIN:Bus:Device:Function:Offset 寻址方案中的最高有效选择器(最高有效地址位选择器)。(PCIe、PCI-X、PCI 和后来的软件兼容总线互连)。
在 PCI-Express (PCIe) 和更早的规范中,DOMAIN 不会出现在总线上(或链路上)或链路事务数据包中。只有 BUS、DEVICE、FUNCTION、OFFSET 出现在事务中或总线上。然而,在基于逻辑软件的 SEGMENT:Bus,Dev,Func:OFFSET 配置空间软件地址如何用于实际创建互连协议包 (PCIe) 或总线周期序列 (PCI) 时,SEGMENT 确实占有一席之地,该数据包被描述为配置空间事务。在 PCI-Express (PCIe) 规范扩展配置空间访问方法 (ECAM) 中,这部分得到了解决。其余部分由 PCI 固件规范 3.2(涵盖较新的 PCIe 规范软件要求)处理。
在现代 PCIe 中,配置空间访问方法由操作系统通过 ECAM 机制来处理,它抽象了这样的配置空间访问机制(将 CPU 内存空间访问指令转换为总线/互连配置空间事务的机制)。操作系统软件将 SEGMENT/DOMAIN 理解为配置空间的 SEGMENT:BUS:DEVICE:FUNC:OFFSET 地址方案中的最高级别(最顶层)逻辑选择器和地址组件。SEGMENT 如何从软件逻辑概念转移到物理硬件实例化以 ECAM 转换器的形式出现,或者特别是平台中存在多个 ECAM 转换器。ECAM 转换器在内存类型事务和配置空间类型事务之间进行转换。PCIe 规范描述了单 ECAM 转换器实现如何将目标转换内存写入或读取中的特定内存地址位转换为配置空间写入或读取。这工作如下:
Address Bits:
11:00 (Offset bits, allows 4K of configuration space per PCIe device)
14:12 Function selection bits.
19:15 Device selection Bits.
27:20 Bus Selection Bits. 1 <= n <= 8 (Maximum of 8 bits, 256 numbers, can be less)
63:28 Base address of the individual ECAM.
没有明确(或根本没有)真正涵盖的是可以存在多个 ECAM。一个平台可以设置多个 ECAM 区域。为什么平台会这样做?因为 ECAM 地址位(8 位)的总线选择位容限是限制性的,仅允许系统中总共有 256 个总线,这在某些系统上是不够的。
PCI 固件规范 3.2(2015 年 1 月 26 日)从软件逻辑角度描述了 ECAM。固件规范描述了称为 MCFG 表的软件内存结构(存在于 BIOS 保留区域中,由 BIOS 和操作系统用于通信)。MCFG 表描述了平台硬件实现中存在的基于 ECAM 硬件的配置空间周期生成器的一个或多个实例。这些是配置空间周期事务转换区域的内存地址空间事务(内存写入)。例如,ECAM 硬件实现是 CPU 实例化以允许软件生成配置空间事务的机制。平台实现(通常由 CPU/芯片组设计指定和限制,但有时也由 BIOS 设计选择决定)允许一定数量的 ECAM 配置空间循环生成器。一个平台必须至少支持一个,然后它才会有一个 SEGMENT。但是一个平台可能支持多个 ECAM,然后每个支持的 ECAM 都有一个 SEGMENT。MCFG 表包含平台支持的每个 ECAM 的配置空间基地址分配结构。单个 SEGMENT 平台将只有一个条目,多 SEGMENT 平台将有多个条目,每个受支持的 ECAM 一个。每个条目包含(ECAM 区域配置空间循环生成器的)内存基地址、与此 ECAM 和总线编号子范围相对应的逻辑 SEGMENT 组,以及存在于这个逻辑段。
BIOS 不能仅仅决定它需要大量 ECAM 并描述多个 ECAM 并使用常规内存地址作为“基地址”。硬件实际上必须通过设计将内存地址实例化到配置空间周期生成逻辑,该逻辑锚定到特定地址(有时由 CPU/芯片组设计固定,有时由 CPU/芯片组特定的非标准位置配置根据位置进行配置在任何一种情况下,BIOS 都会描述存在哪些 ECAM,并且根据设计,描述配置(或禁用)一组 ECAM 以描述 ECAM 的一种方式或特定方式。激活系统上的一个或多个活动 ECAM。此类 BIOS 配置的一部分包括设置可配置的 ECAM,选择启用的数量(如果可配置),它们将住在哪里(在什么基地址),配置哪些芯片组设备对应什么 ECAM,以及配置哪些根端口对应并与哪些 ECAM 相关联。完成此 BIOS 内部配置后,BIOS 必须向操作系统描述这些平台硬件和 BIOS 决策。这是使用 PCI 固件规范定义的 MCFG 表完成的,该表是 BIOS(固件)到操作系统平台描述定义机制的 ACPI 规范的一部分。那么 BIOS 必须向操作系统描述这些平台硬件和 BIOS 决定。这是使用 PCI 固件规范定义的 MCFG 表完成的,该表是 BIOS(固件)到操作系统平台描述定义机制的 ACPI 规范的一部分。那么 BIOS 必须向操作系统描述这些平台硬件和 BIOS 决定。这是使用 PCI 固件规范定义的 MCFG 表完成的,该表是 BIOS(固件)到操作系统平台描述定义机制的 ACPI 规范的一部分。
使用 MCFG 表方案,可以拥有和描述多个 ECAM 和多个逻辑 SEGMENT,每个 ECAM 一个。也可能有一个 SEGMENT,它实际上也被拆分为多个 ECAM。(多个条目,但都使用相同的 SEGMENT,然后是不重叠的总线编号。)但是 MCFG 在多段配置中的典型用途是允许多个段,其中总线编号是重复的。例如,每个 SEGMENT 最多可以有一个完整的 256 总线,这与另一个 SEGMENT 中可能存在的最多 256 个总线是分开的。
三组软件都知道配置空间寻址中的 SEGMENT。BIOS(创建 MCFG 表),操作系统(读取 MCFG 表,获取 ECAM 基地址,并通过访问正确的 ECAM,在正确的偏移量处处理逻辑到物理地址的转换软件任务),以及最后一个组是所有其他总线、设备、功能 (BDF) 感知软件。所有软件必须是 SEGMENT,BUS,DEV,FUNC 感知的,而不仅仅是 Bus,DEV,FUNC 感知的。假定 SEGMENT 始终为 0 的软件已损坏。如果您曾经创建过这样的软件,那么您应该在任何人看到它之前立即回到您的办公桌前修复它,当然在它发布到产品中之前!:-)
平台设计(硬件 ECAM 支持和 BIOS 设计)可以实现多个 ECAM。这样做通常是为了规避仅使用单个 ECAM 带来的 256 条总总线限制。因为 ECAM 是由 PCISIG 定义的,并且因为该定义围绕总线上的总线数限制(在事务字段中),所以单个 ECAM 无法为超过 256 个总线实现配置空间生成器。然而,平台 CAN 和 DO 实例化多个 ECAM 区域,并具有描述具有多个 ECAM 基地址的多个 SEGMENT 的 MCFG 表,这允许平台拥有超过 256 条总线。(但在以 PCIe 根端口为根的每个 PCIe 设备树中最多只有 256 条总线,并且共享一个公共 ECAM 配置空间生成器的所有根端口一起最多也只有 256 条总线。每个 ECAM 区域在其 DOMAIN(或 SEGMENT)中最多可以描述 256 条总线。平台系统如何决定将主机根端口(缓存一致域到 PCI/PCIe 域网桥)分组到 SEGMENT 中是平台特定的,并且对于芯片组/CPU 设计和 BIOS 配置是任意的。大多数平台是固定且简单的(通常只有一个 ECAM),有些平台灵活、严格且可配置,允许多种解决方案。提供在平台级别使用的最大数量的 PCIe 总线数量的解决方案类型是支持每个根端口一个 ECAM。(今天很少有平台这样做,但都应该这样做!)它们是用于描述平台“如何”决定将设备、端点和交换机分组到 SEGMENT 中的两种机制。首先是前面提到的MCFG结构,它简单地列出了多个 SEGMENTS、它们关联的 ECAM(如果一个 SEGMENT 中的总线范围在多个 ECAM 之间拆分,则可能不止一个),以及每个 ECAM 的基地址(或 ECAM 总线编号子区域)。这种方法本身通常足以满足许多枚举任务,因为这允许操作系统枚举所有段,找到它们的 ECAM,然后对每个 SEGMENT 中的所有设备进行 PCI Bus,Device,Function 扫描。但是,也可以使用第二种机制来扩充 MCFG 信息,即 ACPI 命名空间中的 _SEG 描述符。ACPI 规范有一个通用的平台描述机制,以独立于操作系统的方式描述系统中已知设备的关系,但允许操作系统解析数据并消化平台布局。这种机制称为 ACPI 命名空间。在命名空间内,设备是“对象”,因此通常描述了固定并包含在 ACPI 实现系统主板上的 PCIe 端点、PCIe 根端口和 PCIe 开关。在此命名空间中,对象出现,并具有限定符或装饰器。一种这样的装饰器“方法”是 _SEG 方法,它描述了特定对象位于哪个 SEGMENT。通过这种方式,内置设备可以分组到特定的 ECAM 访问区域,或者更常见的是特定的 PCIe ROOT 端口被分组到 SEGMENTS (以及相关的 ECAM 访问区域,具有 MCFG 描述的基地址)。此外,可以热添加的设备(并且不静态存在于主板上)可以描述他们在热插拔时重新创建的 SEGMENT,或者他们在热插拔添加时加入的预先存在的 SEGMENT,以及他们实例化的那个 SEGMENT 中的总线编号。这是在命名空间中使用 _CBA 方法装饰器在此类命名空间中描述的根端口对象上完成的,并且它与 _SEG 方法结合使用。_CBA 仅适用于顶级“已知”热插拔元素,例如两个 4 CPU 系统是否可以动态“加入”到单个 8 CPU 系统中,它们各自的 PCIe 根端口元素也因此“加入”新的从原始基本 4 CPU 系统的 PCIe 根端口扩展的单个系统,以包括添加的 4 个 CPU 的新的附加 PCIe 根端口。这是在命名空间中使用 _CBA 方法装饰器在此类命名空间中描述的根端口对象上完成的,并且它与 _SEG 方法结合使用。_CBA 仅适用于顶级“已知”热插拔元素,例如两个 4 CPU 系统是否可以动态“加入”到单个 8 CPU 系统中,它们各自的 PCIe 根端口元素也因此“加入”新的从原始基本 4 CPU 系统的 PCIe 根端口扩展的单个系统,以包括添加的 4 个 CPU 的新的附加 PCIe 根端口。这是在命名空间中使用 _CBA 方法装饰器在此类命名空间中描述的根端口对象上完成的,并且它与 _SEG 方法结合使用。_CBA 仅适用于顶级“已知”热插拔元素,例如两个 4 CPU 系统是否可以动态“加入”到单个 8 CPU 系统中,它们各自的 PCIe 根端口元素也因此“加入”新的从原始基本 4 CPU 系统的 PCIe 根端口扩展的单个系统,以包括添加的 4 个 CPU 的新的附加 PCIe 根端口。
对于出现在插槽或外部扩展机箱中的 PCIe 交换机,_SEG(或 SEGMENT 值)通常继承自平台中最高级的根端口,位于该 PCIe 设备树的顶层。包含该根端口的 SEGMENT 也是该根端口下的所有设备所属的网段。
人们经常读到较早的资料(在多个 ECAM 发明之前,以及配置空间和相关操作系统软件中的 SEGMENT 概念之前),PCIe 枚举是通过扫描总线编号、然后是设备编号、然后是功能编号来完成的。这是不正确的,并且已经过时了。实际上,现代(当前)BIOS 和操作系统实际上是通过逐步扫描 SEGMENT(选择要使用的 ECAM),然后是总线编号,然后是设备编号,最后是功能编号(在特定 ECAM 中应用偏移量)在特定 PCIe 根端口上和下生成配置周期(例如在特定 PCIe 设备树上)。
较旧的“PCI”机制(在为 PCIe 定义增强配置配置空间之前)不知道 SEGMENT。旧的 CF8/CFC PCI 配置空间访问机制在硬件平台支持时(任何新编写的软件都不应再使用)通常为传统的仅 PCI(不支持 PCIe)实现最佳实用解决方案操作系统,旧机制被硬编码为该机制的 SEGMENT 0。这意味着 PCI-only-aware 系统只能访问 SEGMENT 0 中的设备。所有主要操作系统都支持 PCIe ECAM 增强机制 10 多年了,今天软件对 CF8/CFC 机制的任何使用都被认为是不可行的过时的,陈旧的和破碎的,应该被现代使用的 ECAM 机制所取代,至少支持 MCFG 表和多个 ECAM,如果操作系统要求,辅以 ACPI 规范命名空间 _SEG 和 _CBA 属性对象方法信息由操作系统摄取,以实现完全动态的热插拔情况。如果操作系统没有将 ACPI 热插拔方法用于其他任务,则几乎所有非热插拔情况都可以由 MCFG 单独处理。如果操作系统将 ACPI 热插拔用于其他设备和命名空间操作,则通常需要额外支持 _SEG 和 _CBA,操作系统和 BIOS 都需要以描述设备关联分组的方式生成这些 APCI 命名空间对象SEGMENT 以及支持该设备、根端口或根复合网桥或设备的配置周期生成的特定 ECAM 硬件。
SEGMENT 分组倾向于遵循硬件设计中的一些逻辑原理以及对该设计配置的限制。(但并非总是如此,有时它只是随意和奇怪的。)例如,在 Intel 8 插槽系统(大型多处理器)上,“本机”一致性实现在大多数情况下往往被限制为 4 个插槽。当供应商构建一个 8 插槽系统时,通常通过在它们之间的相干互连上设置两组 4 个插槽,每组由集群交换机连接。这种类型的平台可能实现两个 PCIe SEGMENTS,每个 4 个插槽集群一个。但是对于平台可能希望如何使用多个 SEGMENT 和使用多个 ECAM 没有任何限制。一个双插槽系统可以实现多个 ECAM,每个 CPU 一个 SEGMENT,以便每个 CPU 最多允许 256 个 PCIe 总线,共 512 个。如果这样的平台将两个 CPU 的所有根端口都映射到单个 SEGMENT 中(更常见),那么整个平台只能有 256 条总线用于整个平台。优化设计的平台(并且在 ECAM 硬件资源方面更昂贵)将为系统中的每个根端口提供一个 ECAM,并为平台中的每个根复合体设备提供一个 ECAM。具有 8 个 Root Ports 的两个 CPU 系统,每个 CPU 上 4 个,每个 CPU 上具有 4 个 Root Complex,将实现 16 个 SEGMENT,其中 8 个(Root Port 的)每个将支持最大 256 总线,8 个支持 Root复杂设备树将实例化足够的总线支持来映射根复杂设备和网桥。因此,在 2048+ 总线的高端提供总线支持的情况下,这样一个完全组合的两个插槽系统将支持最多 8*256+ 内置根复合设备所需的总线。今天设计的任何“真实”服务器都应该这样设计。我仍在等待看到这种现代的“真正的”英特尔或 AMD 服务器,而不是这些天推出的玩具。
大多数操作系统软件不需要关心 SEGMENT 关联是如何实现的,它们只需要考虑逻辑 SEGMENT 值是配置空间寻址的一部分这一事实(不要只为总线、设备、功能编码你的东西, 假设 SEGMENT=0) 它必须被编码为 (SEGMENT, BUS, DEVICE, FUNCTION) 除非你想被贴上懒惰的标签,做错了,走捷径的笨蛋。支持 SEGMENT 值!它们现在很重要,并且在未来将变得越来越重要,因为对公交车号空间施加了更大的压力(并且平台由于被限制在单个 SEGMENT 中存在的低且限制性的 256 公交车而耗尽了公交车号。Single SEGMENT由于硬件设计而发生限制,但它也会发生,因为软件没有为多段平台正确编写和准备。不要假设软件是创建不良单SEGMENT(SEGMENT=0)的人。不要成为那个人!)不要以这种方式编写操作系统软件。不要以这种方式编写 BIOS 软件,不要编写支持总线、设备、功能但不支持 SEGMENT、BUS、设备、功能的应用程序。
平台操作系统软件(在 *nix 中的内核中,或在 Windows 中的 HAL 中)获取 SEGMENT 值,并使用该值来选择它将访问哪个 ECAM(例如,它将添加 BDF/偏移量内存地址偏移量的哪个 ECAM 基地址到)。然后它使用总线、设备、函数值来索引该 ECAM 中的较高地址位,最后它使用配置空间设备寄存器偏移地址来填充馈送到 ECAM 配置空间的内存地址的较低部分事务生成器作为其内存地址事务输入。
在英特尔兼容平台(英特尔和 AMD 等)上,PCI 固件规范和 ACPI 规范描述了 BIOS 如何告诉操作系统(例如 Linux、Windows、FreeBSD)一个 ECAM(单段)或每个ECAM(多段)基地址位于内存地址空间中。
SEGMENT 永远不会出现在 PCIe 或 PCI 的总线上。在 PCIe 中,RID(路由标识符)仅对发送方的 Bus# 和 Device/Func# 进行编码。同样在配置周期中,只有目标目标的 Bus# 和 Device#/Func# 被编码在下游事务中。如果启用 ARI (Alternative Routing ID) 模式,Device/Func# 可以在 PCIe 中得到修改处理。但是 SEGMENT 值没有出现(也没有出现在 PCI 总线序列中)。它本质上是一个软件结构,但具有平台硬件支持(CPU 和芯片组)形式的真实硬件实例,用于多个 ECAM(多段)或仅单个 ECAM(单段)。请注意,不同 SEGMENT 中的设备实际上仍然可以进行点对点直接通信。对等事务使用内存寻址发生(这是所有 SEGMENTS 之间的单个全局共享空间,例如,所有段仍然共享一个统一的内存地址空间,至少在 IOMMU 转换和通过根端口传输之后,这是潜在的先决条件在不同的段)。SEGMENT 可以有冲突和重复的总线编号空间,但是当它们出现在 DIFFERENT SEGMENT 中时,它们描述的是不同的总线。多 ECAM 系统实际上可以实现单个共享总线地址空间以及独立的重复总线编号空间。在实践中,这很少见,因为系统通常将单个 ECAM 和单个 SEGMENT 用于单个总线地址空间。然而,一些奇怪的硬件可能需要使用单段、多 ECAM、共享的单总线运行拆分为多个 ECAM,
一个理论平台在其“芯片组/非核心”组件中具有 a) 大量内置设备,并且其设计中有两个 CPU 插槽,如果它愿意,可以实现四段设计。它可以将所有内置的 CPU 设备放在自己的 SEGMENT 中(每个 CPU 一个),使用两个段,然后将每个 CPU 的 PCIe 根端口映射到自己的 SEGMENT 中,同样每个 CPU 一个唯一的 SEGMENT,总共 4分割。这将允许在整个系统中使用 4 * 256 = 1024 条总线。
一个不同的理论平台,具有相同的两个插槽数,可以将来自所有 CPU(在本例中只有两个)和所有内置设备以及所有当前根端口的所有设备映射到单个 ECAM,从而映射到单个 SEGMENT。这样的平台只有一个 ECAM,因此整个系统的总线总数将被限制为 256 条(因此,如果平台加载了大复杂的多端点附加卡,带有 PCIe 开关以支持存在的多设备。例如,前端 AI 支持 GPU 卡,或者如果它有多个扇出开关(以增加其插槽数),或者如果外部 PCIe 开关该供应商正确使用和支持扩展器(到外部 PCIe 机箱)。
目前正在设计的“最佳”平台以及未来将为每个根端口实现独立的 ECAM,允许每个根端口仅在其设备树中支持多达 256 条总线,独立于所有其他根端口。迄今为止,我仍在等待这个平台,它会有很多很多的 PCIe SEGMENT 对应于很多 PCIe 根端口。此类设计对于可组合 I/O 解决方案、共享内存解决方案、分层内存解决方案、可组合存储解决方案、大型外部 I/O 机箱解决方案、启用 CXL 的加速器等至关重要。换句话说,用于现代计算。当一个平台出来并说它的时钟比上一个多 5% 时,我打了个哈欠。当每个根端口 ECAM 支持出现时,我会注意到,
总线编号空间的压力现在处于临界点,因此在不久的将来可能会使用更多的段(或者如果英特尔和 AMD 正在关注的话应该是这样)。像 CXL(一种与 PCIe 软件模型兼容的总线基础设施)这样的技术只会增加对单个 SEGMENT 的配置空间总线数量限制的压力(现在 256 总线并不多。)每个交换机内部都使用一条总线,每个链路都使用一个总线,因此一个大插槽数,高扇出系统将消耗超过 256 个总线。多段设计现在已经出现,并且将越来越普遍。立即修复您的软件!
看:
PCI Express Base Spec 5.0(或任何早期版本)7.2。PCI Express 增强配置访问机制 (ECAM)
http://www.pcisig.com
PCI 固件规范 3.2(或更新版本)http://www.pcisig.com
4.1.2 MCFG 表说明
ACPI 规范“MCFG”定义 http://uefi.org
ACPI 命名空间描述中的 _SEG(段)命名空间限定符。
UEFI 规范 http://uefi.org 描述了操作系统如何在具有 UEFI BIOS(启动固件)的现代 UEFI 平台中找到 MCFG 表和所有其他基于 ACPI 的表。