1. PCIe体系结构概述
做PCIe调试,尤其是ASPM这块,你得先把PCIe的体系结构搞明白。我见过太多工程师,一上来就对着ASPM寄存器猛改,结果链路就是不进L1状态。为什么?说白了,你连PCIe的层次结构都没吃透,改寄存器就是瞎调。
别急,我们先花点时间把地基打牢。PCIe体系和传统总线最大的区别,我总结就三个字:分层次。
1.1 三个核心层次
PCIe设备内部其实分了三个层,各干各的。就像公司的组织架构,分工清晰才能高效运转。
| 层次名称 | 英文缩写 | 一句话职责 |
|---|---|---|
| 事务层 | TL | 打包和解包数据。说白了,CPU想读个地址,事务层就给它包成一个TLP包。 |
| 数据链路层 | DLL | 保证传输可靠。如果包丢了,这层负责重传。有点像快递的保价服务。 |
| 物理层 | PHY | 负责把01信号发到差分线对上。最底层,也跟电气特性直接相关。 |
这三个层次之间,通过握手协议来传递信息。ASPM的电源状态转换,主要发生在物理层和数据链路层。事务层?它基本不关心L0s和L1这些省电状态。
1.2 设备的组成单元
一个标准的PCIe设备,内部有哪些东西呢?我们拿一个RC(根复合体)或者EP(端点设备)来举例。
- 配置空间:设备身份的ID卡,包括Vendor ID、Device ID,还有我们最关心的ASPM能力寄存器。
- IOMMU/ATC:地址翻译相关。这跟ASPM关系不大,但如果你做的是SRIOV设备调试,可能会遇到。
- 中断控制器:MSI/MSI-X。ASPM进入低功耗状态时,中断响应时效是个坑。
每个设备的配置空间,都有一段能力链表。ASPM的功能开关,就藏在这个链表的特定能力结构里。
1.3 链路拓扑与层次结构
PCIe拓扑是树形结构。一个Root Complex下面,可以挂多个Switch,Switch再连接多个Endpoint。每个设备内部,又可以分出多个虚拟通道(VC)。
ASPM的管理,是基于链路的。什么意思呢?ASPM只控制相邻两个设备之间的那根物理链路。RC和Switch之间是一条,Switch和EP之间是另一条,它们各自独立。
下面这张图,是我平时画的最多的结构图,帮你看清楚PCIe的层次和组件关系。你就照着这个思路去理清你的系统。
1.4 从PCI到PCIe:有哪些变化?
很多老工程师是从PCI时代过来的。我记得刚转PCIe那会儿,总觉得ASPM是个多余的功能——老PCI哪有这么多省电花样?但后来发现,移动设备的功耗压力太大了,ASPM不得不做。
我列个对比表,你看完就明白为什么PCIe的调试比PCI复杂那么多。
| 对比项 | PCI | PCIe |
|---|---|---|
| 总线拓扑 | 共享并行总线 | 点对点串行链路 |
| 数据编码 | 并行传输 | 8b/10b 或 128b/130b 编码 |
| 电源管理 | PME# 信号,粗放控制 | ASPM + PCI-PM,逐链路精细控制 |
| 中断机制 | INTx 共享中断 | MSI/MSI-X,每个设备独立中断号 |
| 调试复杂度 | 逻辑分析仪即可 | 需要协议分析仪 + 寄存器访问工具 |
你想想看,PCIe链路是点对点的,中间没有任何并行总线可以"偷听"信号。我们做ASPM调试时,必须通过配置空间的寄存器来感知链路状态,不像以前,直接拿示波器量波形就能猜个八九不离十。
1.5 寄存器访问的基础
我们调试ASPM,最终都要落到读写寄存器上。PCIe配置空间的大小是4KB(传统PCI只有256字节)。而ASPM相关的字段,主要分布在这几个地方:
- PCI Express Capability Structure:包含设备能力、设备控制、设备状态等。我们最常调的是
Device Control 2寄存器,那里有ASPM的使能位。 - Link Capability / Link Control:L0s和L1的可接受延迟,以及是否开启。
- Power Management Capability:PCI-PM的D状态,和ASPM配合使用。
实际调试时,我会用lspci -vvv或者通过访问 /sys/bus/pci/devices/ 下的文件来读取这些寄存器。
来,给你看个实际例子。这是某个网卡的ASPM能力字段:
Capabilities: [50] Power Management version 3
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [a0] Express (v2) Endpoint, MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <4us, L1 <64us
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
MaxPayload 128 bytes, MaxReadReq 512 bytes
LinkCap: Port #0, Speed 5GT/s, Width x4, ASPM L0s L1, Exit Latency L0s <2us, L1 <16us
LinkCtl: ASPM Disabled; RCB 64 bytes, Disabled- CommClk+
上面这段输出里,在LinkCtl行中,ASPM Disabled就表示当前链路根本没开启ASPM。很多系统默认是关闭的,需要你手动或通过驱动去打开。
核心观点: 这一章的基础决定了你后续所有ASPM调试的效率。你脑子里一定要有三层模型、配置空间布局、以及寄存器访问方法。不然,后面我讲L1 Substates状态机、讲LTR延迟容忍报告,你会越听越迷糊。
好了,地基打好了,我们就可以开始动真格的了。下一件事,就是搞清楚ASPM的控制寄存器具体在哪个位置,怎么读、怎么改。这些都是硬功夫,我们后面一一拆解。