PCIe协议基础:分层模型、事务层、数据链路层、物理层
聊聊PCIe这个“三层汉堡”
做Protocol Analyzer抓包分析,逃不开PCIe协议栈。
我个人习惯,是把PCIe协议栈比作一个高效的快递系统。从上到下,一共三层:事务层、数据链路层、物理层。每层干各层的活,分工明确。你想想看,这样分层有个好处:某一层出了问题,不会把整个系统拖垮。
一个数据包从发送端到接收端, 流程是这样的:先由事务层封装,交给数据链路层加校验和序列号,最后物理层把它变成比特流发出去。接收端反过来,层层剥离。嗯,这就是分层通信的精髓——每一层只和相邻的层打交道。
我在项目中遇到过好几次,明明是链路层有CRC错误,结果大家围在一起争论TLP格式对不对。查了半天才发现是物理层的信号完整性问题。所以,你看,理解这个分层模型,不仅仅是为了考试,更是为了实战中快速定位问题。
事务层:TLP 是主角
事务层是离软件最近的一层。说白了,它负责把软件发起的读写请求,打包成一种标准格式——TLP(Transaction Layer Packet)。
常见的 TLP 类型有哪些?
- Memory Read/Write: 最常见,读写内存空间。我抓包分析ASPM时,一半以上的流量都是这个。
- IO Read/Write: 读写IO空间,老设备还在用,新平台逐渐不玩了。
- Configuration Read/Write: 读配置空间,像枚举设备、设置BAR地址,都靠它。
- Message: 中断通知(MSI/MSI-X)、错误报告、电源管理事件等。ASPM的L1/ L2状态切换,就靠Message通信。
我举个例子。假设CPU要读显卡的BAR0寄存器。事务层会生成一个Memory Read TLP,带上目标地址、请求长度、一个唯一的Tag。显卡收到后回复Completion with Data TLP。整个请求-完成过程,在抓包文件里看得清清楚楚。
数据链路层:可靠的搬运工
数据链路层在事务层下面。它的任务很明确:保证TLP从发送端完整、有序地传到接收端。如果出错,就重传。
每个TLP从事务层下来,数据链路层会给它加上两样东西:
- 序列号(Sequence Number): 初始值是0,每发一个TLP加1。接收端靠它检测丢包和乱序。
- LCRC(Link CRC): 32位冗余校验码,覆盖整个TLP(包括包头和Payload)。接收端算一遍,不一致就扔NAK。
ACK/NAK是怎么工作的?
- 发送端发TLP(带Seq Num和LCRC),并保留副本在重传缓冲区。
- 接收端收到后,校验LCRC。正确,发ACK(应答序列号)。错误,发NAK(请求重传序列号)。
- 发送端收到NAK或超时未收到ACK,立即重传。
数据链路层还有一个核心东西——DLLP(Data Link Layer Packet)。它不是传递数据的,而是用于管理链路的:ACK/NAK、电源管理状态切换、流控信息更新等。抓包时,DLLP同样会被记录。
物理层:比特的舞台
物理层是最底层的。它把数据链路层下来的字节,变成电信号或光信号,在PCIe通道上飞。
物理层的主要工作:
- 编码/解码: Gen1/Gen2用8B/10B编码,每10位传递8位数据,多了20%的开销。Gen3/Gen4/Gen5改用128B/130B编码,效率更高。
- 串行化/解串行化: 把并行数据转成串行,在单根差分线上发送。一根线传完,另一根线收,全双工。
- 链路训练与状态管理(LTSSM): 物理层的状态机。上电、复位、降功耗、唤醒,全是LTSSM在管。
LTSSM状态机有几个关键状态,和你抓ASPM时序强相关:
| LTSSM 状态 | 说明 | ASPM 相关性 |
|---|---|---|
| L0 | 正常全速运行,数据传输中 | ASPM的L0s和L1都是从L0进入的 |
| L0s | 轻量级省电,恢复快(几纳秒到微秒) | 由物理层自主进入,不需要软件参与 |
| L1 | 深度省电,恢复慢(几微秒到几十微秒) | 必须由事务层/软件协商,ASPM L1是重点分析对象 |
| L2 | 几乎断电,主电源关闭,只留漏电电流 | 通常只在系统休眠或关机时进入 |
为什么理解物理层对ASPM很重要? 因为ASPM的省电效果和退出延迟,最终都体现在物理层的状态切换上。你抓包看到的PHY电气状态变化(如电气空闲 Electrical Idle),就是物理层在L0和L1之间跳来跳去。
我习惯在Protocol Analyzer里同时开这三层的日志。事务层看TLP类型,数据链路层看ACK/NAK,物理层看LTSSM状态。三张图一对照,ASPM的时序行为就无所遁形了。嗯,这个习惯帮我解决了不止一个疑难杂症。