ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PCIe6.0 协议学习---Introduction

PCIe6.0 协议学习---Introduction

PCIe 最关键的取舍:

保留 PCI 的软件模型(load-store、枚举、配置空间),只把"并行总线"换成"串行点对点 + 分组交换"的物理实现。

PCIe 之所以能"无缝替换 PCI",不是因为它物理上兼容 PCI,而是因为它在软件眼里长得跟 PCI 一模一样——操作系统和驱动完全感知不到下面是串行链路。

1.1 An Evolving I/O Interconnect

第一类:市场与经济性

第二类:软件兼容

  • 用现有 PCI 配置软件就能枚举/配置,不用改
  • 现有操作系统能直接启动,不用改
  • 现有设备驱动直接能用,不用改
  • 新功能通过 PCI 配置范式(configuration paradigm)来使能

这是怎么做到的?靠三样东西在 PCIe 里被原样保留:

  1. 配置空间:每个 Function 有一个 256 字节的、PCI 兼容的配置头(vendor ID / device ID / BAR / 中断引脚等字段位置不变),后面再接 PCIe 扩展能力(capability)链表。
  2. 枚举机制:软件还是按 "bus / device / function" 三级去扫描(扫 bus 0,读 header type 判断是不是 bridge,再往下扫……)。
  3. 地址模型:Memory-mapped I/O(通过 BAR 把设备寄存器映射进内存地址空间)+ I/O 空间。

因为这三样没变,老软件完全不知道自己在跟串行链路打交道。

第三类:性能

  • 低开销、低延迟→ 最大化有效带宽和链路效率(header 小、协议栈薄)
  • 每引脚高带宽→ 串行差分对(每方向一对差分线就是一个 Lane)比并行总线的引脚效率高得多
  • 通过聚合 Lane 和提升速率来扩展性能→ 这就是你们熟悉的x1/x4/x8/x16(Lane 数)× Gen 速率(2.5/5/8/16/32/64 GT/s)两个可扩展维度

第四类:高级特性

① 数据类型与排序规则

  • PCIe 事务分 Memory / IO / Configuration / Message 四类,再加 Posted / Non-Posted / Completion 三种属性
  • 排序规则(ordering rules)保证同一生产者-消费者模型下数据一致性不被打乱。这是 PCI 的"编程模型"能在 PCIe 上成立的前提。

② 电源管理(PM)

  • 识别某 Function 的电源能力(读 capability)
  • 把 Device/Function 切到特定电源状态(D0–D3)
  • 收到当前电源状态通知
  • 从主电源关闭态发起唤醒(WAKE# / PME)
  • 给设备上电排序(power budgeting,避免同时上电把系统电源拉垮)

③ QoS(差异化服务)这是 1.1 里较新、也较容易被忽略的一块,值得单独展开:

  • 每个 QoS 数据流有专用链路资源→ 缓解head-of-line blocking(队头阻塞):一条低优先级的大流量堵在前面时,高优先级流量不必排队等它
  • 每个组件内可配置仲裁策略(arbitration)
  • 每个包都能打端到端的 QoS 标签→ 这就是TC(Traffic Class)字段,配合VC(Virtual Channel)实现物理/逻辑上的分流
  • 能做**等时(isochronous)**传输,用注入速率控制来保证时延上界

④ 热插拔(Hot-Plug)

  • 支持老的 PCI 热插拔方案(带 sideband 信号)
  • 支持原生热插拔(不需要额外边带信号,用带内消息如 Presence Detect + 电气层检测)
  • 支持异步拔出(设备突然被拔走,不通知系统)
  • 所有形态统一一套软件模型

⑤ 数据完整性

  • 链路级完整性:每个 TLP 带 CRC(LCRC)、DLLP 带自己的 CRC,覆盖所有交易层和数据链路层包 → 保护的是"这一跳链路上"不被破坏
  • 端到端完整性:ECRC(End-to-End CRC),用于高可用系统,保护从发送端到接收端(可能跨 Switch)全程不被破坏

⑥ 错误处理

  • 兼容 PCI 的错误处理(老的 parity/status 位)
  • AER(Advanced Error Reporting):更细的故障定位和恢复,把错误分级(Correctable / Uncorrectable Non-Fatal / Fatal),这是做 RAS(Reliability/Availability/Serviceability)的基础

⑦ 工艺独立性

  • 允许 TX 和 RX 用不同的 DC 共模电压。不同工艺节点/不同厂商的芯片,其发送端和接收端的直流偏置可能不一样,所以 PHY 要支持 AC 耦合,把 DC 共模隔离掉。这是为什么 PCIe 链路(和几乎所有 SerDes 互联)都要串一个 AC 耦合电容。

⑧ 易测试性

  • 通过简单连到测试设备就能做电气一致性(electrical compliance)测试,不用复杂夹具。

1.2 PCIe Link

  • Dual-simplex(双单工):这是 PCIe 的实现方式——用两条独立、单向的链路拼成一个双向链路,而不是一条能双向传的信道。
  • PCIe没有单独的时钟线。接收端怎么知道每个比特的边界在哪?答案是:时钟藏在数据流里,靠编码方案保证有足够的信号跳变,接收端从这些跳变里恢复出时钟(CDR,Clock Data Recovery)。

链路宽度和速率是两端硬件在加电后自己"谈判"出来的(Link Training),全程不经过固件或操作系统。

  • x16 = 每个方向 16 对差分线,不是"总共 16 对"。
  • 所以一个 x16 Link 的物理引脚是16 对 TX + 16 对 RX = 32 对差分线 = 64 根信号线(再加边带信号)。

1.3 PCI Express Fabric Topology

1.3.1 RC

P2P路由

两个不同 Root Port 下面的设备(分属不同 hierarchy domain)要互相通信(P2P),数据得经过 RC。但 RC 怎么做这件事,规范说是可选的、实现相关的。两种合法做法:

  1. "冒名顶替":

    • RC 把 P2P 的 Request 拦下来,拆包/重组,让最终的 Completer 以为请求是 RC 自己发的。
    • 收到 Completion 后,RC 再把它重组,送回真正的 Requester。
    • 好处:RC 不用实现完整的 Switch 转发逻辑。
  2. 内嵌真/假 Switch:

    • RC 在内部实现一个真实或虚拟的 Switch,做软件透明的完整 P2P 支持。
    • 软件看起来就像数据经过了普通 Switch 一样。

拆包规则(RC 特有,Switch 没有这个权力)

RC 在 P2P 时可以把一个包拆成几个小包(Switch 不允许),例如把 256B payload 拆成 2×128B。但拆完要遵守规范里的成包规则(Max_Payload_Size、Read Completion Boundary / RCB等)。

  • 警告:拆包可能有性能损失,尤其当目标设备在PCIe→PCI/PCI-X bridge后面时(老桥对拆包的容忍度差)。
  • 例外 1:P2P 路由Deferrable Memory Write(Gen6 新事务)时不允许拆包。
  • 例外 2:P2P 路由Vendor_Defined Message时不允许拆包,除非按 128 字节边界拆(即除最后一个包外,其余都是 128 字节整数倍)——这是为了保住消息能穿过 PCIe→PCI/PCI-X bridge 的能力。

RC的职责清单

三个要点:

  • RC 必须能发配置请求——因为整个系统的枚举就是 RC 往下发 Config Read/Write 完成的。
  • I/O 空间对 RC 是"可支持"——因为要兼容老 PCI 设备。
  • Lock 语义:RC 不能"响应"别人的锁,但可以"发起"锁——这是为了兼容老软件对老 PCI 设备上锁(legacy 软件需求)。

1.3.2 EP

Endpoint 分三类:

  • Legacy Endpoint(遗留端点):本质上是"老 PCI 设备披上 PCIe 外衣",为向后兼容保留了老行为。
  • PCI Express Endpoint(原生端点):真正的 PCIe 原生设备,遵守更严格的新规则。
  • RCiEP(Root Complex Integrated Endpoint,RC 集成端点):直接做在 RC 内部逻辑里的端点,没有物理 Link。

  • 现代 PCIe 设备应该全用 Memory-mapped I/O(通过 BAR 映射进内存空间)。规范在引导整个生态抛弃 I/O 空间。所以原生 EP 禁止 I/O,而 Legacy EP 保留 I/O 是为了让老设备还能用。
  • 现代系统内存已经远超 4GB,PCIe 设备作为 DMA 发起者(Requester)必须能寻址到 4GB 以上的内存。Legacy EP 是迁就老设备所以不强制;RCiEP 要求"≥ Host 能处理的地址"是因为它和 Host 一体,跟着 Host 能力走。
  • RCiEP 有一堆"不得/不适用"是因为它没有物理 Link(做在 RC 内部逻辑里),所以:

    • 链路寄存器(Link Capabilities/Status/Control)没有意义 → 不得实现
    • ASPM(链路的电源管理)没有意义 → 不实现
    • 不能独立热插拔(它和 RC 长在一起,要插拔就得连 RC 一起)
    • 不得出现在 hierarchy domain 里——因为它不在任何 Root Port "后面",而是和 Root Port 平级待在 RC 内部。这是它和另外两类端点最本质的区别。
    • 只能通过Root Complex Event Collector上报 PME/错误(因为没链路可走),且只能关联一个。

1.3.3 Switch
一个 Switch 结构上就是:一个Upstream Port(朝上连 RC 或上层 Switch)+ 多个Downstream Port(朝下连 Endpoint 或下层 Switch),每个 Port 在配置空间里都表现为一个虚拟 PCI-to-PCI Bridge。所以配置软件看到 Switch = 看到 N+1 个桥(1 个上游 + N 个下游)。

Switch的转发规则

① Switch 不许拆包,RC 可以拆包。这是 Switch 和 RC 转发行为上最鲜明的区别。

② 基于地址的路由(address-based routing)。Switch 决定往哪个下游口转发,靠的是内存/IO 地址落在哪个桥的 base/limit 寄存器范围内。

③ 仲裁规则。多个 Ingress Port(入向链路)争同一个下游口、且在同一 Virtual Channel(VC)上发生竞争时,用round robin(轮询)或 weighted round robin(加权轮询)。

1.3.4 RCEC(RC Event Controller)

RCiEP 没有物理 Link,所以它没法像普通设备那样通过链路报错、报电源管理事件(PME)。那它的 error/PME 消息发给谁?RCEC 就是来收这些消息的。可以把 RCEC 理解成 RCiEP 的"消息终结者/接收站"——RCiEP 把 error 和 PME 消息发给它,由它来终结处理。

  • 遵守 RCiEP 的所有规则——它本质上是 RCiEP 的一个特殊变体。
  • 不要求解码任何内存/IO 资源——它不收普通事务,只收 error/PME 消息,所以不需要 BAR 映射地址空间。
  • 通过Device/Port Type字段标识,并且Base Class 08h, Sub-Class 07h, Programming Interface 00h(这是软件识别它的类码)。
  • 住在 RC 内的某条 Bus 上,一条 Bus 上可以有多个 RCEC。
  • 通过RCEC Endpoint Association Extended Capability(关联扩展能力)显式声明它支持哪些 RCiEP。
  • 整体是可选的(optional)。

1.4 PCIe layering Overview

1.4.1 Transaction Layer

职责:组装/拆解 TLP,管理基于信用的流控。

PCIe 里,"读"不是"CPU 占着总线等设备回数据"(老 PCI 是这样),而是拆成两个独立的事:

  1. Requester 发一个Request TLP(带唯一 Tag 标识),然后去干别的事。
  2. Completer 处理完,发一个Completion TLP(带同样的 Tag)。

每个包有唯一标识(Tag),这样多个请求可以outstanding,回来的完成包靠 Tag 对上号。这是 PCIe 能实现高并发、高吞吐的根基——总线不再被一个慢设备卡死。

TLP 的属性(attribute)

  • No Snoop:告诉系统这个事务不需要做 cache 一致性(snoop)。
  • Relaxed Ordering(RO):允许事务不严格按顺序完成,提升性能。
  • ID-Based Ordering(IDO):基于 Requester ID 的排序扩展。

服务:

1.4.2 Data Link Layer

职责:链路管理 + 数据完整性(检错/纠错)。

发送侧:

  1. 接收 Transaction Layer 造好的 TLP
  2. 计算并附加 LCRC + 序列号
  3. 交给 Physical Layer 发出去

接收侧:

  1. 校验收到的 TLP 完整性(验 LCRC)
  2. 正确 → 交给 Transaction Layer
  3. 出错 →请求重传,直到收对,或判定链路失败

要点:

  • 这里做的是链路级(link-level)完整性——保护的是"这一跳"不被破坏,不关心端到端(那是 ECRC,在 Transaction Layer,可选)。
  • 重传机制是 Data Link Layer 的核心:发送端要把发出去的 TLP 存起来(Replay Buffer),收到对端 Ack 才丢掉,收到 Nak 就重发。
  • DLLP 就是干这些活用的:Ack/Nak DLLP 做确认/重传,Flow Control DLLP 做流控更新,还有电源管理等。

服务:

  • 初始化/PM:接受 Transaction Layer 的电源状态请求并传给 Physical Layer;把 active/reset/disconnected/power-managed 状态报给 Transaction Layer。
  • 数据保护/检错/重传:CRC 生成、存储已发 TLP 供重传、错误检查、Ack/Nak 消息、错误上报。

1.4.3 Physical Layer

职责:所有物理电路 + 链路初始化和维护的逻辑功能。

电路层面:驱动器、输入缓冲、并串/串并转换(serdes)、PLL、阻抗匹配。 逻辑层面:链路初始化、宽度/速率协商、训练(LTSSM)。

服务:

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进