拓扑结构

PCIe采用层次化的树形拓扑结构,由Root Complex(根复合体)、Switch(交换器)、Bridge(桥接器)和Endpoint(终端设备)组成。

Root Complex Bus 0 CPU/内存子系统
Switch A Bus 1 上游:Bus0,下游:Bus2-4
Switch B Bus 5 上游:Bus0,下游:Bus6-7
GPU Bus 2 x16 Endpoint
NVMe SSD Bus 3 x4 Endpoint
Switch C Bus 4 级联Switch
网卡 Bus 6 x8 Endpoint
AI加速卡 Bus 7 x16 Endpoint

总线号分配示例

Root Complex (Bus 0)
├── Root Port 0 → Switch A (Bus 1)
│                   ├── Downstream Port 0 → GPU (Bus 2)
│                   ├── Downstream Port 1 → NVMe SSD (Bus 3)
│                   └── Downstream Port 2 → Switch C (Bus 4)
│                                           └── Endpoint (Bus 4-Sub)
└── Root Port 1 → Switch B (Bus 5)
                    ├── Downstream Port 0 → 网卡 (Bus 6)
                    └── Downstream Port 1 → AI加速卡 (Bus 7)
                        

Root Complex (RC)

Root Complex是PCIe层次结构的根节点,连接CPU/内存子系统和PCIe域。它负责:

  • 发起配置访问
  • 处理来自Endpoint的内存请求
  • 管理中断路由
  • 提供时钟和电源管理

Switch

Switch是多端口设备,用于扩展PCIe拓扑:

  • 一个上游端口连接RC或其他Switch
  • 多个下游端口连接Endpoint或下游Switch
  • 执行路由功能,转发TLP

Endpoint

Endpoint是终端设备,可以是:

  • Legacy Endpoint:传统PCI设备
  • PCIe Endpoint:原生PCIe设备
  • 支持Memory、I/O、配置事务
设计动机:为什么用点对点而不是共享总线?

传统 PCI 采用共享总线架构,所有设备分时使用同一条总线,存在三个根本问题:

1. 带宽瓶颈:所有设备共享一条总线的带宽,设备越多每个设备分到的带宽越少。

2. 时钟频率受限:共享总线需要满足所有设备的最差时序约束,无法提升频率。PCI 最高 66MHz,PCIe Gen1 就达到 2.5GHz。

3. 扩展性差:增加设备会增加总线负载电容,信号完整性恶化。

PCIe 采用点对点(Point-to-Point)架构:每个设备独享一条 Link,带宽不共享;Link 是独立的串行差分对,时钟频率可以远高于并行总线;需要更多设备时通过 Switch 扩展,每个下游端口又是一条独立的点对点 Link。

这个设计权衡的代价是:需要 Switch 芯片来扩展拓扑,增加了硬件成本和延迟。但换来的带宽提升和扩展灵活性远超这个代价。

协议分层模型

PCIe协议采用分层架构:发送方自上而下逐层封装,接收方自下而上逐层解析,两侧的同层之间构成对等协议——每层只与对端的同层"对话"。

发送方 · 自上而下逐层封装
软件层
设备驱动 / 操作系统
构造内存 / 配置请求
事务层Transaction Layer
TLP 组包 / 解包 虚拟通道(VC)管理 流量控制
交付 TLP
交付 TLP + Seq + LCRC
物理层Physical Layer
编码 / 解码 串行化 / 解串 链路训练
接收方 · 自下而上逐层解析
软件层
设备驱动 / 操作系统
上交完成包 / 数据
事务层Transaction Layer
TLP 组包 / 解包 虚拟通道(VC)管理 流量控制
校验通过,上交 TLP
解码,剥离帧符号
物理层Physical Layer
编码 / 解码 串行化 / 解串 链路训练

一个 TLP 是如何被逐层"套上"开销的

发送方向下每经过一层,就多封装一层开销;接收方向上则逐层校验、剥离。下图是一个 Memory Write TLP 的完整封装结构:

STP 物理层 · 帧头
TLP Header 事务层 · 12/16B
Data Payload 事务层 · 0–4KB · 可选
ECRC 事务层 · 可选
END 物理层 · 帧尾
事务层生成 数据链路层添加 物理层添加
1
事务层 接收上层请求,构造 TLP:添加 Header 和可选 ECRC
2
数据链路层 添加序列号和 LCRC,并复制一份存入重传缓冲区(等待 Ack)
3
物理层 编码、加扰、添加起始/结束帧符号,串行发送

接收方向完全相反:物理层先剥离帧符号并解码,数据链路层校验 LCRC / 序列号(失败则触发 Nak 重传),最后事务层解析 Header。

事务类型

PCIe定义了多种事务类型,满足不同的访问需求。

用 TLP 构造器亲手组装事务层包
了解事务类型后,打开 TLP 构造器,选择事务类型、填写地址和数据,直观查看 TLP Header 各字段如何编码。
类型 读写 地址空间 用途
Memory Rd/Wr Memory空间 大块数据传输,最常用
I/O Rd/Wr I/O空间 传统设备兼容
Configuration Rd/Wr 配置空间 设备枚举和配置
Message 仅写 无地址 中断、错误报告

Memory事务详解

Memory事务是最常用的事务类型,支持大块数据的高效传输。

Memory Read (MRd)

  • 请求者发起读请求
  • 指定地址、长度、标签
  • 完成者返回CplD(带数据的完成包)
  • 支持拆分事务

Memory Write (MWr)

  • 请求者发送数据和地址
  • Posted事务,无需完成包
  • 提高写入效率
  • 可选原子操作

地址路由方式

地址路由 Memory/I/O事务使用64位或32位地址路由
ID路由 配置事务和部分消息使用Bus/Device/Function号路由
隐式路由 消息事务可路由到RC,无需地址信息

延伸阅读:PCIe Switch 专题——Switch 的路由机制、总线号分配与端口仲裁的完整展开。

流量控制

PCIe采用基于信用的流量控制机制,防止发送方淹没接收方。

发送方信用 = 还能发多少
PH7Posted 头
PB127Posted 数据
NPH7Non-Posted 头
NPD127Non-Posted 数据
CplH7完成包头
CplD127完成包数据
TLP发送前扣减信用
FC Update DLLP接收方归还信用
接收方缓冲区 = 实际能收多少
VC0 缓冲区按 PH / PB / NPH / NPD / CplH / CplD 六类独立划分
VC1–7 缓冲区每个 VC 独立信用池,互不挤占
信用管理腾出缓冲后,通过 DLLP 通告新的可用空间

※ 图中计数为初始信用值示例,实际数值由接收方在链路训练后通告。

信用生命周期:以 PH 信用为例(初始 10 个)

1初始化
链路训练完成后,接收方通过 FC_INIT DLLP 把初始信用通告给发送方
可用 10 / 10
2发送检查
每发送一个 TLP 前先查信用:有剩余才发送,否则该 TLP 排队等待
可用 10 / 10 · 检查通过
3信用消耗
发送 4 个 TLP 后,对应信用计数随之扣减(Header 消耗 PH,数据消耗 PB)
可用 6 / 10
4信用归还
接收方处理完 TLP、腾出缓冲区后,通过 FC_UPDATE DLLP 通告新信用
可用 10 / 10 · 循环往复
当某类信用可用额度为 0 时,发送方必须暂停发送该类 TLP,直到收到新的 FC Update DLLP —— 只会等待,不会丢包

信用类型

信用类型 用途 单位
PH (Posted Header) Posted请求头缓存 Header个数
PB (Posted Data) Posted数据缓存 数据单元(4DW)
NPH (Non-Posted Header) Non-Posted请求头缓存 Header个数
NPD (Non-Posted Data) Non-Posted数据缓存 数据单元
CplH (Completion Header) 完成包头缓存 Header个数
CplD (Completion Data) 完成数据缓存 数据单元
设计动机:为什么需要信用流量控制?

在串行点对点链路上,发送方无法知道接收方的缓冲区状态。如果发送方持续发送,接收方缓冲区溢出后会丢包,而丢包重传的开销极大。

PCIe 选择信用机制而非停等协议(发一个等确认再发下一个),原因是:

1. 流水线效率:信用机制允许发送方在未收到确认前继续发送多个 TLP,充分利用链路带宽。停等协议在长链路下效率极低。

2. 细粒度控制:将信用分为 Header 和 Data 两类,因为接收方需要为 Header 和 Data 分配不同大小的缓冲区。一个 64B 的 Memory Write 消耗 1 个 Header 信用和若干 Data 信用。

3. 多 VC 独立管理:每个虚拟通道(VC)有独立的信用池,避免一个低优先级流量堵死高优先级流量。

代价是:发送方需要维护 6 类 × N 个 VC 的信用计数器,硬件复杂度增加。但对于高速串行链路来说,这是值得的。

中断机制

PCIe支持多种中断方式,从传统的INTx到现代的MSI/MSI-X。

INTx (传统中断)

与传统PCI兼容,使用INTA#/INTB#/INTC#/INTD#信号线。

  • 支持4条中断线
  • 多个设备可共享中断线
  • 需要中断控制器仲裁
  • 性能较低,现代设备很少使用

MSI (消息信号中断)

通过Memory Write TLP发送中断消息,无需专用信号线。

  • 支持1-32个中断向量
  • 每个向量可独立配置目标CPU
  • 避免中断共享,提高性能
  • 适用于大多数设备
MSI消息格式:
┌─────────────────────────────────┐
│ Address: 0xFEExxxxx             │
│ Data:   Vector | CPU ID | etc   │
└─────────────────────────────────┘
                            

MSI-X (增强型MSI)

MSI的增强版本,支持更多向量和更灵活的配置。

  • 支持最多2048个向量
  • 每个向量独立地址/数据
  • 向量配置存储在设备内存
  • 支持动态向量掩码

适用于高性能设备:NVMe SSD、高速网卡等

延伸阅读:软硬件架构全景图中的中断路径——INTx 与 MSI/MSI-X 在系统硬件中如何经 IO-APIC / LAPIC 送达 CPU。

错误处理

PCIe定义了完善的错误检测、报告和恢复机制:错误分为可纠正不可纠正(非致命/致命)两大类,由 AER(高级错误报告)能力结构记录并通过中断通知软件。完整内容见专页:

错误处理与 AER 详解
错误类型分类(可纠正 / 非致命 / 致命)、AER 寄存器布局、五步错误报告流程、三级错误恢复与错误注入测试。
理解检测
1. PCIe 采用点对点架构而非共享总线,主要原因不包括以下哪项?
点对点架构需要 Switch 来扩展拓扑,反而增加了硬件成本。但换来的是带宽、频率和信号质量的提升。
2. PCIe 流量控制使用信用机制,一个 Memory Write TLP 会消耗哪类信用?
Memory Write 是 Posted 事务,会消耗 Posted Header(PH)信用和对应的 Posted Data(PD)信用。Non-Posted 信用用于 Read 类请求,Completion 信用用于完成包。
3. 以下哪种中断机制支持最多的中断向量数量?
MSI-X 最多支持 2048 个中断向量,远超 MSI 的 32 个和 INTx 的 4 个。现代高速设备(如 NVMe)普遍使用 MSI-X。