Linux / NVMe | APST 不完全总结

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

本文简要地从 Linux 内核或者 NVMe 的角度对 APST 进行不完全总结。

更新2023 / 2 / 4


Linux / NVMe | APST 不完全总结


总览

快速可靠的 NVMe SSD 彻底改变了数据存储。但是NVMe SSD 技术有一个缺点高功耗。 幸运的是 NVMe 规范提供很多电源管理功能。

NVMe 电源管理非常重要以在平台散热与 SSD 消耗的总功率之间达成可接受的平衡。

台湾的企业 SSD 制造商 Phison Electronics 公司产品架构总监 Imran Hirani 表示即使规格定义了 SSD 的最大功率主机也可以使用 NVMe 功率状态来改变 SSD 的消耗量。这种改变是基于所需的访问方式以及系统的最大可用热解决方案和气流。 Hirani 说“由于客户端驱动器大部分时间处于空闲状态因此客户端驱动器使用非工作电源状态来延长电池寿命。”


关键电源管理技术和功能

主机可以通过 3 种不同的方式访问 NVMe 电源管理功能

  • 为了为自主电源状态转换功能 Autonomous Power State Transition 设置电源状态条件请使用set feature 命令 FID=0xC, APST 。然后SSD 将根据设置的条件转换到不同的电源状态。
  • 使用 set feature 命令进行电源管理以更改当前 SSD 电源状态。
  • 使用 set feature 命令用于主机控制的热管理以建立两个温度阈值。当设备达到设定温度后设备将自动转换到低功耗状态。

NVMe 电源管理基于工作负载和可用的散热平台。对于客户端、数据中心和企业级固态硬盘会有所不同。
Hirani 说“对于客户端固态硬盘由于驱动器大多数时候都处于空闲状态因此 APST NVMe 电源管理是最佳方法因为驱动器将根据设置的空闲时间限制过渡到较低的电源状态。” 同时数据中心 SSD 通常使用 NVMe 电源管理功能来限制特定工作负载的最大固态硬盘性能以在性能和散热预算要求之间取得平衡。
Hirani 表示“由于企业级 SSD 在大多数时间都是活跃状态因此它们可以使用热管理功能来确保设备不会过热并触发热关机条件。”

NVMe 电源管理功能可在电源、性能、产品可靠性和客户体验之间找到可接受的平衡。但是如果企业未正确配置 NVMe 电源管理则存在风险。
这些风险包括以下内容

  • 无法正确管理 SSD 的活跃电源这会导致产生过多热量这有可能导致可用系统气流无法充分冷却SSDHirani 说“在最坏的情况下SSD 可能达到其热关机极限并且会关机”。
  • 在非运行电源模式下驱动器无法转换为低功耗模式时驱动器将继续消耗功率即使驱动器处于空闲状态也是如此。Hirani 警告说“这会更快耗尽笔记本电脑/笔记本电脑中的电池导致糟糕的客户体验。” 尽管 NVMe 电源状态提供各种节能级别但进入和退出每个状态所需的时间也需要权衡。Hirani 说“最低功率状态将花费最长的时间以进入和退出。不考虑进入和退出延迟可能会导致性能降低或响应时间延长。”

kernel

概念

drivers/nvme/host/core.c 1 中关于 APST 设定的源码如下

/*
 * APST (Autonomous Power State Transition) lets us program a table of power
 * state transitions that the controller will perform automatically.
 *
 * Depending on module params, one of the two supported techniques will be used:
 *
 * - If the parameters provide explicit timeouts and tolerances, they will be
 *   used to build a table with up to 2 non-operational states to transition to.
 *   The default parameter values were selected based on the values used by
 *   Microsoft's and Intel's NVMe drivers. Yet, since we don't implement dynamic
 *   regeneration of the APST table in the event of switching between external
 *   and battery power, the timeouts and tolerances reflect a compromise
 *   between values used by Microsoft for AC and battery scenarios.
 * - If not, we'll configure the table with a simple heuristic: we are willing
 *   to spend at most 2% of the time transitioning between power states.
 *   Therefore, when running in any given state, we will enter the next
 *   lower-power non-operational state after waiting 50 * (enlat + exlat)
 *   microseconds, as long as that state's exit latency is under the requested
 *   maximum latency.
 *
 * We will not autonomously enter any non-operational state for which the total
 * latency exceeds ps_max_latency_us.
 *
 * Users can set ps_max_latency_us to zero to turn off APST.
 */
static int nvme_configure_apst(struct nvme_ctrl *ctrl)
{
	struct nvme_feat_auto_pst *table;
	unsigned apste = 0;
	u64 max_lat_us = 0;
	__le64 target = 0;
	int max_ps = -1;
	int state;
......

因此APST 是一项允许 NVMe ControllerNVMe SSD 内按照可配置规则在电源管理状态之间自主切换的功能。 NVMe Controller 指定进入和退出每个省电状态 power-save state需要多少微秒内核使用此信息来配置 NVMe Controller 内的状态转换规则 2


设置

此前在部分版本的 kernel 的使用中发现倘若 BIOSNvme 在加载驱动前使能 APST那么 APST 无法被永远禁止并且会忽略相关的特定内核参数设置 3
相关的特定内核参数是 default_ps_max_latency_us通过

$ cat /sys/module/nvme_core/parameters/default_ps_max_latency_us

可查询其默认值。
更改可通过修改 /etc/default/grub 文件中相应的行为 nvme_core.default_ps_max_latency_us=0然后 update-grub

修改结果可通过 $ cat /proc/cmdline 确认输出结果

BOOT_IMAGE=/boot/vmlinuz-4.10.0-22-generic.efi.signed root=UUID=365f1a9c-9598-4ad5-a387-d02f771767a1 ro quiet splash nvme_core.default_ps_max_latency_us=0 vt.handoff=7

其中nvme_core.default_ps_max_latency_us=0 出现证明此前的修改已并入启动配置中。

确定当前设备的 APST 功能是否开启与否可通过 $ sudo nvme get-feature -f 0x0c -H /dev/nvme0 命令命令的输出结果将显示是 Didsabled 或者 Enabled

即使可暂时通过手动修改参数禁止 APST只要进行 rebootAPST 功能会被重新启用。


问题

APST Enabled 时设备进入低功耗模式后无法在预计时间内恢复为正常模式或者除非重启 Controller 否则无法醒来的话会让 kernel 不高兴。

为避免此种问题可以设定内核参数最大允许从 APST 状态管理醒来时间为 0以禁止 APST 功能。

如果 Nvme ControllerAPST 功能无法使用Controller 则只能进入 kernel 要求的低功耗状态。

最好的解决方法是NVMe disk firmware 确保 APST 功能正常使用或者至少drive 不预期无法发生的事发生比如不给 APST 功能过于乐观的电源状态切换时间并且 / 或者不允许任何可能会导致 Controller 失败的 APST 功能。

如果证明该问题可以通过编程 APST 来完全避免最深的节能状态那么可能可以通过创建一个 kernel-levelworkaround
kernel 中许多设备的驱动都有 quirk table 用于指定特定硬件模型的解决方法 4

NVMe5以下是会触发 driver 中的各种 workaround 代码的 NVME_QUIRK_ 设置。

static const struct pci_device_id nvme_id_table[] = {
    { PCI_VDEVICE(INTEL, 0x0953),   /* Intel 750/P3500/P3600/P3700 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a53),   /* Intel P3520 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a54),   /* Intel P4500/P4600 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a55),   /* Dell Express Flash P4600 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
        .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                NVME_QUIRK_MEDIUM_PRIO_SQ |
                NVME_QUIRK_NO_TEMP_THRESH_CHANGE |
                NVME_QUIRK_DISABLE_WRITE_ZEROES, },
[...]

请注意一个已经存在的名为 NVME_QUIRK_NO_DEEPEST_PSquirk 设置它可以防止状态转换到最深的电源管理状态。

如果你的 NVMeAPST 问题与英特尔 600P/P3100ADATA SX8200PNP 的解决方案相同那么只需要像这样编写一条新的 quirk table entry替换 <尖括号> 内的内容使用适当的值您可以使用 lspci -nn 获取它们

  { PCI_DEVICE(<PCI vendor ID>, <PCI product ID of the SSD>),   /* <specify make/model of SSD here> */
        .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },

并使用此修改重新编译 kernel

如果设置 NVME_QUIRK_NO_DEEPEST_PS 结果无法解决问题则可能需要实施新的 quirk。这可能会更复杂并且可能需要一些实验或理想情况下来自 SSD 的信息以找出究竟需要做什么来避免这个问题并且可能需要与 Linux NVMe 驱动程序维护者讨论实现它的最佳方法。


参考链接


  1. drivers/nvme/host/core.c ↩︎

  2. clarifying nvme apst problems for linux ↩︎

  3. APST gets enabled against explicit kernel option ↩︎

  4. What are PCI quirks? ↩︎

  5. drivers/nvme/host/pci.c ↩︎

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: linux