驱动程序导致睡眠唤醒失败

时间:2015-02-12 19:32:23

标签: macos debugging kernel iokit xnu

作为一项安全研究,我正在编写一个自定义 IOKit 驱动程序。驱动程序通过电源平面向依赖的驱动程序注册。 (USB服务)。正在调用setPowerState函数,驱动程序正确关闭。

问题是,随机导致睡眠唤醒失败问题并且机器重新启动。实际上,在机器进入睡眠状态后唤醒机器(试图显然进入休眠状态)时会发生复位

问题是,我该如何调试或解决它?我正在使用firewire内核调试来查看正在发生的事情,但调试器和断点导致睡眠计时机制的延迟,一切都很乱。

互联网上的数据在这个问题上相当薄弱,但充满了抱怨OSX机器导致清洁机器中的睡眠唤醒故障。

我正在各种机器和内核版本上测试它并且它是持久的。

任何线索都会有所帮助。

编辑:附加代码

enum
{
    kOffPowerState, kStandbyPowerState, kIdlePowertState, kOnPowerState, kNumPowerStates
};

static IOPMPowerState gPowerStates[kNumPowerStates]   =
{
    //kOffPowerState
    {kIOPMPowerStateVersion1, 0,0,0,0,0,0,0,0,0,0,0},

    //kStandbyPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kIdlePowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kOnPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn | kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0}
};

bool driver::start(IOService* provider)
{
    IOLog("driver::start\n");

    if (IOService::start(provider) == false)
        return false; 

   PMinit();

   provider->joinPMtree(this);    
   makeUsable();
   changePowerStateTo(0);
   registerPowerDriver(this, gPowerStates, kNumPowerStates);
   registerService();
   return true;
}

IOReturn driver::setPowerState (unsigned long whichState, IOService * whatDevice)
{
    IOLog("driver::setPowerState (%lu)\n", whichState);

    if (whichState == 0)
        IOLog("driver: shutdown (%lu)\n", whichState);

    return kIOPMAckImplied;
}

1 个答案:

答案 0 :(得分:1)

未发布的IOService引用导致睡眠序列死锁。

我们使用以下代码获取IOService指针。

mach_timespec time;
time.tv_sec = 0;
time.tv_nsec = 1000;
IOService* service = IOService::waitForService(IOService::serviceMatching(class_name, NULL), &time);
return service; 

IOService::serviceMatchingIOService::waitForService都会增加引用计数器。

更改为以下示例代码:

OSDictionary *dict = IOService::serviceMatching(class_name, NULL);

if (dict == NULL)
    return NULL;

IOService* service = IOService::waitForMatchingService(dict, 1000);

dict->release();

return service;

IOService::waitForMatchingService 增加引用计数器,我们释放OSDictionary指针。