PCIe 体系结构概述

做 PCIe 调试这么多年,我常被问到:“Hot Reset 到底在哪一层搞的?” 问这问题的,多半是刚接触 LTSSM 的工程师。你想想看,链路状态机跑在物理层,但 Reset 信号却要穿透三层,一个地方没对齐链路就挂了。这一章我们先搭好体系结构的骨架,后续你才能理解“状态机为啥这么跳”。

三层架构:数据从哪来,到哪去

PCIe 协议栈分了三个层次,从底往上分别是:

  • 物理层(Physical Layer) —— 管电平、时钟、序列化/反序列化,LTSSM 就住在这层。
  • 数据链路层(Data Link Layer) —— 提供可靠传输、ACK/NAK 和序列号管理。
  • 事务层(Transaction Layer) —— 组装 TLP(事务层包),处理读写请求、完成报文。

我习惯把这三层想象成“快递公司”:

事务层是下单的客户(我要求读数据)
数据链路层是分拣中心(贴标签、验货、重发破损件)
物理层是快递小哥(把包裹跑成电信号送出去)

Hot Reset 发生在物理层的 LTSSM,但它要通知上面两层——把队列清空,把状态重置。所以你不理解上层协议,就搞不清 Reset 的副作用。

拓扑结构:点对点的“树”

PCIe 是树形拓扑,典型组成:

组件角色
Root Complex (RC)根结点,连接 CPU 和内存,是树根
Switch扩展端口,相当于路由器,把一个上游端口拆成多个下游端口
Endpoint (EP)终端设备,比如 GPU、NVMe SSD、网卡
Bridge用于转接旧 PCI/PCI-X 设备,今天很少见了

我在项目中遇到过最头疼的场景:Switch 某下游端口触发 Hot Reset,上游 Root Complex 却还在传 TLP。没搞清楚拓扑里谁跟谁直接相连,就拿着逻辑分析仪乱抓,浪费了两天。

小提示: 调试时先用 lspci -vvv 确认拓扑树,尤其注意 Secondary Bus Number 和 Subordinate Bus Number。Hot Reset 只影响它下游的链路,不会向上传播。

LTSSM:物理层的心脏

LTSSM(链路训练和状态机)是物理层里最复杂的逻辑。它定义了 11 个主状态,从 Detect 到 L0(正常工作)、Recovery、Hot Reset、Disable 等等。我们的课程专门盯着 Hot Reset 场景,但你必须先懂整个状态流转。

为什么?因为 Hot Reset 不是孤立跳进去的——它从 Recovery 进入,或者从配置寄存器直接触发。我曾见过一个 bug:固件写了 Link Control 寄存器的 “Retrain Link” 位,结果链路卡在 Recovery 里出不来,而不是进 Hot Reset。原因就是 LTSSM 在 Recovery 里要先做电气训练,再判断要不要进 Reset。不了解这个顺序,你会被逻辑分析仪里的状态跳变搞晕。

下面这张图概括了 PCIe 体系结构的三层和 LTSSM 在其中的位置:

PCIe 体系结构三层与 LTSSM 位置 事务层(Transaction Layer) 组装 TLP · 处理读写请求与完成报文 数据链路层(Data Link Layer) 序列号 · ACK/NAK · 重传 · 流控 物理层(Physical Layer) 电气子层 · 逻辑子层 · 编码/解码 · 链路训练 LTSSM(链路训练状态机) Hot Reset 在这里触发 向上两层需配合清零 TL DLL PHY
⚠️ 常见误区: 有人以为 Hot Reset 只影响物理层,数据链路层和事务层毫发无损。错!Hot Reset 会清空 DLLP 计数器、重放缓冲区和 TLP 排队缓存。我亲眼见过一个团队,Reset 后忘记重新初始化事务层流控信用量,导致后续所有 TLP 都被接收端扔掉。上板调了三天才找到原因。

关键寄存器:你调试时得盯着

手边没逻辑分析仪怎么办?读寄存器。下面这几个与 Hot Reset 强相关:

寄存器偏移作用
Link Control Register0x80Bit 5: Retrain Link(触发链路重训练,可能进 Hot Reset)
Bit 8: Enable Hardware Autonomous Speed Disable
Link Status Register0x82Bit 7: Link Training(1 表示正在训练)
低 4 位:当前链路速度
Device Control Register0xD8Bit 1: Initiate Function Level Reset (FLR),不是链路级 Reset

我个人习惯在调试脚本里先读 Link Status 的 Bit 7 和速度位,确认链路卡在哪个阶段。如果 Bit 7 为 1 且超过 100ms 不变,大概率是 Recovery 里死循环了。这时候再查 Link Control 看是否有人误写了 Retrain Link。

举个例子:真实波形中的状态变迁

去年我帮客户调过一个 NVMe SSD 热插拔掉盘的问题。插拔后链路没恢复正常,抓 LTSSM 状态发现:

  1. Detect → Polling → Configuration → L0(正常)
  2. 热插拔瞬间链路断开,自动跳回 Detect
  3. 重训练进 Polling,但一直没拿到 TS1/TS2 序列,卡在 Polling.Active
  4. 超时后跳转 Hot Reset,但端点没准备好,Reset 失败

原因是固件在 Hot Reset 时没把数据链路层复位计数器清零。你看,理解这三层协作有多重要。

核心要点回顾:
  • PCIe 三层:事务层、数据链路层、物理层。LTSSM 在物理层。
  • Hot Reset 影响所有三层,不仅仅是物理层电平。
  • 寄存器 Link Control、Link Status 是调试第一入口。
  • 拓扑中 Hot Reset 只影响触发端口的下游链路。