Kernel Panic: Power state transition (0 -> 2) timeout during DriverKit (DEXT) load sequence (IOUserSCSIParallelInterfaceController)

Hi Everyone,

We are currently migrating a mature legacy KEXT to DriverKit for our PCIe SCSI storage controller (connected via Thunderbolt 3). During the DEXT load sequence, we have observed that the system automatically triggers a power state transition from State 0 (Off) to State 2 (On). However, this process results in a Kernel Panic due to a timeout after approximately 21 seconds.

We have verified that our implementation of Start_Impl, UserInitializeController_Impl, and SetPowerState_Impl executes extremely fast, with a total execution time of less than one second. Specifically, SetPowerState_Impl returns kIOReturnSuccess immediately upon being called. Furthermore, our current Info.plist does not contain any IOPowerManagement dictionary or related keys.

Despite the fast execution and the absence of explicit power management declarations in the plist, the kernel power management state machine (IOServicePM) still generates a 21-second timeout, leading to the following panic:

Panic Log:

panic(cpu 7 caller 0xfffffe0020be8fec): MySCSIDriver::setPowerState(0xfffffe2fb1a65c00 : 0xfffffe0020bfed88, 0 -> 2) timed out after 21257 ms @IOServicePM.cpp:5609
com.example.driver.dext: 
    ( id: com.example.driver.dext; path: /Library/SystemExtensions/[UUID]/com.example.driver.dext; state: loaded )

Note on Previous Discussion:

I would like to express my gratitude to Kevin from Apple DTS for the helpful discussion regarding the implementation of BundleParallelTask on the forums. Since then, we have shifted our development focus toward completing the overall management ecosystem, delivering a comprehensive operational interface for users, and handling specific user environments and behaviors. Our current priority is ensuring system stability—specifically resolving these Thunderbolt-related power management issues (sleep/wake)—to prepare the product for upcoming testing. I remain very grateful for the guidance provided on batch task optimization and intend to resume those optimizations once this critical stability baseline is secured.

Technical Guidance Needed for PM Migration

In our legacy KEXT, we utilized PMinit(), registerPowerDriver(), and joinPMtree() to precisely control the timing of power management registration. In transitioning to the DriverKit SDK, we have not found clear guidance on several key points:

  1. Standardized Migration Path: What is the recommended way to implement equivalent power management initialization (formerly PMinit) within a DriverKit subclass? In DriverKit, how should we replicate the behavior of manually calling registerPowerDriver and joinPMtree to ensure the driver is only monitored once the hardware is ready?

  2. Implicit Power Registration: Why does the system enforce a setPowerState(0 -> 2) transition on a subclass of IOUserSCSIParallelInterfaceController even when no IOPowerManagement dictionary is defined in the Info.plist? Is this a default behavior of the SCSI or PCI transport framework?

  3. Thunderbolt Specifics: Are there specific power proxying requirements or configurations for PCIe devices over Thunderbolt to avoid conflicts with the default IOPCIFamily power policies?

Best Regards,

Charles

I would like to express my gratitude to Kevin from Apple DTS

Thank you and you’re very welcome.

In our legacy KEXT, we utilized PMinit(), registerPowerDriver(), and joinPMtree() to precisely control the timing of power management registration. In transitioning to the DriverKit SDK, we have not found clear guidance on several key points:

Please file a bug on this and then post the bug number back here. Power management is definitely an area where the documentation could definitely be improved.

Next, a quick comment here:

Specifically, SetPowerState_Impl returns kIOReturnSuccess immediately upon being called.

Are you calling "super":

DriverKit calls this method to notify your service when the power state of its provider changes. Implement this method in your service object and use it to put your driver in a safe state for the new power setting. Call super as the last step in your implementation.

I think failing to call super can cause exactly the panic you're describing.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Kernel Panic: Power state transition (0 -> 2) timeout during DriverKit (DEXT) load sequence (IOUserSCSIParallelInterfaceController)
 
 
Q