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 的完整状态转换路径:

L1SS 状态转换图 L1SS 状态转换路径 L0(全速运行) 空闲超时 L1.0 AFE 空闲请求 L1.1 PLL 关闭请求 L1.2 退出事件(唤醒) 说明:进入 L1.2 必须经过 L1.0 → L1.1 → L1.2 的逐级握手;退出时可直接从任意子状态回到 L0。

进入条件总结:

  • 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 为例):

  1. 唤醒事件触发: 任意一端发送 WAKE# 信号或 in-band 唤醒序列。
  2. PLL 重新锁定: 主 PLL 从关闭状态恢复,锁定时间约 3 – 10 µs(取决于 PLL 设计)。
  3. AFE 上电: 模拟前端电路上电并稳定,约 1 – 2 µs。
  4. 时钟恢复: 接收端从数据流中恢复时钟,约 0.5 – 1 µs。
  5. 链路训练: 执行快速链路训练(Fast Training Sequence, FTS),约 0.5 – 1 µs。
  6. 返回 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 通常是大多数系统的最佳选择。