导向式电源管理框架简介

从 Windows 10 版本 1903 开始,运行时电源管理框架版本 3 (PoFx) 提供可选的导向式电源模型——导向式 PoFx (DFx)。

借助 DFx,当系统过渡到空闲状态且不存在由激活器代理的软件活动时,操作系统可将设备堆栈定向到其相应的低功率空闲状态,从而可让系统更可靠地进入低功率状态。

其目标是使系统更为节能,并降低不同外形规格的 Windows 设备的能耗。

目前,只有存在 D 状态约束的设备才支持 DFx。 DFx 可跳过存在 F 状态约束的所有设备子树。

DFx 不会关闭分页或调试设备。

WDF(非微型端口)驱动程序的要求

作为电源策略所有者的 WDF 驱动程序必须通过在 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 结构中指定 SystemManagedIdleTimeoutSystemManagedIdleTimeoutWithHint 来实现相应的 S0 空闲策略。 此特性可让设备在空闲时关闭电源。 作为新增的复原措施,驱动程序可通过将以下注册表项添加到 DDInstall.HW 部分中 INF 的 AddReg 指令部分来选择使用 DFx:

HKR,"WDF","WdfDirectedPowerTransitionEnable",0x00010001,1

面向版本 31 及更高版本的 WDF 驱动程序将默认启用 DFx。 如果不想如此,驱动程序则可通过将此注册表项设为 0 来选择不使用 DFx:

HKR,"WDF","WdfDirectedPowerTransitionEnable",0x00010001,0

面向版本 33 及更高版本的 WDF 驱动程序可通过将 WDF_POWER_FRAMEWORK_SETTINGS 结构的 DirectedPoFxEnabled 成员设为 WdfFalse 来选择不使用 DFx。

提示

若要初始化其 WDF_POWER_FRAMEWORK_SETTINGS 结构,驱动程序应调用 WDF_POWER_FRAMEWORK_SETTINGS_INIT

由于请求系统管理的空闲超时会导致 WDF 代表驱动程序向 PoFx 注册,因而在此情况下,驱动程序无需向 PoFx 注册。

如果驱动程序指定了 DriverManagedIdleTimeout,则请考虑切换到系统管理的空闲超时。 如果此举不可行,则请使用以下 WDM 部分中介绍的准则来选择使用 DFx。

如果 WDF 驱动程序未使用运行时电源管理,则请为其添加支持,并使用系统管理的空闲超时。 为此,请提供 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 结构以作为 WdfDeviceAssignS0IdleSettings 的输入。

WDM(非微型端口)驱动程序的要求

如果驱动程序未使用 WDF 提供的系统管理的空闲支持(即,该驱动程序是使用驱动程序管理的空闲的 WDF 驱动程序,或是 WDM 驱动程序),则仍可通过向 PoFx 注册自身来获得 DFx 支持。 在此情况下,驱动程序会通过实现以下内容向 PoFx 注册:

在输入到 PoFxRegisterDevice 函数的 PO_FX_DEVICE_V3 结构中提供指向这些回调的指针。

若要获得 DFx 支持,驱动程序必须:

  • 在注册 PoFx 时提供 PO_FX_DIRECTED_POWER* 回调
  • 从空闲返回时从其 PO_FX_DIRECTED_POWER_UP_CALLBACK 回调函数调用 PoFxReportDevicePoweredOn。 如果它为 WDF 驱动程序,则可设置一个标志,然后在 EvtDeviceD0Entry 中检查该标志并调用 PoFxReportDevicePoweredOn
  • 从 Sx 转换恢复时调用 PoFxReportDevicePoweredOn。 如果它为 WDF 驱动程序,则需预处理 IRP_MN_SET_POWER。 仅当 Parameters.Power.Type == SystemPowerState 时,预处理回调才应继续执行。 由于设备可能会在整个睡眠/恢复周期中保持为 Dx 状态,因此在 EvtDeviceD0Entry 中检查标志的上述方法不起作用。 相反,EvtDeviceWdmIrpPreprocess 事件回调函数应调用 IoSetCompletionRoutine 来设置 IoCompletion 例程,并从完成例程调用 PoFxReportDevicePoweredOn

示例

以下示例显示了上述自注册选项:

PO_FX_DEVICE_V3 MyPoFxDevice;
POHANDLE MyPoFxHandle;

RtlZeroMemory(&MyPoFxDevice, sizeof(PO_FX_DEVICE_V3));
MyPoFxDevice.Version = PO_FX_VERSION_V3;

// Initialize other PoFx callbacks and other fields like
// components and their idle states.

MyPoFxDevice.DirectedPowerUpCallback = <Driver's DFx power up callback>
MyPoFxDevice.DirectedPowerDownCallback = <Driver's DFx power down callback>

Status = PoFxRegisterDevice(
  <Driver's device object>,
  (PPO_FX_DEVICE)&MyPoFxDevice,
  &MyPoFxHandle);
  if (!NT_SUCCESS(Status)) {
  return Status;
}

如果驱动程序之前指定了 PO_FX_VERSION_V1,则请注意,PO_FX_DEVICE_V3 结构会将 PO_FX_COMPONENT_V2 用于组件数组结构。

非微型端口驱动程序的要求

对于遵循端口/微型端口驱动程序模型的设备类,系统提供的端口驱动程序通常会处理电源策略所有权。 大多数微型端口预计无需任何代码更改即可选择使用 DFx,因为相应的端口驱动程序应能处理 DFx 支持。

针对 KS.sys 第三方微型端口的指南

从 Windows 10 版本 2004(也被称为 20H1 或内部版本 19041 开始),KS.sys 会默认选择不使用 DFx 且不遵循相关的 HLK 要求。 KS.sys 的第三方微型端口可通过向 PoFx 注册自身并将 KsDFxSupportEnable 注册表项添加到 INF 来选择使用 DFx 并遵循相关 HLK。

驱动程序可使用本节中提及的实现向 PoFx 注册自身。 此外,需在 AddReg 指令部分添加以下行。

HKR, , KSDFxSupportEnable, 0x00010001, 1

设备的 [DDInstall.HW] 部分或驱动程序的 [service-install-section] 可调用 AddReg 部分。 在 [DDInstall.HW] 部分添加它只会更改该特定设备。 如果同一驱动程序会用于不同 VID/PID 组合,但仅针对特定设备启用 DFx,此操作则非常有用。

在 [service-install-section] 中添加 AddReg 部分会为使用该驱动程序的所有设备选择使用 DFx。

测试

Microsoft 为 DFx 提供了三项测试:用于测试用户指定设备的 Windows 驱动程序工具包中的单设备测试、设备级 HLK 测试以及用于测试系统上所有设备的系统级 HLK 测试。

单设备测试将作为 WDK 随附的 PwrTest 工具的一部分来提供。 若要访问它,请使用 /directedfx 开关运行该工具。 有关详细信息,请参阅 PwrTest DirectedFx 场景

有关 HLK 测试的信息,请参阅以下页面:

建议在 S4 转换后测试 DFx,以便捕获驱动程序在从 S4 恢复后可能无法正确调用 PoFxReportDevicePoweredOn 的所有情况。

DFx 和 S 状态转换

  • DFx 转换的目标 D 状态应与运行时 D3 (RTD3) 的目标 D 状态匹配,而这可能与 S3/S4 转换的目标 D 状态不同。 假设存在以下情况:某一设备针对 RTD3 进入 D2,但针对 S3/S4 则进入 D3。 在此情况下,DFx 的目标 D 状态应为 D2。
  • 同样,DFx 的 arm-for-wake 行为应与 RTD3 的 arm-for-wake 行为相匹配,而这可能与 S3/S4 转换中使用的 arm-for-wake 行为不同。 例如,设备可能会针对 RTD3 而进入 D2/wake-armed,但针对 S3/S4 则进入 D3/no-wake-armed。 在此情况下,DFx 转换也应进入 D2/wake-armed。

DFx 和运行时 D3 (RTD3)

  • 使用 RTD3 时,设备在进入空闲状态时通常会进入低功耗 D 状态。 如果新工作到达,设备会立即唤醒到 D0。 借助 DFx,设备应继续保持其目标 D 状态(并将新工作暂挂到其队列),直到 PoFx 将其定向为重新上电。

另请参阅