第4章:ASPM原理与核心状态机
ASPM,全称是Active State Power Management。
说白了,就是让PCIe链路在不传数据时能偷个懒、省点电。
你想想看,一块NVMe SSD或者一张万兆网卡,大部分时间并非满负荷运转。如果链路始终保持全速待命,那功耗就白白浪费了。
我个人习惯把ASPM看作是PCIe链路的“多级休眠”。从浅睡到深睡,一共分5个档位:L0、L0s、L1、L1.1、L1.2。
4.1 状态总览与对比
先上一张对比表,让你对这几个状态有个大概印象。
| 状态 | 名称 | 功耗节省 | 退出延迟 | 主要机制 |
|---|---|---|---|---|
| L0 | 全速活跃状态 | 无 | 0 | 正常数据传输 |
| L0s | 轻量待机状态 | 低 | 纳秒级 | 独立关闭Tx/Rx |
| L1 | 标准待机状态 | 中 | 微秒级 | 全局通道关闭 |
| L1.1 | 省电扩展状态 | 高 | 数十微秒级 | 关闭Refclk |
| L1.2 | 深度睡眠状态 | 极高 | 毫秒级 | 关闭Refclk & V |
注意,L0是基线,L0s和L1是主流,L1.1和L1.2是后来的增强。
4.2 逐个击破:状态详解
L0 状态:满血输出
这是链路的默认状态。
所有通道都打开,接收器和发送器都全速运行。
所有数据包、流控信息、链路管理报文都正常流动。功耗最高,但延迟为0。没什么好说的。
L0s 状态:浅度小憩
这是我个人比较喜欢的一个设计,因为它比较“聪明”。
L0s允许链路的发送方向独立进入待机。
比如,你的Root Complex端有数据要发,但End Point端没数据回来。那EP端的Tx就可以进入L0s,而RC端保持L0。反过来也一样。
L1 状态:全局浅睡
当链路两侧都没有数据要传输时,双方会协商进入L1。
此时,链路的电气信号会被置为低电平,物理层基本停止工作。
但注意,参考时钟Refclk仍然保持运行。
为什么?因为时钟还在,恢复时间就短,通常在几微秒以内。我调试过一个无线网卡,它的L1进出非常频繁,每次从L1恢复到L0大约需要3微秒。这个延迟对于CPU访问来说,是完全可以接受的。
L1.1 与 L1.2:深度节能
这两个是PCIe规范的扩展,目的是为了进一步降低待机功耗。
L1.1:关掉Refclk
在L1的基础上,如果设备支持,可以连参考时钟都关了。
没有时钟,电路就以几乎零功耗保持状态。但唤醒时,必须先重新锁相环PLL,所以延迟比L1长很多。
L1.2:关掉Refclk + 主电源
这比L1.1更进一步。不仅关时钟,连主电源(V)都切断了。
设备内部的关键上下文会保存在一个叫做“Vaux”的辅助电源区域。这样,功耗可以降到接近零。
4.3 状态机转换流程
为了让你更直观地理解,我画了一张简单的状态转移图。
从图里可以看出来,L0是所有状态解药。
任何低功耗状态(L0s/L1/L1.1/L1.2)在收到数据或事件时,最终都要回到L0才能正常工作。
4.4 关键转换机制
不是你想进什么状态就进什么状态。链路两端的设备必须协商一致。
- L0 <-> L0s: 基于物理层的空闲检测。一侧发现TX Buffer空了,就可以直接进入L0s。退出时,对端通过电气信号变化感知到。
- L0 <-> L1: 通过链路层的“PM_Enter_L1”和“PM_Active_State_Nak”报文协商。需要设备驱动明确指示链路空闲。
- L1 -> L1.1 / L1.2: 需要协议层配合。设备必须通过LTR(延迟容忍报告)告诉Host自己需要多长延迟,Host同意后,才能关闭时钟或电源。
理解这些状态,是做ASPM时序分析的基础。
你只有在抓包时能识别出那个状态对应哪个信号波形,才能准确判断到底是哪个环节慢了。
嗯,这部分内容不少,你先消化一下这些状态的定义和转换关系。