1. PCIe 基础概念:从并行到串行的演进
各位同学,咱们今天聊聊 PCIe 的基础。说实话,我做了十几年驱动,接触过不少总线。但 PCIe 给我的印象最深——它把 PC 架构的 I/O 性能彻底翻了个个儿。
先问大家一个问题:为什么 PCI 总线用了二十年,最后被 PCIe 取代了?答案其实很简单——速度。但背后的故事,远不止这么简单。
1.1 PCIe 总线的发展历史
PCI(Peripheral Component Interconnect)总线诞生于 1992 年,由 Intel 主导。那时候的 PC 还是 486 时代,PCI 的 33MHz/32bit 带宽(133MB/s)已经算很快了。
到了 2000 年左右,显卡、网卡、磁盘控制器对带宽的需求暴涨。PCI 的共享总线架构成了瓶颈。于是 PCI-X 出现了——它把频率提到 133MHz,甚至 533MHz。但问题没解决,反而更严重了。
关键转折点:2003 年,Intel 发布了 PCI Express 1.0 规范。从 PCI 到 PCIe,本质上是把并行总线换成了串行差分信号,把共享总线换成了点对点连接。
我当年第一次看到 PCIe 的 spec 时,心里想的是:串行能比并行快?这不是倒退吗?后来才明白,并行总线有信号同步、串扰、布线长度这些老大难问题。频率一高,并行信号根本稳不住。
PCIe 的发展历程大致如下:
| 版本 | 发布年份 | 单 Lane 速率 | 编码方式 | x16 带宽(单向) |
|---|---|---|---|---|
| PCIe 1.0 | 2003 | 2.5 GT/s | 8b/10b | 4 GB/s |
| PCIe 2.0 | 2007 | 5.0 GT/s | 8b/10b | 8 GB/s |
| PCIe 3.0 | 2010 | 8.0 GT/s | 128b/130b | 16 GB/s |
| PCIe 4.0 | 2017 | 16.0 GT/s | 128b/130b | 32 GB/s |
| PCIe 5.0 | 2019 | 32.0 GT/s | 128b/130b | 64 GB/s |
| PCIe 6.0 | 2022 | 64.0 GT/s | PAM4 + FLIT | 128 GB/s |
小提示:GT/s 是 Giga Transfers per second,不是 Gbps。PCIe 3.0 之后改用 128b/130b 编码,有效数据率更高。算带宽时记得去掉编码开销。
1.2 PCIe 与 PCI/PCI-X 的区别
说白了,PCI 和 PCIe 是两种完全不同的设计哲学。我列几个关键区别:
- 拓扑结构:PCI 是共享总线,所有设备挂在同一条线上。PCIe 是点对点,每个设备独享带宽。
- 信号方式:PCI 用并行信号(32/64 根数据线),PCIe 用差分串行(每个 Lane 一对 TX、一对 RX)。
- 时钟方式:PCI 有独立时钟线,所有设备同步。PCIe 内嵌时钟,从数据流中恢复时钟。
- 热插拔:PCI 基本不支持热插拔(服务器版除外)。PCIe 原生支持热插拔。
- 配置空间:PCI 只有 256 字节配置空间。PCIe 扩展到 4KB,还加了能力结构(Capability Structure)。
避坑提醒:我曾经在一个项目里,把 PCIe 设备当 PCI 设备初始化,结果配置空间只读了前 256 字节,导致扩展能力寄存器没读到,设备死活枚举不出来。后来查了三天才发现——PCIe 的配置空间访问方式跟 PCI 不一样,必须用 ECAM(Enhanced Configuration Access Mechanism)。
还有一个细节:PCI 的地址空间是共享的,所有设备通过 BAR(Base Address Register)映射到同一个地址空间。PCIe 虽然也用了 BAR,但每个设备有自己的独立地址域,通过 RC 的地址转换来访问。
1.3 PCIe 的拓扑结构
PCIe 的拓扑结构,说白了就是一棵树。树根是 Root Complex(RC),树枝是 Switch,树叶是 Endpoint(EP)。
我画了一张图,大家看看:
1.4 三个核心组件详解
Root Complex(RC)
RC 是 PCIe 层次结构的根。它连接 CPU、内存和 PCIe 域。我习惯把 RC 理解成「PCIe 世界的门卫」——所有从 CPU 发往 PCIe 设备的请求,都要经过 RC 转换。
RC 的主要职责:
- 生成配置请求(Configuration Request),枚举总线上的设备
- 处理内存映射 I/O(MMIO)访问,把 CPU 的地址转换成 PCIe 事务
- 处理中断(MSI/MSI-X)和错误报告
- 管理电源状态
Switch
Switch 是 PCIe 的扩展节点。它有一个上游端口(Upstream Port)连向 RC,多个下游端口(Downstream Port)连向 EP 或下级 Switch。
Switch 的核心能力是路由。它根据数据包中的地址信息,把包转发到正确的端口。我遇到过一个问题:某个 Switch 芯片的转发延迟标称是 150ns,但实际测出来有 300ns。后来发现是配置了错误的 VC(Virtual Channel)映射。嗯,这里要注意——Switch 的延迟跟 VC 配置强相关。
Endpoint(EP)
Endpoint 就是实际的 PCIe 设备。它可以是显卡、网卡、NVMe SSD、FPGA 加速卡等等。EP 通过 BAR 向系统暴露自己的寄存器空间和内存空间。
EP 有三种类型:
- Legacy Endpoint:支持 PCI 兼容的 I/O 空间和中断
- PCIe Endpoint:只支持 MMIO 和 MSI/MSI-X
- RCiEP(Root Complex Integrated Endpoint):直接集成在 RC 内部,不经过外部 PCIe 链路
经验之谈:写 EP 驱动时,第一件事就是读 Vendor ID 和 Device ID。如果读出来全是 0xFFFF,说明链路没起来。如果读出来是 0x0000,说明设备没响应。这两个值能帮你快速定位问题。
1.5 数据流的基本路径
咱们看一个最简单的场景:CPU 写数据到 NVMe SSD。
- CPU 执行 store 指令,地址落在 NVMe 的 BAR 空间
- CPU 的 Memory Controller 把请求发给 RC
- RC 查路由表,发现目标设备在 Switch 下游
- RC 封装成 PCIe TLP(Transaction Layer Packet),发给 Switch
- Switch 解析 TLP 中的地址,转发到 NVMe 所在的端口
- NVMe 收到 TLP,解析出数据,写入内部寄存器或 DMA 引擎
整个过程,从 CPU 到设备,延迟通常在几百纳秒到几微秒之间。如果用了 PCIe 4.0 x4,带宽可以到 8GB/s 左右。
核心要点:PCIe 的拓扑是树形结构,数据流是点对点的。每个设备独享带宽,不会因为其他设备忙而阻塞。这是 PCIe 比 PCI 强的最根本原因。
1.6 小结
这一章咱们讲了 PCIe 的来龙去脉。从 PCI 到 PCI-X 再到 PCIe,本质上是总线架构的彻底重构。PCIe 用串行差分信号、点对点拓扑、内嵌时钟,解决了并行总线的瓶颈。
拓扑结构上,RC 是根,Switch 是枝,EP 是叶。理解这三者的关系,是写 PCIe 驱动的第一步。