X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/db6096698656d32db7df630594bd9617ee54f828..f427ee49d309d8fc33ebf3042c3a775f2f530ded:/iokit/Kernel/IOServicePMPrivate.h diff --git a/iokit/Kernel/IOServicePMPrivate.h b/iokit/Kernel/IOServicePMPrivate.h index bdb74358b..31e42e28c 100644 --- a/iokit/Kernel/IOServicePMPrivate.h +++ b/iokit/Kernel/IOServicePMPrivate.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2007 Apple Inc. All rights reserved. + * Copyright (c) 2019-2020 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ @@ -32,39 +32,42 @@ #include #include +#define USE_SETTLE_TIMER 0 + //****************************************************************************** // PM command types //****************************************************************************** enum { - /* Command Types */ - kIOPMRequestTypeInvalid = 0x00, - kIOPMRequestTypePMStop = 0x01, - kIOPMRequestTypeAddPowerChild1 = 0x02, - kIOPMRequestTypeAddPowerChild2 = 0x03, - kIOPMRequestTypeAddPowerChild3 = 0x04, - kIOPMRequestTypeRegisterPowerDriver = 0x05, - kIOPMRequestTypeAdjustPowerState = 0x06, - kIOPMRequestTypePowerDomainWillChange = 0x07, - kIOPMRequestTypePowerDomainDidChange = 0x08, - kIOPMRequestTypePowerOverrideOnPriv = 0x09, - kIOPMRequestTypePowerOverrideOffPriv = 0x0A, - kIOPMRequestTypeActivityTickle = 0x0B, - kIOPMRequestTypeRequestPowerState = 0x0C, - kIOPMRequestTypeSynchronizePowerTree = 0x0D, - kIOPMRequestTypeRequestPowerStateOverride = 0x0E, - kIOPMRequestTypeSetIdleTimerPeriod = 0x0F, - kIOPMRequestTypeIgnoreIdleTimer = 0x10, - - /* Reply Types */ - kIOPMRequestTypeReplyStart = 0x80, - kIOPMRequestTypeAckPowerChange = 0x81, - kIOPMRequestTypeAckSetPowerState = 0x82, - kIOPMRequestTypeAllowPowerChange = 0x83, - kIOPMRequestTypeCancelPowerChange = 0x84, - kIOPMRequestTypeInterestChanged = 0x85, - kIOPMRequestTypeIdleCancel = 0x86, - kIOPMRequestTypeChildNotifyDelayCancel = 0x87 + /* Command Types */ + kIOPMRequestTypeInvalid = 0x00, + kIOPMRequestTypePMStop = 0x01, + kIOPMRequestTypeAddPowerChild1 = 0x02, + kIOPMRequestTypeAddPowerChild2 = 0x03, + kIOPMRequestTypeAddPowerChild3 = 0x04, + kIOPMRequestTypeRegisterPowerDriver = 0x05, + kIOPMRequestTypeAdjustPowerState = 0x06, + kIOPMRequestTypePowerDomainWillChange = 0x07, + kIOPMRequestTypePowerDomainDidChange = 0x08, + kIOPMRequestTypePowerOverrideOnPriv = 0x09, + kIOPMRequestTypePowerOverrideOffPriv = 0x0A, + kIOPMRequestTypeActivityTickle = 0x0B, + kIOPMRequestTypeRequestPowerState = 0x0C, + kIOPMRequestTypeSynchronizePowerTree = 0x0D, + kIOPMRequestTypeRequestPowerStateOverride = 0x0E, + kIOPMRequestTypeSetIdleTimerPeriod = 0x0F, + kIOPMRequestTypeIgnoreIdleTimer = 0x10, + kIOPMRequestTypeQuiescePowerTree = 0x11, + + /* Reply Types */ + kIOPMRequestTypeReplyStart = 0x80, + kIOPMRequestTypeAckPowerChange = 0x81, + kIOPMRequestTypeAckSetPowerState = 0x82, + kIOPMRequestTypeAllowPowerChange = 0x83, + kIOPMRequestTypeCancelPowerChange = 0x84, + kIOPMRequestTypeInterestChanged = 0x85, + kIOPMRequestTypeIdleCancel = 0x86, + kIOPMRequestTypeChildNotifyDelayCancel = 0x87 }; //****************************************************************************** @@ -75,94 +78,85 @@ struct IOPMActions; typedef void (*IOPMActionPowerChangeStart)( - void * target, - IOService * service, - IOPMActions * actions, - uint32_t powerState, - uint32_t * changeFlags ); + void * target, + IOService * service, + IOPMActions * actions, + const IOPMRequest * request, + IOPMPowerStateIndex powerState, + IOPMPowerChangeFlags * changeFlagsPtr ); typedef void (*IOPMActionPowerChangeDone)( - void * target, - IOService * service, - IOPMActions * actions, - uint32_t powerState, - uint32_t changeFlags ); + void * target, + IOService * service, + IOPMActions * actions, + const IOPMRequest * request, + IOPMPowerStateIndex powerState, + IOPMPowerChangeFlags changeFlags ); typedef void (*IOPMActionPowerChangeOverride)( - void * target, - IOService * service, - IOPMActions * actions, - unsigned long * powerState, - uint32_t * changeFlags ); + void * target, + IOService * service, + IOPMActions * actions, + const IOPMRequest * request, + IOPMPowerStateIndex * powerStatePtr, + IOPMPowerChangeFlags * changeFlagsPtr ); typedef void (*IOPMActionActivityTickle)( - void * target, - IOService * service, - IOPMActions * actions ); + void * target, + IOService * service, + IOPMActions * actions ); + +typedef void +(*IOPMActionUpdatePowerClient)( + void * target, + IOService * service, + IOPMActions * actions, + const OSSymbol * powerClient, + IOPMPowerStateIndex oldPowerState, + IOPMPowerStateIndex newPowerState ); struct IOPMActions { - void * target; - uint32_t parameter; - IOPMActionPowerChangeStart actionPowerChangeStart; - IOPMActionPowerChangeDone actionPowerChangeDone; - IOPMActionPowerChangeOverride actionPowerChangeOverride; - IOPMActionActivityTickle actionActivityTickle; + void * target; + IOPMActionPowerChangeStart actionPowerChangeStart; + IOPMActionPowerChangeDone actionPowerChangeDone; + IOPMActionPowerChangeOverride actionPowerChangeOverride; + IOPMActionActivityTickle actionActivityTickle; + IOPMActionUpdatePowerClient actionUpdatePowerClient; + uint32_t darkWakePowerState; + uint16_t flags; + uint16_t state; }; -//****************************************************************************** - +// IOPMActions flags enum { - kIOPMEventClassSystemEvent = 0x00, - kIOPMEventClassDriverEvent = 0x1 + kPMActionsPCIBitNumberMask = 0x00ff, + kPMActionsFlagIsDisplayWrangler = 0x0100, + kPMActionsFlagIsGraphicsDriver = 0x0200, + kPMActionsFlagIsAudioDriver = 0x0400, + kPMActionsFlagHasDarkWakePowerState = 0x0800 }; -class PMEventDetails : public OSObject -{ - OSDeclareDefaultStructors( PMEventDetails ); - friend class IOServicePM; - friend class IOPMrootDomain; - friend class IOPMTimeline; -public: - static PMEventDetails *eventDetails(uint32_t type, - const char *ownerName, - uintptr_t ownerUnique, - const char *interestName, - uint8_t oldState, - uint8_t newState, - uint32_t result, - uint32_t elapsedTimeUS); - - static PMEventDetails *eventDetails(uint32_t type, - const char *uuid, - uint32_t reason, - uint32_t result); -private: - uint8_t eventClassifier; - uint32_t eventType; - const char *ownerName; - uintptr_t ownerUnique; - const char *interestName; - uint8_t oldState; - uint8_t newState; - uint32_t result; - uint32_t elapsedTimeUS; - - const char *uuid; - uint32_t reason; +// IOPMActions state +enum { + kPMActionsStatePowerClamped = 0x0001 }; +//****************************************************************************** // Internal concise representation of IOPMPowerState -struct IOPMPSEntry -{ - IOPMPowerFlags capabilityFlags; - IOPMPowerFlags outputPowerFlags; - IOPMPowerFlags inputPowerFlags; - uint32_t staticPower; - uint32_t settleUpTime; - uint32_t settleDownTime; +struct IOPMPSEntry { + IOPMPowerFlags capabilityFlags; + IOPMPowerFlags outputPowerFlags; + IOPMPowerFlags inputPowerFlags; + unsigned long staticPower; +#if USE_SETTLE_TIMER + uint32_t settleUpTime; + uint32_t settleDownTime; +#endif + IOPMPowerStateIndex stateOrder; + IOPMPowerStateIndex stateOrderToIndex; }; //****************************************************************************** @@ -171,182 +165,209 @@ struct IOPMPSEntry class IOServicePM : public OSObject { - friend class IOService; - friend class IOPMWorkQueue; + friend class IOService; + friend class IOPMWorkQueue; - OSDeclareDefaultStructors( IOServicePM ) + OSDeclareDefaultStructors( IOServicePM ); private: - // Link IOServicePM objects on IOPMWorkQueue. - queue_chain_t WorkChain; - - // Queue of IOPMRequest objects. - queue_head_t RequestHead; +// Link IOServicePM objects on IOPMWorkQueue. + queue_chain_t WorkChain; + +// Queue of IOPMRequest objects. + queue_head_t RequestHead; + +// IOService creator and owner. + IOService * Owner; + +// List of interested drivers (protected by PMLock). + IOPMinformeeList * InterestedDrivers; + +// How long to wait for controlling driver to acknowledge. + IOReturn DriverTimer; - // IOService creator and owner. - IOService * Owner; +// Current power management machine state. + uint32_t MachineState; - // List of interested drivers (protected by PMLock). - IOPMinformeeList * InterestedDrivers; + thread_call_t AckTimer; +#if USE_SETTLE_TIMER + thread_call_t SettleTimer; +#endif + thread_call_t IdleTimer; + thread_call_t WatchdogTimer; + thread_call_t SpinDumpTimer; + + IOLock * WatchdogLock; + OSArray * BlockedArray; + uint64_t PendingResponseDeadline; + uint64_t WatchdogDeadline; + +// Settle time after changing power state. +#if USE_SETTLE_TIMER + uint32_t SettleTimeUS; +#endif + IOPMPowerStateIndex IdleTimerGeneration; + +// The flags describing current change note. + IOPMPowerChangeFlags HeadNoteChangeFlags; - // How long to wait for controlling driver to acknowledge. - IOReturn DriverTimer; +// The new power state number being changed to. + IOPMPowerStateIndex HeadNotePowerState; - // Current power management machine state. - uint32_t MachineState; +// Points to the entry in the power state array. + IOPMPSEntry * HeadNotePowerArrayEntry; - thread_call_t AckTimer; - thread_call_t SettleTimer; - thread_call_t IdleTimer; +// Power flags supplied by all parents (domain). + IOPMPowerFlags HeadNoteDomainFlags; - // Settle time after changing power state. - uint32_t SettleTimeUS; +// Power flags supplied by domain accounting for parent changes. + IOPMPowerFlags HeadNoteDomainTargetFlags; - // The flags describing current change note. - IOPMPowerChangeFlags HeadNoteChangeFlags; +// Connection attached to the changing parent. + IOPowerConnection * HeadNoteParentConnection; - // The new power state number being changed to. - IOPMPowerStateIndex HeadNotePowerState; +// Power flags supplied by the changing parent. + IOPMPowerFlags HeadNoteParentFlags; - // Points to the entry in the power state array. - IOPMPSEntry * HeadNotePowerArrayEntry; +// Number of acks still outstanding. + uint32_t HeadNotePendingAcks; - // Power flags supplied by all parents (domain). - IOPMPowerFlags HeadNoteDomainFlags; - - // Power flags supplied by domain accounting for parent changes. - IOPMPowerFlags HeadNoteDomainTargetFlags; - - // Connection attached to the changing parent. - IOPowerConnection * HeadNoteParentConnection; - - // Power flags supplied by the changing parent. - IOPMPowerFlags HeadNoteParentFlags; - - // Number of acks still outstanding. - uint32_t HeadNotePendingAcks; - - // PM state lock. - IOLock * PMLock; - - unsigned int InitialPowerChange:1; - unsigned int InitialSetPowerState:1; - unsigned int DeviceOverrideEnabled:1; - unsigned int DoNotPowerDown:1; - unsigned int ParentsKnowState:1; - unsigned int StrictTreeOrder:1; - unsigned int IdleTimerStopped:1; - unsigned int AdjustPowerScheduled:1; - unsigned int IsPreChange:1; - unsigned int DriverCallBusy:1; - unsigned int PCDFunctionOverride:1; - unsigned int IdleTimerIgnored:1; - unsigned int HasAdvisoryDesire:1; - unsigned int AdvisoryTickleUsed:1; - - // Time of last device activity. - AbsoluteTime DeviceActiveTimestamp; - - // Used to protect activity flag. - IOLock * ActivityLock; - - // Idle timer's period in seconds. - unsigned long IdleTimerPeriod; - unsigned long IdleTimerMinPowerState; - AbsoluteTime IdleTimerStartTime; - - // Power state desired by a subclassed device object. - IOPMPowerStateIndex DeviceDesire; - - // This is the power state we desire currently. - IOPMPowerStateIndex DesiredPowerState; - - // This is what our parent thinks our need is. - IOPMPowerFlags PreviousRequestPowerFlags; - - // Cache result from getName(), used in logging. - const char * Name; - - // Number of power states in the power array. - IOPMPowerStateIndex NumberOfPowerStates; - - // Power state array. - IOPMPSEntry * PowerStates; - - // The controlling driver. - IOService * ControllingDriver; - - // Our current power state. - IOPMPowerStateIndex CurrentPowerState; - - // Logical OR of power flags for each power domain parent. - IOPMPowerFlags ParentsCurrentPowerFlags; - - // The highest power state we can achieve in current power domain. - IOPMPowerStateIndex MaxPowerState; - - // Logical OR of all output power character flags in the array. - IOPMPowerFlags OutputPowerCharacterFlags; - - // OSArray which manages responses from notified apps and clients. - OSArray * ResponseArray; - OSArray * NotifyClientArray; - - // Used to uniquely identify power management notification to apps and clients. - UInt16 SerialNumber; - - // Used to communicate desired function to tellClientsWithResponse(). - // This is used because it avoids changing the signatures of the affected virtual methods. - int OutOfBandParameter; - - AbsoluteTime DriverCallStartTime; - IOPMPowerFlags CurrentCapabilityFlags; - unsigned long CurrentPowerConsumption; - IOPMPowerStateIndex TempClampPowerState; - OSArray * NotifyChildArray; - OSDictionary * PowerClients; - thread_call_t DriverCallEntry; - void * DriverCallParamPtr; - IOItemCount DriverCallParamCount; - IOItemCount DriverCallParamSlots; - uint32_t DriverCallReason; - uint32_t OutOfBandMessage; - uint32_t TempClampCount; - uint32_t OverrideMaxPowerState; - uint32_t DeviceUsablePowerState; - - // Protected by ActivityLock - BEGIN - int ActivityTicklePowerState; - int AdvisoryTicklePowerState; - uint32_t ActivityTickleCount; - uint32_t DeviceWasActive : 1; - uint32_t AdvisoryTickled : 1; - // Protected by ActivityLock - END - - uint32_t WaitReason; - uint32_t SavedMachineState; - uint32_t RootDomainState; - - // Protected by PMLock - BEGIN - struct { - uint32_t PMStop : 1; - uint32_t PMDriverCallWait : 1; - } LockedFlags; - - queue_head_t PMDriverCallQueue; - OSSet * InsertInterestSet; - OSSet * RemoveInterestSet; - // Protected by PMLock - END +// PM state lock. + IOLock * PMLock; + + unsigned int InitialPowerChange :1; + unsigned int InitialSetPowerState :1; + unsigned int DeviceOverrideEnabled :1; + unsigned int DoNotPowerDown :1; + unsigned int ParentsKnowState :1; + unsigned int StrictTreeOrder :1; + unsigned int IdleTimerStopped :1; + unsigned int AdjustPowerScheduled :1; + + unsigned int IsPreChange :1; + unsigned int DriverCallBusy :1; + unsigned int PCDFunctionOverride :1; + unsigned int IdleTimerIgnored :1; + unsigned int HasAdvisoryDesire :1; + unsigned int AdvisoryTickleUsed :1; + unsigned int ResetPowerStateOnWake :1; + +// Time of last device activity. + AbsoluteTime DeviceActiveTimestamp; + AbsoluteTime MaxPowerStateEntryTime; + AbsoluteTime MaxPowerStateExitTime; + +// Used to protect activity flag. + IOLock * ActivityLock; + +// Idle timer's period in seconds. + int IdleTimerPeriod; + int NextIdleTimerPeriod; + IOPMPowerStateIndex IdleTimerMinPowerState; + AbsoluteTime IdleTimerStartTime; + +// Power state desired by a subclassed device object. + IOPMPowerStateIndex DeviceDesire; + +// This is the power state we desire currently. + IOPMPowerStateIndex DesiredPowerState; + +// This is what our parent thinks our need is. + IOPMPowerFlags PreviousRequestPowerFlags; + +// Cache result from getName(), used in logging. + const char * Name; + +// Number of power states in the power array. + IOPMPowerStateIndex NumberOfPowerStates; + +// Ordered highest power state in the power array. + IOPMPowerStateIndex HighestPowerState; + +// Power state array. + IOPMPSEntry * PowerStates; + +// The controlling driver. + IOService * ControllingDriver; + +// Our current power state. + IOPMPowerStateIndex CurrentPowerState; + +// Logical OR of power flags for each power domain parent. + IOPMPowerFlags ParentsCurrentPowerFlags; + +// The highest power state we can achieve in current power domain. + IOPMPowerStateIndex MaxPowerState; + +// Logical OR of all output power flags in the power state array. + IOPMPowerFlags MergedOutputPowerFlags; + +// OSArray which manages responses from notified apps and clients. + OSArray * ResponseArray; + OSArray * NotifyClientArray; + +// Used to uniquely identify power management notification to apps and clients. + uint16_t SerialNumber; + +// Used to communicate desired function to tellClientsWithResponse(). +// This is used because it avoids changing the signatures of the affected virtual methods. + int OutOfBandParameter; + + AbsoluteTime DriverCallStartTime; + IOPMPowerFlags CurrentCapabilityFlags; + unsigned long CurrentPowerConsumption; + IOPMPowerStateIndex TempClampPowerState; + OSArray * NotifyChildArray; + OSDictionary * PowerClients; + thread_call_t DriverCallEntry; + void * DriverCallParamPtr; + IOItemCount DriverCallParamCount; + IOItemCount DriverCallParamSlots; + uint32_t DriverCallReason; + uint32_t OutOfBandMessage; + uint32_t TempClampCount; + IOPMPowerStateIndex OverrideMaxPowerState; + IOPMPowerStateIndex DeviceUsablePowerState; + +// Protected by ActivityLock - BEGIN + IOPMPowerStateIndex ActivityTicklePowerState; + IOPMPowerStateIndex AdvisoryTicklePowerState; + uint32_t ActivityTickleCount; + uint32_t DeviceWasActive : 1; + uint32_t AdvisoryTickled : 1; +// Protected by ActivityLock - END + + uint32_t WaitReason; + uint32_t SavedMachineState; + +// Protected by PMLock - BEGIN + struct { + uint32_t PMStop : 1; + uint32_t PMDriverCallWait : 1; + } LockedFlags; + + queue_head_t PMDriverCallQueue; + OSSet * InsertInterestSet; + OSSet * RemoveInterestSet; + +// IOReporter Data + uint32_t ReportClientCnt; + void * ReportBuf; +// Protected by PMLock - END #if PM_VARS_SUPPORT - IOPMprot * PMVars; + IOPMprot * PMVars; #endif - IOPMActions PMActions; + IOPMActions PMActions; - // Serialize IOServicePM state for debug output. - IOReturn gatedSerialize( OSSerialize * s ); - virtual bool serialize( OSSerialize * s ) const; +// Serialize IOServicePM state for debug output. + IOReturn gatedSerialize( OSSerialize * s ) const; + virtual bool serialize( OSSerialize * s ) const APPLE_KEXT_OVERRIDE; + +// PM log and trace + void pmPrint( uint32_t event, uintptr_t param1, uintptr_t param2 ) const; + void pmTrace( uint32_t event, uint32_t eventFunc, uintptr_t param1, uintptr_t param2 ) const; }; #define fOwner pwrMgt->Owner @@ -356,7 +377,13 @@ private: #define fAckTimer pwrMgt->AckTimer #define fSettleTimer pwrMgt->SettleTimer #define fIdleTimer pwrMgt->IdleTimer +#define fWatchdogTimer pwrMgt->WatchdogTimer +#define fWatchdogDeadline pwrMgt->WatchdogDeadline +#define fWatchdogLock pwrMgt->WatchdogLock +#define fBlockedArray pwrMgt->BlockedArray +#define fPendingResponseDeadline pwrMgt->PendingResponseDeadline #define fSettleTimeUS pwrMgt->SettleTimeUS +#define fIdleTimerGeneration pwrMgt->IdleTimerGeneration #define fHeadNoteChangeFlags pwrMgt->HeadNoteChangeFlags #define fHeadNotePowerState pwrMgt->HeadNotePowerState #define fHeadNotePowerArrayEntry pwrMgt->HeadNotePowerArrayEntry @@ -380,22 +407,27 @@ private: #define fIdleTimerIgnored pwrMgt->IdleTimerIgnored #define fHasAdvisoryDesire pwrMgt->HasAdvisoryDesire #define fAdvisoryTickleUsed pwrMgt->AdvisoryTickleUsed +#define fResetPowerStateOnWake pwrMgt->ResetPowerStateOnWake #define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp +#define fMaxPowerStateEntryTime pwrMgt->MaxPowerStateEntryTime +#define fMaxPowerStateExitTime pwrMgt->MaxPowerStateExitTime #define fActivityLock pwrMgt->ActivityLock #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod #define fIdleTimerMinPowerState pwrMgt->IdleTimerMinPowerState +#define fNextIdleTimerPeriod pwrMgt->NextIdleTimerPeriod #define fIdleTimerStartTime pwrMgt->IdleTimerStartTime #define fDeviceDesire pwrMgt->DeviceDesire #define fDesiredPowerState pwrMgt->DesiredPowerState #define fPreviousRequestPowerFlags pwrMgt->PreviousRequestPowerFlags #define fName pwrMgt->Name #define fNumberOfPowerStates pwrMgt->NumberOfPowerStates +#define fHighestPowerState pwrMgt->HighestPowerState #define fPowerStates pwrMgt->PowerStates #define fControllingDriver pwrMgt->ControllingDriver #define fCurrentPowerState pwrMgt->CurrentPowerState #define fParentsCurrentPowerFlags pwrMgt->ParentsCurrentPowerFlags #define fMaxPowerState pwrMgt->MaxPowerState -#define fOutputPowerCharacterFlags pwrMgt->OutputPowerCharacterFlags +#define fMergedOutputPowerFlags pwrMgt->MergedOutputPowerFlags #define fResponseArray pwrMgt->ResponseArray #define fNotifyClientArray pwrMgt->NotifyClientArray #define fSerialNumber pwrMgt->SerialNumber @@ -422,33 +454,50 @@ private: #define fAdvisoryTickled pwrMgt->AdvisoryTickled #define fWaitReason pwrMgt->WaitReason #define fSavedMachineState pwrMgt->SavedMachineState -#define fRootDomainState pwrMgt->RootDomainState #define fLockedFlags pwrMgt->LockedFlags #define fPMDriverCallQueue pwrMgt->PMDriverCallQueue #define fInsertInterestSet pwrMgt->InsertInterestSet #define fRemoveInterestSet pwrMgt->RemoveInterestSet +#define fReportClientCnt pwrMgt->ReportClientCnt +#define fReportBuf pwrMgt->ReportBuf #define fPMVars pwrMgt->PMVars #define fPMActions pwrMgt->PMActions +#define StateOrder(state) (((state) < fNumberOfPowerStates) \ + ? pwrMgt->PowerStates[(state)].stateOrder \ + : (state)) +#define StateMax(a, b) (StateOrder((a)) < StateOrder((b)) ? (b) : (a)) +#define StateMin(a, b) (StateOrder((a)) < StateOrder((b)) ? (a) : (b)) + +#define kPowerStateZero (0) + /* -When an IOService is waiting for acknowledgement to a power change -notification from an interested driver or the controlling driver, -the ack timer is ticking every tenth of a second. -(100000000 nanoseconds are one tenth of a second). -*/ + * When an IOService is waiting for acknowledgement to a power change + * notification from an interested driver or the controlling driver, + * the ack timer is ticking every tenth of a second. + * (100000000 nanoseconds are one tenth of a second). + */ #define ACK_TIMER_PERIOD 100000000 +#if defined(__i386__) || defined(__x86_64__) +#define WATCHDOG_SLEEP_TIMEOUT (180) // 180 secs +#define WATCHDOG_WAKE_TIMEOUT (180) // 180 secs +#else +#define WATCHDOG_SLEEP_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) +#define WATCHDOG_WAKE_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) +#endif + // Max wait time in microseconds for kernel priority and capability clients // with async message handlers to acknowledge. -// +// #define kPriorityClientMaxWait (90 * 1000 * 1000) #define kCapabilityClientMaxWait (240 * 1000 * 1000) // Attributes describing a power state change. // See IOPMPowerChangeFlags data type. // -#define kIOPMParentInitiated 0x0001 // this power change initiated by our parent -#define kIOPMSelfInitiated 0x0002 // this power change initiated by this device +#define kIOPMParentInitiated 0x0001 // power change initiated by our parent +#define kIOPMSelfInitiated 0x0002 // power change initiated by this device #define kIOPMNotDone 0x0004 // we couldn't make this change #define kIOPMDomainWillChange 0x0008 // change started by PowerDomainWillChangeTo #define kIOPMDomainDidChange 0x0010 // change started by PowerDomainDidChangeTo @@ -460,147 +509,214 @@ the ack timer is ticking every tenth of a second. #define kIOPMSyncTellPowerDown 0x0400 // send the ask/will power off messages #define kIOPMSyncCancelPowerDown 0x0800 // sleep cancel for maintenance wake #define kIOPMInitialPowerChange 0x1000 // set for initial power change +#define kIOPMRootChangeUp 0x2000 // Root power domain change up +#define kIOPMRootChangeDown 0x4000 // Root power domain change down +#define kIOPMExpireIdleTimer 0x8000 // Accelerate idle timer expiration + +#define kIOPMRootBroadcastFlags (kIOPMSynchronize | \ + kIOPMRootChangeUp | kIOPMRootChangeDown) + +// Activity tickle request flags +#define kTickleTypePowerDrop 0x01 +#define kTickleTypePowerRise 0x02 +#define kTickleTypeActivity 0x04 +#define kTickleTypeAdvisory 0x08 enum { - kDriverCallInformPreChange, - kDriverCallInformPostChange, - kDriverCallSetPowerState + kDriverCallInformPreChange, + kDriverCallInformPostChange, + kDriverCallSetPowerState, + kRootDomainInformPreChange }; struct DriverCallParam { - OSObject * Target; - IOReturn Result; + OSObject * Target; + IOReturn Result; }; // values of OutOfBandParameter enum { - kNotifyApps, - kNotifyPriority, - kNotifyCapabilityChangeApps, - kNotifyCapabilityChangePriority + kNotifyApps, + kNotifyPriority, + kNotifyCapabilityChangeApps, + kNotifyCapabilityChangePriority }; typedef bool (*IOPMMessageFilter)( - void * target, void * object, void * arg1, void * arg2, void * arg3 ); + void * target, void * object, void * arg1, void * arg2, void * arg3 ); // used for applyToInterested struct IOPMInterestContext { - OSArray * responseArray; - OSArray * notifyClients; - uint16_t serialNumber; - uint8_t isPreChange; - uint8_t enableTracing; - uint32_t maxTimeRequested; - uint32_t messageType; - uint32_t notifyType; - IOService * us; - IOPMPowerStateIndex stateNumber; - IOPMPowerFlags stateFlags; - IOPMPowerChangeFlags changeFlags; - const char * errorLog; - IOPMMessageFilter messageFilter; + OSArray * responseArray; + OSArray * notifyClients; + uint16_t serialNumber; + uint8_t isPreChange; + uint8_t enableTracing; + uint32_t maxTimeRequested; + uint32_t messageType; + uint32_t notifyType; + uint32_t skippedInDark; + uint32_t notSkippedInDark; + IOService * us; + IOPMPowerStateIndex stateNumber; + IOPMPowerFlags stateFlags; + IOPMPowerChangeFlags changeFlags; + const char * errorLog; + IOPMMessageFilter messageFilter; }; // assertPMDriverCall() options enum { - kIOPMADC_NoInactiveCheck = 1 + kIOPMDriverCallNoInactiveCheck = 1 +}; + +// assertPMDriverCall() method +enum { + kIOPMDriverCallMethodUnknown = 0, + kIOPMDriverCallMethodSetPowerState = 1, + kIOPMDriverCallMethodWillChange = 2, + kIOPMDriverCallMethodDidChange = 3, + kIOPMDriverCallMethodChangeDone = 4, + kIOPMDriverCallMethodSetAggressive = 5 }; //****************************************************************************** // PM Statistics & Diagnostics //****************************************************************************** -extern const OSSymbol *gIOPMStatsApplicationResponseTimedOut; -extern const OSSymbol *gIOPMStatsApplicationResponseCancel; -extern const OSSymbol *gIOPMStatsApplicationResponseSlow; +extern OSPtr gIOPMStatsResponseTimedOut; +extern OSPtr gIOPMStatsResponseCancel; +extern OSPtr gIOPMStatsResponseSlow; +extern OSPtr gIOPMStatsResponsePrompt; +extern OSPtr gIOPMStatsDriverPSChangeSlow; //****************************************************************************** // IOPMRequest //****************************************************************************** -typedef void (*IOPMCompletionAction)(void * target, void * param, IOReturn status); - class IOPMRequest : public IOCommand { - OSDeclareDefaultStructors( IOPMRequest ) + OSDeclareDefaultStructors( IOPMRequest ); protected: - IOService * fTarget; // request target - IOPMRequest * fRequestNext; // the next request in the chain - IOPMRequest * fRequestRoot; // the root request in the issue tree - IOItemCount fWorkWaitCount; // execution blocked if non-zero - IOItemCount fFreeWaitCount; // completion blocked if non-zero - uint32_t fType; // request type - - IOPMCompletionAction fCompletionAction; - void * fCompletionTarget; - void * fCompletionParam; - IOReturn fCompletionStatus; + IOService * fTarget; // request target + IOPMRequest * fRequestNext; // the next request in the chain + IOPMRequest * fRequestRoot; // the root request in the call tree + uint32_t fWorkWaitCount; // execution blocked if non-zero + uint32_t fFreeWaitCount; // completion blocked if non-zero + uint64_t fTimestamp; // MCTU + uint32_t fRequestType; // request type + bool fIsQuiesceBlocker; + + IOPMCompletionAction fCompletionAction; + void * fCompletionTarget; + void * fCompletionParam; public: - void * fArg0; - void * fArg1; - void * fArg2; - - inline bool isWorkBlocked( void ) const - { - return (fWorkWaitCount != 0); - } - - inline bool isFreeBlocked( void ) const - { - return (fFreeWaitCount != 0); - } - - inline IOPMRequest * getNextRequest( void ) const - { - return fRequestNext; - } - - inline IOPMRequest * getRootRequest( void ) const - { - if (fRequestRoot) return fRequestRoot; - if (fCompletionAction) return (IOPMRequest *) this; - return 0; - } - - inline uint32_t getType( void ) const - { - return fType; - } - - inline bool isReplyType( void ) const - { - return (fType > kIOPMRequestTypeReplyStart); - } - - inline IOService * getTarget( void ) const - { - return fTarget; - } - - inline bool isCompletionInstalled( void ) - { - return (fCompletionAction != 0); - } - - inline void installCompletionAction( - IOPMCompletionAction action, - void * target, - void * param ) - { - fCompletionAction = action; - fCompletionTarget = target; - fCompletionParam = param; - } - - static IOPMRequest * create( void ); - bool init( IOService * owner, IOOptionBits type ); - void reset( void ); - bool attachNextRequest( IOPMRequest * next ); - bool detachNextRequest( void ); - bool attachRootRequest( IOPMRequest * root ); - bool detachRootRequest( void ); + uint32_t fTag; + void * fArg0; + void * fArg1; + void * fArg2; + + inline bool + isWorkBlocked( void ) const + { + return fWorkWaitCount != 0; + } + + inline bool + isFreeBlocked( void ) const + { + return fFreeWaitCount != 0; + } + + inline IOPMRequest * + getNextRequest( void ) const + { + return fRequestNext; + } + + inline IOPMRequest * + getRootRequest( void ) const + { + if (fRequestRoot) { + return fRequestRoot; + } +#if NOT_READY + if (fCompletionAction) { + return (IOPMRequest *) this; + } +#endif + return NULL; + } + + inline uint32_t + getType( void ) const + { + return fRequestType; + } + + inline uint32_t + getTag( void ) const + { + return fTag; + } + + inline bool + isReplyType( void ) const + { + return fRequestType > kIOPMRequestTypeReplyStart; + } + + inline IOService * + getTarget( void ) const + { + return fTarget; + } + + inline bool + isQuiesceBlocker( void ) const + { + return fIsQuiesceBlocker; + } + + inline bool + isQuiesceType( void ) const + { + return (kIOPMRequestTypeQuiescePowerTree == fRequestType) && + (fCompletionAction != NULL) && (fCompletionTarget != NULL); + } + + inline void + installCompletionAction( + void * target, + IOPMCompletionAction action, + void * param ) + { + fCompletionTarget = target; + fCompletionAction = action; + fCompletionParam = param; + } + + inline void + setTimestamp( uint64_t time ) + { + fTimestamp = time; + } + + inline uint64_t + getTimestamp( void ) const + { + return fTimestamp; + } + + static IOPMRequest * create( void ); + bool init( IOService * owner, IOOptionBits type ); + void reset( void ); + bool attachNextRequest( IOPMRequest * next ); + bool detachNextRequest( void ); + bool attachRootRequest( IOPMRequest * root ); + bool detachRootRequest( void ); }; //****************************************************************************** @@ -609,23 +725,25 @@ public: class IOPMRequestQueue : public IOEventSource { - OSDeclareDefaultStructors( IOPMRequestQueue ) + OSDeclareDefaultStructors( IOPMRequestQueue ); public: - typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); + typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); protected: - queue_head_t fQueue; - IOLock * fLock; + queue_head_t fQueue; + IOLock * fLock; - virtual bool checkForWork( void ); - virtual void free( void ); - virtual bool init( IOService * inOwner, Action inAction ); + enum { kMaxDequeueCount = 256 }; + + virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; + virtual void free( void ) APPLE_KEXT_OVERRIDE; + virtual bool init( IOService * inOwner, Action inAction ); public: - static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); - void queuePMRequest( IOPMRequest * request ); - void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); + static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); + void queuePMRequest( LIBKERN_CONSUMED IOPMRequest * request ); + void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); }; //****************************************************************************** @@ -636,35 +754,40 @@ public: class IOPMWorkQueue : public IOEventSource { - OSDeclareDefaultStructors( IOPMWorkQueue ) + OSDeclareDefaultStructors( IOPMWorkQueue ); public: - typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * ); + typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * ); #if WORK_QUEUE_STATS - uint64_t fStatCheckForWork; - uint64_t fStatScanEntries; - uint64_t fStatQueueEmpty; - uint64_t fStatNoWorkDone; + uint64_t fStatCheckForWork; + uint64_t fStatScanEntries; + uint64_t fStatQueueEmpty; + uint64_t fStatNoWorkDone; #endif protected: - queue_head_t fWorkQueue; - Action fWorkAction; - Action fRetireAction; - uint32_t fQueueLength; - uint32_t fConsumerCount; - volatile uint32_t fProducerCount; - - virtual bool checkForWork( void ); - virtual bool init( IOService * inOwner, Action work, Action retire ); - bool checkRequestQueue( queue_head_t * queue, bool * empty ); + queue_head_t fWorkQueue; + Action fInvokeAction; + Action fRetireAction; + uint32_t fQueueLength; + uint32_t fConsumerCount; + volatile uint32_t fProducerCount; + IOPMRequest * fQuiesceRequest; + AbsoluteTime fQuiesceStartTime; + AbsoluteTime fQuiesceFinishTime; + + virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; + virtual bool init( IOService * inOwner, Action invoke, Action retire ); + bool checkRequestQueue( queue_head_t * queue, bool * empty ); public: - static IOPMWorkQueue * create( IOService * inOwner, Action work, Action retire ); - bool queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt ); - void signalWorkAvailable( void ); - void incrementProducerCount( void ); + static IOPMWorkQueue * create( IOService * inOwner, Action invoke, Action retire ); + bool queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt ); + void signalWorkAvailable( void ); + void incrementProducerCount( void ); + void attachQuiesceRequest( IOPMRequest * quiesceRequest ); + void finishQuiesceRequest( IOPMRequest * quiesceRequest ); }; //****************************************************************************** @@ -673,20 +796,20 @@ public: class IOPMCompletionQueue : public IOEventSource { - OSDeclareDefaultStructors( IOPMCompletionQueue ) + OSDeclareDefaultStructors( IOPMCompletionQueue ); public: - typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); + typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); protected: - queue_head_t fQueue; + queue_head_t fQueue; - virtual bool checkForWork( void ); - virtual bool init( IOService * inOwner, Action inAction ); + virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; + virtual bool init( IOService * inOwner, Action inAction ); public: - static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); - bool queuePMRequest( IOPMRequest * request ); + static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); + bool queuePMRequest( IOPMRequest * request ); }; #endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */