3. L1SS 子状态详解:L1.0, L1.1, L1.2
L1 Substates(L1SS)是 PCIe 链路在进入 L1 低功耗状态后,进一步关闭内部电路以降低静态功耗的机制。L1SS 包含三个子状态:L1.0、L1.1 和 L1.2。每个子状态在功耗节省和退出延迟之间做出不同权衡,理解这些差异是进行深度功耗优化的基础。
核心概念: L1SS 的深度越深(L1.0 → L1.1 → L1.2),关闭的电路越多,功耗节省越大,但退出延迟也越长。配置的关键在于找到满足系统延迟要求的“最深”子状态。
3.1 子状态定义与功耗节省比例
下表对比了 L1SS 三个子状态的核心特征:
| 特性 | L1.0 | L1.1 | L1.2 |
|---|---|---|---|
| 定义 | 基本 L1 状态,仅关闭主时钟 | 关闭 Tx/Rx 模拟前端(AFE) | 关闭 Tx/Rx AFE 并关闭主 PLL |
| 功耗节省比例 | 约 30% – 50% | 约 60% – 80% | 约 85% – 95% |
| 退出延迟 | 约 1 – 2 µs | 约 2 – 5 µs | 约 5 – 20 µs |
| 时钟状态 | 主时钟关闭,PLL 保持锁定 | 主时钟关闭,PLL 保持锁定 | 主时钟关闭,PLL 关闭 |
| 电气空闲 | 电气空闲(Electrical Idle) | 电气空闲 + 共模电压关闭 | 电气空闲 + 共模电压关闭 |
关键洞察: L1.2 的功耗节省可达 95%,但退出延迟可能高达 20 µs。对于延迟敏感型设备(如 NVMe SSD),通常只能使用 L1.1 或 L1.0。
3.2 进入条件与状态转换
L1SS 的进入遵循严格的握手协议。下图展示了从 L0 到 L1.2 的完整状态转换路径:
进入条件总结:
- L1.0 进入条件:链路空闲超时(通常由软件配置的 L1 进入延迟控制),且两端均支持 L1。
- L1.1 进入条件:在 L1.0 基础上,两端通过
L1PM_SUBSTATE寄存器协商,确认支持 L1.1,且链路无待处理流量。 - L1.2 进入条件:在 L1.1 基础上,两端确认支持 L1.2,且系统允许关闭 PLL(通常需要平台固件配合)。
常见配置陷阱: 如果只使能 L1.2 而未使能 L1.1,链路将无法进入 L1.2,因为 L1.2 的进入必须经过 L1.1 握手。务必在配置寄存器时同时使能所有中间子状态。
3.3 退出延迟与唤醒机制
退出延迟是 L1SS 配置中最关键的权衡因素。下表详细列出了各子状态的退出延迟组成:
| 子状态 | 延迟组成 | 典型延迟范围 | 适用场景 |
|---|---|---|---|
| L1.0 | 时钟恢复 + 链路训练 | 1 – 2 µs | 延迟敏感型(如 NVMe、GPU) |
| L1.1 | 时钟恢复 + AFE 上电 + 链路训练 | 2 – 5 µs | 中等延迟容忍(如网卡、存储) |
| L1.2 | PLL 锁定 + 时钟恢复 + AFE 上电 + 链路训练 | 5 – 20 µs | 深度省电(如移动设备、IoT) |
唤醒流程(以 L1.2 为例):
- 唤醒事件触发: 任意一端发送
WAKE#信号或 in-band 唤醒序列。 - PLL 重新锁定: 主 PLL 从关闭状态恢复,锁定时间约 3 – 10 µs(取决于 PLL 设计)。
- AFE 上电: 模拟前端电路上电并稳定,约 1 – 2 µs。
- 时钟恢复: 接收端从数据流中恢复时钟,约 0.5 – 1 µs。
- 链路训练: 执行快速链路训练(Fast Training Sequence, FTS),约 0.5 – 1 µs。
- 返回 L0: 链路恢复全速数据传输。
优化建议: 对于大多数服务器场景,推荐使用 L1.1 作为默认深度,因为它在功耗节省(约 70%)和退出延迟(约 3 µs)之间取得了最佳平衡。仅在电池供电或散热受限的设备中启用 L1.2。
3.4 寄存器配置示例
L1SS 的使能通过 PCIe 配置空间的 L1PM Substates Control Register(Offset 0x1B8)进行配置。以下是一个典型的配置代码片段:
// 使能 L1.1 和 L1.2,设置 L1.2 退出延迟阈值为 10 µs
// 寄存器地址:PCIe Capability + 0x1B8
uint32_t l1ss_ctrl = pcie_read32(dev, cap_offset + 0x1B8);
// 位域定义:
// [1:0] L1.0 使能 (01b = 使能)
// [3:2] L1.1 使能 (01b = 使能)
// [5:4] L1.2 使能 (01b = 使能)
// [15:8] L1.2 退出延迟阈值 (单位: 2 µs)
l1ss_ctrl &= ~0x003F; // 清除低 6 位
l1ss_ctrl |= 0x0015; // 使能 L1.0 (01) + L1.1 (01) + L1.2 (01)
// 设置 L1.2 退出延迟阈值为 10 µs (10 / 2 = 5)
l1ss_ctrl &= ~0xFF00; // 清除 [15:8]
l1ss_ctrl |= (5 & 0xFF) << 8; // 写入阈值
pcie_write32(dev, cap_offset + 0x1B8, l1ss_ctrl);
调试技巧: 配置后,读取
L1PM Substates Status Register(Offset 0x1BC)确认子状态是否成功使能。如果状态位未置位,检查链路两端是否均支持该子状态,以及平台固件是否允许 PLL 关闭。
3.5 功耗节省比例实测参考
以下数据基于 Gen4 x4 链路在典型工作负载下的实测结果:
| 子状态 | 链路功耗(mW) | 节省比例 | 退出延迟(µs) |
|---|---|---|---|
| L0(空闲) | 150 | 基准 | — |
| L1.0 | 75 | 50% | 1.2 |
| L1.1 | 35 | 77% | 3.5 |
| L1.2 | 12 | 92% | 12.0 |
从实测数据可以看出,从 L1.0 到 L1.1 的功耗节省提升最为显著(额外节省 27%),而 L1.2 虽然节省更多,但退出延迟增加了近 4 倍。因此,L1.1 通常是大多数系统的最佳选择。