☰
PCIe 链路是怎么练成的:速率、宽度、均衡与故障判断
2026/9/27 2:22:41 网站建设 项目流程

目录

1. 分层:不要把所有现象都算到 Lane 上

2. Lane 上实际传的是什么

3. 时钟、复位和供电

4. 链路训练状态机

Detect

Polling

Configuration:宽度、反转和极性

Recovery:升速和重训练

5. 均衡在补偿什么

四相分别由谁主导

均衡结果写在哪

6. L0 之后的两层

7. 低功耗和几种复位

8. 配置空间怎么读

9. 和 Lane 无关、但会影响性能的配置

10. 一份正常 Gen4 x4 里哪些异常才算数

11. 按场景排查

12. 结论


一条 PCIe Link 最终显示成什么样,是电气检测、低速训练、宽度编号、升速、均衡和两层协议栈依次完成的结果。Lane 数只是其中一项。下面按信号、状态机、均衡、进入 L0 之后的协议,以及常见故障场景说明这些读数分别代表什么。

1. 分层:不要把所有现象都算到 Lane 上

从金手指到 NVMe 命令,经过五层:

层负责什么失败时通常看到
供电、时钟、复位3.3 V、100 MHz 参考时钟、PERST#配置空间完全不出现
电气 / 逻辑物理层差分信号、编码、Lane、速率、均衡降速、降宽、RxErr、链路反复训练
数据链路层序列号、LCRC、ACK/NAK、重放、流控信用BadTLP、BadDLLP、Replay Timeout
事务层Memory Read/Write、CompletionCompletion Timeout、Unsupported Request
NVMe队列、门铃、PRP/SGL、命名空间I/O timeout、控制器复位;LnkSta可能仍正常

带宽不够时,先看LnkSta是不是仍为满速满宽。是,就离开 Lane 这一层,去查 Max Payload、Tag、队列、温度和盘内通道。不是,才沿训练和物理连接往下查。

2. Lane 上实际传的是什么

一条 Lane 是两对差分线,收发同时进行,所以是全双工。x4 是四条这样的 Lane 组成一条 Link,不是把一条 Lane 分成四股。

接收端看的是正负两线的电压差。两边同时抬高或降低的共模噪声会被抵消。发送端串联交流耦合电容,只传递跳变,不传递直流电平。对端接有终端时,Detect 阶段的充电特征与开路不同;开路就被当成“这条 Lane 没有设备”。

速率的单位是 GT/s,表示每秒原始比特,不是每秒字节。编码开销如下:

代速率编码效率
Gen12.5 GT/s8b/10b80%
Gen25 GT/s8b/10b80%
Gen38 GT/s128b/130b约 98.5%
Gen416 GT/s128b/130b约 98.5%
Gen532 GT/s128b/130b约 98.5%

单向理论带宽:

GT/s × Lane 数 × 编码效率 / 8

Gen4 x4 约为 7.88 GB/s(十进制),约 7.34 GiB/s。这是物理层数据速率。门铃、命令、完成项、短包和流控都会再占掉一部分,所以顺序读写略低于此仍可能完全正常。

Gen1/2 用 8b/10b,每个字节变成 10 比特,并用极性失衡约束帮助接收端保持锁定。Gen3 起改用 128b/130b:128 比特数据加 2 比特同步头。同步头区分数据块和有序集,不再靠 8b/10b 那种逗号符号。

链路上除了事务包,还有只在物理层使用的有序集:

有序集作用
TS1 / TS2训练。携带链路号、Lane 号、速率、FTS 数量、均衡阶段和系数
SKP补偿两端时钟的微小频差,由弹性缓冲吸收
EIOS通知对端“我将进入电气空闲”
EIEOS从电气空闲返回时,给接收端一个容易锁定的固定图案
FTS从很浅的 L0s 恢复时,帮助接收端重新锁定
SDS训练结束、正式数据流开始前的起始标记

SKP 不是用户数据。独立且带扩频的参考时钟频差更大,需要更密的 SKP 和更深的弹性缓冲。缓冲溢出或抽空,会记成接收错误。

3. 时钟、复位和供电

差分 Lane 之外,还有三样东西决定训练能不能开始。

参考时钟通常是 100 MHz,有三种架构:

  • 共同时钟:主板把同一路时钟送给 Root Port 和 SSD,多数还带扩频。两端的CommClk都应置位,再重训练,退出低功耗状态的时序才匹配。
  • 独立时钟、不扩频(SRNS):两端各有时钟源,频差较小。
  • 独立时钟、各自扩频(SRIS):频差最大,对弹性缓冲要求最高。

SlotClk+表示设备使用插槽提供的时钟。它和CommClk+同时出现,才是典型的共同时钟。两个都是减号,表示独立时钟;链路已经稳定时,不要为了把这两个比特“改成加号”去重训练。时钟架构判断错了,余量会变差。

PERST#有效期间,设备停在确定状态,不会开始 Detect。释放顺序应是电源和时钟先稳定,再释放复位。转接卡把PERST#一直拉住,软件侧就是设备消失,没有任何LnkSta。

3.3 V跌落不一定造成永久掉速。它可能只在上电瞬间制造一次接收错误,也可能在负载电流升高后让设备掉线。M.2 还有功耗档。盘的峰值超过插槽供给时,表现可以很像链路闪断,但重新枚举后的速率和宽度仍是满的。

4. 链路训练状态机

上电后的主路径:

电源、参考时钟稳定 │ PERST# 释放 │ Detect 逐 Lane 判断有没有终端 │ Polling 2.5 GT/s 上交换 TS1/TS2,完成位锁定和块锁定 │ Configuration 协商宽度、Lane 编号、极性 │ L0 @ 2.5 GT/s 先建立一条可用的低速链路 │ Recovery 按能力和目标速率升速 │ Equalization 8 GT/s 及以上才有 │ L0 @ 目标速率 配置空间稳定可读

无论设备最终是 Gen3、Gen4 还是 Gen5,第一段通信一定发生在 2.5 GT/s。最终显示 16 GT/s,只说明后面的升速和均衡成功了。

Detect

发送端先处于电气空闲,再发出接收端检测脉冲,通过交流耦合电容观察对端终端。有终端才进入后续训练。x4 里只有两条能检测到,后面最多协商成 x2。接触不良、转接卡断线、插槽本身没布线,在这里就被当成 Lane 不存在,而不是“训练失败”。

Polling

Polling.Active 连续发送 TS1。双方都收到对方后进入 Polling.Configuration,用 TS2 确认,然后离开 Polling。这一阶段完成位锁定;128b/130b 下还要完成块锁定。锁定失败就没有机会谈宽度。

Polling 里还有 Compliance 子状态,用于一致性测试夹具。普通 SSD 正常启动不会停在那里。

Configuration:宽度、反转和极性

  1. Linkwidth.Start / Accept:两端在 TS 里宣告支持的宽度。下游端口根据实际检测到的 Lane 提议,上游端口接受一个共同支持的合法宽度。合法值是 x1、x2、x4、x8、x12、x16、x32。消费级 SSD 一般最高 x4。
  2. Lanenum.Wait / Accept:给留下的 Lane 分配逻辑编号,并识别整组反转。
  3. Complete / Idle:TS2 确认,数据链路层准备进入活动状态,随后到达 2.5 GT/s 的 L0。

两种看起来像布线错误、实际合法的情况:

  • 极性翻转:同一对差分线的 P/N 接反。训练图案可以发现,接收端内部交换,不降宽。
  • Lane 反转:下游 Lane0 接到上游最后一条 Lane。状态机整组重编号,x4 仍然是 x4。

宽度变小,说明有 Lane 没检测到,或者检测到了但中途失去锁定,只能用剩余 Lane 重新接受一个更窄的宽度。它不是极性问题。

服务器 CPU 还可以做Bifurcation。一个 x16 控制器在复位前被拆成 x8x8 或 x4x4x4x4,每段是独立 Link,各自训练。SSD 不能在训练中把相邻两段合成一条 x8。BIOS 拆分方式和背板布线不一致时,典型现象是降宽,或者部分盘完全不出现。

术语方向要固定:

  • 下游端口靠近主机,是 CPU Root Port 或 Switch 的下行口。
  • 上游端口靠近设备,SSD 端点上的 PCIe 口就是上游端口。

“主机发往 SSD”是下游发送、上游接收。“SSD 发往主机”相反。后面的均衡和报错方向都按这个区分。

Recovery:升速和重训练

低速 L0 建立后,如果LnkCap支持更高速率,而且LnkCtl2的 Target Link Speed 也允许,链路进入 Recovery:

  1. RcvrLock:重新锁定,并用 TS 协商目标速率。
  2. Speed:发送端进入电气空闲,两端切换时钟和速率,再用 EIEOS 帮助对方重新锁定。
  3. 目标不低于 8 GT/s 时进入Equalization。
  4. RcvrCfg / Idle:确认新速率可用,返回 L0。

8 GT/s 失败通常退回 5 或 2.5 GT/s;16 GT/s 失败可以停在 8 GT/s。所以“能力是 Gen4,实际是 Gen3”有两种完全不同的原因:目标速率根本没允许 16 GT/s,或者允许了,但这一代的均衡没通过。

运行中的误码、对端要求、改宽度或再切速,也会从 L0 进入 Recovery。短暂经过是正常机制。反复进入并且回不到原来的速率和宽度,才是不稳定。

5. 均衡在补偿什么

到 8 GT/s 以后,过孔、连接器、长走线和背板会明显削弱高频。接收端眼图闭上后,单靠加大摆幅没有用,因为高频和低频一起被通道改变了。

发送端用三游标均衡:

  • 预游标:提前改变边沿,补偿尚未到达的码间干扰。
  • 主游标:当前比特的主要能量。
  • 后游标:削弱拖尾,也就是去加重。

若干合法组合被定义成预设P0–P10。预设只是起点,随后还可以按单个游标增减,这叫系数调整。主游标与前后游标要满足幅度和比例限制,不能任意加大。

接收端再做两类处理:

  • CTLE是模拟高频提升,能把眼图张开,但也会放大噪声。
  • DFE用已经判决的前几个比特估计拖尾,从当前比特里减掉。它不按 CTLE 那种方式放大噪声,但判决错了会把错误往后传。

参数取决于这块板的通道,没有一组可以写死的最优值。每次升到 8、16 或 32 GT/s,都要重新做。

四相分别由谁主导

阶段实际动作优化方向
Phase 0下游端口按预设发送。上游端口只调自己的接收端,先可靠识别 TS1主机 → SSD,初步接收恢复
Phase 1交换预设,上游端口也开始按预设发送。目标是双向都能稳定接收训练序列,还不追求最佳眼图双向先达到“能通信”
Phase 2下游端口要求上游端口调整发送端SSD → 主机
Phase 3上游端口要求下游端口调整发送端主机 → SSD

Phase 2 和 Phase 3 的主从关系不能记反。主机收不好 SSD 的数据,对应 Phase 2;SSD 收不好主机的数据,对应 Phase 3。TS1 里的 EC 字段用00、01、10、11表示当前阶段。任一阶段不能维持可靠的训练通信,这一代速率失败,链路退回较低速率。

路径上还可以有Retimer。它含时钟恢复和重新发送,把一条长通道拆成两段分别均衡。协议能检测到一个或两个 Retimer。Redriver 只做模拟放大,训练状态不会把它报告成 Retimer。能力位只说明“我能报告”,状态位才说明“这次检测到了”。没有 Retimer 不是故障;长背板本应有 Retimer 却没有,Gen4 失败、Gen3 成功才是典型现象。

均衡结果写在哪

LnkSta2的 Equalization Complete 和 Phase1/2/3,记录的是8 GT/s那一次,不是 16 GT/s。16 GT/s 的对应位在 Physical Layer 16.0 GT/s Status,lspci里通常是Phy16Sta一类字段;32 GT/s 还有另一组。

因此:

  • 链路当前是 16 GT/s,只看LnkSta2全成功,只能证明 8 GT/s 曾经成功。
  • 16 GT/s 是否走完,要看Phy16Sta的 EquComplete 和 Phase1/2/3。
  • 这些位表示最近一次结果,停在 L0 后不会自动清除。
  • 同时没有 Link Equalization Request,才表示硬件没有请求软件再安排一次均衡。

6. L0 之后的两层

物理层进入 L0,只说明比特和块已经稳定。

数据链路层给每个事务包加序列号和 LCRC。对端用 ACK 或 NAK DLLP 回应。NAK、LCRC 错误或重放计时器到期,发送端从重放缓冲重传。偶发误码通常停在这一层,表现为可纠正错误。重放次数滚翻,或重放计时器超时,说明误码已经连续到影响传输。

事务层使用信用流控。转发、非转发和完成这三类,Header 与 Data 信用分开。信用暂时耗尽时,链路速率不变,吞吐会停。信用用完却不再更新,是流控协议错误,不是降速,也不会把 x4 变成 x1。

NVMe 使用其中几种事务:

  • 主机写门铃、写寄存器:主机发出的小 Memory Write。
  • 主机读寄存器:Memory Read 加 Completion。
  • SSD 读取命令、PRP/SGL,以及主机写盘时读取主机内存:SSD 主动发出 Memory Read。
  • SSD 把读出的数据写回主机:SSD 发出 Memory Write。
  • 完成队列项:也是 SSD 写到主机内存。

所以“盘读主机内存”才受 SSD 作为请求方的 Tag 数量限制;“盘把数据写给主机”不受这个数量限制。

7. 低功耗和几种复位

ASPM 是运行中的链路省电,不是系统睡眠本身:

  • L0s很浅,方向可以单独进入。退出要靠 FTS。FTS 数量不够,接收端就锁不回。现在的 SSD 很多不支持它。
  • L1双向都进入电气空闲,恢复更慢。
  • L1.1 / L1.2进一步关闭共模电压或时钟,依赖CLKREQ#。退出异常时表现为随机超时或掉盘。

LnkCap写着 ASPM not supported,同时LnkCtl是 Disabled,就不要从 L1 开始排查。

几种复位的影响不同:

复位链路是否重新训练速率宽度是否可能变化
PERST#一定会重新协商
Hot Reset会离开 L0 再回来会重新协商
Function Level Reset重置 NVMe 功能通常不变
D3hot / 系统睡眠后恢复可能重新训练可能停在更低速率

故障前后各读一次LnkSta。没变,优先查控制器、固件和供电;变了,优先查训练、时钟和信道。

8. 配置空间怎么读

设备出现在lspci里,只说明它曾经到达 L0。判断当前链路,看两端的这些字段:

字段含义
LnkCap硬件上限:最高速率、最大宽度、ASPM
LnkCap2支持的速率向量,以及是否支持 Retimer 报告
LnkCtl2软件允许尝试的目标速率。低于能力时,不会去练更高代
LnkSta当前速率和宽度。(ok)表示达到该端能力,downgraded才是降级
LnkSta28 GT/s 均衡结果、均衡请求、Retimer 是否检测到
Phy16Sta16 GT/s 均衡结果,不能用LnkSta2代替
LaneErrStat哪一条 Lane 的接收端记过错误
UESta/CESta不可纠正错误和可纠正错误,都是粘滞位

端点上一些减号没有诊断意义:

  • TrErr-是早期规范遗留位,现在固定为 0。
  • Train-只给下游端口表示“正在训练”。
  • DLActive-只由下游端口报告数据链路层活动。端点即使完全正常也是 0。
  • Surprise-属于下游端口的热插拔状态。

能读到配置空间并且nvme已绑定,本身就说明链路当前可访问。不要用端点的DLActive-判断断链。要看这个状态,去读上游端口。

错误有方向。SSD 的RxErr只代表主机发往 SSD 的方向;主机收 SSD 的错误记在 Root Port 或 Switch 下行口。只看盘,会漏掉一半信道。

CEMsk某位为减,只说明这种错误没有被屏蔽。DevCtl的CorrErr-则表示设备不被允许向上游发送可纠正错误消息。配置空间里可以有加号,内核日志却是空的。

9. 和 Lane 无关、但会影响性能的配置

Max Payload是一个事务包最多携带的数据。路径上每一跳取最小值。能力 512、实际启用 256,通常是上游某跳只保证 256。它降低一点包效率,不改变LnkSta。不要用setpci把它改大。

Max Read Request是请求方希望一次读多少。完成包仍按 Max Payload 拆开。它不要求整条路径相同,也不代表链路宽度。

Tag是 SSD 作为请求方时,未完成的非转发事务数量。5-bit 大约 32 个,8-bit 扩展到 256 个。直连 CPU、往返时间不到 1 µs 时,Gen4 x4 需要同时在途的数据大约只有几 KB 到十来 KB,32 个 Tag 通常够用。中间经过多层 Switch、往返到数微秒时,32 个 Tag 乘以较小的读请求长度,才可能限制“SSD 读主机内存”的吞吐。Tag 不够不会把训练结果变成 x2。

10. 一份正常 Gen4 x4 里哪些异常才算数

设 NVMe 端点是01:00.0,驱动已绑定,读数是:

  • LnkCap:16 GT/s、x4、不支持 ASPM。
  • LnkCtl2:目标就是 16 GT/s。
  • LnkSta:16GT/s (ok), Width x4 (ok)。
  • LnkSta2:8 GT/s 四相成功,无均衡请求。
  • Phy16Sta:16 GT/s 四相也成功,无均衡请求。
  • LaneErrStat为 0,UESta全未置位。
  • SlotClk-、CommClk-:独立参考时钟。
  • Max Payload 能力 512、启用 256。
  • 扩展 Tag 未启用。

这表示当前就是满速满宽。单向上限约 7.88 GB/s。顺序带宽明显低于此,不再查 Lane。独立时钟、端点上的DLActive-、没有 Retimer、256 字节 Payload,都不能单独解释成降速。

若唯一异常是:

DevSta: CorrErr+ CESta: RxErr+ BadTLP- BadDLLP- Rollover- Timeout-

它表示 SSD 接收端曾经见到一次物理层接收错误。旁边没有坏 TLP、坏 DLLP 和重放超时,不可纠正错误也为空,所以数据链路层没有进入连续重放。可纠正状态是粘滞的,上电、插拔或一次电源抖动都会留下这个加号。

它还不能证明盘坏或槽坏。下一步是看反方向,清除后复测。清除是对 AER 状态位写 1,不是改速率:

lspci -PP -s 01:00.0 lspci -tv dmesg -T | grep -iE 'aer|pcie|nvme|01:00.0' setpci -s 01:00.0 ECAP_AER+0x10.L=0xffffffff # 对上游端口的 AER 不可纠正/可纠正状态也做同样的清除 # 再做一段实际读写 lspci -s 01:00.0 -vv | grep -E 'LnkSta|LnkSta2|Phy16|CESta|UESta|LaneErr'

同时读lspci -PP给出的上游端口。清除后不再增加,可以忽略。空闲也快速增加,或同时出现BadDLLP、Replay Timeout、Completion Timeout,再查金手指、转接卡、背板和供电。高负载下偶发,而两端始终是16GT/s (ok), Width x4 (ok),只说明余量一般。生产环境不要用setpci修改目标速率、Max Payload 或 ASPM。

11. 按场景排查

速度下降,宽度仍是 x4。先看两端LnkCtl2。目标被限制在 8 GT/s,就去查 BIOS 和平台,而不是盘。目标已是 16 GT/s,却停在 8 GT/s,再看Phy16Sta停在哪一相。长背板、延长线、无 Retimer 的转接卡,是这一类的常见原因。锁回 Gen3 后错误消失,问题在信道余量。

宽度下降,速度仍高。优先查物理连接和拓扑:金手指、M.2 座、转接卡断 Lane、插槽只布了 x2、相邻插槽共用 Lane、Bifurcation 与背板不一致。极性翻转和 Lane 反转不会造成降宽。换到已知按 x4 布线的直连槽后恢复,就不是 SSD 端口能力的问题。

设备完全不出现。没有配置空间可读。查 3.3 V、参考时钟、PERST#、BIOS 是否关闭插槽,以及转接板键位。这是 Detect 之前或 Detect 失败,不是LnkSta降级。

运行中掉盘。温度节流时速率和宽度通常不变。链路闪断则上游端口会出现链路下降或 Surprise Down,NVMe 同时报超时或控制器复位。支持 ASPM 的设备,可以把 ASPM 临时关闭做对比;能力里写着不支持,就不要从这里开始。还要区分功耗不足:掉线后重新枚举仍是满速满宽,更像供电或复位,不像均衡。

只在一个方向报错。SSD 只有RxErr,上游端口干净:查主机发往 SSD 的发送端、连接器和 SSD 接收端。上游端口有接收错误,SSD 干净:查反方向,也就是均衡 Phase 2 优化的那一路。某一位在LaneErrStat里反复置位,查对应 Lane 的接触或走线,而不是整条链路降速。

可纠正错误变成不可纠正错误。BadTLP或BadDLLP开始伴随 Replay Timeout、Replay Rollover,说明重放已经救不回来。再出现 Completion Timeout 或 Data Link Protocol Error,NVMe 命令会失败。此时先保留两端lspci和内核日志,再复位;只重启机器会把粘滞位清掉。

睡眠或热复位后停在 Gen1。看目标速率有没有被软件改低,以及参考时钟是否在恢复时晚于PERST#。这是重新训练没有升速,不是 NAND 变慢。

性能低,但两端已经是 Gen4 x4。按这个顺序排除:

  1. 温度和电源状态是否降频,固件是否在稳态而不是 SLC cache 阶段。
  2. IO 大小、队列深度、线程和测试区间是否足够大。
  3. 盘接在 CPU 直连 Lane,还是接在芯片组后面。芯片组上行和多个设备共享带宽。
  4. Max Payload 是否异常地只有 128 字节。256 字节很少单独造成数量级下降。
  5. 只有跨 Switch、延迟明显偏大时,才评估 32 个 Tag。
  6. 最后才看 NVMe 的队列数、MDTS、LBA 格式和主机调度器。

一个槽正常、另一个槽降级。用同一块盘交换。问题跟着槽走,查布线、Bifurcation 和转接卡;问题跟着盘走,再查盘的金手指和固件。不要同时更换盘、线和 BIOS,否则无法归因。

12. 结论

Lane 是一条全双工差分通道,Link 是若干 Lane 在同一速率下训练出来的整条连接。训练先在 2.5 GT/s 完成检测、锁定、宽度和编号,进入 L0 后再升速;8 GT/s 及以上还要按四相均衡。Phase 2 优化 SSD 到主机,Phase 3 优化主机到 SSD。LnkSta才是当前速率和宽度;LnkSta2的均衡位属于 8 GT/s,16 GT/s 要另看Phy16Sta。

端点上的DLActive、训练位和独立参考时钟,不能单独当成故障。NAND 通道、Tag 和 Max Payload 影响性能,不改变已经完成的训练结果。一个孤立且能清除的RxErr+,只是一次粘滞记录;它与降速、降宽、重放超时或对端错误同时出现时,才说明这条信道需要继续查。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询