7

我试图了解 PCI 段(域)如何与多个主机桥相关?

有人说多个PCI域对应多个Host Bridge,但也有人说是指一个Host Bridge下的多个Root Bridge。我很困惑,在 PCI SIG 基本规范中找不到太多有用的信息。

我想知道

(1) 假设我在 MCFG 中设置了 3 个 PCI 域,我有 3 个连接 3 个 CPU 和总线的主机桥,还是有 3 个支持 3 倍总线但在一个 CPU 中共享一个公共主机桥的根桥?

(2) 如果我有多个主机桥(或根桥),这些桥是共享一个共同的南桥(例如,ICH9),还是有单独的?

我是初学者,谷歌并没有解决我的问题。如果有人能给我一些线索,我将不胜感激。

4

2 回答 2

22

使用的措辞令人困惑。
我将尝试通过对 PCI 和 PCI Express 技术的简短且不完整的总结来修正我的术语。
跳到最后一节阅读答案。


PCI

常规 PCI 总线(以下简称PCI 是围绕总线拓扑设计的:共享总线用于连接所有设备。

为了创建更复杂的层次结构,一些设备可以作为桥接器运行:桥接器将 PCI 总线连接到另一个辅助总线。
辅助总线可以是另一个 PCI 总线(该设备称为PCI-to-PCI 桥,因此称为P2P)或不同类型的总线(例如 PCI-to-ISA 桥)。

这将创建以下形式的拓扑:

           _____          _______
----------| P2P |--------| P2ISA |-------------  PCI BUS 0
           ‾‾|‾‾          ‾‾‾|‾‾‾
-------------|---------------+-----------------  ISA BUS 0
             |
-------------+---------------------------------  PCI BUS 1

非正式地,每条 PCI 总线称为一个PCI 段
在上图中,显示了两个段(PCI BUS 0 和 PCI BUS 1)。

PCI 定义了三种类型的事务:内存、IO 和配置。
前两个被认为是必需的知识。
第三个用于访问每个设备的配置地址空间(CAS);在这个 CAS 中,可以对设备进行元配置。
例如,它在系统内存地址空间中的映射位置。

为了访问设备的 CAS,设备必须是可寻址的。
在电气上,PCI 总线段中的每个 PCI 插槽(无论是否集成)都被连接以创建由三部分组成的寻址方案:设备(0-31)、功能(0-7)、寄存器(0-255) .
每个设备最多可以有 7 个逻辑功能,每个具有 256 字节的 CAS。

将总线编号添加到上述三元组中,以唯一标识整个总线拓扑中的设备(而不仅仅是总线段内)。
这个四联体称为ID 地址
需要注意的是,这些 ID 地址是由软件分配的(但对于设备部分,由接线固定)。
它们是合乎逻辑的,但是,建议从根开始按顺序对总线进行编号。

CPU 本身不会生成 PCI 事务,需要主机桥
它是一个让 CPU 执行 PCI 事务的桥接器(概念上是主机到 PCI 桥接器)。
例如,在 x86 情况下,任何未被其他代理(例如内存、内存映射的 CPU 组件、遗留设备等)回收的内存写入或 IO 写入都由主机桥传递到 PCI 总线。
要生成 CAS 事务,x86 CPU 会写入 IO 端口0xcf80xcfc(第一个包含 ID 地址,第二个包含要读取/写入的数据)。

CPU 可以有多个主机桥,没有什么可以阻止它,尽管它非常罕见。
更有可能的是,一个系统可以有多个 CPU,并且每个 CPU 都集成了一个主机桥,一个系统可以有多个主机桥。

对于 PCI,每个主机桥建立一个PCI 域:一组总线段。
PCI 域的主要特征是它与其他 PCI 域隔离:事务不需要在域之间可路由。

操作系统可以随意分配每个 PCI 域的总线号,它可以重用总线号,也可以按顺序分配它们:

          NON OVERLAPPING                 |            OVERLAPPING
                                          |
Host-to-PCI        Host-to-PCI            |  Host-to-PCI        Host-to-PCI 
 bridge 0           bridge 1              |   bridge 0           bridge 1
                                          |
   |                  |                   |     |                  |
   |                  |                   |     |                  | 
  BUS 0   |         BUS 2    |            |    BUS 0   |         BUS 0    | 
   |      |           |      |            |     |      |           |      |
   +------+           +------+            |     +------+           +------+
   |      |           |      |            |     |      |           |      |
   |      |           |      |            |     |      |           |      |  
   |      BUS 1       |      BUS 3        |     |      BUS 1       |      BUS 1

不幸的是,PCI 域这个词在 Linux 内核中也有一个含义,它用于对每个主机桥进行编号。
就 PCI 而言,这是可行的,但是随着 PCI express 的引入,这变得令人困惑,因为 PCI express 有自己的“主机桥号”名称(即 PCI 段组),而术语PCI 域表示下游链路PCI Express 根端口。


PCI Express

PCI Express 总线(以下称为 PCIe)是围绕点对点拓扑设计的:一个设备仅连接到另一个设备。

为了保持软件兼容性,大量使用虚拟 P2P 网桥。
PCI 总线的基本组件是设备和桥接器,而 PCIe 的基本组件是设备和交换机。
从软件的角度来看,没有任何改变(除了添加的新功能),总线的枚举方式相同:使用设备和网桥。

PCIe 交换机是设备之间的基本粘合剂,它有n 个 下游端口
交换机内部有一个 PCI 总线段,对于每个端口,在内部总线段中创建一个虚拟 P2P 桥(虚拟形容词在那里是因为每个 P2P 只响应 CAS 事务,这对于 PCI 兼容软件来说已经足够了)。
每个下游端口都是一条 PCIe 链路。
一条 PCIe 链路被视为一个 PCI 总线段;这检查了交换机为每个下游端口都有一个 P2P 桥接器的事实(总共有 1 + n 个用于交换机的 PCI 总线段)。
一台交换机还有一个端口:上行端口。
它就像一个下游端口,但它使用减法解码,就像网络交换机一样,它用于接收来自“逻辑外部网络”的流量并路由未知目的地。

PCIe 交换机的逻辑块

所以一个交换机需要 1 + N + 1 个 PCI 段总线。

设备直接连接到交换机。

在 PCI 的情况下,一个桥将 CPU 连接到 PCI 子系统,因此期望交换机将 CPU 连接到 PCIe 子系统是合乎逻辑的。对于PCI 复合根(PCR)
,情况确实如此。 PCR 基本上是一个具有重要转折的交换机:它的每个端口都建立一个新的PCI 域。 这意味着不需要将流量从端口 1 路由到端口 2(当然,交换机需要)。如前所述,这与 Linux 术语产生了转变,因为 Linux 为每个主机桥或 PCR 分配了一个域编号,而根据规范,每个 PCR 都有多个域。 长话短说:同一个词,不同的意思。 PCIe 规范使用词PCI 段组



为每个PCR定义一个编号(简单的说PCI段组就是每个PCR的扩展CAS机制的基地址,所以原生是一对一映射的)。

由于它们的隔离特性,PCR 的端口被称为PCIe Root Port


笔记

规范中不存在术语根桥,我只能在UEFI 根桥 IO 规范中找到它作为主机桥和 PCR 的总称(因为它们具有相似的职责)。

主机桥也使用主机适配器的名称。


最后你的问题

(1) 假设我在 MCFG 中设置了 3 个 PCI 域,我有 3 个连接 3 个 CPU 和总线的主机桥,还是有 3 个支持 3 倍总线但在一个 CPU 中共享一个公共主机桥的根桥?

如果您有 3 个 PCI 域,则您有 3 个主机桥接端口或 3 个 PCIe 根端口。

如果 PCI 域是指 PCI 总线,在 PCI 总线段的意义上(不管它们的隔离),那么您可以让单个主机桥/PCR 处理具有 3 条总线的拓扑,或者多个主机桥/PCR 处理一个3条总线的组合。
在这种情况下没有具体要求,因为您可以看到可以将总线与桥接在一起。

如果您希望总线不被隔离(因此不是 PCI 域),您需要一个主机桥或一个 PCIe 根端口。
一组 P2P 桥接器(真实的或虚拟的)将总线连接在一起。

(2) 如果我有多个主机桥(或根桥),这些桥是共享一个共同的南桥(例如,ICH9),还是有单独的?

桥接平台几年前就已经淡出,我们现在将一个系统代理集成到 CPU 中,它公开了一组 PCIe 通道(通常为 20 多个)和一个平台控制器集线器 (PCH),通过 DMI 链接连接到 CPU。
PCH 也可以集成到与 CPU 相同的插槽中。
从软件的角度来看,PCH 暴露了更多似乎来自 CPU PCR 的通道。

无论如何,如果您有多个主机桥,它们通常位于不同的套接字上,但它们通常只有一个南桥。
但是,这是(并且不是)严格强制性的。
现代 Intel C620 PCH 可以在仅端点模式 (EPO) 下运行,它不用作主 PCH(具有固件和引导职责),而是用作一组 PCIe 端点。

这个想法是主机桥只是将 CPU 事务转换为 PCI 事务,这些事务的路由取决于总线拓扑,这本身就是一个非常有创意的话题。
集成此拓扑的组件是另一项创造性任务,最终可能有单独的芯片专用于每个主机桥,或者同时在所有或什至两者之间共享(或分区)一个大的单芯片!

于 2018-03-03T23:28:59.080 回答
3

配置空间寻址中的 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 个总线。多段设计现在已经出现,并且将越来越普遍。立即修复您的软件!

看:

  1. PCI Express Base Spec 5.0(或任何早期版本)7.2。PCI Express 增强配置访问机制 (ECAM) http://www.pcisig.com

  2. PCI 固件规范 3.2(或更新版本)http://www.pcisig.com 4.1.2 MCFG 表说明

  3. ACPI 规范“MCFG”定义 http://uefi.org ACPI 命名空间描述中的 _SEG(段)命名空间限定符。

  4. UEFI 规范 http://uefi.org 描述了操作系统如何在具有 UEFI BIOS(启动固件)的现代 UEFI 平台中找到 MCFG 表和所有其他基于 ACPI 的表。

于 2020-09-24T03:32:25.053 回答