]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
xnu-4903.270.47.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
1 /*
2 * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #include <libkern/c++/OSKext.h>
29 #include <libkern/c++/OSMetaClass.h>
30 #include <libkern/OSAtomic.h>
31 #include <libkern/OSDebug.h>
32 #include <IOKit/IOWorkLoop.h>
33 #include <IOKit/IOCommandGate.h>
34 #include <IOKit/IOPlatformExpert.h>
35 #include <IOKit/IOCPU.h>
36 #include <IOKit/IOKitDebug.h>
37 #include <IOKit/IOTimeStamp.h>
38 #include <IOKit/pwr_mgt/IOPMlog.h>
39 #include <IOKit/pwr_mgt/RootDomain.h>
40 #include <IOKit/pwr_mgt/IOPMPrivate.h>
41 #include <IOKit/IODeviceTreeSupport.h>
42 #include <IOKit/IOMessage.h>
43 #include <IOKit/IOReturn.h>
44 #include <IOKit/IONVRAM.h>
45 #include "RootDomainUserClient.h"
46 #include "IOKit/pwr_mgt/IOPowerConnection.h"
47 #include "IOPMPowerStateQueue.h"
48 #include <IOKit/IOCatalogue.h>
49 #include <IOKit/IOReportMacros.h>
50 #include "IOKitKernelInternal.h"
51 #if HIBERNATION
52 #include <IOKit/IOHibernatePrivate.h>
53 #endif
54 #include <console/video_console.h>
55 #include <sys/syslog.h>
56 #include <sys/sysctl.h>
57 #include <sys/vnode.h>
58 #include <sys/vnode_internal.h>
59 #include <sys/fcntl.h>
60 #include <os/log.h>
61 #include <pexpert/protos.h>
62 #include <AssertMacros.h>
63
64 #include <sys/time.h>
65 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
66 #include "IOServicePMPrivate.h"
67
68 #include <libkern/zlib.h>
69
70 __BEGIN_DECLS
71 #include <mach/shared_region.h>
72 #include <kern/clock.h>
73 __END_DECLS
74
75 #if defined(__i386__) || defined(__x86_64__)
76 __BEGIN_DECLS
77 #include "IOPMrootDomainInternal.h"
78 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
79 __END_DECLS
80 #endif
81
82 #define kIOPMrootDomainClass "IOPMrootDomain"
83 #define LOG_PREFIX "PMRD: "
84
85
86 #define MSG(x...) \
87 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
88
89 #define LOG(x...) \
90 do { kprintf(LOG_PREFIX x); } while (false)
91
92 #if DEVELOPMENT
93 #define DLOG(x...) do { \
94 if (kIOLogPMRootDomain & gIOKitDebug) \
95 kprintf(LOG_PREFIX x); \
96 else \
97 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
98 } while (false)
99 #else
100 #define DLOG(x...) do { \
101 if (kIOLogPMRootDomain & gIOKitDebug) \
102 kprintf(LOG_PREFIX x); \
103 } while (false)
104 #endif
105
106 #define DMSG(x...) do { \
107 if (kIOLogPMRootDomain & gIOKitDebug) { \
108 kprintf(LOG_PREFIX x); \
109 } \
110 } while (false)
111
112
113 #define _LOG(x...)
114
115 #define CHECK_THREAD_CONTEXT
116 #ifdef CHECK_THREAD_CONTEXT
117 static IOWorkLoop * gIOPMWorkLoop = 0;
118 #define ASSERT_GATED() \
119 do { \
120 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
121 panic("RootDomain: not inside PM gate"); \
122 } \
123 } while(false)
124 #else
125 #define ASSERT_GATED()
126 #endif /* CHECK_THREAD_CONTEXT */
127
128 #define CAP_LOSS(c) \
129 (((_pendingCapability & (c)) == 0) && \
130 ((_currentCapability & (c)) != 0))
131
132 #define CAP_GAIN(c) \
133 (((_currentCapability & (c)) == 0) && \
134 ((_pendingCapability & (c)) != 0))
135
136 #define CAP_CHANGE(c) \
137 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
138
139 #define CAP_CURRENT(c) \
140 ((_currentCapability & (c)) != 0)
141
142 #define CAP_HIGHEST(c) \
143 ((_highestCapability & (c)) != 0)
144
145 #if defined(__i386__) || defined(__x86_64__)
146 #define DARK_TO_FULL_EVALUATE_CLAMSHELL 1
147 #endif
148
149 // Event types for IOPMPowerStateQueue::submitPowerEvent()
150 enum {
151 kPowerEventFeatureChanged = 1, // 1
152 kPowerEventReceivedPowerNotification, // 2
153 kPowerEventSystemBootCompleted, // 3
154 kPowerEventSystemShutdown, // 4
155 kPowerEventUserDisabledSleep, // 5
156 kPowerEventRegisterSystemCapabilityClient, // 6
157 kPowerEventRegisterKernelCapabilityClient, // 7
158 kPowerEventPolicyStimulus, // 8
159 kPowerEventAssertionCreate, // 9
160 kPowerEventAssertionRelease, // 10
161 kPowerEventAssertionSetLevel, // 11
162 kPowerEventQueueSleepWakeUUID, // 12
163 kPowerEventPublishSleepWakeUUID, // 13
164 kPowerEventSetDisplayPowerOn // 14
165 };
166
167 // For evaluatePolicy()
168 // List of stimuli that affects the root domain policy.
169 enum {
170 kStimulusDisplayWranglerSleep, // 0
171 kStimulusDisplayWranglerWake, // 1
172 kStimulusAggressivenessChanged, // 2
173 kStimulusDemandSystemSleep, // 3
174 kStimulusAllowSystemSleepChanged, // 4
175 kStimulusDarkWakeActivityTickle, // 5
176 kStimulusDarkWakeEntry, // 6
177 kStimulusDarkWakeReentry, // 7
178 kStimulusDarkWakeEvaluate, // 8
179 kStimulusNoIdleSleepPreventers, // 9
180 kStimulusEnterUserActiveState, // 10
181 kStimulusLeaveUserActiveState // 11
182 };
183
184 extern "C" {
185 IOReturn OSKextSystemSleepOrWake( UInt32 );
186 }
187 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
188 extern "C" addr64_t kvtophys(vm_offset_t va);
189 extern "C" boolean_t kdp_has_polled_corefile();
190
191 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
192 static void notifySystemShutdown( IOService * root, uint32_t messageType );
193 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
194 static void pmEventTimeStamp(uint64_t *recordTS);
195
196 // "IOPMSetSleepSupported" callPlatformFunction name
197 static const OSSymbol *sleepSupportedPEFunction = NULL;
198 static const OSSymbol *sleepMessagePEFunction = NULL;
199
200 static const OSSymbol * gIOPMPSExternalConnectedKey;
201 static const OSSymbol * gIOPMPSExternalChargeCapableKey;
202 static const OSSymbol * gIOPMPSBatteryInstalledKey;
203 static const OSSymbol * gIOPMPSIsChargingKey;
204 static const OSSymbol * gIOPMPSAtWarnLevelKey;
205 static const OSSymbol * gIOPMPSAtCriticalLevelKey;
206 static const OSSymbol * gIOPMPSCurrentCapacityKey;
207 static const OSSymbol * gIOPMPSMaxCapacityKey;
208 static const OSSymbol * gIOPMPSDesignCapacityKey;
209 static const OSSymbol * gIOPMPSTimeRemainingKey;
210 static const OSSymbol * gIOPMPSAmperageKey;
211 static const OSSymbol * gIOPMPSVoltageKey;
212 static const OSSymbol * gIOPMPSCycleCountKey;
213 static const OSSymbol * gIOPMPSMaxErrKey;
214 static const OSSymbol * gIOPMPSAdapterInfoKey;
215 static const OSSymbol * gIOPMPSLocationKey;
216 static const OSSymbol * gIOPMPSErrorConditionKey;
217 static const OSSymbol * gIOPMPSManufacturerKey;
218 static const OSSymbol * gIOPMPSManufactureDateKey;
219 static const OSSymbol * gIOPMPSModelKey;
220 static const OSSymbol * gIOPMPSSerialKey;
221 static const OSSymbol * gIOPMPSLegacyBatteryInfoKey;
222 static const OSSymbol * gIOPMPSBatteryHealthKey;
223 static const OSSymbol * gIOPMPSHealthConfidenceKey;
224 static const OSSymbol * gIOPMPSCapacityEstimatedKey;
225 static const OSSymbol * gIOPMPSBatteryChargeStatusKey;
226 static const OSSymbol * gIOPMPSBatteryTemperatureKey;
227 static const OSSymbol * gIOPMPSAdapterDetailsKey;
228 static const OSSymbol * gIOPMPSChargerConfigurationKey;
229 static const OSSymbol * gIOPMPSAdapterDetailsIDKey;
230 static const OSSymbol * gIOPMPSAdapterDetailsWattsKey;
231 static const OSSymbol * gIOPMPSAdapterDetailsRevisionKey;
232 static const OSSymbol * gIOPMPSAdapterDetailsSerialNumberKey;
233 static const OSSymbol * gIOPMPSAdapterDetailsFamilyKey;
234 static const OSSymbol * gIOPMPSAdapterDetailsAmperageKey;
235 static const OSSymbol * gIOPMPSAdapterDetailsDescriptionKey;
236 static const OSSymbol * gIOPMPSAdapterDetailsPMUConfigurationKey;
237 static const OSSymbol * gIOPMPSAdapterDetailsSourceIDKey;
238 static const OSSymbol * gIOPMPSAdapterDetailsErrorFlagsKey;
239 static const OSSymbol * gIOPMPSAdapterDetailsSharedSourceKey;
240 static const OSSymbol * gIOPMPSAdapterDetailsCloakedKey;
241 static const OSSymbol * gIOPMPSInvalidWakeSecondsKey;
242 static const OSSymbol * gIOPMPSPostChargeWaitSecondsKey;
243 static const OSSymbol * gIOPMPSPostDishargeWaitSecondsKey;
244
245 #define kIOSleepSupportedKey "IOSleepSupported"
246 #define kIOPMSystemCapabilitiesKey "System Capabilities"
247
248 #define kIORequestWranglerIdleKey "IORequestIdle"
249 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
250
251 #define kIOSleepWakeFailureString "SleepWakeFailureString"
252 #define kIOOSWatchdogFailureString "OSWatchdogFailureString"
253 #define kIOEFIBootRomFailureKey "wake-failure"
254
255 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
256 | kIOPMSupportedOnBatt \
257 | kIOPMSupportedOnUPS)
258
259 #define kLocalEvalClamshellCommand (1 << 15)
260 #define kIdleSleepRetryInterval (3 * 60)
261
262 enum {
263 kWranglerPowerStateMin = 0,
264 kWranglerPowerStateSleep = 2,
265 kWranglerPowerStateDim = 3,
266 kWranglerPowerStateMax = 4
267 };
268
269 enum {
270 OFF_STATE = 0,
271 RESTART_STATE = 1,
272 SLEEP_STATE = 2,
273 ON_STATE = 3,
274 NUM_POWER_STATES
275 };
276
277 #define ON_POWER kIOPMPowerOn
278 #define RESTART_POWER kIOPMRestart
279 #define SLEEP_POWER kIOPMAuxPowerOn
280
281 static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
282 {
283 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
284 {1, kIOPMRestartCapability, kIOPMRestart, RESTART_POWER, 0, 0, 0, 0, 0, 0, 0, 0},
285 {1, kIOPMSleepCapability, kIOPMSleep, SLEEP_POWER, 0, 0, 0, 0, 0, 0, 0, 0},
286 {1, kIOPMPowerOn, kIOPMPowerOn, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0}
287 };
288
289 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
290 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
291 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
292 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
293 #define kIOPMRootDomainWakeTypeUser "User"
294 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
295 #define kIOPMRootDomainWakeTypeNetwork "Network"
296 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
297 #define kIOPMRootDomainWakeTypeNotification "Notification"
298 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
299
300 // Special interest that entitles the interested client from receiving
301 // all system messages. Only used by powerd.
302 //
303 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
304
305 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
306 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
307
308 /*
309 * Aggressiveness
310 */
311 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
312 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
313
314 #define kAggressivesMinValue 1
315
316 enum {
317 kAggressivesStateBusy = 0x01,
318 kAggressivesStateQuickSpindown = 0x02
319 };
320
321 struct AggressivesRecord {
322 uint32_t flags;
323 uint32_t type;
324 uint32_t value;
325 };
326
327 struct AggressivesRequest {
328 queue_chain_t chain;
329 uint32_t options;
330 uint32_t dataType;
331 union {
332 IOService * service;
333 AggressivesRecord record;
334 } data;
335 };
336
337 enum {
338 kAggressivesRequestTypeService = 1,
339 kAggressivesRequestTypeRecord
340 };
341
342 enum {
343 kAggressivesOptionSynchronous = 0x00000001,
344 kAggressivesOptionQuickSpindownEnable = 0x00000100,
345 kAggressivesOptionQuickSpindownDisable = 0x00000200,
346 kAggressivesOptionQuickSpindownMask = 0x00000300
347 };
348
349 enum {
350 kAggressivesRecordFlagModified = 0x00000001,
351 kAggressivesRecordFlagMinValue = 0x00000002
352 };
353
354 // gDarkWakeFlags
355 enum {
356 kDarkWakeFlagHIDTickleEarly = 0x01,// hid tickle before gfx suppression
357 kDarkWakeFlagHIDTickleLate = 0x02,// hid tickle after gfx suppression
358 kDarkWakeFlagHIDTickleNone = 0x03,// hid tickle is not posted
359 kDarkWakeFlagHIDTickleMask = 0x03,
360 kDarkWakeFlagAlarmIsDark = 0x0100,
361 kDarkWakeFlagGraphicsPowerState1 = 0x0200,
362 kDarkWakeFlagAudioNotSuppressed = 0x0400
363 };
364
365 static IOPMrootDomain * gRootDomain;
366 static IONotifier * gSysPowerDownNotifier = 0;
367 static UInt32 gSleepOrShutdownPending = 0;
368 static UInt32 gWillShutdown = 0;
369 static UInt32 gPagingOff = 0;
370 static UInt32 gSleepWakeUUIDIsSet = false;
371 static uint32_t gAggressivesState = 0;
372 static uint32_t gHaltTimeMaxLog;
373 static uint32_t gHaltTimeMaxPanic;
374 IOLock * gHaltLogLock;
375 static char * gHaltLog;
376 enum { kHaltLogSize = 2048 };
377 static size_t gHaltLogPos;
378 static uint64_t gHaltStartTime;
379
380
381 uuid_string_t bootsessionuuid_string;
382
383 static uint32_t gDarkWakeFlags = kDarkWakeFlagHIDTickleNone;
384 static uint32_t gNoIdleFlag = 0;
385 static uint32_t gSwdPanic = 0;
386 static uint32_t gSwdSleepTimeout = 0;
387 static uint32_t gSwdWakeTimeout = 0;
388 static uint32_t gSwdSleepWakeTimeout = 0;
389 static PMStatsStruct gPMStats;
390
391
392 #if HIBERNATION
393 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = 0;
394 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = 0;
395 static void * gSleepPolicyTarget;
396 #endif
397
398 struct timeval gIOLastSleepTime;
399 struct timeval gIOLastWakeTime;
400
401 static char gWakeReasonString[128];
402 static bool gWakeReasonSysctlRegistered = false;
403 static AbsoluteTime gIOLastWakeAbsTime;
404 static AbsoluteTime gIOLastSleepAbsTime;
405 static AbsoluteTime gUserActiveAbsTime;
406 static AbsoluteTime gUserInactiveAbsTime;
407
408 #if defined(__i386__) || defined(__x86_64__)
409 static bool gSpinDumpBufferFull = false;
410 #endif
411
412 z_stream swd_zs;
413 vm_offset_t swd_zs_zmem;
414 //size_t swd_zs_zsize;
415 size_t swd_zs_zoffset;
416 #if defined(__i386__) || defined(__x86_64__)
417 IOCPU *currentShutdownTarget = NULL;
418 #endif
419
420 static unsigned int gPMHaltBusyCount;
421 static unsigned int gPMHaltIdleCount;
422 static int gPMHaltDepth;
423 static uint32_t gPMHaltMessageType;
424 static IOLock * gPMHaltLock = 0;
425 static OSArray * gPMHaltArray = 0;
426 static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
427 static bool gPMQuiesced;
428
429 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
430 #define kCPUUnknownIndex 9999999
431 enum {
432 kInformAC = 0,
433 kInformLid = 1,
434 kInformableCount = 2
435 };
436
437 const OSSymbol *gIOPMStatsResponseTimedOut;
438 const OSSymbol *gIOPMStatsResponseCancel;
439 const OSSymbol *gIOPMStatsResponseSlow;
440 const OSSymbol *gIOPMStatsResponsePrompt;
441 const OSSymbol *gIOPMStatsDriverPSChangeSlow;
442
443 #define kBadPMFeatureID 0
444
445 /*
446 * PMSettingHandle
447 * Opaque handle passed to clients of registerPMSettingController()
448 */
449 class PMSettingHandle : public OSObject
450 {
451 OSDeclareFinalStructors( PMSettingHandle )
452 friend class PMSettingObject;
453
454 private:
455 PMSettingObject *pmso;
456 void free(void) APPLE_KEXT_OVERRIDE;
457 };
458
459 /*
460 * PMSettingObject
461 * Internal object to track each PM setting controller
462 */
463 class PMSettingObject : public OSObject
464 {
465 OSDeclareFinalStructors( PMSettingObject )
466 friend class IOPMrootDomain;
467
468 private:
469 queue_head_t calloutQueue;
470 thread_t waitThread;
471 IOPMrootDomain *parent;
472 PMSettingHandle *pmsh;
473 IOPMSettingControllerCallback func;
474 OSObject *target;
475 uintptr_t refcon;
476 uint32_t *publishedFeatureID;
477 uint32_t settingCount;
478 bool disabled;
479
480 void free(void) APPLE_KEXT_OVERRIDE;
481
482 public:
483 static PMSettingObject *pmSettingObject(
484 IOPMrootDomain *parent_arg,
485 IOPMSettingControllerCallback handler_arg,
486 OSObject *target_arg,
487 uintptr_t refcon_arg,
488 uint32_t supportedPowerSources,
489 const OSSymbol *settings[],
490 OSObject **handle_obj);
491
492 void dispatchPMSetting(const OSSymbol *type, OSObject *object);
493 void clientHandleFreed(void);
494 };
495
496 struct PMSettingCallEntry {
497 queue_chain_t link;
498 thread_t thread;
499 };
500
501 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
502 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
503 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
504 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
505
506 /*
507 * PMTraceWorker
508 * Internal helper object for logging trace points to RTC
509 * IOPMrootDomain and only IOPMrootDomain should instantiate
510 * exactly one of these.
511 */
512
513 typedef void (*IOPMTracePointHandler)(
514 void * target, uint32_t code, uint32_t data );
515
516 class PMTraceWorker : public OSObject
517 {
518 OSDeclareDefaultStructors(PMTraceWorker)
519 public:
520 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
521
522 static PMTraceWorker *tracer( IOPMrootDomain * );
523 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
524 void tracePoint(uint8_t phase);
525 void traceDetail(uint32_t detail);
526 void traceComponentWakeProgress(uint32_t component, uint32_t data);
527 int recordTopLevelPCIDevice(IOService *);
528 void RTC_TRACE(void);
529 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
530
531 IOPMTracePointHandler tracePointHandler;
532 void * tracePointTarget;
533 uint64_t getPMStatusCode();
534 uint8_t getTracePhase();
535 uint32_t getTraceData();
536 private:
537 IOPMrootDomain *owner;
538 IOLock *pmTraceWorkerLock;
539 OSArray *pciDeviceBitMappings;
540
541 uint8_t addedToRegistry;
542 uint8_t tracePhase;
543 uint32_t traceData32;
544 uint8_t loginWindowData;
545 uint8_t coreDisplayData;
546 uint8_t coreGraphicsData;
547 };
548
549 /*
550 * PMAssertionsTracker
551 * Tracks kernel and user space PM assertions
552 */
553 class PMAssertionsTracker : public OSObject
554 {
555 OSDeclareFinalStructors(PMAssertionsTracker)
556 public:
557 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
558
559 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
560 IOReturn releaseAssertion(IOPMDriverAssertionID);
561 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
562 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
563
564 OSArray *copyAssertionsArray(void);
565 IOPMDriverAssertionType getActivatedAssertions(void);
566 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
567
568 IOReturn handleCreateAssertion(OSData *);
569 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
570 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
571 IOReturn handleSetUserAssertionLevels(void * arg0);
572 void publishProperties(void);
573
574 private:
575 typedef struct {
576 IOPMDriverAssertionID id;
577 IOPMDriverAssertionType assertionBits;
578 uint64_t createdTime;
579 uint64_t modifiedTime;
580 const OSSymbol *ownerString;
581 IOService *ownerService;
582 uint64_t registryEntryID;
583 IOPMDriverAssertionLevel level;
584 } PMAssertStruct;
585
586 uint32_t tabulateProducerCount;
587 uint32_t tabulateConsumerCount;
588
589 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
590 void tabulate(void);
591
592 IOPMrootDomain *owner;
593 OSArray *assertionsArray;
594 IOLock *assertionsArrayLock;
595 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
596 IOPMDriverAssertionType assertionsKernel;
597 IOPMDriverAssertionType assertionsUser;
598 IOPMDriverAssertionType assertionsCombined;
599 };
600
601 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
602
603 /*
604 * PMHaltWorker
605 * Internal helper object for Shutdown/Restart notifications.
606 */
607 #define kPMHaltMaxWorkers 8
608 #define kPMHaltTimeoutMS 100
609
610 class PMHaltWorker : public OSObject
611 {
612 OSDeclareFinalStructors( PMHaltWorker )
613
614 public:
615 IOService * service;// service being worked on
616 AbsoluteTime startTime; // time when work started
617 int depth; // work on nubs at this PM-tree depth
618 int visits; // number of nodes visited (debug)
619 IOLock * lock;
620 bool timeout;// service took too long
621
622 static PMHaltWorker * worker( void );
623 static void main( void * arg, wait_result_t waitResult );
624 static void work( PMHaltWorker * me );
625 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
626 virtual void free( void ) APPLE_KEXT_OVERRIDE;
627 };
628
629 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
630
631
632 #define super IOService
633 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
634
635 static void
636 IOPMRootDomainWillShutdown(void)
637 {
638 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
639 OSKext::willShutdown();
640 for (int i = 0; i < 100; i++) {
641 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
642 break;
643 }
644 IOSleep( 100 );
645 }
646 }
647 }
648
649 extern "C" IONotifier *
650 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
651 {
652 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref );
653 }
654
655 extern "C" IONotifier *
656 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
657 {
658 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref );
659 }
660
661 extern "C" IOReturn
662 acknowledgeSleepWakeNotification(void * PMrefcon)
663 {
664 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
665 }
666
667 extern "C" IOReturn
668 vetoSleepWakeNotification(void * PMrefcon)
669 {
670 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
671 }
672
673 extern "C" IOReturn
674 rootDomainRestart( void )
675 {
676 return gRootDomain->restartSystem();
677 }
678
679 extern "C" IOReturn
680 rootDomainShutdown( void )
681 {
682 return gRootDomain->shutdownSystem();
683 }
684
685 static void
686 halt_log_putc(char c)
687 {
688 if (gHaltLogPos >= (kHaltLogSize - 2)) {
689 return;
690 }
691 gHaltLog[gHaltLogPos++] = c;
692 }
693
694 extern "C" void
695 _doprnt_log(const char *fmt,
696 va_list *argp,
697 void (*putc)(char),
698 int radix);
699
700 static int
701 halt_log(const char *fmt, ...)
702 {
703 va_list listp;
704
705 va_start(listp, fmt);
706 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
707 va_end(listp);
708
709 return 0;
710 }
711
712 extern "C" void
713 halt_log_enter(const char * what, const void * pc, uint64_t time)
714 {
715 uint64_t nano, millis;
716
717 if (!gHaltLog) {
718 return;
719 }
720 absolutetime_to_nanoseconds(time, &nano);
721 millis = nano / NSEC_PER_MSEC;
722 if (millis < 100) {
723 return;
724 }
725
726 IOLockLock(gHaltLogLock);
727 if (pc) {
728 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
729 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
730 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
731 } else {
732 halt_log("%s: %qd ms\n", what, millis);
733 }
734
735 gHaltLog[gHaltLogPos] = 0;
736 IOLockUnlock(gHaltLogLock);
737 }
738
739 extern uint32_t gFSState;
740
741 extern "C" void
742 IOSystemShutdownNotification(int stage)
743 {
744 uint64_t startTime;
745
746 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
747 #if !CONFIG_EMBEDDED
748 uint64_t nano, millis;
749 startTime = mach_absolute_time();
750 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
751 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
752 millis = nano / NSEC_PER_MSEC;
753 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
754 printf("waitQuiet() for unmount %qd ms\n", millis);
755 }
756 #endif
757 return;
758 }
759
760 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
761
762 IOLockLock(gHaltLogLock);
763 if (!gHaltLog) {
764 gHaltLog = IONew(char, kHaltLogSize);
765 gHaltStartTime = mach_absolute_time();
766 if (gHaltLog) {
767 halt_log_putc('\n');
768 }
769 }
770 IOLockUnlock(gHaltLogLock);
771
772 startTime = mach_absolute_time();
773 IOPMRootDomainWillShutdown();
774 halt_log_enter("IOPMRootDomainWillShutdown", 0, mach_absolute_time() - startTime);
775 #if HIBERNATION
776 startTime = mach_absolute_time();
777 IOHibernateSystemPostWake(true);
778 halt_log_enter("IOHibernateSystemPostWake", 0, mach_absolute_time() - startTime);
779 #endif
780 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
781 #if !CONFIG_EMBEDDED
782 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
783 #endif
784 }
785 }
786
787
788 extern "C" int sync_internal(void);
789
790 /*
791 * A device is always in the highest power state which satisfies its driver,
792 * its policy-maker, and any power children it has, but within the constraint
793 * of the power state provided by its parent. The driver expresses its desire by
794 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
795 * changePowerStateToPriv(), and the children express their desires by calling
796 * requestPowerDomainState().
797 *
798 * The Root Power Domain owns the policy for idle and demand sleep for the system.
799 * It is a power-managed IOService just like the others in the system.
800 * It implements several power states which map to what we see as Sleep and On.
801 *
802 * The sleep policy is as follows:
803 * 1. Sleep is prevented if the case is open so that nobody will think the machine
804 * is off and plug/unplug cards.
805 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
806 * 3. System cannot Sleep if some object in the tree is in a power state marked
807 * kIOPMPreventSystemSleep.
808 *
809 * These three conditions are enforced using the "driver clamp" by calling
810 * changePowerStateTo(). For example, if the case is opened,
811 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
812 * of the desires of the children of the root or the state of the other clamp.
813 *
814 * Demand Sleep is initiated by pressing the front panel power button, closing
815 * the clamshell, or selecting the menu item. In this case the root's parent
816 * actually initiates the power state change so that the root domain has no
817 * choice and does not give applications the opportunity to veto the change.
818 *
819 * Idle Sleep occurs if no objects in the tree are in a state marked
820 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
821 * the root on, so it sets the "policy-maker clamp" by calling
822 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
823 * This timer is set for the difference between the sleep timeout slider and the
824 * display dim timeout slider. When the timer expires, it releases its clamp and
825 * now nothing is holding it awake, so it falls asleep.
826 *
827 * Demand sleep is prevented when the system is booting. When preferences are
828 * transmitted by the loginwindow at the end of boot, a flag is cleared,
829 * and this allows subsequent Demand Sleep.
830 */
831
832 //******************************************************************************
833
834 IOPMrootDomain *
835 IOPMrootDomain::construct( void )
836 {
837 IOPMrootDomain *root;
838
839 root = new IOPMrootDomain;
840 if (root) {
841 root->init();
842 }
843
844 return root;
845 }
846
847 //******************************************************************************
848 // updateConsoleUsersCallout
849 //
850 //******************************************************************************
851
852 static void
853 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
854 {
855 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
856 rootDomain->updateConsoleUsers();
857 }
858
859 void
860 IOPMrootDomain::updateConsoleUsers(void)
861 {
862 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
863 if (tasksSuspended) {
864 tasksSuspended = FALSE;
865 tasks_system_suspend(tasksSuspended);
866 }
867 }
868
869 //******************************************************************************
870
871 static void
872 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
873 {
874 IOService * rootDomain = (IOService *) p0;
875 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
876 uint32_t powerState = rootDomain->getPowerState();
877
878 DLOG("disk_sync_callout ps=%u\n", powerState);
879
880 if (ON_STATE == powerState) {
881 sync_internal();
882
883 #if HIBERNATION
884 // Block sleep until trim issued on previous wake path is completed.
885 IOHibernateSystemPostWake(true);
886 #endif
887 }
888 #if HIBERNATION
889 else {
890 IOHibernateSystemPostWake(false);
891
892 if (gRootDomain) {
893 gRootDomain->sleepWakeDebugSaveSpinDumpFile();
894 }
895 }
896 #endif
897
898 rootDomain->allowPowerChange(notifyRef);
899 DLOG("disk_sync_callout finish\n");
900 }
901
902 //******************************************************************************
903 static UInt32
904 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
905 {
906 AbsoluteTime endTime;
907 UInt64 nano = 0;
908
909 clock_get_uptime(&endTime);
910 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
911 *elapsedTime = 0;
912 } else {
913 SUB_ABSOLUTETIME(&endTime, startTime);
914 absolutetime_to_nanoseconds(endTime, &nano);
915 *elapsedTime = endTime;
916 }
917
918 return (UInt32)(nano / NSEC_PER_MSEC);
919 }
920
921 //******************************************************************************
922
923 static int
924 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
925 {
926 struct timeval *swt = (struct timeval *)arg1;
927 struct proc *p = req->p;
928
929 if (p == kernproc) {
930 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
931 } else if (proc_is64bit(p)) {
932 struct user64_timeval t = {};
933 t.tv_sec = swt->tv_sec;
934 t.tv_usec = swt->tv_usec;
935 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
936 } else {
937 struct user32_timeval t = {};
938 t.tv_sec = swt->tv_sec;
939 t.tv_usec = swt->tv_usec;
940 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
941 }
942 }
943
944 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
945 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
946 &gIOLastSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
947
948 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
949 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
950 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
951
952 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
953 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
954 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
955 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
956
957 static int
958 sysctl_willshutdown
959 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
960 {
961 int new_value, changed;
962 int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
963 if (changed) {
964 if (!gWillShutdown && (new_value == 1)) {
965 IOPMRootDomainWillShutdown();
966 } else {
967 error = EINVAL;
968 }
969 }
970 return error;
971 }
972
973 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
974 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
975 0, 0, sysctl_willshutdown, "I", "");
976
977 extern struct sysctl_oid sysctl__kern_iokittest;
978 extern struct sysctl_oid sysctl__debug_iokit;
979
980 #if !CONFIG_EMBEDDED
981
982 static int
983 sysctl_progressmeterenable
984 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
985 {
986 int error;
987 int new_value, changed;
988
989 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
990
991 if (changed) {
992 vc_enable_progressmeter(new_value);
993 }
994
995 return error;
996 }
997
998 static int
999 sysctl_progressmeter
1000 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1001 {
1002 int error;
1003 int new_value, changed;
1004
1005 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1006
1007 if (changed) {
1008 vc_set_progressmeter(new_value);
1009 }
1010
1011 return error;
1012 }
1013
1014 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1015 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1016 0, 0, sysctl_progressmeterenable, "I", "");
1017
1018 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1019 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1020 0, 0, sysctl_progressmeter, "I", "");
1021
1022 #endif /* !CONFIG_EMBEDDED */
1023
1024
1025
1026 static int
1027 sysctl_consoleoptions
1028 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1029 {
1030 int error, changed;
1031 uint32_t new_value;
1032
1033 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1034
1035 if (changed) {
1036 vc_user_options.options = new_value;
1037 }
1038
1039 return error;
1040 }
1041
1042 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1043 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1044 0, 0, sysctl_consoleoptions, "I", "");
1045
1046
1047 static int
1048 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1049 {
1050 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1051 }
1052
1053 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1054 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1055 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1056
1057
1058 static int
1059 sysctl_wakereason SYSCTL_HANDLER_ARGS
1060 {
1061 char wr[sizeof(gWakeReasonString)];
1062
1063 wr[0] = '\0';
1064 if (gRootDomain) {
1065 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1066 }
1067
1068 return sysctl_io_string(req, wr, 0, 0, NULL);
1069 }
1070
1071 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1072 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1073 NULL, 0, sysctl_wakereason, "A", "wakereason");
1074
1075 static int
1076 sysctl_targettype SYSCTL_HANDLER_ARGS
1077 {
1078 IOService * root;
1079 OSObject * obj;
1080 OSData * data;
1081 char tt[32];
1082
1083 tt[0] = '\0';
1084 root = IOService::getServiceRoot();
1085 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1086 if ((data = OSDynamicCast(OSData, obj))) {
1087 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1088 }
1089 obj->release();
1090 }
1091 return sysctl_io_string(req, tt, 0, 0, NULL);
1092 }
1093
1094 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1095 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
1096 NULL, 0, sysctl_targettype, "A", "targettype");
1097
1098 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1099 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1100 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1101 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1102 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1103 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1104
1105
1106 static const OSSymbol * gIOPMSettingAutoWakeCalendarKey;
1107 static const OSSymbol * gIOPMSettingAutoWakeSecondsKey;
1108 static const OSSymbol * gIOPMSettingDebugWakeRelativeKey;
1109 static const OSSymbol * gIOPMSettingMaintenanceWakeCalendarKey;
1110 static const OSSymbol * gIOPMSettingSleepServiceWakeCalendarKey;
1111 static const OSSymbol * gIOPMSettingSilentRunningKey;
1112 static const OSSymbol * gIOPMUserTriggeredFullWakeKey;
1113 static const OSSymbol * gIOPMUserIsActiveKey;
1114
1115 //******************************************************************************
1116 // start
1117 //
1118 //******************************************************************************
1119
1120 #define kRootDomainSettingsCount 17
1121
1122 bool
1123 IOPMrootDomain::start( IOService * nub )
1124 {
1125 OSIterator *psIterator;
1126 OSDictionary *tmpDict;
1127 IORootParent * patriarch;
1128
1129 super::start(nub);
1130
1131 gRootDomain = this;
1132 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1133 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1134 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1135 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1136 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1137 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1138 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1139 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1140
1141 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1142 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1143 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1144 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1145 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1146
1147 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1148 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1149
1150 const OSSymbol *settingsArr[kRootDomainSettingsCount] =
1151 {
1152 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1153 gIOPMSettingAutoWakeSecondsKey,
1154 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey),
1155 gIOPMSettingAutoWakeCalendarKey,
1156 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey),
1157 gIOPMSettingDebugWakeRelativeKey,
1158 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey),
1159 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1160 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1161 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1162 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1163 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1164 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1165 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1166 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1167 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1168 gIOPMSettingSilentRunningKey
1169 };
1170
1171 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1172 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1173 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1174 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1175 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1176 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1177 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1178
1179 queue_init(&aggressivesQueue);
1180 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1181 aggressivesData = OSData::withCapacity(
1182 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1183
1184 featuresDictLock = IOLockAlloc();
1185 settingsCtrlLock = IOLockAlloc();
1186 wakeEventLock = IOLockAlloc();
1187 gHaltLogLock = IOLockAlloc();
1188 setPMRootDomain(this);
1189
1190 extraSleepTimer = thread_call_allocate(
1191 idleSleepTimerExpired,
1192 (thread_call_param_t) this);
1193
1194 diskSyncCalloutEntry = thread_call_allocate(
1195 &disk_sync_callout,
1196 (thread_call_param_t) this);
1197 updateConsoleUsersEntry = thread_call_allocate(
1198 &updateConsoleUsersCallout,
1199 (thread_call_param_t) this);
1200
1201 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
1202 fullWakeThreadCall = thread_call_allocate(
1203 OSMemberFunctionCast(thread_call_func_t, this,
1204 &IOPMrootDomain::fullWakeDelayedWork),
1205 (thread_call_param_t) this);
1206 #endif
1207
1208 setProperty(kIOSleepSupportedKey, true);
1209
1210 bzero(&gPMStats, sizeof(gPMStats));
1211
1212 pmTracer = PMTraceWorker::tracer(this);
1213
1214 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1215
1216 userDisabledAllSleep = false;
1217 systemBooting = true;
1218 idleSleepEnabled = false;
1219 sleepSlider = 0;
1220 idleSleepTimerPending = false;
1221 wrangler = NULL;
1222 clamshellClosed = false;
1223 clamshellExists = false;
1224 clamshellDisabled = true;
1225 acAdaptorConnected = true;
1226 clamshellSleepDisabled = false;
1227 gWakeReasonString[0] = '\0';
1228
1229 // Initialize to user active.
1230 // Will never transition to user inactive w/o wrangler.
1231 fullWakeReason = kFullWakeReasonLocalUser;
1232 userIsActive = userWasActive = true;
1233 clock_get_uptime(&gUserActiveAbsTime);
1234 setProperty(gIOPMUserIsActiveKey, kOSBooleanTrue);
1235
1236 // Set the default system capabilities at boot.
1237 _currentCapability = kIOPMSystemCapabilityCPU |
1238 kIOPMSystemCapabilityGraphics |
1239 kIOPMSystemCapabilityAudio |
1240 kIOPMSystemCapabilityNetwork;
1241
1242 _pendingCapability = _currentCapability;
1243 _desiredCapability = _currentCapability;
1244 _highestCapability = _currentCapability;
1245 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1246
1247 queuedSleepWakeUUIDString = NULL;
1248 initializeBootSessionUUID();
1249 pmStatsAppResponses = OSArray::withCapacity(5);
1250 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1251 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1252 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1253 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1254 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1255 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1256 assertOnWakeSecs = -1;// Invalid value to prevent updates
1257
1258 pmStatsLock = IOLockAlloc();
1259 idxPMCPUClamshell = kCPUUnknownIndex;
1260 idxPMCPULimitedPower = kCPUUnknownIndex;
1261
1262 tmpDict = OSDictionary::withCapacity(1);
1263 setProperty(kRootDomainSupportedFeatures, tmpDict);
1264 tmpDict->release();
1265
1266 settingsCallbacks = OSDictionary::withCapacity(1);
1267
1268 // Create a list of the valid PM settings that we'll relay to
1269 // interested clients in setProperties() => setPMSetting()
1270 allowedPMSettings = OSArray::withObjects(
1271 (const OSObject **)settingsArr,
1272 kRootDomainSettingsCount,
1273 0);
1274
1275 // List of PM settings that should not automatically publish itself
1276 // as a feature when registered by a listener.
1277 noPublishPMSettings = OSArray::withObjects(
1278 (const OSObject **) &gIOPMSettingSilentRunningKey, 1, 0);
1279
1280 fPMSettingsDict = OSDictionary::withCapacity(5);
1281 preventIdleSleepList = OSSet::withCapacity(8);
1282 preventSystemSleepList = OSSet::withCapacity(2);
1283
1284 PMinit(); // creates gIOPMWorkLoop
1285 gIOPMWorkLoop = getIOPMWorkloop();
1286
1287 // Create IOPMPowerStateQueue used to queue external power
1288 // events, and to handle those events on the PM work loop.
1289 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1290 this, OSMemberFunctionCast(IOEventSource::Action, this,
1291 &IOPMrootDomain::dispatchPowerEvent));
1292 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1293
1294 // create our power parent
1295 patriarch = new IORootParent;
1296 patriarch->init();
1297 patriarch->attach(this);
1298 patriarch->start(this);
1299 patriarch->addPowerChild(this);
1300
1301 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1302 changePowerStateToPriv(ON_STATE);
1303
1304 // install power change handler
1305 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
1306
1307 #if !NO_KERNEL_HID
1308 // Register for a notification when IODisplayWrangler is published
1309 if ((tmpDict = serviceMatching("IODisplayWrangler"))) {
1310 _displayWranglerNotifier = addMatchingNotification(
1311 gIOPublishNotification, tmpDict,
1312 (IOServiceMatchingNotificationHandler) & displayWranglerMatchPublished,
1313 this, 0);
1314 tmpDict->release();
1315 }
1316 #endif
1317
1318 #if defined(__i386__) || defined(__x86_64__)
1319
1320 wranglerIdleSettings = NULL;
1321 OSNumber * wranglerIdlePeriod = NULL;
1322 wranglerIdleSettings = OSDictionary::withCapacity(1);
1323 wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1324
1325 if (wranglerIdleSettings && wranglerIdlePeriod) {
1326 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1327 wranglerIdlePeriod);
1328 }
1329
1330 if (wranglerIdlePeriod) {
1331 wranglerIdlePeriod->release();
1332 }
1333 #endif
1334
1335 const OSSymbol *ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1336 setProperty(gIOUserClientClassKey, (OSObject *) ucClassName);
1337 ucClassName->release();
1338
1339 // IOBacklightDisplay can take a long time to load at boot, or it may
1340 // not load at all if you're booting with clamshell closed. We publish
1341 // 'DisplayDims' here redundantly to get it published early and at all.
1342 OSDictionary * matching;
1343 matching = serviceMatching("IOPMPowerSource");
1344 psIterator = getMatchingServices( matching );
1345 if (matching) {
1346 matching->release();
1347 }
1348 if (psIterator && psIterator->getNextObject()) {
1349 // There's at least one battery on the system, so we publish
1350 // 'DisplayDims' support for the LCD.
1351 publishFeature("DisplayDims");
1352 }
1353 if (psIterator) {
1354 psIterator->release();
1355 }
1356
1357 sysctl_register_oid(&sysctl__kern_sleeptime);
1358 sysctl_register_oid(&sysctl__kern_waketime);
1359 sysctl_register_oid(&sysctl__kern_willshutdown);
1360 sysctl_register_oid(&sysctl__kern_iokittest);
1361 sysctl_register_oid(&sysctl__debug_iokit);
1362 sysctl_register_oid(&sysctl__hw_targettype);
1363
1364 #if !CONFIG_EMBEDDED
1365 sysctl_register_oid(&sysctl__kern_progressmeterenable);
1366 sysctl_register_oid(&sysctl__kern_progressmeter);
1367 sysctl_register_oid(&sysctl__kern_wakereason);
1368 #endif /* !CONFIG_EMBEDDED */
1369 sysctl_register_oid(&sysctl__kern_consoleoptions);
1370 sysctl_register_oid(&sysctl__kern_progressoptions);
1371
1372 #if HIBERNATION
1373 IOHibernateSystemInit(this);
1374 #endif
1375
1376 registerService(); // let clients find us
1377
1378 return true;
1379 }
1380
1381 //******************************************************************************
1382 // setProperties
1383 //
1384 // Receive a setProperty call
1385 // The "System Boot" property means the system is completely booted.
1386 //******************************************************************************
1387
1388 IOReturn
1389 IOPMrootDomain::setProperties( OSObject * props_obj )
1390 {
1391 IOReturn return_value = kIOReturnSuccess;
1392 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1393 OSBoolean *b;
1394 OSNumber *n;
1395 const OSSymbol *key;
1396 OSObject *obj;
1397 OSCollectionIterator * iter = 0;
1398
1399 const OSSymbol *publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1400 const OSSymbol *boot_complete_string = OSSymbol::withCString("System Boot Complete");
1401 const OSSymbol *sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1402 const OSSymbol *stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1403 const OSSymbol *battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1404 const OSSymbol *idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1405 const OSSymbol *sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1406 const OSSymbol *ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1407 const OSSymbol *loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1408 const OSSymbol *coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1409 const OSSymbol *coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1410 #if HIBERNATION
1411 const OSSymbol *hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1412 const OSSymbol *hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1413 const OSSymbol *hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1414 const OSSymbol *hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1415 const OSSymbol *hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1416 const OSSymbol *hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1417 #endif
1418
1419 if (!dict) {
1420 return_value = kIOReturnBadArgument;
1421 goto exit;
1422 }
1423
1424 iter = OSCollectionIterator::withCollection(dict);
1425 if (!iter) {
1426 return_value = kIOReturnNoMemory;
1427 goto exit;
1428 }
1429
1430 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1431 (obj = dict->getObject(key))) {
1432 if (key->isEqualTo(publish_simulated_battery_string)) {
1433 if (OSDynamicCast(OSBoolean, obj)) {
1434 publishResource(key, kOSBooleanTrue);
1435 }
1436 } else if (key->isEqualTo(idle_seconds_string)) {
1437 if ((n = OSDynamicCast(OSNumber, obj))) {
1438 setProperty(key, n);
1439 idleSeconds = n->unsigned32BitValue();
1440 }
1441 } else if (key->isEqualTo(boot_complete_string)) {
1442 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1443 } else if (key->isEqualTo(sys_shutdown_string)) {
1444 if ((b = OSDynamicCast(OSBoolean, obj))) {
1445 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1446 }
1447 } else if (key->isEqualTo(battery_warning_disabled_string)) {
1448 setProperty(key, obj);
1449 }
1450 #if HIBERNATION
1451 else if (key->isEqualTo(hibernatemode_string) ||
1452 key->isEqualTo(hibernatefilemin_string) ||
1453 key->isEqualTo(hibernatefilemax_string) ||
1454 key->isEqualTo(hibernatefreeratio_string) ||
1455 key->isEqualTo(hibernatefreetime_string)) {
1456 if ((n = OSDynamicCast(OSNumber, obj))) {
1457 setProperty(key, n);
1458 }
1459 } else if (key->isEqualTo(hibernatefile_string)) {
1460 OSString * str = OSDynamicCast(OSString, obj);
1461 if (str) {
1462 setProperty(key, str);
1463 }
1464 }
1465 #endif
1466 else if (key->isEqualTo(sleepdisabled_string)) {
1467 if ((b = OSDynamicCast(OSBoolean, obj))) {
1468 setProperty(key, b);
1469 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1470 }
1471 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string)) {
1472 obj->retain();
1473 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1474 } else if (key->isEqualTo(loginwindow_progress_string)) {
1475 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1476 uint32_t data = n->unsigned32BitValue();
1477 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1478 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1479 }
1480 } else if (key->isEqualTo(coredisplay_progress_string)) {
1481 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1482 uint32_t data = n->unsigned32BitValue();
1483 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1484 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1485 }
1486 } else if (key->isEqualTo(coregraphics_progress_string)) {
1487 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1488 uint32_t data = n->unsigned32BitValue();
1489 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1490 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1491 }
1492 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1493 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1494 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1495 key->isEqualTo(stall_halt_string)) {
1496 if ((b = OSDynamicCast(OSBoolean, obj))) {
1497 setProperty(key, b);
1498 }
1499 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1500 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1501 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1502 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1503 if ((n = OSDynamicCast(OSNumber, obj))) {
1504 setProperty(key, n);
1505 }
1506 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1507 if (kOSBooleanTrue == obj) {
1508 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarm);
1509 } else {
1510 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarm);
1511 }
1512 DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm);
1513 }
1514 // Relay our allowed PM settings onto our registered PM clients
1515 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
1516 return_value = setPMSetting(key, obj);
1517 if (kIOReturnSuccess != return_value) {
1518 break;
1519 }
1520
1521 if (gIOPMSettingDebugWakeRelativeKey == key) {
1522 if ((n = OSDynamicCast(OSNumber, obj)) &&
1523 (_debugWakeSeconds = n->unsigned32BitValue())) {
1524 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarms);
1525 } else {
1526 _debugWakeSeconds = 0;
1527 OSBitAndAtomic(~kIOPMAlarmBitDebugWake, &_scheduledAlarms);
1528 }
1529 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
1530 } else if (gIOPMSettingAutoWakeCalendarKey == key) {
1531 OSData * data;
1532 if ((data = OSDynamicCast(OSData, obj)) &&
1533 (data->getLength() == sizeof(IOPMCalendarStruct))) {
1534 const IOPMCalendarStruct * cs =
1535 (const IOPMCalendarStruct *) data->getBytesNoCopy();
1536
1537 if (cs->year) {
1538 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
1539 } else {
1540 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
1541 }
1542 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
1543 }
1544 }
1545 } else {
1546 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
1547 }
1548 }
1549
1550 exit:
1551 if (publish_simulated_battery_string) {
1552 publish_simulated_battery_string->release();
1553 }
1554 if (boot_complete_string) {
1555 boot_complete_string->release();
1556 }
1557 if (sys_shutdown_string) {
1558 sys_shutdown_string->release();
1559 }
1560 if (stall_halt_string) {
1561 stall_halt_string->release();
1562 }
1563 if (battery_warning_disabled_string) {
1564 battery_warning_disabled_string->release();
1565 }
1566 if (idle_seconds_string) {
1567 idle_seconds_string->release();
1568 }
1569 if (sleepdisabled_string) {
1570 sleepdisabled_string->release();
1571 }
1572 if (ondeck_sleepwake_uuid_string) {
1573 ondeck_sleepwake_uuid_string->release();
1574 }
1575 if (loginwindow_progress_string) {
1576 loginwindow_progress_string->release();
1577 }
1578 if (coredisplay_progress_string) {
1579 coredisplay_progress_string->release();
1580 }
1581 if (coregraphics_progress_string) {
1582 coregraphics_progress_string->release();
1583 }
1584 #if HIBERNATION
1585 if (hibernatemode_string) {
1586 hibernatemode_string->release();
1587 }
1588 if (hibernatefile_string) {
1589 hibernatefile_string->release();
1590 }
1591 if (hibernatefreeratio_string) {
1592 hibernatefreeratio_string->release();
1593 }
1594 if (hibernatefreetime_string) {
1595 hibernatefreetime_string->release();
1596 }
1597 #endif
1598 if (iter) {
1599 iter->release();
1600 }
1601 return return_value;
1602 }
1603
1604 // MARK: -
1605 // MARK: Aggressiveness
1606
1607 //******************************************************************************
1608 // setAggressiveness
1609 //
1610 // Override IOService::setAggressiveness()
1611 //******************************************************************************
1612
1613 IOReturn
1614 IOPMrootDomain::setAggressiveness(
1615 unsigned long type,
1616 unsigned long value )
1617 {
1618 return setAggressiveness( type, value, 0 );
1619 }
1620
1621 /*
1622 * Private setAggressiveness() with an internal options argument.
1623 */
1624 IOReturn
1625 IOPMrootDomain::setAggressiveness(
1626 unsigned long type,
1627 unsigned long value,
1628 IOOptionBits options )
1629 {
1630 AggressivesRequest * entry;
1631 AggressivesRequest * request;
1632 bool found = false;
1633
1634 DLOG("setAggressiveness(%x) 0x%x = %u\n",
1635 (uint32_t) options, (uint32_t) type, (uint32_t) value);
1636
1637 request = IONew(AggressivesRequest, 1);
1638 if (!request) {
1639 return kIOReturnNoMemory;
1640 }
1641
1642 memset(request, 0, sizeof(*request));
1643 request->options = options;
1644 request->dataType = kAggressivesRequestTypeRecord;
1645 request->data.record.type = (uint32_t) type;
1646 request->data.record.value = (uint32_t) value;
1647
1648 AGGRESSIVES_LOCK();
1649
1650 // Update disk quick spindown flag used by getAggressiveness().
1651 // Never merge requests with quick spindown flags set.
1652
1653 if (options & kAggressivesOptionQuickSpindownEnable) {
1654 gAggressivesState |= kAggressivesStateQuickSpindown;
1655 } else if (options & kAggressivesOptionQuickSpindownDisable) {
1656 gAggressivesState &= ~kAggressivesStateQuickSpindown;
1657 } else {
1658 // Coalesce requests with identical aggressives types.
1659 // Deal with callers that calls us too "aggressively".
1660
1661 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1662 {
1663 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1664 (entry->data.record.type == type) &&
1665 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
1666 entry->data.record.value = value;
1667 found = true;
1668 break;
1669 }
1670 }
1671 }
1672
1673 if (!found) {
1674 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1675 }
1676
1677 AGGRESSIVES_UNLOCK();
1678
1679 if (found) {
1680 IODelete(request, AggressivesRequest, 1);
1681 }
1682
1683 if (options & kAggressivesOptionSynchronous) {
1684 handleAggressivesRequests(); // not truly synchronous
1685 } else {
1686 thread_call_enter(aggressivesThreadCall);
1687 }
1688
1689 return kIOReturnSuccess;
1690 }
1691
1692 //******************************************************************************
1693 // getAggressiveness
1694 //
1695 // Override IOService::setAggressiveness()
1696 // Fetch the aggressiveness factor with the given type.
1697 //******************************************************************************
1698
1699 IOReturn
1700 IOPMrootDomain::getAggressiveness(
1701 unsigned long type,
1702 unsigned long * outLevel )
1703 {
1704 uint32_t value = 0;
1705 int source = 0;
1706
1707 if (!outLevel) {
1708 return kIOReturnBadArgument;
1709 }
1710
1711 AGGRESSIVES_LOCK();
1712
1713 // Disk quick spindown in effect, report value = 1
1714
1715 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
1716 (type == kPMMinutesToSpinDown)) {
1717 value = kAggressivesMinValue;
1718 source = 1;
1719 }
1720
1721 // Consult the pending request queue.
1722
1723 if (!source) {
1724 AggressivesRequest * entry;
1725
1726 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1727 {
1728 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1729 (entry->data.record.type == type) &&
1730 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
1731 value = entry->data.record.value;
1732 source = 2;
1733 break;
1734 }
1735 }
1736 }
1737
1738 // Consult the backend records.
1739
1740 if (!source && aggressivesData) {
1741 AggressivesRecord * record;
1742 int i, count;
1743
1744 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1745 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1746
1747 for (i = 0; i < count; i++, record++) {
1748 if (record->type == type) {
1749 value = record->value;
1750 source = 3;
1751 break;
1752 }
1753 }
1754 }
1755
1756 AGGRESSIVES_UNLOCK();
1757
1758 if (source) {
1759 DLOG("getAggressiveness(%d) 0x%x = %u\n",
1760 source, (uint32_t) type, value);
1761 *outLevel = (unsigned long) value;
1762 return kIOReturnSuccess;
1763 } else {
1764 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
1765 *outLevel = 0; // default return = 0, driver may not check for error
1766 return kIOReturnInvalid;
1767 }
1768 }
1769
1770 //******************************************************************************
1771 // joinAggressiveness
1772 //
1773 // Request from IOService to join future aggressiveness broadcasts.
1774 //******************************************************************************
1775
1776 IOReturn
1777 IOPMrootDomain::joinAggressiveness(
1778 IOService * service )
1779 {
1780 AggressivesRequest * request;
1781
1782 if (!service || (service == this)) {
1783 return kIOReturnBadArgument;
1784 }
1785
1786 DLOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
1787
1788 request = IONew(AggressivesRequest, 1);
1789 if (!request) {
1790 return kIOReturnNoMemory;
1791 }
1792
1793 service->retain(); // released by synchronizeAggressives()
1794
1795 memset(request, 0, sizeof(*request));
1796 request->dataType = kAggressivesRequestTypeService;
1797 request->data.service = service;
1798
1799 AGGRESSIVES_LOCK();
1800 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1801 AGGRESSIVES_UNLOCK();
1802
1803 thread_call_enter(aggressivesThreadCall);
1804
1805 return kIOReturnSuccess;
1806 }
1807
1808 //******************************************************************************
1809 // handleAggressivesRequests
1810 //
1811 // Backend thread processes all incoming aggressiveness requests in the queue.
1812 //******************************************************************************
1813
1814 static void
1815 handleAggressivesFunction(
1816 thread_call_param_t param1,
1817 thread_call_param_t param2 )
1818 {
1819 if (param1) {
1820 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
1821 }
1822 }
1823
1824 void
1825 IOPMrootDomain::handleAggressivesRequests( void )
1826 {
1827 AggressivesRecord * start;
1828 AggressivesRecord * record;
1829 AggressivesRequest * request;
1830 queue_head_t joinedQueue;
1831 int i, count;
1832 bool broadcast;
1833 bool found;
1834 bool pingSelf = false;
1835
1836 AGGRESSIVES_LOCK();
1837
1838 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
1839 queue_empty(&aggressivesQueue)) {
1840 goto unlock_done;
1841 }
1842
1843 gAggressivesState |= kAggressivesStateBusy;
1844 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1845 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1846
1847 do{
1848 broadcast = false;
1849 queue_init(&joinedQueue);
1850
1851 do{
1852 // Remove request from the incoming queue in FIFO order.
1853 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
1854 switch (request->dataType) {
1855 case kAggressivesRequestTypeRecord:
1856 // Update existing record if found.
1857 found = false;
1858 for (i = 0, record = start; i < count; i++, record++) {
1859 if (record->type == request->data.record.type) {
1860 found = true;
1861
1862 if (request->options & kAggressivesOptionQuickSpindownEnable) {
1863 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
1864 broadcast = true;
1865 record->flags |= (kAggressivesRecordFlagMinValue |
1866 kAggressivesRecordFlagModified);
1867 DLOG("disk spindown accelerated, was %u min\n",
1868 record->value);
1869 }
1870 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
1871 if (record->flags & kAggressivesRecordFlagMinValue) {
1872 broadcast = true;
1873 record->flags |= kAggressivesRecordFlagModified;
1874 record->flags &= ~kAggressivesRecordFlagMinValue;
1875 DLOG("disk spindown restored to %u min\n",
1876 record->value);
1877 }
1878 } else if (record->value != request->data.record.value) {
1879 record->value = request->data.record.value;
1880 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
1881 broadcast = true;
1882 record->flags |= kAggressivesRecordFlagModified;
1883 }
1884 }
1885 break;
1886 }
1887 }
1888
1889 // No matching record, append a new record.
1890 if (!found &&
1891 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
1892 AggressivesRecord newRecord;
1893
1894 newRecord.flags = kAggressivesRecordFlagModified;
1895 newRecord.type = request->data.record.type;
1896 newRecord.value = request->data.record.value;
1897 if (request->options & kAggressivesOptionQuickSpindownEnable) {
1898 newRecord.flags |= kAggressivesRecordFlagMinValue;
1899 DLOG("disk spindown accelerated\n");
1900 }
1901
1902 aggressivesData->appendBytes(&newRecord, sizeof(newRecord));
1903
1904 // OSData may have switched to another (larger) buffer.
1905 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1906 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1907 broadcast = true;
1908 }
1909
1910 // Finished processing the request, release it.
1911 IODelete(request, AggressivesRequest, 1);
1912 break;
1913
1914 case kAggressivesRequestTypeService:
1915 // synchronizeAggressives() will free request.
1916 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
1917 break;
1918
1919 default:
1920 panic("bad aggressives request type %x\n", request->dataType);
1921 break;
1922 }
1923 } while (!queue_empty(&aggressivesQueue));
1924
1925 // Release the lock to perform work, with busy flag set.
1926 if (!queue_empty(&joinedQueue) || broadcast) {
1927 AGGRESSIVES_UNLOCK();
1928 if (!queue_empty(&joinedQueue)) {
1929 synchronizeAggressives(&joinedQueue, start, count);
1930 }
1931 if (broadcast) {
1932 broadcastAggressives(start, count);
1933 }
1934 AGGRESSIVES_LOCK();
1935 }
1936
1937 // Remove the modified flag from all records.
1938 for (i = 0, record = start; i < count; i++, record++) {
1939 if ((record->flags & kAggressivesRecordFlagModified) &&
1940 ((record->type == kPMMinutesToDim) ||
1941 (record->type == kPMMinutesToSleep))) {
1942 pingSelf = true;
1943 }
1944
1945 record->flags &= ~kAggressivesRecordFlagModified;
1946 }
1947
1948 // Check the incoming queue again since new entries may have been
1949 // added while lock was released above.
1950 } while (!queue_empty(&aggressivesQueue));
1951
1952 gAggressivesState &= ~kAggressivesStateBusy;
1953
1954 unlock_done:
1955 AGGRESSIVES_UNLOCK();
1956
1957 // Root domain is interested in system and display sleep slider changes.
1958 // Submit a power event to handle those changes on the PM work loop.
1959
1960 if (pingSelf && pmPowerStateQueue) {
1961 pmPowerStateQueue->submitPowerEvent(
1962 kPowerEventPolicyStimulus,
1963 (void *) kStimulusAggressivenessChanged );
1964 }
1965 }
1966
1967 //******************************************************************************
1968 // synchronizeAggressives
1969 //
1970 // Push all known aggressiveness records to one or more IOService.
1971 //******************************************************************************
1972
1973 void
1974 IOPMrootDomain::synchronizeAggressives(
1975 queue_head_t * joinedQueue,
1976 const AggressivesRecord * array,
1977 int count )
1978 {
1979 IOService * service;
1980 AggressivesRequest * request;
1981 const AggressivesRecord * record;
1982 IOPMDriverCallEntry callEntry;
1983 uint32_t value;
1984 int i;
1985
1986 while (!queue_empty(joinedQueue)) {
1987 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
1988 if (request->dataType == kAggressivesRequestTypeService) {
1989 service = request->data.service;
1990 } else {
1991 service = 0;
1992 }
1993
1994 IODelete(request, AggressivesRequest, 1);
1995 request = 0;
1996
1997 if (service) {
1998 if (service->assertPMDriverCall(&callEntry)) {
1999 for (i = 0, record = array; i < count; i++, record++) {
2000 value = record->value;
2001 if (record->flags & kAggressivesRecordFlagMinValue) {
2002 value = kAggressivesMinValue;
2003 }
2004
2005 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2006 record->type, value, service->getName());
2007 service->setAggressiveness(record->type, value);
2008 }
2009 service->deassertPMDriverCall(&callEntry);
2010 }
2011 service->release(); // retained by joinAggressiveness()
2012 }
2013 }
2014 }
2015
2016 //******************************************************************************
2017 // broadcastAggressives
2018 //
2019 // Traverse PM tree and call setAggressiveness() for records that have changed.
2020 //******************************************************************************
2021
2022 void
2023 IOPMrootDomain::broadcastAggressives(
2024 const AggressivesRecord * array,
2025 int count )
2026 {
2027 IORegistryIterator * iter;
2028 IORegistryEntry * entry;
2029 IOPowerConnection * connect;
2030 IOService * service;
2031 const AggressivesRecord * record;
2032 IOPMDriverCallEntry callEntry;
2033 uint32_t value;
2034 int i;
2035
2036 iter = IORegistryIterator::iterateOver(
2037 this, gIOPowerPlane, kIORegistryIterateRecursively);
2038 if (iter) {
2039 do{
2040 iter->reset();
2041 while ((entry = iter->getNextObject())) {
2042 connect = OSDynamicCast(IOPowerConnection, entry);
2043 if (!connect || !connect->getReadyFlag()) {
2044 continue;
2045 }
2046
2047 if ((service = OSDynamicCast(IOService, connect->copyChildEntry(gIOPowerPlane)))) {
2048 if (service->assertPMDriverCall(&callEntry)) {
2049 for (i = 0, record = array; i < count; i++, record++) {
2050 if (record->flags & kAggressivesRecordFlagModified) {
2051 value = record->value;
2052 if (record->flags & kAggressivesRecordFlagMinValue) {
2053 value = kAggressivesMinValue;
2054 }
2055 _LOG("broadcastAggressives %x = %u to %s\n",
2056 record->type, value, service->getName());
2057 service->setAggressiveness(record->type, value);
2058 }
2059 }
2060 service->deassertPMDriverCall(&callEntry);
2061 }
2062 service->release();
2063 }
2064 }
2065 }while (!entry && !iter->isValid());
2066 iter->release();
2067 }
2068 }
2069
2070 // MARK: -
2071 // MARK: System Sleep
2072
2073 //******************************************************************************
2074 // startIdleSleepTimer
2075 //
2076 //******************************************************************************
2077
2078 void
2079 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds )
2080 {
2081 AbsoluteTime deadline;
2082
2083 ASSERT_GATED();
2084 if (gNoIdleFlag) {
2085 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2086 return;
2087 }
2088 if (inSeconds) {
2089 clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
2090 thread_call_enter_delayed(extraSleepTimer, deadline);
2091 idleSleepTimerPending = true;
2092 } else {
2093 thread_call_enter(extraSleepTimer);
2094 }
2095 DLOG("idle timer set for %u seconds\n", inSeconds);
2096 }
2097
2098 //******************************************************************************
2099 // cancelIdleSleepTimer
2100 //
2101 //******************************************************************************
2102
2103 void
2104 IOPMrootDomain::cancelIdleSleepTimer( void )
2105 {
2106 ASSERT_GATED();
2107 if (idleSleepTimerPending) {
2108 DLOG("idle timer cancelled\n");
2109 thread_call_cancel(extraSleepTimer);
2110 idleSleepTimerPending = false;
2111
2112 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2113 AbsoluteTime now;
2114 clock_usec_t microsecs;
2115 clock_get_uptime(&now);
2116 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2117 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2118 if (assertOnWakeReport) {
2119 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2120 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2121 }
2122 }
2123 }
2124 }
2125
2126 //******************************************************************************
2127 // idleSleepTimerExpired
2128 //
2129 //******************************************************************************
2130
2131 static void
2132 idleSleepTimerExpired(
2133 thread_call_param_t us, thread_call_param_t )
2134 {
2135 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2136 }
2137
2138 //******************************************************************************
2139 // handleSleepTimerExpiration
2140 //
2141 // The time between the sleep idle timeout and the next longest one has elapsed.
2142 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2143 //******************************************************************************
2144
2145 void
2146 IOPMrootDomain::handleSleepTimerExpiration( void )
2147 {
2148 if (!gIOPMWorkLoop->inGate()) {
2149 gIOPMWorkLoop->runAction(
2150 OSMemberFunctionCast(IOWorkLoop::Action, this,
2151 &IOPMrootDomain::handleSleepTimerExpiration),
2152 this);
2153 return;
2154 }
2155
2156 AbsoluteTime time;
2157
2158 DLOG("sleep timer expired\n");
2159 ASSERT_GATED();
2160
2161 idleSleepTimerPending = false;
2162
2163 clock_get_uptime(&time);
2164 setQuickSpinDownTimeout();
2165 adjustPowerState(true);
2166 }
2167
2168 //******************************************************************************
2169 // getTimeToIdleSleep
2170 //
2171 // Returns number of seconds left before going into idle sleep.
2172 // Caller has to make sure that idle sleep is allowed at the time of calling
2173 // this function
2174 //******************************************************************************
2175
2176 uint32_t
2177 IOPMrootDomain::getTimeToIdleSleep( void )
2178 {
2179 AbsoluteTime now, lastActivityTime;
2180 uint64_t nanos;
2181 uint32_t minutesSinceUserInactive = 0;
2182 uint32_t sleepDelay = 0;
2183
2184 if (!idleSleepEnabled) {
2185 return 0xffffffff;
2186 }
2187
2188 if (userActivityTime) {
2189 lastActivityTime = userActivityTime;
2190 } else {
2191 lastActivityTime = userBecameInactiveTime;
2192 }
2193
2194 clock_get_uptime(&now);
2195 if (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0) {
2196 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2197 absolutetime_to_nanoseconds(now, &nanos);
2198 minutesSinceUserInactive = nanos / (60000000000ULL);
2199
2200 if (minutesSinceUserInactive >= sleepSlider) {
2201 sleepDelay = 0;
2202 } else {
2203 sleepDelay = sleepSlider - minutesSinceUserInactive;
2204 }
2205 } else {
2206 sleepDelay = sleepSlider;
2207 }
2208
2209 DLOG("user inactive %u min, time to idle sleep %u min\n",
2210 minutesSinceUserInactive, sleepDelay);
2211
2212 return sleepDelay * 60;
2213 }
2214
2215 //******************************************************************************
2216 // setQuickSpinDownTimeout
2217 //
2218 //******************************************************************************
2219
2220 void
2221 IOPMrootDomain::setQuickSpinDownTimeout( void )
2222 {
2223 ASSERT_GATED();
2224 setAggressiveness(
2225 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2226 }
2227
2228 //******************************************************************************
2229 // restoreUserSpinDownTimeout
2230 //
2231 //******************************************************************************
2232
2233 void
2234 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2235 {
2236 ASSERT_GATED();
2237 setAggressiveness(
2238 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2239 }
2240
2241 //******************************************************************************
2242 // sleepSystem
2243 //
2244 //******************************************************************************
2245
2246 /* public */
2247 IOReturn
2248 IOPMrootDomain::sleepSystem( void )
2249 {
2250 return sleepSystemOptions(NULL);
2251 }
2252
2253 /* private */
2254 IOReturn
2255 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2256 {
2257 OSObject *obj = NULL;
2258 OSString *reason = NULL;
2259 /* sleepSystem is a public function, and may be called by any kernel driver.
2260 * And that's bad - drivers should sleep the system by calling
2261 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2262 *
2263 * Note that user space app calls to IOPMSleepSystem() will also travel
2264 * this code path and thus be correctly identified as software sleeps.
2265 */
2266
2267 if (options && options->getObject("OSSwitch")) {
2268 // Log specific sleep cause for OS Switch hibernation
2269 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2270 }
2271
2272 if (options && (obj = options->getObject("Sleep Reason"))) {
2273 reason = OSDynamicCast(OSString, obj);
2274 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2275 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2276 }
2277 }
2278
2279 return privateSleepSystem( kIOPMSleepReasonSoftware);
2280 }
2281
2282 /* private */
2283 IOReturn
2284 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2285 {
2286 /* Called from both gated and non-gated context */
2287
2288 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2289 return kIOReturnNotPermitted;
2290 }
2291
2292 pmPowerStateQueue->submitPowerEvent(
2293 kPowerEventPolicyStimulus,
2294 (void *) kStimulusDemandSystemSleep,
2295 sleepReason);
2296
2297 return kIOReturnSuccess;
2298 }
2299
2300 //******************************************************************************
2301 // powerChangeDone
2302 //
2303 // This overrides powerChangeDone in IOService.
2304 //******************************************************************************
2305
2306 void
2307 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2308 {
2309 #if !__i386__ && !__x86_64__
2310 uint64_t timeSinceReset = 0;
2311 #endif
2312 uint64_t now;
2313 ASSERT_GATED();
2314 DLOG("PowerChangeDone: %u->%u\n",
2315 (uint32_t) previousPowerState, (uint32_t) getPowerState());
2316
2317 notifierThread = current_thread();
2318 switch (getPowerState()) {
2319 case SLEEP_STATE: {
2320 if (previousPowerState != ON_STATE) {
2321 break;
2322 }
2323
2324 acceptSystemWakeEvents(true);
2325
2326 // re-enable this timer for next sleep
2327 cancelIdleSleepTimer();
2328
2329 clock_sec_t secs;
2330 clock_usec_t microsecs;
2331 clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
2332 logtime(secs);
2333 gIOLastSleepTime.tv_sec = secs;
2334 gIOLastSleepTime.tv_usec = microsecs;
2335 gIOLastWakeTime.tv_sec = 0;
2336 gIOLastWakeTime.tv_usec = 0;
2337 gIOLastSleepAbsTime = now;
2338
2339 if (wake2DarkwakeDelay && sleepDelaysReport) {
2340 clock_usec_t microsecs;
2341 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2342 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2343
2344 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2345 absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
2346 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
2347 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2348 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2349
2350 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2351 wake2DarkwakeDelay = 0;
2352 }
2353 #if HIBERNATION
2354 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2355
2356 IOHibernateSystemHasSlept();
2357
2358 evaluateSystemSleepPolicyFinal();
2359 #else
2360 LOG("System Sleep\n");
2361 #endif
2362 if (thermalWarningState) {
2363 const OSSymbol *event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2364 if (event) {
2365 systemPowerEventOccurred(event, kIOPMThermalLevelUnknown);
2366 event->release();
2367 }
2368 }
2369 assertOnWakeSecs = 0;
2370 lowBatteryCondition = false;
2371
2372 #if DEVELOPMENT || DEBUG
2373 extern int g_should_log_clock_adjustments;
2374 if (g_should_log_clock_adjustments) {
2375 clock_sec_t secs = 0;
2376 clock_usec_t microsecs = 0;
2377 uint64_t now_b = mach_absolute_time();
2378
2379 PEGetUTCTimeOfDay(&secs, &microsecs);
2380
2381 uint64_t now_a = mach_absolute_time();
2382 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2383 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2384 }
2385 #endif
2386
2387 getPlatform()->sleepKernel();
2388
2389 // The CPU(s) are off at this point,
2390 // Code will resume execution here upon wake.
2391
2392 clock_get_uptime(&gIOLastWakeAbsTime);
2393 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2394 _highestCapability = 0;
2395
2396 #if HIBERNATION
2397 IOHibernateSystemWake();
2398 #endif
2399
2400 // sleep transition complete
2401 gSleepOrShutdownPending = 0;
2402
2403 // trip the reset of the calendar clock
2404 {
2405 clock_sec_t wakeSecs;
2406 clock_usec_t wakeMicrosecs;
2407
2408 clock_wakeup_calendar();
2409
2410 clock_get_calendar_microtime(&wakeSecs, &wakeMicrosecs);
2411 gIOLastWakeTime.tv_sec = wakeSecs;
2412 gIOLastWakeTime.tv_usec = wakeMicrosecs;
2413 }
2414
2415 #if HIBERNATION
2416 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
2417 #endif
2418
2419 lastSleepReason = 0;
2420
2421 _lastDebugWakeSeconds = _debugWakeSeconds;
2422 _debugWakeSeconds = 0;
2423 _scheduledAlarms = 0;
2424
2425 #if defined(__i386__) || defined(__x86_64__)
2426 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
2427 wranglerTickled = false;
2428 graphicsSuppressed = false;
2429 darkWakePostTickle = false;
2430 darkWakeHibernateError = false;
2431 darkWakeToSleepASAP = true;
2432 logGraphicsClamp = true;
2433 sleepTimerMaintenance = false;
2434 sleepToStandby = false;
2435 wranglerTickleLatched = false;
2436 userWasActive = false;
2437 fullWakeReason = kFullWakeReasonNone;
2438
2439 OSString * wakeType = OSDynamicCast(
2440 OSString, getProperty(kIOPMRootDomainWakeTypeKey));
2441 OSString * wakeReason = OSDynamicCast(
2442 OSString, getProperty(kIOPMRootDomainWakeReasonKey));
2443
2444 if (wakeReason && (wakeReason->getLength() >= 2) &&
2445 gWakeReasonString[0] == '\0') {
2446 // Until the platform driver can claim its wake reasons
2447 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
2448 sizeof(gWakeReasonString));
2449 }
2450
2451 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
2452 lowBatteryCondition = true;
2453 darkWakeMaintenance = true;
2454 } else if ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) != 0) {
2455 #if HIBERNATION
2456 OSNumber * hibOptions = OSDynamicCast(
2457 OSNumber, getProperty(kIOHibernateOptionsKey));
2458 if (hibernateAborted || ((hibOptions &&
2459 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
2460 // Hibernate aborted, or EFI brought up graphics
2461 wranglerTickled = true;
2462 DLOG("hibernation aborted %d, options 0x%x\n",
2463 hibernateAborted,
2464 hibOptions ? hibOptions->unsigned32BitValue() : 0);
2465 } else
2466 #endif
2467 if (wakeType && (
2468 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
2469 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
2470 // User wake or RTC alarm
2471 wranglerTickled = true;
2472 } else if (wakeType &&
2473 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
2474 // SMC standby timer trumps SleepX
2475 darkWakeMaintenance = true;
2476 sleepTimerMaintenance = true;
2477 } else if ((_lastDebugWakeSeconds != 0) &&
2478 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
2479 // SleepX before maintenance
2480 wranglerTickled = true;
2481 } else if (wakeType &&
2482 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
2483 darkWakeMaintenance = true;
2484 } else if (wakeType &&
2485 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
2486 darkWakeMaintenance = true;
2487 darkWakeSleepService = true;
2488 #if HIBERNATION
2489 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
2490 sleepToStandby = true;
2491 }
2492 #endif
2493 } else if (wakeType &&
2494 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
2495 darkWakeMaintenance = true;
2496 darkWakeHibernateError = true;
2497 } else {
2498 // Unidentified wake source, resume to full wake if debug
2499 // alarm is pending.
2500
2501 if (_lastDebugWakeSeconds &&
2502 (!wakeReason || wakeReason->isEqualTo(""))) {
2503 wranglerTickled = true;
2504 }
2505 }
2506 } else {
2507 if (wakeType &&
2508 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
2509 darkWakeMaintenance = true;
2510 sleepTimerMaintenance = true;
2511 } else if (hibernateAborted || !wakeType ||
2512 !wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance) ||
2513 !wakeReason || !wakeReason->isEqualTo("RTC")) {
2514 // Post a HID tickle immediately - except for RTC maintenance wake.
2515 wranglerTickled = true;
2516 } else {
2517 darkWakeMaintenance = true;
2518 }
2519 }
2520
2521 if (wranglerTickled) {
2522 darkWakeToSleepASAP = false;
2523 fullWakeReason = kFullWakeReasonLocalUser;
2524 reportUserInput();
2525 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
2526 handleDisplayPowerOn();
2527 } else if (!darkWakeMaintenance) {
2528 // Early/late tickle for non-maintenance wake.
2529 if (((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
2530 kDarkWakeFlagHIDTickleEarly) ||
2531 ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
2532 kDarkWakeFlagHIDTickleLate)) {
2533 darkWakePostTickle = true;
2534 }
2535 }
2536 #else /* !__i386__ && !__x86_64__ */
2537 timeSinceReset = ml_get_time_since_reset();
2538
2539 kdebugTrace(kPMLogSystemWake, 0, timeSinceReset >> 32, timeSinceReset);
2540 // stay awake for at least 30 seconds
2541 wranglerTickled = true;
2542 fullWakeReason = kFullWakeReasonLocalUser;
2543 startIdleSleepTimer(30);
2544 #endif
2545 sleepCnt++;
2546
2547 thread_call_enter(updateConsoleUsersEntry);
2548
2549 changePowerStateToPriv(ON_STATE);
2550 } break;
2551 #if !__i386__ && !__x86_64__
2552 case ON_STATE: {
2553 if (previousPowerState != ON_STATE) {
2554 DLOG("Force re-evaluating aggressiveness\n");
2555 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
2556 pmPowerStateQueue->submitPowerEvent(
2557 kPowerEventPolicyStimulus,
2558 (void *) kStimulusNoIdleSleepPreventers );
2559 }
2560 break;
2561 }
2562
2563 #endif
2564 }
2565 notifierThread = NULL;
2566 }
2567
2568 //******************************************************************************
2569 // requestPowerDomainState
2570 //
2571 // Extend implementation in IOService. Running on PM work loop thread.
2572 //******************************************************************************
2573
2574 IOReturn
2575 IOPMrootDomain::requestPowerDomainState(
2576 IOPMPowerFlags childDesire,
2577 IOPowerConnection * childConnection,
2578 unsigned long specification )
2579 {
2580 // Idle and system sleep prevention flags affects driver desire.
2581 // Children desire are irrelevant so they are cleared.
2582
2583 return super::requestPowerDomainState(0, childConnection, specification);
2584 }
2585
2586
2587 //******************************************************************************
2588 // updatePreventIdleSleepList
2589 //
2590 // Called by IOService on PM work loop.
2591 // Returns true if PM policy recognized the driver's desire to prevent idle
2592 // sleep and updated the list of idle sleep preventers. Returns false otherwise
2593 //******************************************************************************
2594
2595 bool
2596 IOPMrootDomain::updatePreventIdleSleepList(
2597 IOService * service, bool addNotRemove )
2598 {
2599 unsigned int oldCount, newCount;
2600
2601 ASSERT_GATED();
2602
2603 #if defined(__i386__) || defined(__x86_64__)
2604 // Disregard disk I/O (besides the display wrangler) as a factor preventing
2605 // idle sleep, except in the case of legacy disk I/O
2606 if ((service != wrangler) && (service != this)) {
2607 return false;
2608 }
2609 #endif
2610
2611 oldCount = preventIdleSleepList->getCount();
2612 if (addNotRemove) {
2613 preventIdleSleepList->setObject(service);
2614 DLOG("prevent idle sleep list: %s+ (%u)\n",
2615 service->getName(), preventIdleSleepList->getCount());
2616 } else if (preventIdleSleepList->member(service)) {
2617 preventIdleSleepList->removeObject(service);
2618 DLOG("prevent idle sleep list: %s- (%u)\n",
2619 service->getName(), preventIdleSleepList->getCount());
2620 }
2621 newCount = preventIdleSleepList->getCount();
2622
2623 if ((oldCount == 0) && (newCount != 0)) {
2624 // Driver added to empty prevent list.
2625 // Update the driver desire to prevent idle sleep.
2626 // Driver desire does not prevent demand sleep.
2627
2628 changePowerStateTo(ON_STATE);
2629 } else if ((oldCount != 0) && (newCount == 0)) {
2630 // Last driver removed from prevent list.
2631 // Drop the driver clamp to allow idle sleep.
2632
2633 changePowerStateTo(SLEEP_STATE);
2634 evaluatePolicy( kStimulusNoIdleSleepPreventers );
2635 }
2636 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier,
2637 &newCount, sizeof(newCount));
2638
2639 #if defined(__i386__) || defined(__x86_64__)
2640 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
2641 DLOG("Cannot cancel idle sleep\n");
2642 return false; // do not idle-cancel
2643 }
2644 #endif
2645
2646 return true;
2647 }
2648
2649 //******************************************************************************
2650 // startSpinDump
2651 //******************************************************************************
2652
2653 void
2654 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
2655 {
2656 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
2657 }
2658
2659 //******************************************************************************
2660 // preventSystemSleepListUpdate
2661 //
2662 // Called by IOService on PM work loop.
2663 //******************************************************************************
2664
2665 void
2666 IOPMrootDomain::updatePreventSystemSleepList(
2667 IOService * service, bool addNotRemove )
2668 {
2669 unsigned int oldCount, newCount;
2670
2671 ASSERT_GATED();
2672 if (this == service) {
2673 return;
2674 }
2675
2676 oldCount = preventSystemSleepList->getCount();
2677 if (addNotRemove) {
2678 preventSystemSleepList->setObject(service);
2679 DLOG("prevent system sleep list: %s+ (%u)\n",
2680 service->getName(), preventSystemSleepList->getCount());
2681 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2682 AbsoluteTime now;
2683 clock_usec_t microsecs;
2684 clock_get_uptime(&now);
2685 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2686 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2687 if (assertOnWakeReport) {
2688 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2689 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2690 }
2691 }
2692 } else if (preventSystemSleepList->member(service)) {
2693 preventSystemSleepList->removeObject(service);
2694 DLOG("prevent system sleep list: %s- (%u)\n",
2695 service->getName(), preventSystemSleepList->getCount());
2696
2697 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
2698 // Lost all system sleep preventers.
2699 // Send stimulus if system sleep was blocked, and is in dark wake.
2700 evaluatePolicy( kStimulusDarkWakeEvaluate );
2701 }
2702 }
2703 newCount = preventSystemSleepList->getCount();
2704 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier,
2705 &newCount, sizeof(newCount));
2706 }
2707
2708 void
2709 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
2710 {
2711 OSCollectionIterator *iterator = NULL;
2712 OSObject *object = NULL;
2713 OSArray *array = NULL;
2714
2715 if (!gIOPMWorkLoop->inGate()) {
2716 gIOPMWorkLoop->runAction(
2717 OSMemberFunctionCast(IOWorkLoop::Action, this,
2718 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
2719 this, (void *)idleSleepList, (void *)systemSleepList);
2720 return;
2721 }
2722
2723 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
2724 iterator = OSCollectionIterator::withCollection(preventIdleSleepList);
2725 array = OSArray::withCapacity(5);
2726
2727 while ((object = iterator->getNextObject())) {
2728 IOService *service = OSDynamicCast(IOService, object);
2729 if (object) {
2730 array->setObject(OSSymbol::withCString(service->getName()));
2731 }
2732 }
2733
2734 iterator->release();
2735 *idleSleepList = array;
2736 }
2737
2738 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
2739 iterator = OSCollectionIterator::withCollection(preventSystemSleepList);
2740 array = OSArray::withCapacity(5);
2741
2742 while ((object = iterator->getNextObject())) {
2743 IOService *service = OSDynamicCast(IOService, object);
2744 if (object) {
2745 array->setObject(OSSymbol::withCString(service->getName()));
2746 }
2747 }
2748
2749 iterator->release();
2750 *systemSleepList = array;
2751 }
2752 }
2753
2754 //******************************************************************************
2755 // tellChangeDown
2756 //
2757 // Override the superclass implementation to send a different message type.
2758 //******************************************************************************
2759
2760 bool
2761 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
2762 {
2763 DLOG("tellChangeDown %u->%u\n",
2764 (uint32_t) getPowerState(), (uint32_t) stateNum);
2765
2766 if (SLEEP_STATE == stateNum) {
2767 // Legacy apps were already told in the full->dark transition
2768 if (!ignoreTellChangeDown) {
2769 tracePoint( kIOPMTracePointSleepApplications );
2770 } else {
2771 tracePoint( kIOPMTracePointSleepPriorityClients );
2772 }
2773 }
2774
2775 if (!ignoreTellChangeDown) {
2776 userActivityAtSleep = userActivityCount;
2777 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
2778
2779 if (SLEEP_STATE == stateNum) {
2780 hibernateAborted = false;
2781
2782 // Direct callout into OSKext so it can disable kext unloads
2783 // during sleep/wake to prevent deadlocks.
2784 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
2785
2786 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
2787
2788 // Two change downs are sent by IOServicePM. Ignore the 2nd.
2789 // But tellClientsWithResponse() must be called for both.
2790 ignoreTellChangeDown = true;
2791 }
2792 }
2793
2794 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
2795 }
2796
2797 //******************************************************************************
2798 // askChangeDown
2799 //
2800 // Override the superclass implementation to send a different message type.
2801 // This must be idle sleep since we don't ask during any other power change.
2802 //******************************************************************************
2803
2804 bool
2805 IOPMrootDomain::askChangeDown( unsigned long stateNum )
2806 {
2807 DLOG("askChangeDown %u->%u\n",
2808 (uint32_t) getPowerState(), (uint32_t) stateNum);
2809
2810 // Don't log for dark wake entry
2811 if (kSystemTransitionSleep == _systemTransitionType) {
2812 tracePoint( kIOPMTracePointSleepApplications );
2813 }
2814
2815 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
2816 }
2817
2818 //******************************************************************************
2819 // askChangeDownDone
2820 //
2821 // An opportunity for root domain to cancel the power transition,
2822 // possibily due to an assertion created by powerd in response to
2823 // kIOMessageCanSystemSleep.
2824 //
2825 // Idle sleep:
2826 // full -> dark wake transition
2827 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
2828 // 2. askChangeDownDone()
2829 // dark -> sleep transition
2830 // 1. Notify powerd with kIOMessageCanSystemSleep
2831 // 2. askChangeDownDone()
2832 //
2833 // Demand sleep:
2834 // full -> dark wake transition
2835 // 1. Notify powerd with kIOMessageCanSystemSleep
2836 // 2. askChangeDownDone()
2837 // dark -> sleep transition
2838 // 1. Notify powerd with kIOMessageCanSystemSleep
2839 // 2. askChangeDownDone()
2840 //******************************************************************************
2841
2842 void
2843 IOPMrootDomain::askChangeDownDone(
2844 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
2845 {
2846 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
2847 *inOutChangeFlags, *cancel,
2848 _systemTransitionType,
2849 _currentCapability, _pendingCapability);
2850
2851 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
2852 // Dark->Sleep transition.
2853 // Check if there are any deny sleep assertions.
2854 // lastSleepReason already set by handleOurPowerChangeStart()
2855
2856 if (!checkSystemCanSleep(lastSleepReason)) {
2857 // Cancel dark wake to sleep transition.
2858 // Must re-scan assertions upon entering dark wake.
2859
2860 *cancel = true;
2861 DLOG("cancel dark->sleep\n");
2862 }
2863 }
2864 }
2865
2866 //******************************************************************************
2867 // systemDidNotSleep
2868 //
2869 // Work common to both canceled or aborted sleep.
2870 //******************************************************************************
2871
2872 void
2873 IOPMrootDomain::systemDidNotSleep( void )
2874 {
2875 // reset console lock state
2876 thread_call_enter(updateConsoleUsersEntry);
2877
2878 if (!wrangler) {
2879 if (idleSleepEnabled) {
2880 // stay awake for at least idleSeconds
2881 startIdleSleepTimer(idleSeconds);
2882 }
2883 } else {
2884 if (idleSleepEnabled && !userIsActive) {
2885 // Manually start the idle sleep timer besides waiting for
2886 // the user to become inactive.
2887 startIdleSleepTimer( kIdleSleepRetryInterval );
2888 }
2889 }
2890
2891 preventTransitionToUserActive(false);
2892 IOService::setAdvisoryTickleEnable( true );
2893
2894 // After idle revert and cancel, send a did-change message to powerd
2895 // to balance the previous will-change message. Kernel clients do not
2896 // need this since sleep cannot be canceled once they are notified.
2897
2898 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
2899 (_pendingCapability != _currentCapability) &&
2900 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
2901 // Differs from a real capability gain change where notifyRef != 0,
2902 // but it is zero here since no response is expected.
2903
2904 IOPMSystemCapabilityChangeParameters params;
2905
2906 bzero(&params, sizeof(params));
2907 params.fromCapabilities = _pendingCapability;
2908 params.toCapabilities = _currentCapability;
2909 params.changeFlags = kIOPMSystemCapabilityDidChange;
2910
2911 DLOG("MESG cap %x->%x did change\n",
2912 params.fromCapabilities, params.toCapabilities);
2913 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier,
2914 &params, sizeof(params));
2915 }
2916 }
2917
2918 //******************************************************************************
2919 // tellNoChangeDown
2920 //
2921 // Notify registered applications and kernel clients that we are not dropping
2922 // power.
2923 //
2924 // We override the superclass implementation so we can send a different message
2925 // type to the client or application being notified.
2926 //
2927 // This must be a vetoed idle sleep, since no other power change can be vetoed.
2928 //******************************************************************************
2929
2930 void
2931 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
2932 {
2933 DLOG("tellNoChangeDown %u->%u\n",
2934 (uint32_t) getPowerState(), (uint32_t) stateNum);
2935
2936 // Sleep canceled, clear the sleep trace point.
2937 tracePoint(kIOPMTracePointSystemUp);
2938
2939 systemDidNotSleep();
2940 return tellClients( kIOMessageSystemWillNotSleep );
2941 }
2942
2943 //******************************************************************************
2944 // tellChangeUp
2945 //
2946 // Notify registered applications and kernel clients that we are raising power.
2947 //
2948 // We override the superclass implementation so we can send a different message
2949 // type to the client or application being notified.
2950 //******************************************************************************
2951
2952 void
2953 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
2954 {
2955 DLOG("tellChangeUp %u->%u\n",
2956 (uint32_t) getPowerState(), (uint32_t) stateNum);
2957
2958 ignoreTellChangeDown = false;
2959
2960 if (stateNum == ON_STATE) {
2961 // Direct callout into OSKext so it can disable kext unloads
2962 // during sleep/wake to prevent deadlocks.
2963 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
2964
2965 // Notify platform that sleep was cancelled or resumed.
2966 getPlatform()->callPlatformFunction(
2967 sleepMessagePEFunction, false,
2968 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
2969 NULL, NULL, NULL);
2970
2971 if (getPowerState() == ON_STATE) {
2972 // this is a quick wake from aborted sleep
2973 systemDidNotSleep();
2974 tellClients( kIOMessageSystemWillPowerOn );
2975 }
2976
2977 tracePoint( kIOPMTracePointWakeApplications );
2978 tellClients( kIOMessageSystemHasPoweredOn );
2979 }
2980 }
2981
2982 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
2983 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
2984 ((params)->fromCapabilities & (flag)) && \
2985 (((params)->toCapabilities & (flag)) == 0))
2986
2987 #define CAP_DID_CHANGE_TO_ON(params, flag) \
2988 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
2989 ((params)->toCapabilities & (flag)) && \
2990 (((params)->fromCapabilities & (flag)) == 0))
2991
2992 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
2993 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
2994 ((params)->fromCapabilities & (flag)) && \
2995 (((params)->toCapabilities & (flag)) == 0))
2996
2997 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
2998 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
2999 ((params)->toCapabilities & (flag)) && \
3000 (((params)->fromCapabilities & (flag)) == 0))
3001
3002 //******************************************************************************
3003 // sysPowerDownHandler
3004 //
3005 // Perform a vfs sync before system sleep.
3006 //******************************************************************************
3007
3008 IOReturn
3009 IOPMrootDomain::sysPowerDownHandler(
3010 void * target, void * refCon,
3011 UInt32 messageType, IOService * service,
3012 void * messageArgs, vm_size_t argSize )
3013 {
3014 IOReturn ret = 0;
3015
3016 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3017
3018 if (!gRootDomain) {
3019 return kIOReturnUnsupported;
3020 }
3021
3022 if (messageType == kIOMessageSystemCapabilityChange) {
3023 IOPMSystemCapabilityChangeParameters * params =
3024 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3025
3026 // Interested applications have been notified of an impending power
3027 // change and have acked (when applicable).
3028 // This is our chance to save whatever state we can before powering
3029 // down.
3030 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3031 // via callout
3032
3033 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3034 params->fromCapabilities, params->toCapabilities,
3035 params->changeFlags);
3036
3037 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3038 // We will ack within 20 seconds
3039 params->maxWaitForReply = 20 * 1000 * 1000;
3040
3041 #if HIBERNATION
3042 gRootDomain->evaluateSystemSleepPolicyEarly();
3043
3044 // add in time we could spend freeing pages
3045 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3046 params->maxWaitForReply = kCapabilityClientMaxWait;
3047 }
3048 DLOG("sysPowerDownHandler max wait %d s\n",
3049 (int) (params->maxWaitForReply / 1000 / 1000));
3050 #endif
3051
3052 // Notify platform that sleep has begun, after the early
3053 // sleep policy evaluation.
3054 getPlatform()->callPlatformFunction(
3055 sleepMessagePEFunction, false,
3056 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3057 NULL, NULL, NULL);
3058
3059 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3060 // Purposely delay the ack and hope that shutdown occurs quickly.
3061 // Another option is not to schedule the thread and wait for
3062 // ack timeout...
3063 AbsoluteTime deadline;
3064 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3065 thread_call_enter1_delayed(
3066 gRootDomain->diskSyncCalloutEntry,
3067 (thread_call_param_t)(uintptr_t) params->notifyRef,
3068 deadline );
3069 } else {
3070 thread_call_enter1(
3071 gRootDomain->diskSyncCalloutEntry,
3072 (thread_call_param_t)(uintptr_t) params->notifyRef);
3073 }
3074 }
3075 #if HIBERNATION
3076 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3077 // We will ack within 110 seconds
3078 params->maxWaitForReply = 110 * 1000 * 1000;
3079
3080 thread_call_enter1(
3081 gRootDomain->diskSyncCalloutEntry,
3082 (thread_call_param_t)(uintptr_t) params->notifyRef);
3083 }
3084 #endif
3085 ret = kIOReturnSuccess;
3086 }
3087
3088 return ret;
3089 }
3090
3091 //******************************************************************************
3092 // handleQueueSleepWakeUUID
3093 //
3094 // Called from IOPMrootDomain when we're initiating a sleep,
3095 // or indirectly from PM configd when PM decides to clear the UUID.
3096 // PM clears the UUID several minutes after successful wake from sleep,
3097 // so that we might associate App spindumps with the immediately previous
3098 // sleep/wake.
3099 //
3100 // @param obj has a retain on it. We're responsible for releasing that retain.
3101 //******************************************************************************
3102
3103 void
3104 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3105 {
3106 OSString *str = NULL;
3107
3108 if (kOSBooleanFalse == obj) {
3109 handlePublishSleepWakeUUID(NULL);
3110 } else if ((str = OSDynamicCast(OSString, obj))) {
3111 // This branch caches the UUID for an upcoming sleep/wake
3112 if (queuedSleepWakeUUIDString) {
3113 queuedSleepWakeUUIDString->release();
3114 queuedSleepWakeUUIDString = NULL;
3115 }
3116 queuedSleepWakeUUIDString = str;
3117 queuedSleepWakeUUIDString->retain();
3118
3119 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3120 }
3121
3122 if (obj) {
3123 obj->release();
3124 }
3125 return;
3126 }
3127 //******************************************************************************
3128 // handlePublishSleepWakeUUID
3129 //
3130 // Called from IOPMrootDomain when we're initiating a sleep,
3131 // or indirectly from PM configd when PM decides to clear the UUID.
3132 // PM clears the UUID several minutes after successful wake from sleep,
3133 // so that we might associate App spindumps with the immediately previous
3134 // sleep/wake.
3135 //******************************************************************************
3136
3137 void
3138 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3139 {
3140 ASSERT_GATED();
3141
3142 /*
3143 * Clear the current UUID
3144 */
3145 if (gSleepWakeUUIDIsSet) {
3146 DLOG("SleepWake UUID cleared\n");
3147
3148 gSleepWakeUUIDIsSet = false;
3149
3150 removeProperty(kIOPMSleepWakeUUIDKey);
3151 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3152 }
3153
3154 /*
3155 * Optionally, publish a new UUID
3156 */
3157 if (queuedSleepWakeUUIDString && shouldPublish) {
3158 OSString *publishThisUUID = NULL;
3159
3160 publishThisUUID = queuedSleepWakeUUIDString;
3161 publishThisUUID->retain();
3162
3163 if (publishThisUUID) {
3164 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID);
3165 publishThisUUID->release();
3166 }
3167
3168 gSleepWakeUUIDIsSet = true;
3169 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3170
3171 queuedSleepWakeUUIDString->release();
3172 queuedSleepWakeUUIDString = NULL;
3173 }
3174 }
3175
3176 //******************************************************************************
3177 // IOPMGetSleepWakeUUIDKey
3178 //
3179 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3180 // To get the full key -- a C string -- the buffer must large enough for
3181 // the end-of-string character.
3182 // The key is expected to be an UUID string
3183 //******************************************************************************
3184
3185 extern "C" bool
3186 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3187 {
3188 if (!gSleepWakeUUIDIsSet) {
3189 return false;
3190 }
3191
3192 if (buffer != NULL) {
3193 OSString *string;
3194
3195 string = (OSString *)
3196 gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey);
3197
3198 if (string == NULL) {
3199 *buffer = '\0';
3200 } else {
3201 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3202
3203 string->release();
3204 }
3205 }
3206
3207 return true;
3208 }
3209
3210 //******************************************************************************
3211 // initializeBootSessionUUID
3212 //
3213 // Initialize the boot session uuid at boot up and sets it into registry.
3214 //******************************************************************************
3215
3216 void
3217 IOPMrootDomain::initializeBootSessionUUID(void)
3218 {
3219 uuid_t new_uuid;
3220 uuid_string_t new_uuid_string;
3221
3222 uuid_generate(new_uuid);
3223 uuid_unparse_upper(new_uuid, new_uuid_string);
3224 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
3225
3226 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
3227 }
3228
3229 //******************************************************************************
3230 // changePowerStateTo & changePowerStateToPriv
3231 //
3232 // Override of these methods for logging purposes.
3233 //******************************************************************************
3234
3235 IOReturn
3236 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
3237 {
3238 DLOG("changePowerStateTo(%lu)\n", ordinal);
3239
3240 if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE)) {
3241 return kIOReturnUnsupported;
3242 }
3243
3244 return super::changePowerStateTo(ordinal);
3245 }
3246
3247 IOReturn
3248 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
3249 {
3250 DLOG("changePowerStateToPriv(%lu)\n", ordinal);
3251
3252 if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE)) {
3253 return kIOReturnUnsupported;
3254 }
3255
3256 return super::changePowerStateToPriv(ordinal);
3257 }
3258
3259 //******************************************************************************
3260 // activity detect
3261 //
3262 //******************************************************************************
3263
3264 bool
3265 IOPMrootDomain::activitySinceSleep(void)
3266 {
3267 return userActivityCount != userActivityAtSleep;
3268 }
3269
3270 bool
3271 IOPMrootDomain::abortHibernation(void)
3272 {
3273 bool ret = activitySinceSleep();
3274
3275 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
3276 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
3277 hibernateAborted = true;
3278 }
3279 return ret;
3280 }
3281
3282 extern "C" int
3283 hibernate_should_abort(void)
3284 {
3285 if (gRootDomain) {
3286 return gRootDomain->abortHibernation();
3287 } else {
3288 return 0;
3289 }
3290 }
3291
3292 //******************************************************************************
3293 // willNotifyPowerChildren
3294 //
3295 // Called after all interested drivers have all acknowledged the power change,
3296 // but before any power children is informed. Dispatched though a thread call,
3297 // so it is safe to perform work that might block on a sleeping disk. PM state
3298 // machine (not thread) will block w/o timeout until this function returns.
3299 //******************************************************************************
3300
3301 void
3302 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
3303 {
3304 OSDictionary *dict;
3305 OSNumber *secs;
3306
3307 if (SLEEP_STATE == newPowerState) {
3308 notifierThread = current_thread();
3309 if (!tasksSuspended) {
3310 AbsoluteTime deadline;
3311 tasksSuspended = TRUE;
3312 tasks_system_suspend(tasksSuspended);
3313
3314 clock_interval_to_deadline(10, kSecondScale, &deadline);
3315 #if !CONFIG_EMBEDDED
3316 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
3317 #endif /* !CONFIG_EMBEDDED */
3318 }
3319
3320 #if HIBERNATION
3321 IOHibernateSystemSleep();
3322 IOHibernateIOKitSleep();
3323 #endif
3324 if (gRootDomain->activitySinceSleep()) {
3325 dict = OSDictionary::withCapacity(1);
3326 secs = OSNumber::withNumber(1, 32);
3327
3328 if (dict && secs) {
3329 dict->setObject(gIOPMSettingDebugWakeRelativeKey, secs);
3330 gRootDomain->setProperties(dict);
3331 MSG("Reverting sleep with relative wake\n");
3332 }
3333 if (dict) {
3334 dict->release();
3335 }
3336 if (secs) {
3337 secs->release();
3338 }
3339 }
3340
3341 notifierThread = NULL;
3342 }
3343 }
3344
3345 //******************************************************************************
3346 // sleepOnClamshellClosed
3347 //
3348 // contains the logic to determine if the system should sleep when the clamshell
3349 // is closed.
3350 //******************************************************************************
3351
3352 bool
3353 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3354 {
3355 if (!clamshellExists) {
3356 return false;
3357 }
3358
3359 DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3360 clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled);
3361
3362 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled;
3363 }
3364
3365 void
3366 IOPMrootDomain::sendClientClamshellNotification( void )
3367 {
3368 /* Only broadcast clamshell alert if clamshell exists. */
3369 if (!clamshellExists) {
3370 return;
3371 }
3372
3373 setProperty(kAppleClamshellStateKey,
3374 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
3375
3376 setProperty(kAppleClamshellCausesSleepKey,
3377 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
3378
3379 /* Argument to message is a bitfiel of
3380 * ( kClamshellStateBit | kClamshellSleepBit )
3381 */
3382 messageClients(kIOPMMessageClamshellStateChange,
3383 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
3384 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
3385 }
3386
3387 //******************************************************************************
3388 // getSleepSupported
3389 //
3390 // Deprecated
3391 //******************************************************************************
3392
3393 IOOptionBits
3394 IOPMrootDomain::getSleepSupported( void )
3395 {
3396 return platformSleepSupport;
3397 }
3398
3399 //******************************************************************************
3400 // setSleepSupported
3401 //
3402 // Deprecated
3403 //******************************************************************************
3404
3405 void
3406 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
3407 {
3408 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
3409 OSBitOrAtomic(flags, &platformSleepSupport);
3410 }
3411
3412 //******************************************************************************
3413 // setDisableClamShellSleep
3414 //
3415 //******************************************************************************
3416
3417 void
3418 IOPMrootDomain::setDisableClamShellSleep( bool val )
3419 {
3420 if (gIOPMWorkLoop->inGate() == false) {
3421 gIOPMWorkLoop->runAction(
3422 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setDisableClamShellSleep),
3423 (OSObject *)this,
3424 (void *)val);
3425
3426 return;
3427 } else {
3428 DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val);
3429 if (clamshellSleepDisabled != val) {
3430 clamshellSleepDisabled = val;
3431 // If clamshellSleepDisabled is reset to 0, reevaluate if
3432 // system need to go to sleep due to clamshell state
3433 if (!clamshellSleepDisabled && clamshellClosed) {
3434 handlePowerNotification(kLocalEvalClamshellCommand);
3435 }
3436 }
3437 }
3438 }
3439
3440 //******************************************************************************
3441 // wakeFromDoze
3442 //
3443 // Deprecated.
3444 //******************************************************************************
3445
3446 void
3447 IOPMrootDomain::wakeFromDoze( void )
3448 {
3449 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
3450 }
3451
3452 // MARK: -
3453 // MARK: Features
3454
3455 //******************************************************************************
3456 // publishFeature
3457 //
3458 // Adds a new feature to the supported features dictionary
3459 //******************************************************************************
3460
3461 void
3462 IOPMrootDomain::publishFeature( const char * feature )
3463 {
3464 publishFeature(feature, kRD_AllPowerSources, NULL);
3465 }
3466
3467 //******************************************************************************
3468 // publishFeature (with supported power source specified)
3469 //
3470 // Adds a new feature to the supported features dictionary
3471 //******************************************************************************
3472
3473 void
3474 IOPMrootDomain::publishFeature(
3475 const char *feature,
3476 uint32_t supportedWhere,
3477 uint32_t *uniqueFeatureID)
3478 {
3479 static uint16_t next_feature_id = 500;
3480
3481 OSNumber *new_feature_data = NULL;
3482 OSNumber *existing_feature = NULL;
3483 OSArray *existing_feature_arr = NULL;
3484 OSObject *osObj = NULL;
3485 uint32_t feature_value = 0;
3486
3487 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
3488
3489 if (!supportedWhere) {
3490 // Feature isn't supported anywhere!
3491 return;
3492 }
3493
3494 if (next_feature_id > 5000) {
3495 // Far, far too many features!
3496 return;
3497 }
3498
3499 if (featuresDictLock) {
3500 IOLockLock(featuresDictLock);
3501 }
3502
3503 OSDictionary *features =
3504 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
3505
3506 // Create new features dict if necessary
3507 if (features && OSDynamicCast(OSDictionary, features)) {
3508 features = OSDictionary::withDictionary(features);
3509 } else {
3510 features = OSDictionary::withCapacity(1);
3511 }
3512
3513 // Create OSNumber to track new feature
3514
3515 next_feature_id += 1;
3516 if (uniqueFeatureID) {
3517 // We don't really mind if the calling kext didn't give us a place
3518 // to stash their unique id. Many kexts don't plan to unload, and thus
3519 // have no need to remove themselves later.
3520 *uniqueFeatureID = next_feature_id;
3521 }
3522
3523 feature_value = (uint32_t)next_feature_id;
3524 feature_value <<= 16;
3525 feature_value += supportedWhere;
3526
3527 new_feature_data = OSNumber::withNumber(
3528 (unsigned long long)feature_value, 32);
3529
3530 // Does features object already exist?
3531 if ((osObj = features->getObject(feature))) {
3532 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
3533 // We need to create an OSArray to hold the now 2 elements.
3534 existing_feature_arr = OSArray::withObjects(
3535 (const OSObject **)&existing_feature, 1, 2);
3536 } else if ((existing_feature_arr = OSDynamicCast(OSArray, osObj))) {
3537 // Add object to existing array
3538 existing_feature_arr = OSArray::withArray(
3539 existing_feature_arr,
3540 existing_feature_arr->getCount() + 1);
3541 }
3542
3543 if (existing_feature_arr) {
3544 existing_feature_arr->setObject(new_feature_data);
3545 features->setObject(feature, existing_feature_arr);
3546 existing_feature_arr->release();
3547 existing_feature_arr = 0;
3548 }
3549 } else {
3550 // The easy case: no previously existing features listed. We simply
3551 // set the OSNumber at key 'feature' and we're on our way.
3552 features->setObject(feature, new_feature_data);
3553 }
3554
3555 new_feature_data->release();
3556
3557 setProperty(kRootDomainSupportedFeatures, features);
3558
3559 features->release();
3560
3561 if (featuresDictLock) {
3562 IOLockUnlock(featuresDictLock);
3563 }
3564
3565 // Notify EnergySaver and all those in user space so they might
3566 // re-populate their feature specific UI
3567 if (pmPowerStateQueue) {
3568 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
3569 }
3570 }
3571
3572 //******************************************************************************
3573 // removePublishedFeature
3574 //
3575 // Removes previously published feature
3576 //******************************************************************************
3577
3578 IOReturn
3579 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
3580 {
3581 IOReturn ret = kIOReturnError;
3582 uint32_t feature_value = 0;
3583 uint16_t feature_id = 0;
3584 bool madeAChange = false;
3585
3586 OSSymbol *dictKey = NULL;
3587 OSCollectionIterator *dictIterator = NULL;
3588 OSArray *arrayMember = NULL;
3589 OSNumber *numberMember = NULL;
3590 OSObject *osObj = NULL;
3591 OSNumber *osNum = NULL;
3592 OSArray *arrayMemberCopy;
3593
3594 if (kBadPMFeatureID == removeFeatureID) {
3595 return kIOReturnNotFound;
3596 }
3597
3598 if (featuresDictLock) {
3599 IOLockLock(featuresDictLock);
3600 }
3601
3602 OSDictionary *features =
3603 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
3604
3605 if (features && OSDynamicCast(OSDictionary, features)) {
3606 // Any modifications to the dictionary are made to the copy to prevent
3607 // races & crashes with userland clients. Dictionary updated
3608 // automically later.
3609 features = OSDictionary::withDictionary(features);
3610 } else {
3611 features = NULL;
3612 ret = kIOReturnNotFound;
3613 goto exit;
3614 }
3615
3616 // We iterate 'features' dictionary looking for an entry tagged
3617 // with 'removeFeatureID'. If found, we remove it from our tracking
3618 // structures and notify the OS via a general interest message.
3619
3620 dictIterator = OSCollectionIterator::withCollection(features);
3621 if (!dictIterator) {
3622 goto exit;
3623 }
3624
3625 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
3626 osObj = features->getObject(dictKey);
3627
3628 // Each Feature is either tracked by an OSNumber
3629 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
3630 feature_value = numberMember->unsigned32BitValue();
3631 feature_id = (uint16_t)(feature_value >> 16);
3632
3633 if (feature_id == (uint16_t)removeFeatureID) {
3634 // Remove this node
3635 features->removeObject(dictKey);
3636 madeAChange = true;
3637 break;
3638 }
3639
3640 // Or tracked by an OSArray of OSNumbers
3641 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
3642 unsigned int arrayCount = arrayMember->getCount();
3643
3644 for (unsigned int i = 0; i < arrayCount; i++) {
3645 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
3646 if (!osNum) {
3647 continue;
3648 }
3649
3650 feature_value = osNum->unsigned32BitValue();
3651 feature_id = (uint16_t)(feature_value >> 16);
3652
3653 if (feature_id == (uint16_t)removeFeatureID) {
3654 // Remove this node
3655 if (1 == arrayCount) {
3656 // If the array only contains one element, remove
3657 // the whole thing.
3658 features->removeObject(dictKey);
3659 } else {
3660 // Otherwise remove the element from a copy of the array.
3661 arrayMemberCopy = OSArray::withArray(arrayMember);
3662 if (arrayMemberCopy) {
3663 arrayMemberCopy->removeObject(i);
3664 features->setObject(dictKey, arrayMemberCopy);
3665 arrayMemberCopy->release();
3666 }
3667 }
3668
3669 madeAChange = true;
3670 break;
3671 }
3672 }
3673 }
3674 }
3675
3676 dictIterator->release();
3677
3678 if (madeAChange) {
3679 ret = kIOReturnSuccess;
3680
3681 setProperty(kRootDomainSupportedFeatures, features);
3682
3683 // Notify EnergySaver and all those in user space so they might
3684 // re-populate their feature specific UI
3685 if (pmPowerStateQueue) {
3686 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
3687 }
3688 } else {
3689 ret = kIOReturnNotFound;
3690 }
3691
3692 exit:
3693 if (features) {
3694 features->release();
3695 }
3696 if (featuresDictLock) {
3697 IOLockUnlock(featuresDictLock);
3698 }
3699 return ret;
3700 }
3701
3702 //******************************************************************************
3703 // publishPMSetting (private)
3704 //
3705 // Should only be called by PMSettingObject to publish a PM Setting as a
3706 // supported feature.
3707 //******************************************************************************
3708
3709 void
3710 IOPMrootDomain::publishPMSetting(
3711 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
3712 {
3713 if (noPublishPMSettings &&
3714 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
3715 // Setting found in noPublishPMSettings array
3716 *featureID = kBadPMFeatureID;
3717 return;
3718 }
3719
3720 publishFeature(
3721 feature->getCStringNoCopy(), where, featureID);
3722 }
3723
3724 //******************************************************************************
3725 // setPMSetting (private)
3726 //
3727 // Internal helper to relay PM settings changes from user space to individual
3728 // drivers. Should be called only by IOPMrootDomain::setProperties.
3729 //******************************************************************************
3730
3731 IOReturn
3732 IOPMrootDomain::setPMSetting(
3733 const OSSymbol *type,
3734 OSObject *object )
3735 {
3736 PMSettingCallEntry *entries = 0;
3737 OSArray *chosen = 0;
3738 const OSArray *array;
3739 PMSettingObject *pmso;
3740 thread_t thisThread;
3741 int i, j, count, capacity;
3742
3743 if (NULL == type) {
3744 return kIOReturnBadArgument;
3745 }
3746
3747 PMSETTING_LOCK();
3748
3749 // Update settings dict so changes are visible from copyPMSetting().
3750 fPMSettingsDict->setObject(type, object);
3751
3752 // Prep all PMSetting objects with the given 'type' for callout.
3753 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
3754 if (!array || ((capacity = array->getCount()) == 0)) {
3755 goto unlock_exit;
3756 }
3757
3758 // Array to retain PMSetting objects targeted for callout.
3759 chosen = OSArray::withCapacity(capacity);
3760 if (!chosen) {
3761 goto unlock_exit; // error
3762 }
3763 entries = IONew(PMSettingCallEntry, capacity);
3764 if (!entries) {
3765 goto unlock_exit; // error
3766 }
3767 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
3768
3769 thisThread = current_thread();
3770
3771 for (i = 0, j = 0; i < capacity; i++) {
3772 pmso = (PMSettingObject *) array->getObject(i);
3773 if (pmso->disabled) {
3774 continue;
3775 }
3776 entries[j].thread = thisThread;
3777 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
3778 chosen->setObject(pmso);
3779 j++;
3780 }
3781 count = j;
3782 if (!count) {
3783 goto unlock_exit;
3784 }
3785
3786 PMSETTING_UNLOCK();
3787
3788 // Call each pmso in the chosen array.
3789 for (i = 0; i < count; i++) {
3790 pmso = (PMSettingObject *) chosen->getObject(i);
3791 pmso->dispatchPMSetting(type, object);
3792 }
3793
3794 PMSETTING_LOCK();
3795 for (i = 0; i < count; i++) {
3796 pmso = (PMSettingObject *) chosen->getObject(i);
3797 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
3798 if (pmso->waitThread) {
3799 PMSETTING_WAKEUP(pmso);
3800 }
3801 }
3802 unlock_exit:
3803 PMSETTING_UNLOCK();
3804
3805 if (chosen) {
3806 chosen->release();
3807 }
3808 if (entries) {
3809 IODelete(entries, PMSettingCallEntry, capacity);
3810 }
3811
3812 return kIOReturnSuccess;
3813 }
3814
3815 //******************************************************************************
3816 // copyPMSetting (public)
3817 //
3818 // Allows kexts to safely read setting values, without being subscribed to
3819 // notifications.
3820 //******************************************************************************
3821
3822 OSObject *
3823 IOPMrootDomain::copyPMSetting(
3824 OSSymbol *whichSetting)
3825 {
3826 OSObject *obj = NULL;
3827
3828 if (!whichSetting) {
3829 return NULL;
3830 }
3831
3832 PMSETTING_LOCK();
3833 obj = fPMSettingsDict->getObject(whichSetting);
3834 if (obj) {
3835 obj->retain();
3836 }
3837 PMSETTING_UNLOCK();
3838
3839 return obj;
3840 }
3841
3842 //******************************************************************************
3843 // registerPMSettingController (public)
3844 //
3845 // direct wrapper to registerPMSettingController with uint32_t power source arg
3846 //******************************************************************************
3847
3848 IOReturn
3849 IOPMrootDomain::registerPMSettingController(
3850 const OSSymbol * settings[],
3851 IOPMSettingControllerCallback func,
3852 OSObject *target,
3853 uintptr_t refcon,
3854 OSObject **handle)
3855 {
3856 return registerPMSettingController(
3857 settings,
3858 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
3859 func, target, refcon, handle);
3860 }
3861
3862 //******************************************************************************
3863 // registerPMSettingController (public)
3864 //
3865 // Kexts may register for notifications when a particular setting is changed.
3866 // A list of settings is available in IOPM.h.
3867 // Arguments:
3868 // * settings - An OSArray containing OSSymbols. Caller should populate this
3869 // array with a list of settings caller wants notifications from.
3870 // * func - A C function callback of the type IOPMSettingControllerCallback
3871 // * target - caller may provide an OSObject *, which PM will pass as an
3872 // target to calls to "func"
3873 // * refcon - caller may provide an void *, which PM will pass as an
3874 // argument to calls to "func"
3875 // * handle - This is a return argument. We will populate this pointer upon
3876 // call success. Hold onto this and pass this argument to
3877 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
3878 // Returns:
3879 // kIOReturnSuccess on success
3880 //******************************************************************************
3881
3882 IOReturn
3883 IOPMrootDomain::registerPMSettingController(
3884 const OSSymbol * settings[],
3885 uint32_t supportedPowerSources,
3886 IOPMSettingControllerCallback func,
3887 OSObject *target,
3888 uintptr_t refcon,
3889 OSObject **handle)
3890 {
3891 PMSettingObject *pmso = NULL;
3892 OSObject *pmsh = NULL;
3893 OSArray *list = NULL;
3894 int i;
3895
3896 if (NULL == settings ||
3897 NULL == func ||
3898 NULL == handle) {
3899 return kIOReturnBadArgument;
3900 }
3901
3902 pmso = PMSettingObject::pmSettingObject(
3903 (IOPMrootDomain *) this, func, target,
3904 refcon, supportedPowerSources, settings, &pmsh);
3905
3906 if (!pmso) {
3907 *handle = NULL;
3908 return kIOReturnInternalError;
3909 }
3910
3911 PMSETTING_LOCK();
3912 for (i = 0; settings[i]; i++) {
3913 list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
3914 if (!list) {
3915 // New array of callbacks for this setting
3916 list = OSArray::withCapacity(1);
3917 settingsCallbacks->setObject(settings[i], list);
3918 list->release();
3919 }
3920
3921 // Add caller to the callback list
3922 list->setObject(pmso);
3923 }
3924 PMSETTING_UNLOCK();
3925
3926 // Return handle to the caller, the setting object is private.
3927 *handle = pmsh;
3928
3929 return kIOReturnSuccess;
3930 }
3931
3932 //******************************************************************************
3933 // deregisterPMSettingObject (private)
3934 //
3935 // Only called from PMSettingObject.
3936 //******************************************************************************
3937
3938 void
3939 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
3940 {
3941 thread_t thisThread = current_thread();
3942 PMSettingCallEntry *callEntry;
3943 OSCollectionIterator *iter;
3944 OSSymbol *sym;
3945 OSArray *array;
3946 int index;
3947 bool wait;
3948
3949 PMSETTING_LOCK();
3950
3951 pmso->disabled = true;
3952
3953 // Wait for all callout threads to finish.
3954 do {
3955 wait = false;
3956 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
3957 {
3958 if (callEntry->thread != thisThread) {
3959 wait = true;
3960 break;
3961 }
3962 }
3963 if (wait) {
3964 assert(0 == pmso->waitThread);
3965 pmso->waitThread = thisThread;
3966 PMSETTING_WAIT(pmso);
3967 pmso->waitThread = 0;
3968 }
3969 } while (wait);
3970
3971 // Search each PM settings array in the kernel.
3972 iter = OSCollectionIterator::withCollection(settingsCallbacks);
3973 if (iter) {
3974 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
3975 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
3976 index = array->getNextIndexOfObject(pmso, 0);
3977 if (-1 != index) {
3978 array->removeObject(index);
3979 }
3980 }
3981 iter->release();
3982 }
3983
3984 PMSETTING_UNLOCK();
3985
3986 pmso->release();
3987 }
3988
3989 //******************************************************************************
3990 // informCPUStateChange
3991 //
3992 // Call into PM CPU code so that CPU power savings may dynamically adjust for
3993 // running on battery, with the lid closed, etc.
3994 //
3995 // informCPUStateChange is a no-op on non x86 systems
3996 // only x86 has explicit support in the IntelCPUPowerManagement kext
3997 //******************************************************************************
3998
3999 void
4000 IOPMrootDomain::informCPUStateChange(
4001 uint32_t type,
4002 uint32_t value )
4003 {
4004 #if defined(__i386__) || defined(__x86_64__)
4005
4006 pmioctlVariableInfo_t varInfoStruct;
4007 int pmCPUret = 0;
4008 const char *varNameStr = NULL;
4009 int32_t *varIndex = NULL;
4010
4011 if (kInformAC == type) {
4012 varNameStr = kIOPMRootDomainBatPowerCString;
4013 varIndex = &idxPMCPULimitedPower;
4014 } else if (kInformLid == type) {
4015 varNameStr = kIOPMRootDomainLidCloseCString;
4016 varIndex = &idxPMCPUClamshell;
4017 } else {
4018 return;
4019 }
4020
4021 // Set the new value!
4022 // pmCPUControl will assign us a new ID if one doesn't exist yet
4023 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
4024 varInfoStruct.varID = *varIndex;
4025 varInfoStruct.varType = vBool;
4026 varInfoStruct.varInitValue = value;
4027 varInfoStruct.varCurValue = value;
4028 strlcpy((char *)varInfoStruct.varName,
4029 (const char *)varNameStr,
4030 sizeof(varInfoStruct.varName));
4031
4032 // Set!
4033 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
4034
4035 // pmCPU only assigns numerical id's when a new varName is specified
4036 if ((0 == pmCPUret)
4037 && (*varIndex == kCPUUnknownIndex)) {
4038 // pmCPUControl has assigned us a new variable ID.
4039 // Let's re-read the structure we just SET to learn that ID.
4040 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
4041
4042 if (0 == pmCPUret) {
4043 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
4044 *varIndex = varInfoStruct.varID;
4045 }
4046 }
4047
4048 return;
4049
4050 #endif /* __i386__ || __x86_64__ */
4051 }
4052
4053 // MARK: -
4054 // MARK: Deep Sleep Policy
4055
4056 #if HIBERNATION
4057
4058 //******************************************************************************
4059 // evaluateSystemSleepPolicy
4060 //******************************************************************************
4061
4062 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
4063
4064 // Sleep flags
4065 enum {
4066 kIOPMSleepFlagHibernate = 0x00000001,
4067 kIOPMSleepFlagSleepTimerEnable = 0x00000002
4068 };
4069
4070 struct IOPMSystemSleepPolicyEntry {
4071 uint32_t factorMask;
4072 uint32_t factorBits;
4073 uint32_t sleepFlags;
4074 uint32_t wakeEvents;
4075 } __attribute__((packed));
4076
4077 struct IOPMSystemSleepPolicyTable {
4078 uint32_t signature;
4079 uint16_t version;
4080 uint16_t entryCount;
4081 IOPMSystemSleepPolicyEntry entries[];
4082 } __attribute__((packed));
4083
4084 enum {
4085 kIOPMSleepAttributeHibernateSetup = 0x00000001,
4086 kIOPMSleepAttributeHibernateSleep = 0x00000002
4087 };
4088
4089 static uint32_t
4090 getSleepTypeAttributes( uint32_t sleepType )
4091 {
4092 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
4093 {
4094 /* invalid */ 0,
4095 /* abort */ 0,
4096 /* normal */ 0,
4097 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
4098 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
4099 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
4100 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
4101 /* deepidle */ 0
4102 };
4103
4104 if (sleepType >= kIOPMSleepTypeLast) {
4105 return 0;
4106 }
4107
4108 return sleepTypeAttributes[sleepType];
4109 }
4110
4111 bool
4112 IOPMrootDomain::evaluateSystemSleepPolicy(
4113 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
4114 {
4115 const IOPMSystemSleepPolicyTable * pt;
4116 OSObject * prop = 0;
4117 OSData * policyData;
4118 uint64_t currentFactors = 0;
4119 uint32_t standbyDelay = 0;
4120 uint32_t powerOffDelay = 0;
4121 uint32_t powerOffTimer = 0;
4122 uint32_t standbyTimer = 0;
4123 uint32_t mismatch;
4124 bool standbyEnabled;
4125 bool powerOffEnabled;
4126 bool found = false;
4127
4128 // Get platform's sleep policy table
4129 if (!gSleepPolicyHandler) {
4130 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
4131 if (!prop) {
4132 goto done;
4133 }
4134 }
4135
4136 // Fetch additional settings
4137 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
4138 && (getProperty(kIOPMDeepSleepEnabledKey) == kOSBooleanTrue));
4139 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
4140 && (getProperty(kIOPMAutoPowerOffEnabledKey) == kOSBooleanTrue));
4141 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
4142 powerOffTimer = powerOffDelay;
4143 }
4144 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
4145 standbyTimer = standbyDelay;
4146 }
4147
4148 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
4149 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
4150 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
4151
4152 // pmset level overrides
4153 if ((*hibMode & kIOHibernateModeOn) == 0) {
4154 if (!gSleepPolicyHandler) {
4155 standbyEnabled = false;
4156 powerOffEnabled = false;
4157 }
4158 } else if (!(*hibMode & kIOHibernateModeSleep)) {
4159 // Force hibernate (i.e. mode 25)
4160 // If standby is enabled, force standy.
4161 // If poweroff is enabled, force poweroff.
4162 if (standbyEnabled) {
4163 currentFactors |= kIOPMSleepFactorStandbyForced;
4164 } else if (powerOffEnabled) {
4165 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
4166 } else {
4167 currentFactors |= kIOPMSleepFactorHibernateForced;
4168 }
4169 }
4170
4171 // Current factors based on environment and assertions
4172 if (sleepTimerMaintenance) {
4173 currentFactors |= kIOPMSleepFactorSleepTimerWake;
4174 }
4175 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
4176 currentFactors |= kIOPMSleepFactorSleepTimerWake;
4177 }
4178 if (!clamshellClosed) {
4179 currentFactors |= kIOPMSleepFactorLidOpen;
4180 }
4181 if (acAdaptorConnected) {
4182 currentFactors |= kIOPMSleepFactorACPower;
4183 }
4184 if (lowBatteryCondition) {
4185 currentFactors |= kIOPMSleepFactorBatteryLow;
4186 }
4187 if (!standbyDelay || !standbyTimer) {
4188 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
4189 }
4190 if (standbyNixed || !standbyEnabled) {
4191 currentFactors |= kIOPMSleepFactorStandbyDisabled;
4192 }
4193 if (resetTimers) {
4194 currentFactors |= kIOPMSleepFactorLocalUserActivity;
4195 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
4196 }
4197 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
4198 kIOPMDriverAssertionLevelOff) {
4199 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
4200 }
4201 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
4202 kIOPMDriverAssertionLevelOff) {
4203 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
4204 }
4205 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
4206 kIOPMDriverAssertionLevelOff) {
4207 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
4208 }
4209 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
4210 kIOPMDriverAssertionLevelOff) {
4211 currentFactors |= kIOPMSleepFactorThunderboltDevice;
4212 }
4213 if (_scheduledAlarms != 0) {
4214 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
4215 }
4216 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
4217 kIOPMDriverAssertionLevelOff) {
4218 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
4219 }
4220 #define TCPKEEPALIVE 1
4221 #if TCPKEEPALIVE
4222 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
4223 kIOPMDriverAssertionLevelOff) {
4224 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
4225 }
4226 #endif
4227 if (!powerOffEnabled) {
4228 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
4229 }
4230 if (desktopMode) {
4231 currentFactors |= kIOPMSleepFactorExternalDisplay;
4232 }
4233 if (userWasActive) {
4234 currentFactors |= kIOPMSleepFactorLocalUserActivity;
4235 }
4236 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
4237 currentFactors |= kIOPMSleepFactorHibernateFailed;
4238 }
4239 if (thermalWarningState) {
4240 currentFactors |= kIOPMSleepFactorThermalWarning;
4241 }
4242
4243 DLOG("sleep factors 0x%llx\n", currentFactors);
4244
4245 if (gSleepPolicyHandler) {
4246 uint32_t savedHibernateMode;
4247 IOReturn result;
4248
4249 if (!gSleepPolicyVars) {
4250 gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1);
4251 if (!gSleepPolicyVars) {
4252 goto done;
4253 }
4254 bzero(gSleepPolicyVars, sizeof(*gSleepPolicyVars));
4255 }
4256 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
4257 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
4258 gSleepPolicyVars->currentCapability = _currentCapability;
4259 gSleepPolicyVars->highestCapability = _highestCapability;
4260 gSleepPolicyVars->sleepFactors = currentFactors;
4261 gSleepPolicyVars->sleepReason = lastSleepReason;
4262 gSleepPolicyVars->sleepPhase = sleepPhase;
4263 gSleepPolicyVars->standbyDelay = standbyDelay;
4264 gSleepPolicyVars->standbyTimer = standbyTimer;
4265 gSleepPolicyVars->poweroffDelay = powerOffDelay;
4266 gSleepPolicyVars->scheduledAlarms = _scheduledAlarms | _userScheduledAlarm;
4267 gSleepPolicyVars->poweroffTimer = powerOffTimer;
4268
4269 if (kIOPMSleepPhase0 == sleepPhase) {
4270 // preserve hibernateMode
4271 savedHibernateMode = gSleepPolicyVars->hibernateMode;
4272 gSleepPolicyVars->hibernateMode = *hibMode;
4273 } else if (kIOPMSleepPhase1 == sleepPhase) {
4274 // use original hibernateMode for phase2
4275 gSleepPolicyVars->hibernateMode = *hibMode;
4276 }
4277
4278 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
4279
4280 if (kIOPMSleepPhase0 == sleepPhase) {
4281 // restore hibernateMode
4282 gSleepPolicyVars->hibernateMode = savedHibernateMode;
4283 }
4284
4285 if ((result != kIOReturnSuccess) ||
4286 (kIOPMSleepTypeInvalid == params->sleepType) ||
4287 (params->sleepType >= kIOPMSleepTypeLast) ||
4288 (kIOPMSystemSleepParametersVersion != params->version)) {
4289 MSG("sleep policy handler error\n");
4290 goto done;
4291 }
4292
4293 if ((getSleepTypeAttributes(params->sleepType) &
4294 kIOPMSleepAttributeHibernateSetup) &&
4295 ((*hibMode & kIOHibernateModeOn) == 0)) {
4296 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
4297 }
4298
4299 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
4300 params->version, params->sleepType, params->sleepFlags,
4301 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
4302 found = true;
4303 goto done;
4304 }
4305
4306 // Policy table is meaningless without standby enabled
4307 if (!standbyEnabled) {
4308 goto done;
4309 }
4310
4311 // Validate the sleep policy table
4312 policyData = OSDynamicCast(OSData, prop);
4313 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
4314 goto done;
4315 }
4316
4317 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
4318 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
4319 (pt->version != 1) || (0 == pt->entryCount)) {
4320 goto done;
4321 }
4322
4323 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
4324 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
4325 goto done;
4326 }
4327
4328 for (uint32_t i = 0; i < pt->entryCount; i++) {
4329 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
4330 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
4331
4332 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
4333 entry->factorMask, entry->factorBits,
4334 entry->sleepFlags, entry->wakeEvents, mismatch);
4335 if (mismatch) {
4336 continue;
4337 }
4338
4339 DLOG("^ found match\n");
4340 found = true;
4341
4342 params->version = kIOPMSystemSleepParametersVersion;
4343 params->reserved1 = 1;
4344 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
4345 params->sleepType = kIOPMSleepTypeStandby;
4346 } else {
4347 params->sleepType = kIOPMSleepTypeNormalSleep;
4348 }
4349
4350 params->ecWakeEvents = entry->wakeEvents;
4351 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
4352 if (kIOPMSleepPhase2 == sleepPhase) {
4353 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
4354
4355 if (!_standbyTimerResetSeconds ||
4356 (now_secs <= _standbyTimerResetSeconds)) {
4357 // Reset standby timer adjustment
4358 _standbyTimerResetSeconds = now_secs;
4359 DLOG("standby delay %u, reset %u\n",
4360 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
4361 } else if (standbyDelay) {
4362 // Shorten the standby delay timer
4363 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
4364 if (standbyDelay > elapsed) {
4365 standbyDelay -= elapsed;
4366 } else {
4367 standbyDelay = 1; // must be > 0
4368 }
4369 DLOG("standby delay %u, elapsed %u\n",
4370 standbyDelay, (uint32_t) elapsed);
4371 }
4372 }
4373 params->ecWakeTimer = standbyDelay;
4374 } else if (kIOPMSleepPhase2 == sleepPhase) {
4375 // A sleep that does not enable the sleep timer will reset
4376 // the standby delay adjustment.
4377 _standbyTimerResetSeconds = 0;
4378 }
4379 break;
4380 }
4381
4382 done:
4383 if (prop) {
4384 prop->release();
4385 }
4386
4387 return found;
4388 }
4389
4390 static IOPMSystemSleepParameters gEarlySystemSleepParams;
4391
4392 void
4393 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
4394 {
4395 // Evaluate early (priority interest phase), before drivers sleep.
4396
4397 DLOG("%s\n", __FUNCTION__);
4398 removeProperty(kIOPMSystemSleepParametersKey);
4399
4400 // Full wake resets the standby timer delay adjustment
4401 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
4402 _standbyTimerResetSeconds = 0;
4403 }
4404
4405 hibernateDisabled = false;
4406 hibernateMode = 0;
4407 getSleepOption(kIOHibernateModeKey, &hibernateMode);
4408
4409 // Save for late evaluation if sleep is aborted
4410 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
4411
4412 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
4413 &hibernateMode)) {
4414 if (!hibernateRetry &&
4415 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
4416 kIOPMSleepAttributeHibernateSetup) == 0)) {
4417 // skip hibernate setup
4418 hibernateDisabled = true;
4419 }
4420 }
4421
4422 // Publish IOPMSystemSleepType
4423 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
4424 if (sleepType == kIOPMSleepTypeInvalid) {
4425 // no sleep policy
4426 sleepType = kIOPMSleepTypeNormalSleep;
4427 if (hibernateMode & kIOHibernateModeOn) {
4428 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
4429 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
4430 }
4431 } else if ((sleepType == kIOPMSleepTypeStandby) &&
4432 (gEarlySystemSleepParams.ecPoweroffTimer)) {
4433 // report the lowest possible sleep state
4434 sleepType = kIOPMSleepTypePowerOff;
4435 }
4436
4437 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
4438 }
4439
4440 void
4441 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
4442 {
4443 IOPMSystemSleepParameters params;
4444 OSData * paramsData;
4445 bool wakeNow;
4446 // Evaluate sleep policy after sleeping drivers but before platform sleep.
4447
4448 DLOG("%s\n", __FUNCTION__);
4449
4450 bzero(&params, sizeof(params));
4451 wakeNow = false;
4452 if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
4453 if ((kIOPMSleepTypeStandby == params.sleepType)
4454 && gIOHibernateStandbyDisabled && gSleepPolicyVars
4455 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
4456 & gSleepPolicyVars->sleepFactors))) {
4457 standbyNixed = true;
4458 wakeNow = true;
4459 }
4460 if (wakeNow
4461 || ((hibernateDisabled || hibernateAborted) &&
4462 (getSleepTypeAttributes(params.sleepType) &
4463 kIOPMSleepAttributeHibernateSetup))) {
4464 // Final evaluation picked a state requiring hibernation,
4465 // but hibernate isn't going to proceed. Arm a short sleep using
4466 // the early non-hibernate sleep parameters.
4467 bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
4468 params.sleepType = kIOPMSleepTypeAbortedSleep;
4469 params.ecWakeTimer = 1;
4470 if (standbyNixed) {
4471 resetTimers = true;
4472 } else {
4473 // Set hibernateRetry flag to force hibernate setup on the
4474 // next sleep.
4475 hibernateRetry = true;
4476 }
4477 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
4478 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
4479 } else {
4480 hibernateRetry = false;
4481 }
4482
4483 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
4484 resetTimers = false;
4485 }
4486
4487 paramsData = OSData::withBytes(&params, sizeof(params));
4488 if (paramsData) {
4489 setProperty(kIOPMSystemSleepParametersKey, paramsData);
4490 paramsData->release();
4491 }
4492
4493 if (getSleepTypeAttributes(params.sleepType) &
4494 kIOPMSleepAttributeHibernateSleep) {
4495 // Disable sleep to force hibernation
4496 gIOHibernateMode &= ~kIOHibernateModeSleep;
4497 }
4498 }
4499 }
4500
4501 bool
4502 IOPMrootDomain::getHibernateSettings(
4503 uint32_t * hibernateModePtr,
4504 uint32_t * hibernateFreeRatio,
4505 uint32_t * hibernateFreeTime )
4506 {
4507 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
4508 // has updated the hibernateDisabled flag.
4509
4510 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
4511 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
4512 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
4513 if (hibernateDisabled) {
4514 *hibernateModePtr = 0;
4515 } else if (gSleepPolicyHandler) {
4516 *hibernateModePtr = hibernateMode;
4517 }
4518 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
4519 return ok;
4520 }
4521
4522 bool
4523 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
4524 {
4525 OSObject * optionsProp;
4526 OSDictionary * optionsDict;
4527 OSObject * obj = 0;
4528 OSNumber * num;
4529 bool ok = false;
4530
4531 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
4532 optionsDict = OSDynamicCast(OSDictionary, optionsProp);
4533
4534 if (optionsDict) {
4535 obj = optionsDict->getObject(key);
4536 if (obj) {
4537 obj->retain();
4538 }
4539 }
4540 if (!obj) {
4541 obj = copyProperty(key);
4542 }
4543 if (obj) {
4544 if ((num = OSDynamicCast(OSNumber, obj))) {
4545 *option = num->unsigned32BitValue();
4546 ok = true;
4547 } else if (OSDynamicCast(OSBoolean, obj)) {
4548 *option = (obj == kOSBooleanTrue) ? 1 : 0;
4549 ok = true;
4550 }
4551 }
4552
4553 if (obj) {
4554 obj->release();
4555 }
4556 if (optionsProp) {
4557 optionsProp->release();
4558 }
4559
4560 return ok;
4561 }
4562 #endif /* HIBERNATION */
4563
4564 IOReturn
4565 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
4566 {
4567 #if HIBERNATION
4568 IOPMSystemSleepParameters params;
4569 uint32_t hibMode = 0;
4570 bool ok;
4571
4572 if (gIOPMWorkLoop->inGate() == false) {
4573 IOReturn ret = gIOPMWorkLoop->runAction(
4574 OSMemberFunctionCast(IOWorkLoop::Action, this,
4575 &IOPMrootDomain::getSystemSleepType),
4576 (OSObject *) this,
4577 (void *) sleepType, (void *) standbyTimer);
4578 return ret;
4579 }
4580
4581 getSleepOption(kIOHibernateModeKey, &hibMode);
4582 bzero(&params, sizeof(params));
4583
4584 ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
4585 if (ok) {
4586 *sleepType = params.sleepType;
4587 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
4588 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
4589 DLOG("Standby delay is not set\n");
4590 *standbyTimer = 0;
4591 }
4592 return kIOReturnSuccess;
4593 }
4594 #endif
4595
4596 return kIOReturnUnsupported;
4597 }
4598
4599 // MARK: -
4600 // MARK: Shutdown and Restart
4601
4602 //******************************************************************************
4603 // handlePlatformHaltRestart
4604 //
4605 //******************************************************************************
4606
4607 // Phases while performing shutdown/restart
4608 typedef enum {
4609 kNotifyDone = 0x00,
4610 kNotifyPriorityClients = 0x10,
4611 kNotifyPowerPlaneDrivers = 0x20,
4612 kNotifyHaltRestartAction = 0x30,
4613 kQuiescePM = 0x40,
4614 } shutdownPhase_t;
4615
4616
4617 struct HaltRestartApplierContext {
4618 IOPMrootDomain * RootDomain;
4619 unsigned long PowerState;
4620 IOPMPowerFlags PowerFlags;
4621 UInt32 MessageType;
4622 UInt32 Counter;
4623 const char * LogString;
4624 shutdownPhase_t phase;
4625
4626 IOServiceInterestHandler handler;
4627 } gHaltRestartCtx;
4628
4629 const char *
4630 shutdownPhase2String(shutdownPhase_t phase)
4631 {
4632 switch (phase) {
4633 case kNotifyDone:
4634 return "Notifications completed";
4635 case kNotifyPriorityClients:
4636 return "Notifying priority clients";
4637 case kNotifyPowerPlaneDrivers:
4638 return "Notifying power plane drivers";
4639 case kNotifyHaltRestartAction:
4640 return "Notifying HaltRestart action handlers";
4641 case kQuiescePM:
4642 return "Quiescing PM";
4643 default:
4644 return "Unknown";
4645 }
4646 }
4647
4648 static void
4649 platformHaltRestartApplier( OSObject * object, void * context )
4650 {
4651 IOPowerStateChangeNotification notify;
4652 HaltRestartApplierContext * ctx;
4653 AbsoluteTime startTime, elapsedTime;
4654 uint32_t deltaTime;
4655
4656 ctx = (HaltRestartApplierContext *) context;
4657
4658 _IOServiceInterestNotifier * notifier;
4659 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
4660 memset(&notify, 0, sizeof(notify));
4661 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
4662 notify.returnValue = 0;
4663 notify.stateNumber = ctx->PowerState;
4664 notify.stateFlags = ctx->PowerFlags;
4665
4666 if (notifier) {
4667 ctx->handler = notifier->handler;
4668 }
4669
4670 clock_get_uptime(&startTime);
4671 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
4672 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
4673
4674 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
4675 LOG("%s handler %p took %u ms\n",
4676 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
4677 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
4678 }
4679
4680 ctx->handler = 0;
4681 ctx->Counter++;
4682 }
4683
4684 static void
4685 quiescePowerTreeCallback( void * target, void * param )
4686 {
4687 IOLockLock(gPMHaltLock);
4688 gPMQuiesced = true;
4689 thread_wakeup(param);
4690 IOLockUnlock(gPMHaltLock);
4691 }
4692
4693 void
4694 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
4695 {
4696 AbsoluteTime startTime, elapsedTime;
4697 uint32_t deltaTime;
4698
4699 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
4700 gHaltRestartCtx.RootDomain = this;
4701
4702 clock_get_uptime(&startTime);
4703 switch (pe_type) {
4704 case kPEHaltCPU:
4705 case kPEUPSDelayHaltCPU:
4706 gHaltRestartCtx.PowerState = OFF_STATE;
4707 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
4708 gHaltRestartCtx.LogString = "PowerOff";
4709 break;
4710
4711 case kPERestartCPU:
4712 gHaltRestartCtx.PowerState = RESTART_STATE;
4713 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
4714 gHaltRestartCtx.LogString = "Restart";
4715 break;
4716
4717 case kPEPagingOff:
4718 gHaltRestartCtx.PowerState = ON_STATE;
4719 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
4720 gHaltRestartCtx.LogString = "PagingOff";
4721 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
4722 #if HIBERNATION
4723 IOHibernateSystemRestart();
4724 #endif
4725 break;
4726
4727 default:
4728 return;
4729 }
4730
4731 gHaltRestartCtx.phase = kNotifyPriorityClients;
4732 // Notify legacy clients
4733 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
4734
4735 // For normal shutdown, turn off File Server Mode.
4736 if (kPEHaltCPU == pe_type) {
4737 const OSSymbol * setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
4738 OSNumber * num = OSNumber::withNumber((unsigned long long) 0, 32);
4739 if (setting && num) {
4740 setPMSetting(setting, num);
4741 setting->release();
4742 num->release();
4743 }
4744 }
4745
4746
4747 if (kPEPagingOff != pe_type) {
4748 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
4749 // Notify in power tree order
4750 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
4751 }
4752
4753 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
4754 IOCPURunPlatformHaltRestartActions(pe_type);
4755
4756 // Wait for PM to quiesce
4757 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
4758 gHaltRestartCtx.phase = kQuiescePM;
4759 AbsoluteTime quiesceTime = mach_absolute_time();
4760
4761 IOLockLock(gPMHaltLock);
4762 gPMQuiesced = false;
4763 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
4764 kIOReturnSuccess) {
4765 while (!gPMQuiesced) {
4766 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
4767 }
4768 }
4769 IOLockUnlock(gPMHaltLock);
4770 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
4771 DLOG("PM quiesce took %u ms\n", deltaTime);
4772 halt_log_enter("Quiesce", NULL, elapsedTime);
4773 }
4774 gHaltRestartCtx.phase = kNotifyDone;
4775
4776 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
4777 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
4778
4779 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
4780
4781 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
4782 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
4783
4784 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
4785 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
4786 }
4787
4788 checkShutdownTimeout();
4789 }
4790
4791 bool
4792 IOPMrootDomain::checkShutdownTimeout()
4793 {
4794 AbsoluteTime elapsedTime;
4795 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
4796
4797 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
4798 return true;
4799 }
4800 return false;
4801 }
4802
4803 void
4804 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
4805 {
4806 if (gHaltLog) {
4807 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
4808 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
4809 }
4810 panic("%s timed out in phase '%s'. Total %d ms:%s",
4811 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
4812 } else {
4813 panic("%s timed out in phase \'%s\'. Total %d ms",
4814 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
4815 }
4816 }
4817
4818 //******************************************************************************
4819 // shutdownSystem
4820 //
4821 //******************************************************************************
4822
4823 IOReturn
4824 IOPMrootDomain::shutdownSystem( void )
4825 {
4826 return kIOReturnUnsupported;
4827 }
4828
4829 //******************************************************************************
4830 // restartSystem
4831 //
4832 //******************************************************************************
4833
4834 IOReturn
4835 IOPMrootDomain::restartSystem( void )
4836 {
4837 return kIOReturnUnsupported;
4838 }
4839
4840 // MARK: -
4841 // MARK: System Capability
4842
4843 //******************************************************************************
4844 // tagPowerPlaneService
4845 //
4846 // Running on PM work loop thread.
4847 //******************************************************************************
4848
4849 void
4850 IOPMrootDomain::tagPowerPlaneService(
4851 IOService * service,
4852 IOPMActions * actions )
4853 {
4854 uint32_t flags = 0;
4855 bool isDisplayWrangler;
4856
4857 memset(actions, 0, sizeof(*actions));
4858 actions->target = this;
4859
4860 if (service == this) {
4861 actions->actionPowerChangeStart =
4862 OSMemberFunctionCast(
4863 IOPMActionPowerChangeStart, this,
4864 &IOPMrootDomain::handleOurPowerChangeStart);
4865
4866 actions->actionPowerChangeDone =
4867 OSMemberFunctionCast(
4868 IOPMActionPowerChangeDone, this,
4869 &IOPMrootDomain::handleOurPowerChangeDone);
4870
4871 actions->actionPowerChangeOverride =
4872 OSMemberFunctionCast(
4873 IOPMActionPowerChangeOverride, this,
4874 &IOPMrootDomain::overrideOurPowerChange);
4875 return;
4876 }
4877
4878 #if !NO_KERNEL_HID
4879 isDisplayWrangler = (0 != service->metaCast("IODisplayWrangler"));
4880 if (isDisplayWrangler) {
4881 wrangler = service;
4882 // found the display wrangler, check for any display assertions already created
4883 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
4884 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
4885 wrangler->setIgnoreIdleTimer( true );
4886 }
4887 }
4888 #else
4889 isDisplayWrangler = false;
4890 #endif
4891
4892 #if defined(__i386__) || defined(__x86_64__)
4893 if (isDisplayWrangler) {
4894 flags |= kPMActionsFlagIsDisplayWrangler;
4895 }
4896 if (service->getProperty("IOPMStrictTreeOrder")) {
4897 flags |= kPMActionsFlagIsGraphicsDevice;
4898 }
4899 if (service->getProperty("IOPMUnattendedWakePowerState")) {
4900 flags |= kPMActionsFlagIsAudioDevice;
4901 }
4902 #endif
4903
4904 // Find the power connection object that is a child of the PCI host
4905 // bridge, and has a graphics/audio device attached below. Mark the
4906 // power branch for delayed child notifications.
4907
4908 if (flags) {
4909 IORegistryEntry * child = service;
4910 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
4911
4912 while (child != this) {
4913 if (child->getProperty("IOPCITunnelled") == kOSBooleanTrue) {
4914 // Skip delaying notifications and clamping power on external graphics and audio devices.
4915 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
4916 flags = 0;
4917 break;
4918 }
4919 if ((parent == pciHostBridgeDriver) ||
4920 (parent == this)) {
4921 if (OSDynamicCast(IOPowerConnection, child)) {
4922 IOPowerConnection * conn = (IOPowerConnection *) child;
4923 conn->delayChildNotification = true;
4924 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
4925 }
4926 break;
4927 }
4928 child = parent;
4929 parent = child->getParentEntry(gIOPowerPlane);
4930 }
4931 }
4932
4933 if (flags) {
4934 DLOG("%s tag flags %x\n", service->getName(), flags);
4935 actions->parameter |= flags;
4936 actions->actionPowerChangeOverride =
4937 OSMemberFunctionCast(
4938 IOPMActionPowerChangeOverride, this,
4939 &IOPMrootDomain::overridePowerChangeForUIService);
4940
4941 if (flags & kPMActionsFlagIsDisplayWrangler) {
4942 actions->actionActivityTickle =
4943 OSMemberFunctionCast(
4944 IOPMActionActivityTickle, this,
4945 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
4946
4947 actions->actionUpdatePowerClient =
4948 OSMemberFunctionCast(
4949 IOPMActionUpdatePowerClient, this,
4950 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
4951 }
4952 return;
4953 }
4954
4955 // Locate the first PCI host bridge for PMTrace.
4956 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
4957 IOService * provider = service->getProvider();
4958 if (OSDynamicCast(IOPlatformDevice, provider) &&
4959 provider->inPlane(gIODTPlane)) {
4960 pciHostBridgeDevice = provider;
4961 pciHostBridgeDriver = service;
4962 DLOG("PMTrace found PCI host bridge %s->%s\n",
4963 provider->getName(), service->getName());
4964 }
4965 }
4966
4967 // Tag top-level PCI devices. The order of PMinit() call does not
4968 // change across boots and is used as the PCI bit number.
4969 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
4970 // Would prefer to check built-in property, but tagPowerPlaneService()
4971 // is called before pciDevice->registerService().
4972 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
4973 if ((parent == pciHostBridgeDevice) && service->getProperty("acpi-device")) {
4974 int bit = pmTracer->recordTopLevelPCIDevice( service );
4975 if (bit >= 0) {
4976 // Save the assigned bit for fast lookup.
4977 actions->parameter |= (bit & kPMActionsPCIBitNumberMask);
4978
4979 actions->actionPowerChangeStart =
4980 OSMemberFunctionCast(
4981 IOPMActionPowerChangeStart, this,
4982 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
4983
4984 actions->actionPowerChangeDone =
4985 OSMemberFunctionCast(
4986 IOPMActionPowerChangeDone, this,
4987 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
4988 }
4989 }
4990 }
4991 }
4992
4993 //******************************************************************************
4994 // PM actions for root domain
4995 //******************************************************************************
4996
4997 void
4998 IOPMrootDomain::overrideOurPowerChange(
4999 IOService * service,
5000 IOPMActions * actions,
5001 IOPMPowerStateIndex * inOutPowerState,
5002 IOPMPowerChangeFlags * inOutChangeFlags,
5003 IOPMRequestTag requestTag )
5004 {
5005 uint32_t powerState = (uint32_t) *inOutPowerState;
5006 uint32_t changeFlags = *inOutChangeFlags;
5007 uint32_t currentPowerState = (uint32_t) getPowerState();
5008
5009 if (changeFlags & kIOPMParentInitiated) {
5010 // Root parent is permanently pegged at max power,
5011 // a parent initiated power change is unexpected.
5012 *inOutChangeFlags |= kIOPMNotDone;
5013 return;
5014 }
5015
5016 if (powerState < currentPowerState) {
5017 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
5018 // Root domain is dropping power state ON->SLEEP.
5019 // If system is in full wake, first enter dark wake by
5020 // converting the power drop to a capability change.
5021 // Once in dark wake, transition to sleep state ASAP.
5022
5023 darkWakeToSleepASAP = true;
5024
5025 // Drop graphics and audio capability
5026 _desiredCapability &= ~(
5027 kIOPMSystemCapabilityGraphics |
5028 kIOPMSystemCapabilityAudio);
5029
5030 // Convert to capability change (ON->ON)
5031 *inOutPowerState = ON_STATE;
5032 *inOutChangeFlags |= kIOPMSynchronize;
5033
5034 // Revert device desire from SLEEP to ON
5035 changePowerStateToPriv(ON_STATE);
5036 } else {
5037 // System is in dark wake, ok to drop power state.
5038 // Broadcast root powering down to entire tree.
5039 *inOutChangeFlags |= kIOPMRootChangeDown;
5040 }
5041 } else if (powerState > currentPowerState) {
5042 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
5043 // Broadcast power up when waking from sleep, but not for the
5044 // initial power change at boot by checking for cpu capability.
5045 *inOutChangeFlags |= kIOPMRootChangeUp;
5046 }
5047 }
5048 }
5049
5050 void
5051 IOPMrootDomain::handleOurPowerChangeStart(
5052 IOService * service,
5053 IOPMActions * actions,
5054 IOPMPowerStateIndex powerState,
5055 IOPMPowerChangeFlags * inOutChangeFlags,
5056 IOPMRequestTag requestTag )
5057 {
5058 uint32_t changeFlags = *inOutChangeFlags;
5059 uint32_t currentPowerState = (uint32_t) getPowerState();
5060 uint32_t sleepReason = requestTag ? requestTag : kIOPMSleepReasonIdle;
5061 bool publishSleepReason = false;
5062
5063 _systemTransitionType = kSystemTransitionNone;
5064 _systemMessageClientMask = 0;
5065 capabilityLoss = false;
5066 toldPowerdCapWillChange = false;
5067
5068 if (lowBatteryCondition) {
5069 // Low battery notification may arrive after the initial sleep request
5070 // has been queued. Override the sleep reason so powerd and others can
5071 // treat this as an emergency sleep.
5072 sleepReason = kIOPMSleepReasonLowPower;
5073 }
5074
5075 // 1. Explicit capability change.
5076
5077 if (changeFlags & kIOPMSynchronize) {
5078 if (powerState == ON_STATE) {
5079 if (changeFlags & kIOPMSyncNoChildNotify) {
5080 _systemTransitionType = kSystemTransitionNewCapClient;
5081 } else {
5082 _systemTransitionType = kSystemTransitionCapability;
5083 }
5084 }
5085 }
5086 // 2. Going to sleep (cancellation still possible).
5087 else if (powerState < currentPowerState) {
5088 _systemTransitionType = kSystemTransitionSleep;
5089 }
5090 // 3. Woke from (idle or demand) sleep.
5091 else if (!systemBooting &&
5092 (changeFlags & kIOPMSelfInitiated) &&
5093 (powerState > currentPowerState)) {
5094 _systemTransitionType = kSystemTransitionWake;
5095 _desiredCapability = kIOPMSystemCapabilityCPU |
5096 kIOPMSystemCapabilityNetwork;
5097
5098 // Early exit from dark wake to full (e.g. LID open)
5099 if (kFullWakeReasonNone != fullWakeReason) {
5100 _desiredCapability |= (
5101 kIOPMSystemCapabilityGraphics |
5102 kIOPMSystemCapabilityAudio);
5103 }
5104 #if HIBERNATION
5105 IOHibernateSetWakeCapabilities(_desiredCapability);
5106 #endif
5107 }
5108
5109 // Update pending wake capability at the beginning of every
5110 // state transition (including synchronize). This will become
5111 // the current capability at the end of the transition.
5112
5113 if (kSystemTransitionSleep == _systemTransitionType) {
5114 _pendingCapability = 0;
5115 capabilityLoss = true;
5116 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
5117 _pendingCapability = _desiredCapability |
5118 kIOPMSystemCapabilityCPU |
5119 kIOPMSystemCapabilityNetwork;
5120
5121 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
5122 _pendingCapability |= kIOPMSystemCapabilityAudio;
5123 }
5124
5125 if ((kSystemTransitionCapability == _systemTransitionType) &&
5126 (_pendingCapability == _currentCapability)) {
5127 // Cancel the PM state change.
5128 _systemTransitionType = kSystemTransitionNone;
5129 *inOutChangeFlags |= kIOPMNotDone;
5130 }
5131 if (__builtin_popcount(_pendingCapability) <
5132 __builtin_popcount(_currentCapability)) {
5133 capabilityLoss = true;
5134 }
5135 }
5136
5137 // 1. Capability change.
5138
5139 if (kSystemTransitionCapability == _systemTransitionType) {
5140 // Dark to Full transition.
5141 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
5142 tracePoint( kIOPMTracePointDarkWakeExit );
5143
5144 willEnterFullWake();
5145 }
5146
5147 // Full to Dark transition.
5148 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
5149 // Clear previous stats
5150 IOLockLock(pmStatsLock);
5151 if (pmStatsAppResponses) {
5152 pmStatsAppResponses->release();
5153 pmStatsAppResponses = OSArray::withCapacity(5);
5154 }
5155 IOLockUnlock(pmStatsLock);
5156
5157
5158 tracePoint( kIOPMTracePointDarkWakeEntry );
5159 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
5160 _systemMessageClientMask = kSystemMessageClientPowerd |
5161 kSystemMessageClientLegacyApp;
5162
5163
5164 // rdar://15971327
5165 // Prevent user active transitions before notifying clients
5166 // that system will sleep.
5167 preventTransitionToUserActive(true);
5168
5169 IOService::setAdvisoryTickleEnable( false );
5170
5171 // Publish the sleep reason for full to dark wake
5172 publishSleepReason = true;
5173 lastSleepReason = fullToDarkReason = sleepReason;
5174
5175 // Publish a UUID for the Sleep --> Wake cycle
5176 handlePublishSleepWakeUUID(true);
5177 if (sleepDelaysReport) {
5178 clock_get_uptime(&ts_sleepStart);
5179 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
5180 }
5181
5182 wranglerTickled = false;
5183 }
5184 }
5185 // 2. System sleep.
5186 else if (kSystemTransitionSleep == _systemTransitionType) {
5187 // Beginning of a system sleep transition.
5188 // Cancellation is still possible.
5189 tracePoint( kIOPMTracePointSleepStarted );
5190
5191 _systemMessageClientMask = kSystemMessageClientAll;
5192 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
5193 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
5194 }
5195 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
5196 _systemMessageClientMask &= ~kSystemMessageClientKernel;
5197 }
5198 #if HIBERNATION
5199 gIOHibernateState = 0;
5200 #endif
5201
5202 // Record the reason for dark wake back to sleep
5203 // System may not have ever achieved full wake
5204
5205 publishSleepReason = true;
5206 lastSleepReason = sleepReason;
5207 if (sleepDelaysReport) {
5208 clock_get_uptime(&ts_sleepStart);
5209 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
5210 }
5211 }
5212 // 3. System wake.
5213 else if (kSystemTransitionWake == _systemTransitionType) {
5214 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
5215 // Clear stats about sleep
5216
5217 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
5218 willEnterFullWake();
5219 } else {
5220 // Message powerd only
5221 _systemMessageClientMask = kSystemMessageClientPowerd;
5222 tellClients(kIOMessageSystemWillPowerOn);
5223 }
5224 }
5225
5226 // The only location where the sleep reason is published. At this point
5227 // sleep can still be cancelled, but sleep reason should be published
5228 // early for logging purposes.
5229
5230 if (publishSleepReason) {
5231 static const char * IOPMSleepReasons[] =
5232 {
5233 kIOPMClamshellSleepKey,
5234 kIOPMPowerButtonSleepKey,
5235 kIOPMSoftwareSleepKey,
5236 kIOPMOSSwitchHibernationKey,
5237 kIOPMIdleSleepKey,
5238 kIOPMLowPowerSleepKey,
5239 kIOPMThermalEmergencySleepKey,
5240 kIOPMMaintenanceSleepKey,
5241 kIOPMSleepServiceExitKey,
5242 kIOPMDarkWakeThermalEmergencyKey
5243 };
5244
5245 // Record sleep cause in IORegistry
5246 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
5247 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
5248 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
5249 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
5250 }
5251 }
5252
5253 if ((kSystemTransitionNone != _systemTransitionType) &&
5254 (kSystemTransitionNewCapClient != _systemTransitionType)) {
5255 _systemStateGeneration++;
5256 systemDarkWake = false;
5257
5258 DLOG("=== START (%u->%u, 0x%x) type %u, gen %u, msg %x, "
5259 "dcp %x:%x:%x\n",
5260 currentPowerState, (uint32_t) powerState, *inOutChangeFlags,
5261 _systemTransitionType, _systemStateGeneration,
5262 _systemMessageClientMask,
5263 _desiredCapability, _currentCapability, _pendingCapability);
5264 }
5265 }
5266
5267 void
5268 IOPMrootDomain::handleOurPowerChangeDone(
5269 IOService * service,
5270 IOPMActions * actions,
5271 IOPMPowerStateIndex powerState,
5272 IOPMPowerChangeFlags changeFlags,
5273 IOPMRequestTag requestTag __unused )
5274 {
5275 if (kSystemTransitionNewCapClient == _systemTransitionType) {
5276 _systemTransitionType = kSystemTransitionNone;
5277 return;
5278 }
5279
5280 if (_systemTransitionType != kSystemTransitionNone) {
5281 uint32_t currentPowerState = (uint32_t) getPowerState();
5282
5283 if (changeFlags & kIOPMNotDone) {
5284 // Power down was cancelled or vetoed.
5285 _pendingCapability = _currentCapability;
5286 lastSleepReason = 0;
5287
5288 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
5289 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
5290 #if !CONFIG_EMBEDDED
5291 pmPowerStateQueue->submitPowerEvent(
5292 kPowerEventPolicyStimulus,
5293 (void *) kStimulusDarkWakeReentry,
5294 _systemStateGeneration );
5295 #else
5296 // On embedded, there are no factors that can prolong a
5297 // "darkWake" when a power down is vetoed. We need to
5298 // promote to "fullWake" at least once so that factors
5299 // that prevent idle sleep can assert themselves if required
5300 pmPowerStateQueue->submitPowerEvent(
5301 kPowerEventPolicyStimulus,
5302 (void *) kStimulusDarkWakeActivityTickle);
5303 #endif
5304 }
5305
5306 // Revert device desire to max.
5307 changePowerStateToPriv(ON_STATE);
5308 } else {
5309 // Send message on dark wake to full wake promotion.
5310 // tellChangeUp() handles the normal SLEEP->ON case.
5311
5312 if (kSystemTransitionCapability == _systemTransitionType) {
5313 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
5314 lastSleepReason = 0; // stop logging wrangler tickles
5315 tellClients(kIOMessageSystemHasPoweredOn);
5316 }
5317 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
5318 // Going dark, reset full wake state
5319 // userIsActive will be cleared by wrangler powering down
5320 fullWakeReason = kFullWakeReasonNone;
5321
5322 if (ts_sleepStart) {
5323 clock_get_uptime(&wake2DarkwakeDelay);
5324 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
5325 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
5326 ts_sleepStart = 0;
5327 }
5328 }
5329 }
5330
5331 // Reset state after exiting from dark wake.
5332
5333 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
5334 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
5335 darkWakeMaintenance = false;
5336 darkWakeToSleepASAP = false;
5337 pciCantSleepValid = false;
5338 darkWakeSleepService = false;
5339
5340 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
5341 // Remove the influence of display power assertion
5342 // before next system wake.
5343 if (wrangler) {
5344 wrangler->changePowerStateForRootDomain(
5345 kWranglerPowerStateMin );
5346 }
5347 removeProperty(gIOPMUserTriggeredFullWakeKey);
5348 }
5349 }
5350
5351 // Entered dark mode.
5352
5353 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
5354 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
5355 // Queue an evaluation of whether to remain in dark wake,
5356 // and for how long. This serves the purpose of draining
5357 // any assertions from the queue.
5358
5359 pmPowerStateQueue->submitPowerEvent(
5360 kPowerEventPolicyStimulus,
5361 (void *) kStimulusDarkWakeEntry,
5362 _systemStateGeneration );
5363 }
5364 }
5365
5366 DLOG("=== FINISH (%u->%u, 0x%x) type %u, gen %u, msg %x, "
5367 "dcp %x:%x:%x, dbgtimer %u\n",
5368 currentPowerState, (uint32_t) powerState, changeFlags,
5369 _systemTransitionType, _systemStateGeneration,
5370 _systemMessageClientMask,
5371 _desiredCapability, _currentCapability, _pendingCapability,
5372 _lastDebugWakeSeconds);
5373
5374 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
5375 displayWakeCnt++;
5376 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
5377 if (clamshellExists && fullWakeThreadCall &&
5378 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5379 // Not the initial graphics full power, graphics won't
5380 // send a power notification to trigger a lid state
5381 // evaluation.
5382
5383 AbsoluteTime deadline;
5384 clock_interval_to_deadline(45, kSecondScale, &deadline);
5385 thread_call_enter_delayed(fullWakeThreadCall, deadline);
5386 }
5387 #endif
5388 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
5389 darkWakeCnt++;
5390 }
5391
5392 // Update current system capability.
5393 if (_currentCapability != _pendingCapability) {
5394 _currentCapability = _pendingCapability;
5395 }
5396
5397 // Update highest system capability.
5398
5399 _highestCapability |= _currentCapability;
5400
5401 if (darkWakePostTickle &&
5402 (kSystemTransitionWake == _systemTransitionType) &&
5403 (gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
5404 kDarkWakeFlagHIDTickleLate) {
5405 darkWakePostTickle = false;
5406 reportUserInput();
5407 } else if (wranglerTickled) {
5408 requestFullWake( kFullWakeReasonLocalUser );
5409 }
5410
5411 // Reset tracepoint at completion of capability change,
5412 // completion of wake transition, and aborted sleep transition.
5413
5414 if ((_systemTransitionType == kSystemTransitionCapability) ||
5415 (_systemTransitionType == kSystemTransitionWake) ||
5416 ((_systemTransitionType == kSystemTransitionSleep) &&
5417 (changeFlags & kIOPMNotDone))) {
5418 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
5419 tracePoint( kIOPMTracePointSystemUp );
5420 }
5421
5422 _systemTransitionType = kSystemTransitionNone;
5423 _systemMessageClientMask = 0;
5424 toldPowerdCapWillChange = false;
5425
5426 logGraphicsClamp = false;
5427
5428 if (lowBatteryCondition) {
5429 privateSleepSystem(kIOPMSleepReasonLowPower);
5430 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && (!displayPowerOnRequested)) {
5431 // Request for full wake is removed while system is waking up to full wake
5432 DLOG("DisplayOn fullwake request is removed\n");
5433 handleDisplayPowerOn();
5434 }
5435 }
5436 }
5437
5438 //******************************************************************************
5439 // PM actions for graphics and audio.
5440 //******************************************************************************
5441
5442 void
5443 IOPMrootDomain::overridePowerChangeForUIService(
5444 IOService * service,
5445 IOPMActions * actions,
5446 IOPMPowerStateIndex * inOutPowerState,
5447 IOPMPowerChangeFlags * inOutChangeFlags )
5448 {
5449 uint32_t powerState = (uint32_t) *inOutPowerState;
5450 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
5451
5452 if (kSystemTransitionNone == _systemTransitionType) {
5453 // Not in midst of a system transition.
5454 // Do not modify power limit enable state.
5455 } else if ((actions->parameter & kPMActionsFlagLimitPower) == 0) {
5456 // Activate power limiter.
5457
5458 if ((actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
5459 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
5460 (changeFlags & kIOPMSynchronize)) {
5461 actions->parameter |= kPMActionsFlagLimitPower;
5462 } else if ((actions->parameter & kPMActionsFlagIsAudioDevice) &&
5463 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
5464 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
5465 (changeFlags & kIOPMSynchronize)) {
5466 actions->parameter |= kPMActionsFlagLimitPower;
5467 } else if ((actions->parameter & kPMActionsFlagIsGraphicsDevice) &&
5468 (_systemTransitionType == kSystemTransitionSleep)) {
5469 // For graphics devices, arm the limiter when entering
5470 // system sleep. Not when dropping to dark wake.
5471 actions->parameter |= kPMActionsFlagLimitPower;
5472 }
5473
5474 if (actions->parameter & kPMActionsFlagLimitPower) {
5475 DLOG("+ plimit %s %p\n",
5476 service->getName(), OBFUSCATE(service));
5477 }
5478 } else {
5479 // Remove power limit.
5480
5481 if ((actions->parameter & (
5482 kPMActionsFlagIsDisplayWrangler |
5483 kPMActionsFlagIsGraphicsDevice)) &&
5484 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
5485 actions->parameter &= ~kPMActionsFlagLimitPower;
5486 } else if ((actions->parameter & kPMActionsFlagIsAudioDevice) &&
5487 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
5488 actions->parameter &= ~kPMActionsFlagLimitPower;
5489 }
5490
5491 if ((actions->parameter & kPMActionsFlagLimitPower) == 0) {
5492 DLOG("- plimit %s %p\n",
5493 service->getName(), OBFUSCATE(service));
5494 }
5495 }
5496
5497 if (actions->parameter & kPMActionsFlagLimitPower) {
5498 uint32_t maxPowerState = (uint32_t)(-1);
5499
5500 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
5501 // Enforce limit for system power/cap transitions.
5502
5503 maxPowerState = 0;
5504 if ((service->getPowerState() > maxPowerState) &&
5505 (actions->parameter & kPMActionsFlagIsDisplayWrangler)) {
5506 maxPowerState++;
5507
5508 // Remove lingering effects of any tickle before entering
5509 // dark wake. It will take a new tickle to return to full
5510 // wake, so the existing tickle state is useless.
5511
5512 if (changeFlags & kIOPMDomainDidChange) {
5513 *inOutChangeFlags |= kIOPMExpireIdleTimer;
5514 }
5515 } else if (actions->parameter & kPMActionsFlagIsGraphicsDevice) {
5516 maxPowerState++;
5517 }
5518 } else {
5519 // Deny all self-initiated changes when power is limited.
5520 // Wrangler tickle should never defeat the limiter.
5521
5522 maxPowerState = service->getPowerState();
5523 }
5524
5525 if (powerState > maxPowerState) {
5526 DLOG("> plimit %s %p (%u->%u, 0x%x)\n",
5527 service->getName(), OBFUSCATE(service), powerState, maxPowerState,
5528 changeFlags);
5529 *inOutPowerState = maxPowerState;
5530
5531 if (darkWakePostTickle &&
5532 (actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
5533 (changeFlags & kIOPMDomainWillChange) &&
5534 ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
5535 kDarkWakeFlagHIDTickleEarly)) {
5536 darkWakePostTickle = false;
5537 reportUserInput();
5538 }
5539 }
5540
5541 if (!graphicsSuppressed && (changeFlags & kIOPMDomainDidChange)) {
5542 if (logGraphicsClamp) {
5543 AbsoluteTime now;
5544 uint64_t nsec;
5545
5546 clock_get_uptime(&now);
5547 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
5548 absolutetime_to_nanoseconds(now, &nsec);
5549 if (kIOLogPMRootDomain & gIOKitDebug) {
5550 MSG("Graphics suppressed %u ms\n",
5551 ((int)((nsec) / NSEC_PER_MSEC)));
5552 }
5553 }
5554 graphicsSuppressed = true;
5555 }
5556 }
5557 }
5558
5559 void
5560 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
5561 IOService * service,
5562 IOPMActions * actions )
5563 {
5564 #if !NO_KERNEL_HID
5565 // Warning: Not running in PM work loop context - don't modify state !!!
5566 // Trap tickle directed to IODisplayWrangler while running with graphics
5567 // capability suppressed.
5568
5569 assert(service == wrangler);
5570
5571 clock_get_uptime(&userActivityTime);
5572 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
5573 || (lastSleepReason == kIOPMSleepReasonMaintenance)
5574 || (lastSleepReason == kIOPMSleepReasonSoftware));
5575 if (aborting) {
5576 userActivityCount++;
5577 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
5578 userActivityCount, lastSleepReason);
5579 }
5580
5581 if (!wranglerTickled &&
5582 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
5583 DLOG("display wrangler tickled\n");
5584 if (kIOLogPMRootDomain & gIOKitDebug) {
5585 OSReportWithBacktrace("Dark wake display tickle");
5586 }
5587 if (pmPowerStateQueue) {
5588 pmPowerStateQueue->submitPowerEvent(
5589 kPowerEventPolicyStimulus,
5590 (void *) kStimulusDarkWakeActivityTickle,
5591 true /* set wake type */ );
5592 }
5593 }
5594 #endif
5595 }
5596
5597 void
5598 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
5599 IOService * service,
5600 IOPMActions * actions,
5601 const OSSymbol * powerClient,
5602 IOPMPowerStateIndex oldPowerState,
5603 IOPMPowerStateIndex newPowerState )
5604 {
5605 #if !NO_KERNEL_HID
5606 assert(service == wrangler);
5607
5608 // This function implements half of the user active detection
5609 // by monitoring changes to the display wrangler's device desire.
5610 //
5611 // User becomes active when either:
5612 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
5613 // in max power state. This desire change in absence of a power state
5614 // change is detected within. This handles the case when user becomes
5615 // active while the display is already lit by setDisplayPowerOn().
5616 //
5617 // 2. Power state change to max, and DeviceDesire is also at max.
5618 // Handled by displayWranglerNotification().
5619 //
5620 // User becomes inactive when DeviceDesire drops to sleep state or below.
5621
5622 DLOG("wrangler %s (ps %u, %u->%u)\n",
5623 powerClient->getCStringNoCopy(),
5624 (uint32_t) service->getPowerState(),
5625 (uint32_t) oldPowerState, (uint32_t) newPowerState);
5626
5627 if (powerClient == gIOPMPowerClientDevice) {
5628 if ((newPowerState > oldPowerState) &&
5629 (newPowerState == kWranglerPowerStateMax) &&
5630 (service->getPowerState() == kWranglerPowerStateMax)) {
5631 evaluatePolicy( kStimulusEnterUserActiveState );
5632 } else if ((newPowerState < oldPowerState) &&
5633 (newPowerState <= kWranglerPowerStateSleep)) {
5634 evaluatePolicy( kStimulusLeaveUserActiveState );
5635 }
5636 }
5637
5638 if (newPowerState <= kWranglerPowerStateSleep) {
5639 evaluatePolicy( kStimulusDisplayWranglerSleep );
5640 } else if (newPowerState == kWranglerPowerStateMax) {
5641 evaluatePolicy( kStimulusDisplayWranglerWake );
5642 }
5643 #endif
5644 }
5645
5646 //******************************************************************************
5647 // User active state management
5648 //******************************************************************************
5649
5650 void
5651 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
5652 {
5653 #if !NO_KERNEL_HID
5654 _preventUserActive = prevent;
5655 if (wrangler && !_preventUserActive) {
5656 // Allowing transition to user active, but the wrangler may have
5657 // already powered ON in case of sleep cancel/revert. Poll the
5658 // same conditions checked for in displayWranglerNotification()
5659 // to bring the user active state up to date.
5660
5661 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
5662 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
5663 kWranglerPowerStateMax)) {
5664 evaluatePolicy( kStimulusEnterUserActiveState );
5665 }
5666 }
5667 #endif
5668 }
5669
5670 //******************************************************************************
5671 // Approve usage of delayed child notification by PM.
5672 //******************************************************************************
5673
5674 bool
5675 IOPMrootDomain::shouldDelayChildNotification(
5676 IOService * service )
5677 {
5678 if (((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) != 0) &&
5679 (kFullWakeReasonNone == fullWakeReason) &&
5680 (kSystemTransitionWake == _systemTransitionType)) {
5681 DLOG("%s: delay child notify\n", service->getName());
5682 return true;
5683 }
5684 return false;
5685 }
5686
5687 //******************************************************************************
5688 // PM actions for PCI device.
5689 //******************************************************************************
5690
5691 void
5692 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
5693 IOService * service,
5694 IOPMActions * actions,
5695 IOPMPowerStateIndex powerState,
5696 IOPMPowerChangeFlags * inOutChangeFlags )
5697 {
5698 pmTracer->tracePCIPowerChange(
5699 PMTraceWorker::kPowerChangeStart,
5700 service, *inOutChangeFlags,
5701 (actions->parameter & kPMActionsPCIBitNumberMask));
5702 }
5703
5704 void
5705 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
5706 IOService * service,
5707 IOPMActions * actions,
5708 IOPMPowerStateIndex powerState,
5709 IOPMPowerChangeFlags changeFlags )
5710 {
5711 pmTracer->tracePCIPowerChange(
5712 PMTraceWorker::kPowerChangeCompleted,
5713 service, changeFlags,
5714 (actions->parameter & kPMActionsPCIBitNumberMask));
5715 }
5716
5717 //******************************************************************************
5718 // registerInterest
5719 //
5720 // Override IOService::registerInterest() to intercept special clients.
5721 //******************************************************************************
5722
5723 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
5724 {
5725 friend class IOPMrootDomain;
5726 OSDeclareDefaultStructors(IOPMServiceInterestNotifier)
5727
5728 protected:
5729 uint32_t ackTimeoutCnt;
5730 uint32_t msgType;// Message pending ack
5731
5732 uint64_t uuid0;
5733 uint64_t uuid1;
5734 const OSSymbol *identifier;
5735 };
5736
5737 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
5738
5739 IONotifier * IOPMrootDomain::registerInterest(
5740 const OSSymbol * typeOfInterest,
5741 IOServiceInterestHandler handler,
5742 void * target, void * ref )
5743 {
5744 IOPMServiceInterestNotifier *notifier = 0;
5745 bool isSystemCapabilityClient;
5746 bool isKernelCapabilityClient;
5747 IOReturn rc = kIOReturnError;;
5748
5749 isSystemCapabilityClient =
5750 typeOfInterest &&
5751 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
5752
5753 isKernelCapabilityClient =
5754 typeOfInterest &&
5755 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
5756
5757 if (isSystemCapabilityClient) {
5758 typeOfInterest = gIOAppPowerStateInterest;
5759 }
5760
5761 notifier = new IOPMServiceInterestNotifier;
5762 if (!notifier) {
5763 return NULL;
5764 }
5765
5766 if (notifier->init()) {
5767 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
5768 }
5769 if (rc != kIOReturnSuccess) {
5770 notifier->release();
5771 notifier = 0;
5772
5773 return NULL;
5774 }
5775 if (pmPowerStateQueue) {
5776 notifier->ackTimeoutCnt = 0;
5777 if (isSystemCapabilityClient) {
5778 notifier->retain();
5779 if (pmPowerStateQueue->submitPowerEvent(
5780 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
5781 notifier->release();
5782 }
5783 }
5784
5785 if (isKernelCapabilityClient) {
5786 notifier->retain();
5787 if (pmPowerStateQueue->submitPowerEvent(
5788 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
5789 notifier->release();
5790 }
5791 }
5792 }
5793
5794 OSData *data = NULL;
5795 uint8_t *uuid = NULL;
5796 OSKext *kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
5797 if (kext) {
5798 data = kext->copyUUID();
5799 }
5800 if (data && (data->getLength() == sizeof(uuid_t))) {
5801 uuid = (uint8_t *)(data->getBytesNoCopy());
5802
5803 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
5804 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
5805 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
5806 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
5807 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
5808 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
5809
5810 notifier->identifier = kext->getIdentifier();
5811 }
5812 if (kext) {
5813 kext->release();
5814 }
5815 if (data) {
5816 data->release();
5817 }
5818
5819 return notifier;
5820 }
5821
5822 //******************************************************************************
5823 // systemMessageFilter
5824 //
5825 //******************************************************************************
5826
5827 bool
5828 IOPMrootDomain::systemMessageFilter(
5829 void * object, void * arg1, void * arg2, void * arg3 )
5830 {
5831 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
5832 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
5833 bool isCapClient = false;
5834 bool allow = false;
5835 IOPMServiceInterestNotifier *notifier;
5836
5837 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
5838 do {
5839 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
5840 (!isCapMsg || !_joinedCapabilityClients ||
5841 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
5842 break;
5843 }
5844
5845 // Capability change message for app and kernel clients.
5846
5847 if (isCapMsg) {
5848 if ((context->notifyType == kNotifyPriority) ||
5849 (context->notifyType == kNotifyCapabilityChangePriority)) {
5850 isCapClient = true;
5851 }
5852
5853 if ((context->notifyType == kNotifyCapabilityChangeApps) &&
5854 (object == (void *) systemCapabilityNotifier)) {
5855 isCapClient = true;
5856 }
5857 }
5858
5859 if (isCapClient) {
5860 IOPMSystemCapabilityChangeParameters * capArgs =
5861 (IOPMSystemCapabilityChangeParameters *) arg2;
5862
5863 if (kSystemTransitionNewCapClient == _systemTransitionType) {
5864 capArgs->fromCapabilities = 0;
5865 capArgs->toCapabilities = _currentCapability;
5866 capArgs->changeFlags = 0;
5867 } else {
5868 capArgs->fromCapabilities = _currentCapability;
5869 capArgs->toCapabilities = _pendingCapability;
5870
5871 if (context->isPreChange) {
5872 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
5873 } else {
5874 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
5875 }
5876
5877 if ((object == (void *) systemCapabilityNotifier) &&
5878 context->isPreChange) {
5879 toldPowerdCapWillChange = true;
5880 }
5881 }
5882
5883 // Capability change messages only go to the PM configd plugin.
5884 // Wait for response post-change if capabilitiy is increasing.
5885 // Wait for response pre-change if capability is decreasing.
5886
5887 if ((context->notifyType == kNotifyCapabilityChangeApps) && arg3 &&
5888 ((capabilityLoss && context->isPreChange) ||
5889 (!capabilityLoss && !context->isPreChange))) {
5890 // app has not replied yet, wait for it
5891 *((OSObject **) arg3) = kOSBooleanFalse;
5892 }
5893
5894 allow = true;
5895 break;
5896 }
5897
5898 // Capability client will always see kIOMessageCanSystemSleep,
5899 // even for demand sleep. It will also have a chance to veto
5900 // sleep one last time after all clients have responded to
5901 // kIOMessageSystemWillSleep
5902
5903 if ((kIOMessageCanSystemSleep == context->messageType) ||
5904 (kIOMessageSystemWillNotSleep == context->messageType)) {
5905 if (object == (OSObject *) systemCapabilityNotifier) {
5906 allow = true;
5907 break;
5908 }
5909
5910 // Not idle sleep, don't ask apps.
5911 if (context->changeFlags & kIOPMSkipAskPowerDown) {
5912 break;
5913 }
5914 }
5915
5916 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
5917 if ((object == (OSObject *) systemCapabilityNotifier) &&
5918 CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
5919 (fullToDarkReason == kIOPMSleepReasonIdle)) {
5920 allow = true;
5921 }
5922 break;
5923 }
5924
5925 // Reject capability change messages for legacy clients.
5926 // Reject legacy system sleep messages for capability client.
5927
5928 if (isCapMsg || (object == (OSObject *) systemCapabilityNotifier)) {
5929 break;
5930 }
5931
5932 // Filter system sleep messages.
5933
5934 if ((context->notifyType == kNotifyApps) &&
5935 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
5936 allow = true;
5937
5938 if (notifier) {
5939 if (arg3) {
5940 if (notifier->ackTimeoutCnt >= 3) {
5941 *((OSObject **) arg3) = kOSBooleanFalse;
5942 } else {
5943 *((OSObject **) arg3) = kOSBooleanTrue;
5944 }
5945 }
5946 }
5947 } else if ((context->notifyType == kNotifyPriority) &&
5948 (_systemMessageClientMask & kSystemMessageClientKernel)) {
5949 allow = true;
5950 }
5951 }while (false);
5952
5953 if (allow && isCapMsg && _joinedCapabilityClients) {
5954 _joinedCapabilityClients->removeObject((OSObject *) object);
5955 if (_joinedCapabilityClients->getCount() == 0) {
5956 DLOG("destroyed capability client set %p\n",
5957 OBFUSCATE(_joinedCapabilityClients));
5958 _joinedCapabilityClients->release();
5959 _joinedCapabilityClients = 0;
5960 }
5961 }
5962 if (notifier) {
5963 notifier->msgType = context->messageType;
5964 }
5965
5966 return allow;
5967 }
5968
5969 //******************************************************************************
5970 // setMaintenanceWakeCalendar
5971 //
5972 //******************************************************************************
5973
5974 IOReturn
5975 IOPMrootDomain::setMaintenanceWakeCalendar(
5976 const IOPMCalendarStruct * calendar )
5977 {
5978 OSData * data;
5979 IOReturn ret = 0;
5980
5981 if (!calendar) {
5982 return kIOReturnBadArgument;
5983 }
5984
5985 data = OSData::withBytes((void *) calendar, sizeof(*calendar));
5986 if (!data) {
5987 return kIOReturnNoMemory;
5988 }
5989
5990 if (kPMCalendarTypeMaintenance == calendar->selector) {
5991 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey, data);
5992 if (kIOReturnSuccess == ret) {
5993 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarms);
5994 }
5995 } else if (kPMCalendarTypeSleepService == calendar->selector) {
5996 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey, data);
5997 if (kIOReturnSuccess == ret) {
5998 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarms);
5999 }
6000 }
6001 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
6002
6003 data->release();
6004 return ret;
6005 }
6006
6007 // MARK: -
6008 // MARK: Display Wrangler
6009
6010 //******************************************************************************
6011 // displayWranglerNotification
6012 //
6013 // Handle the notification when the IODisplayWrangler changes power state.
6014 //******************************************************************************
6015
6016 IOReturn
6017 IOPMrootDomain::displayWranglerNotification(
6018 void * target, void * refCon,
6019 UInt32 messageType, IOService * service,
6020 void * messageArgument, vm_size_t argSize )
6021 {
6022 #if !NO_KERNEL_HID
6023 int displayPowerState;
6024 IOPowerStateChangeNotification * params =
6025 (IOPowerStateChangeNotification *) messageArgument;
6026
6027 if ((messageType != kIOMessageDeviceWillPowerOff) &&
6028 (messageType != kIOMessageDeviceHasPoweredOn)) {
6029 return kIOReturnUnsupported;
6030 }
6031
6032 ASSERT_GATED();
6033 if (!gRootDomain) {
6034 return kIOReturnUnsupported;
6035 }
6036
6037 displayPowerState = params->stateNumber;
6038 DLOG("wrangler %s ps %d\n",
6039 getIOMessageString(messageType), displayPowerState);
6040
6041 switch (messageType) {
6042 case kIOMessageDeviceWillPowerOff:
6043 // Display wrangler has dropped power due to display idle
6044 // or force system sleep.
6045 //
6046 // 4 Display ON kWranglerPowerStateMax
6047 // 3 Display Dim kWranglerPowerStateDim
6048 // 2 Display Sleep kWranglerPowerStateSleep
6049 // 1 Not visible to user
6050 // 0 Not visible to user kWranglerPowerStateMin
6051
6052 if (displayPowerState <= kWranglerPowerStateSleep) {
6053 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
6054 }
6055 break;
6056
6057 case kIOMessageDeviceHasPoweredOn:
6058 // Display wrangler has powered on due to user activity
6059 // or wake from sleep.
6060
6061 if (kWranglerPowerStateMax == displayPowerState) {
6062 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
6063
6064 // See comment in handleUpdatePowerClientForDisplayWrangler
6065 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
6066 kWranglerPowerStateMax) {
6067 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
6068 }
6069 }
6070 break;
6071 }
6072 #endif
6073 return kIOReturnUnsupported;
6074 }
6075
6076 //******************************************************************************
6077 // displayWranglerMatchPublished
6078 //
6079 // Receives a notification when the IODisplayWrangler is published.
6080 // When it's published we install a power state change handler.
6081 //******************************************************************************
6082
6083 bool
6084 IOPMrootDomain::displayWranglerMatchPublished(
6085 void * target,
6086 void * refCon,
6087 IOService * newService,
6088 IONotifier * notifier __unused)
6089 {
6090 #if !NO_KERNEL_HID
6091 // install a handler
6092 if (!newService->registerInterest( gIOGeneralInterest,
6093 &displayWranglerNotification, target, 0)) {
6094 return false;
6095 }
6096 #endif
6097 return true;
6098 }
6099
6100 //******************************************************************************
6101 // reportUserInput
6102 //
6103 //******************************************************************************
6104
6105 void
6106 IOPMrootDomain::reportUserInput( void )
6107 {
6108 #if !NO_KERNEL_HID
6109 OSIterator * iter;
6110 OSDictionary * matching;
6111
6112 if (!wrangler) {
6113 matching = serviceMatching("IODisplayWrangler");
6114 iter = getMatchingServices(matching);
6115 if (matching) {
6116 matching->release();
6117 }
6118 if (iter) {
6119 wrangler = OSDynamicCast(IOService, iter->getNextObject());
6120 iter->release();
6121 }
6122 }
6123
6124 if (wrangler) {
6125 wrangler->activityTickle(0, 0);
6126 }
6127 #endif
6128 }
6129
6130 //******************************************************************************
6131 // latchDisplayWranglerTickle
6132 //******************************************************************************
6133
6134 bool
6135 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
6136 {
6137 #if !NO_KERNEL_HID
6138 if (latch) {
6139 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
6140 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
6141 !checkSystemCanSustainFullWake()) {
6142 // Currently in dark wake, and not transitioning to full wake.
6143 // Full wake is unsustainable, so latch the tickle to prevent
6144 // the display from lighting up momentarily.
6145 wranglerTickleLatched = true;
6146 } else {
6147 wranglerTickleLatched = false;
6148 }
6149 } else if (wranglerTickleLatched && checkSystemCanSustainFullWake()) {
6150 wranglerTickleLatched = false;
6151
6152 pmPowerStateQueue->submitPowerEvent(
6153 kPowerEventPolicyStimulus,
6154 (void *) kStimulusDarkWakeActivityTickle );
6155 }
6156
6157 return wranglerTickleLatched;
6158 #else
6159 return false;
6160 #endif
6161 }
6162
6163 //******************************************************************************
6164 // setDisplayPowerOn
6165 //
6166 // For root domain user client
6167 //******************************************************************************
6168
6169 void
6170 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
6171 {
6172 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
6173 (void *) 0, options );
6174 }
6175
6176 // MARK: -
6177 // MARK: Battery
6178
6179 //******************************************************************************
6180 // batteryPublished
6181 //
6182 // Notification on battery class IOPowerSource appearance
6183 //******************************************************************************
6184
6185 bool
6186 IOPMrootDomain::batteryPublished(
6187 void * target,
6188 void * root_domain,
6189 IOService * resourceService,
6190 IONotifier * notifier __unused )
6191 {
6192 // rdar://2936060&4435589
6193 // All laptops have dimmable LCD displays
6194 // All laptops have batteries
6195 // So if this machine has a battery, publish the fact that the backlight
6196 // supports dimming.
6197 ((IOPMrootDomain *)root_domain)->publishFeature("DisplayDims");
6198
6199 return true;
6200 }
6201
6202 // MARK: -
6203 // MARK: System PM Policy
6204
6205 //******************************************************************************
6206 // checkSystemSleepAllowed
6207 //
6208 //******************************************************************************
6209
6210 bool
6211 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
6212 uint32_t sleepReason )
6213 {
6214 int err = 0;
6215
6216 // Conditions that prevent idle and demand system sleep.
6217
6218 do {
6219 if (userDisabledAllSleep) {
6220 err = 1; // 1. user-space sleep kill switch
6221 break;
6222 }
6223
6224 if (systemBooting || systemShutdown || gWillShutdown) {
6225 err = 2; // 2. restart or shutdown in progress
6226 break;
6227 }
6228
6229 if (options == 0) {
6230 break;
6231 }
6232
6233 // Conditions above pegs the system at full wake.
6234 // Conditions below prevent system sleep but does not prevent
6235 // dark wake, and must be called from gated context.
6236
6237 #if !CONFIG_SLEEP
6238 err = 3; // 3. config does not support sleep
6239 break;
6240 #endif
6241
6242 if (lowBatteryCondition || thermalWarningState) {
6243 break; // always sleep on low battery or when in thermal warning state
6244 }
6245
6246 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
6247 break; // always sleep on dark wake thermal emergencies
6248 }
6249
6250 if (preventSystemSleepList->getCount() != 0) {
6251 err = 4; // 4. child prevent system sleep clamp
6252 break;
6253 }
6254
6255 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
6256 kIOPMDriverAssertionLevelOn) {
6257 err = 5; // 5. CPU assertion
6258 break;
6259 }
6260
6261 if (pciCantSleepValid) {
6262 if (pciCantSleepFlag) {
6263 err = 6; // 6. PCI card does not support PM (cached)
6264 }
6265 break;
6266 } else if (sleepSupportedPEFunction &&
6267 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
6268 IOReturn ret;
6269 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
6270 ret = getPlatform()->callPlatformFunction(
6271 sleepSupportedPEFunction, false,
6272 NULL, NULL, NULL, NULL);
6273 pciCantSleepValid = true;
6274 pciCantSleepFlag = false;
6275 if ((platformSleepSupport & kPCICantSleep) ||
6276 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
6277 err = 6; // 6. PCI card does not support PM
6278 pciCantSleepFlag = true;
6279 break;
6280 }
6281 }
6282 }while (false);
6283
6284 if (err) {
6285 DLOG("System sleep prevented by %d\n", err);
6286 return false;
6287 }
6288 return true;
6289 }
6290
6291 bool
6292 IOPMrootDomain::checkSystemSleepEnabled( void )
6293 {
6294 return checkSystemSleepAllowed(0, 0);
6295 }
6296
6297 bool
6298 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
6299 {
6300 ASSERT_GATED();
6301 return checkSystemSleepAllowed(1, sleepReason);
6302 }
6303
6304 //******************************************************************************
6305 // checkSystemCanSustainFullWake
6306 //******************************************************************************
6307
6308 bool
6309 IOPMrootDomain::checkSystemCanSustainFullWake( void )
6310 {
6311 #if !NO_KERNEL_HID
6312 if (lowBatteryCondition || thermalWarningState) {
6313 // Low battery wake, or received a low battery notification
6314 // while system is awake. This condition will persist until
6315 // the following wake.
6316 return false;
6317 }
6318
6319 if (clamshellExists && clamshellClosed && !clamshellSleepDisabled) {
6320 // Graphics state is unknown and external display might not be probed.
6321 // Do not incorporate state that requires graphics to be in max power
6322 // such as desktopMode or clamshellDisabled.
6323
6324 if (!acAdaptorConnected) {
6325 DLOG("full wake check: no AC\n");
6326 return false;
6327 }
6328 }
6329 #endif
6330 return true;
6331 }
6332
6333 //******************************************************************************
6334 // mustHibernate
6335 //******************************************************************************
6336
6337 #if HIBERNATION
6338
6339 bool
6340 IOPMrootDomain::mustHibernate( void )
6341 {
6342 return lowBatteryCondition || thermalWarningState;
6343 }
6344
6345 #endif /* HIBERNATION */
6346
6347 //******************************************************************************
6348 // adjustPowerState
6349 //
6350 // Conditions that affect our wake/sleep decision has changed.
6351 // If conditions dictate that the system must remain awake, clamp power
6352 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
6353 // is TRUE, then remove the power clamp and allow the power state to drop
6354 // to SLEEP_STATE.
6355 //******************************************************************************
6356
6357 void
6358 IOPMrootDomain::adjustPowerState( bool sleepASAP )
6359 {
6360 DLOG("adjustPowerState ps %u, asap %d, idleSleepEnabled %d\n",
6361 (uint32_t) getPowerState(), sleepASAP, idleSleepEnabled);
6362
6363 ASSERT_GATED();
6364
6365 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
6366 changePowerStateToPriv(ON_STATE);
6367 } else if (sleepASAP) {
6368 changePowerStateToPriv(SLEEP_STATE);
6369 }
6370 }
6371
6372 void
6373 IOPMrootDomain::handleDisplayPowerOn()
6374 {
6375 if (!wrangler) {
6376 return;
6377 }
6378 if (displayPowerOnRequested) {
6379 if (!checkSystemCanSustainFullWake()) {
6380 return;
6381 }
6382
6383 // Force wrangler to max power state. If system is in dark wake
6384 // this alone won't raise the wrangler's power state.
6385
6386 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
6387
6388 // System in dark wake, always requesting full wake should
6389 // not have any bad side-effects, even if the request fails.
6390
6391 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6392 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
6393 requestFullWake( kFullWakeReasonDisplayOn );
6394 }
6395 } else {
6396 // Relenquish desire to power up display.
6397 // Must first transition to state 1 since wrangler doesn't
6398 // power off the displays at state 0. At state 0 the root
6399 // domain is removed from the wrangler's power client list.
6400
6401 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
6402 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
6403 }
6404 }
6405
6406 //******************************************************************************
6407 // dispatchPowerEvent
6408 //
6409 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
6410 //******************************************************************************
6411
6412 void
6413 IOPMrootDomain::dispatchPowerEvent(
6414 uint32_t event, void * arg0, uint64_t arg1 )
6415 {
6416 ASSERT_GATED();
6417
6418 switch (event) {
6419 case kPowerEventFeatureChanged:
6420 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6421 messageClients(kIOPMMessageFeatureChange, this);
6422 break;
6423
6424 case kPowerEventReceivedPowerNotification:
6425 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6426 handlePowerNotification((UInt32)(uintptr_t) arg0 );
6427 break;
6428
6429 case kPowerEventSystemBootCompleted:
6430 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6431 if (systemBooting) {
6432 systemBooting = false;
6433
6434 // read noidle setting from Device Tree
6435 IORegistryEntry *defaults = IORegistryEntry::fromPath("IODeviceTree:/defaults");
6436 if (defaults != NULL) {
6437 OSData *data = OSDynamicCast(OSData, defaults->getProperty("no-idle"));
6438 if ((data != NULL) && (data->getLength() == 4)) {
6439 gNoIdleFlag = *(uint32_t*)data->getBytesNoCopy();
6440 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
6441 }
6442 defaults->release();
6443 }
6444 if (lowBatteryCondition) {
6445 privateSleepSystem(kIOPMSleepReasonLowPower);
6446
6447 // The rest is unnecessary since the system is expected
6448 // to sleep immediately. The following wake will update
6449 // everything.
6450 break;
6451 }
6452
6453 sleepWakeDebugMemAlloc();
6454 saveFailureData2File();
6455
6456 // If lid is closed, re-send lid closed notification
6457 // now that booting is complete.
6458 if (clamshellClosed) {
6459 handlePowerNotification(kLocalEvalClamshellCommand);
6460 }
6461 evaluatePolicy( kStimulusAllowSystemSleepChanged );
6462 }
6463 break;
6464
6465 case kPowerEventSystemShutdown:
6466 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6467 if (kOSBooleanTrue == (OSBoolean *) arg0) {
6468 /* We set systemShutdown = true during shutdown
6469 * to prevent sleep at unexpected times while loginwindow is trying
6470 * to shutdown apps and while the OS is trying to transition to
6471 * complete power of.
6472 *
6473 * Set to true during shutdown, as soon as loginwindow shows
6474 * the "shutdown countdown dialog", through individual app
6475 * termination, and through black screen kernel shutdown.
6476 */
6477 systemShutdown = true;
6478 } else {
6479 /*
6480 * A shutdown was initiated, but then the shutdown
6481 * was cancelled, clearing systemShutdown to false here.
6482 */
6483 systemShutdown = false;
6484 }
6485 break;
6486
6487 case kPowerEventUserDisabledSleep:
6488 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6489 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
6490 break;
6491
6492 case kPowerEventRegisterSystemCapabilityClient:
6493 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6494 if (systemCapabilityNotifier) {
6495 systemCapabilityNotifier->release();
6496 systemCapabilityNotifier = 0;
6497 }
6498 if (arg0) {
6499 systemCapabilityNotifier = (IONotifier *) arg0;
6500 systemCapabilityNotifier->retain();
6501 }
6502 /* intentional fall-through */
6503 [[clang::fallthrough]];
6504
6505 case kPowerEventRegisterKernelCapabilityClient:
6506 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6507 if (!_joinedCapabilityClients) {
6508 _joinedCapabilityClients = OSSet::withCapacity(8);
6509 }
6510 if (arg0) {
6511 IONotifier * notify = (IONotifier *) arg0;
6512 if (_joinedCapabilityClients) {
6513 _joinedCapabilityClients->setObject(notify);
6514 synchronizePowerTree( kIOPMSyncNoChildNotify );
6515 }
6516 notify->release();
6517 }
6518 break;
6519
6520 case kPowerEventPolicyStimulus:
6521 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6522 if (arg0) {
6523 int stimulus = (uintptr_t) arg0;
6524 evaluatePolicy( stimulus, (uint32_t) arg1 );
6525 }
6526 break;
6527
6528 case kPowerEventAssertionCreate:
6529 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6530 if (pmAssertions) {
6531 pmAssertions->handleCreateAssertion((OSData *)arg0);
6532 }
6533 break;
6534
6535
6536 case kPowerEventAssertionRelease:
6537 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6538 if (pmAssertions) {
6539 pmAssertions->handleReleaseAssertion(arg1);
6540 }
6541 break;
6542
6543 case kPowerEventAssertionSetLevel:
6544 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6545 if (pmAssertions) {
6546 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
6547 }
6548 break;
6549
6550 case kPowerEventQueueSleepWakeUUID:
6551 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6552 handleQueueSleepWakeUUID((OSObject *)arg0);
6553 break;
6554 case kPowerEventPublishSleepWakeUUID:
6555 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6556 handlePublishSleepWakeUUID((bool)arg0);
6557 break;
6558
6559 case kPowerEventSetDisplayPowerOn:
6560 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
6561 if (!wrangler) {
6562 break;
6563 }
6564 if (arg1 != 0) {
6565 displayPowerOnRequested = true;
6566 } else {
6567 displayPowerOnRequested = false;
6568 }
6569 handleDisplayPowerOn();
6570 break;
6571 }
6572 }
6573
6574 //******************************************************************************
6575 // systemPowerEventOccurred
6576 //
6577 // The power controller is notifying us of a hardware-related power management
6578 // event that we must handle.
6579 //
6580 // systemPowerEventOccurred covers the same functionality that
6581 // receivePowerNotification does; it simply provides a richer API for conveying
6582 // more information.
6583 //******************************************************************************
6584
6585 IOReturn
6586 IOPMrootDomain::systemPowerEventOccurred(
6587 const OSSymbol *event,
6588 uint32_t intValue)
6589 {
6590 IOReturn attempt = kIOReturnSuccess;
6591 OSNumber *newNumber = NULL;
6592
6593 if (!event) {
6594 return kIOReturnBadArgument;
6595 }
6596
6597 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
6598 if (!newNumber) {
6599 return kIOReturnInternalError;
6600 }
6601
6602 attempt = systemPowerEventOccurred(event, (OSObject *)newNumber);
6603
6604 newNumber->release();
6605
6606 return attempt;
6607 }
6608
6609 void
6610 IOPMrootDomain::setThermalState(OSObject *value)
6611 {
6612 OSNumber * num;
6613
6614 if (gIOPMWorkLoop->inGate() == false) {
6615 gIOPMWorkLoop->runAction(
6616 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
6617 (OSObject *)this,
6618 (void *)value);
6619
6620 return;
6621 }
6622 if (value && (num = OSDynamicCast(OSNumber, value))) {
6623 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
6624 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
6625 }
6626 }
6627
6628 IOReturn
6629 IOPMrootDomain::systemPowerEventOccurred(
6630 const OSSymbol *event,
6631 OSObject *value)
6632 {
6633 OSDictionary *thermalsDict = NULL;
6634 bool shouldUpdate = true;
6635
6636 if (!event || !value) {
6637 return kIOReturnBadArgument;
6638 }
6639
6640 // LOCK
6641 // We reuse featuresDict Lock because it already exists and guards
6642 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
6643 // of stepping on that lock.
6644 if (featuresDictLock) {
6645 IOLockLock(featuresDictLock);
6646 }
6647
6648 thermalsDict = (OSDictionary *)getProperty(kIOPMRootDomainPowerStatusKey);
6649
6650 if (thermalsDict && OSDynamicCast(OSDictionary, thermalsDict)) {
6651 thermalsDict = OSDictionary::withDictionary(thermalsDict);
6652 } else {
6653 thermalsDict = OSDictionary::withCapacity(1);
6654 }
6655
6656 if (!thermalsDict) {
6657 shouldUpdate = false;
6658 goto exit;
6659 }
6660
6661 thermalsDict->setObject(event, value);
6662
6663 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict);
6664
6665 thermalsDict->release();
6666
6667 exit:
6668 // UNLOCK
6669 if (featuresDictLock) {
6670 IOLockUnlock(featuresDictLock);
6671 }
6672
6673 if (shouldUpdate) {
6674 if (event &&
6675 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
6676 setThermalState(value);
6677 }
6678 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
6679 }
6680
6681 return kIOReturnSuccess;
6682 }
6683
6684 //******************************************************************************
6685 // receivePowerNotification
6686 //
6687 // The power controller is notifying us of a hardware-related power management
6688 // event that we must handle. This may be a result of an 'environment' interrupt
6689 // from the power mgt micro.
6690 //******************************************************************************
6691
6692 IOReturn
6693 IOPMrootDomain::receivePowerNotification( UInt32 msg )
6694 {
6695 pmPowerStateQueue->submitPowerEvent(
6696 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
6697 return kIOReturnSuccess;
6698 }
6699
6700 void
6701 IOPMrootDomain::handlePowerNotification( UInt32 msg )
6702 {
6703 bool eval_clamshell = false;
6704
6705 ASSERT_GATED();
6706
6707 /*
6708 * Local (IOPMrootDomain only) eval clamshell command
6709 */
6710 if (msg & kLocalEvalClamshellCommand) {
6711 eval_clamshell = true;
6712 }
6713
6714 /*
6715 * Overtemp
6716 */
6717 if (msg & kIOPMOverTemp) {
6718 MSG("PowerManagement emergency overtemp signal. Going to sleep!");
6719 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6720 }
6721
6722 /*
6723 * Forward DW thermal notification to client, if system is not going to sleep
6724 */
6725 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
6726 DLOG("DarkWake thermal limits message received!\n");
6727
6728 messageClients(kIOPMMessageDarkWakeThermalEmergency);
6729 }
6730
6731 /*
6732 * Sleep Now!
6733 */
6734 if (msg & kIOPMSleepNow) {
6735 privateSleepSystem(kIOPMSleepReasonSoftware);
6736 }
6737
6738 /*
6739 * Power Emergency
6740 */
6741 if (msg & kIOPMPowerEmergency) {
6742 lowBatteryCondition = true;
6743 privateSleepSystem(kIOPMSleepReasonLowPower);
6744 }
6745
6746 /*
6747 * Clamshell OPEN
6748 */
6749 if (msg & kIOPMClamshellOpened) {
6750 DLOG("Clamshell opened\n");
6751 // Received clamshel open message from clamshell controlling driver
6752 // Update our internal state and tell general interest clients
6753 clamshellClosed = false;
6754 clamshellExists = true;
6755
6756 // Don't issue a hid tickle when lid is open and polled on wake
6757 if (msg & kIOPMSetValue) {
6758 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
6759 reportUserInput();
6760 }
6761
6762 // Tell PMCPU
6763 informCPUStateChange(kInformLid, 0);
6764
6765 // Tell general interest clients
6766 sendClientClamshellNotification();
6767
6768 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
6769 || (lastSleepReason == kIOPMSleepReasonIdle)
6770 || (lastSleepReason == kIOPMSleepReasonMaintenance));
6771 if (aborting) {
6772 userActivityCount++;
6773 }
6774 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
6775 }
6776
6777 /*
6778 * Clamshell CLOSED
6779 * Send the clamshell interest notification since the lid is closing.
6780 */
6781 if (msg & kIOPMClamshellClosed) {
6782 if (clamshellClosed && clamshellExists) {
6783 DLOG("Ignoring redundant Clamshell close event\n");
6784 } else {
6785 DLOG("Clamshell closed\n");
6786 // Received clamshel open message from clamshell controlling driver
6787 // Update our internal state and tell general interest clients
6788 clamshellClosed = true;
6789 clamshellExists = true;
6790
6791 // Tell PMCPU
6792 informCPUStateChange(kInformLid, 1);
6793
6794 // Tell general interest clients
6795 sendClientClamshellNotification();
6796
6797 // And set eval_clamshell = so we can attempt
6798 eval_clamshell = true;
6799 }
6800 }
6801
6802 /*
6803 * Set Desktop mode (sent from graphics)
6804 *
6805 * -> reevaluate lid state
6806 */
6807 if (msg & kIOPMSetDesktopMode) {
6808 DLOG("Desktop mode\n");
6809 desktopMode = (0 != (msg & kIOPMSetValue));
6810 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
6811
6812 sendClientClamshellNotification();
6813
6814 // Re-evaluate the lid state
6815 eval_clamshell = true;
6816 }
6817
6818 /*
6819 * AC Adaptor connected
6820 *
6821 * -> reevaluate lid state
6822 */
6823 if (msg & kIOPMSetACAdaptorConnected) {
6824 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
6825 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
6826
6827 // Tell CPU PM
6828 informCPUStateChange(kInformAC, !acAdaptorConnected);
6829
6830 // Tell BSD if AC is connected
6831 // 0 == external power source; 1 == on battery
6832 post_sys_powersource(acAdaptorConnected ? 0:1);
6833
6834 sendClientClamshellNotification();
6835
6836 // Re-evaluate the lid state
6837 eval_clamshell = true;
6838
6839 // Lack of AC may have latched a display wrangler tickle.
6840 // This mirrors the hardware's USB wake event latch, where a latched
6841 // USB wake event followed by an AC attach will trigger a full wake.
6842 latchDisplayWranglerTickle( false );
6843
6844 #if HIBERNATION
6845 // AC presence will reset the standy timer delay adjustment.
6846 _standbyTimerResetSeconds = 0;
6847 #endif
6848 if (!userIsActive) {
6849 // Reset userActivityTime when power supply is changed(rdr 13789330)
6850 clock_get_uptime(&userActivityTime);
6851 }
6852 }
6853
6854 /*
6855 * Enable Clamshell (external display disappear)
6856 *
6857 * -> reevaluate lid state
6858 */
6859 if (msg & kIOPMEnableClamshell) {
6860 DLOG("Clamshell enabled\n");
6861 // Re-evaluate the lid state
6862 // System should sleep on external display disappearance
6863 // in lid closed operation.
6864 if (true == clamshellDisabled) {
6865 eval_clamshell = true;
6866 }
6867
6868 clamshellDisabled = false;
6869 sendClientClamshellNotification();
6870 }
6871
6872 /*
6873 * Disable Clamshell (external display appeared)
6874 * We don't bother re-evaluating clamshell state. If the system is awake,
6875 * the lid is probably open.
6876 */
6877 if (msg & kIOPMDisableClamshell) {
6878 DLOG("Clamshell disabled\n");
6879 clamshellDisabled = true;
6880 sendClientClamshellNotification();
6881 }
6882
6883 /*
6884 * Evaluate clamshell and SLEEP if appropiate
6885 */
6886 if (eval_clamshell && clamshellClosed) {
6887 if (shouldSleepOnClamshellClosed()) {
6888 privateSleepSystem(kIOPMSleepReasonClamshell);
6889 } else {
6890 evaluatePolicy( kStimulusDarkWakeEvaluate );
6891 }
6892 }
6893
6894 /*
6895 * Power Button
6896 */
6897 if (msg & kIOPMPowerButton) {
6898 DLOG("Powerbutton press\n");
6899 if (!wranglerAsleep) {
6900 OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
6901 // Check that power button sleep is enabled
6902 if (pbs) {
6903 if (kOSBooleanTrue != getProperty(pbs)) {
6904 privateSleepSystem(kIOPMSleepReasonPowerButton);
6905 }
6906 }
6907 } else {
6908 reportUserInput();
6909 }
6910 }
6911 }
6912
6913 //******************************************************************************
6914 // evaluatePolicy
6915 //
6916 // Evaluate root-domain policy in response to external changes.
6917 //******************************************************************************
6918
6919 void
6920 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
6921 {
6922 union {
6923 struct {
6924 int idleSleepEnabled : 1;
6925 int idleSleepDisabled : 1;
6926 int displaySleep : 1;
6927 int sleepDelayChanged : 1;
6928 int evaluateDarkWake : 1;
6929 int adjustPowerState : 1;
6930 int userBecameInactive : 1;
6931 } bit;
6932 uint32_t u32;
6933 } flags;
6934
6935
6936 ASSERT_GATED();
6937 flags.u32 = 0;
6938
6939 switch (stimulus) {
6940 case kStimulusDisplayWranglerSleep:
6941 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6942 if (!wranglerAsleep) {
6943 // first transition to wrangler sleep or lower
6944 flags.bit.displaySleep = true;
6945 }
6946 break;
6947
6948 case kStimulusDisplayWranglerWake:
6949 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6950 displayIdleForDemandSleep = false;
6951 wranglerAsleep = false;
6952 break;
6953
6954 case kStimulusEnterUserActiveState:
6955 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6956 if (_preventUserActive) {
6957 DLOG("user active dropped\n");
6958 break;
6959 }
6960 if (!userIsActive) {
6961 userIsActive = true;
6962 userWasActive = true;
6963 clock_get_uptime(&gUserActiveAbsTime);
6964
6965 // Stay awake after dropping demand for display power on
6966 if (kFullWakeReasonDisplayOn == fullWakeReason) {
6967 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
6968 DLOG("User activity while in notification wake\n");
6969 changePowerStateWithOverrideTo( ON_STATE, 0);
6970 }
6971
6972 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
6973 setProperty(gIOPMUserIsActiveKey, kOSBooleanTrue);
6974 messageClients(kIOPMMessageUserIsActiveChanged);
6975 }
6976 flags.bit.idleSleepDisabled = true;
6977 break;
6978
6979 case kStimulusLeaveUserActiveState:
6980 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6981 if (userIsActive) {
6982 clock_get_uptime(&gUserInactiveAbsTime);
6983 userIsActive = false;
6984 clock_get_uptime(&userBecameInactiveTime);
6985 flags.bit.userBecameInactive = true;
6986
6987 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
6988 setProperty(gIOPMUserIsActiveKey, kOSBooleanFalse);
6989 messageClients(kIOPMMessageUserIsActiveChanged);
6990 }
6991 break;
6992
6993 case kStimulusAggressivenessChanged:
6994 {
6995 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6996 unsigned long minutesToIdleSleep = 0;
6997 unsigned long minutesToDisplayDim = 0;
6998 unsigned long minutesDelta = 0;
6999
7000 // Fetch latest display and system sleep slider values.
7001 getAggressiveness(kPMMinutesToSleep, &minutesToIdleSleep);
7002 getAggressiveness(kPMMinutesToDim, &minutesToDisplayDim);
7003 DLOG("aggressiveness changed: system %u->%u, display %u\n",
7004 (uint32_t) sleepSlider,
7005 (uint32_t) minutesToIdleSleep,
7006 (uint32_t) minutesToDisplayDim);
7007
7008 DLOG("idle time -> %ld secs (ena %d)\n",
7009 idleSeconds, (minutesToIdleSleep != 0));
7010
7011
7012 // How long to wait before sleeping the system once
7013 // the displays turns off is indicated by 'extraSleepDelay'.
7014
7015 if (minutesToIdleSleep > minutesToDisplayDim) {
7016 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
7017 } else if (minutesToIdleSleep == minutesToDisplayDim) {
7018 minutesDelta = 1;
7019 }
7020
7021 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
7022 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
7023 }
7024
7025 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
7026 flags.bit.idleSleepDisabled = true;
7027 idleSleepEnabled = false;
7028 }
7029 if (0x7fffffff == minutesToIdleSleep) {
7030 minutesToIdleSleep = idleSeconds;
7031 }
7032
7033 if (((minutesDelta != extraSleepDelay) ||
7034 (userActivityTime != userActivityTime_prev)) &&
7035 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
7036 flags.bit.sleepDelayChanged = true;
7037 }
7038
7039 if (systemDarkWake && !darkWakeToSleepASAP &&
7040 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
7041 // Reconsider decision to remain in dark wake
7042 flags.bit.evaluateDarkWake = true;
7043 }
7044
7045 sleepSlider = minutesToIdleSleep;
7046 extraSleepDelay = minutesDelta;
7047 userActivityTime_prev = userActivityTime;
7048 } break;
7049
7050 case kStimulusDemandSystemSleep:
7051 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7052 displayIdleForDemandSleep = true;
7053 if (wrangler && wranglerIdleSettings) {
7054 // Request wrangler idle only when demand sleep is triggered
7055 // from full wake.
7056 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7057 wrangler->setProperties(wranglerIdleSettings);
7058 DLOG("Requested wrangler idle\n");
7059 }
7060 }
7061 // arg = sleepReason
7062 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
7063 break;
7064
7065 case kStimulusAllowSystemSleepChanged:
7066 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7067 flags.bit.adjustPowerState = true;
7068 break;
7069
7070 case kStimulusDarkWakeActivityTickle:
7071 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7072 // arg == true implies real and not self generated wrangler tickle.
7073 // Update wake type on PM work loop instead of the tickle thread to
7074 // eliminate the possibility of an early tickle clobbering the wake
7075 // type set by the platform driver.
7076 if (arg == true) {
7077 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
7078 }
7079
7080 if (false == wranglerTickled) {
7081 if (latchDisplayWranglerTickle(true)) {
7082 DLOG("latched tickle\n");
7083 break;
7084 }
7085
7086 wranglerTickled = true;
7087 DLOG("Requesting full wake after dark wake activity tickle\n");
7088 requestFullWake( kFullWakeReasonLocalUser );
7089 }
7090 break;
7091
7092 case kStimulusDarkWakeEntry:
7093 case kStimulusDarkWakeReentry:
7094 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7095 // Any system transitions since the last dark wake transition
7096 // will invalid the stimulus.
7097
7098 if (arg == _systemStateGeneration) {
7099 DLOG("dark wake entry\n");
7100 systemDarkWake = true;
7101
7102 // Keep wranglerAsleep an invariant when wrangler is absent
7103 if (wrangler) {
7104 wranglerAsleep = true;
7105 }
7106
7107 if (kStimulusDarkWakeEntry == stimulus) {
7108 clock_get_uptime(&userBecameInactiveTime);
7109 flags.bit.evaluateDarkWake = true;
7110 if (activitySinceSleep()) {
7111 DLOG("User activity recorded while going to darkwake\n");
7112 reportUserInput();
7113 }
7114 }
7115
7116 // Always accelerate disk spindown while in dark wake,
7117 // even if system does not support/allow sleep.
7118
7119 cancelIdleSleepTimer();
7120 setQuickSpinDownTimeout();
7121 }
7122 break;
7123
7124 case kStimulusDarkWakeEvaluate:
7125 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7126 if (systemDarkWake) {
7127 flags.bit.evaluateDarkWake = true;
7128 }
7129 break;
7130
7131 case kStimulusNoIdleSleepPreventers:
7132 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
7133 flags.bit.adjustPowerState = true;
7134 break;
7135 } /* switch(stimulus) */
7136
7137 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
7138 if (darkWakeToSleepASAP ||
7139 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
7140 uint32_t newSleepReason;
7141
7142 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7143 // System was previously in full wake. Sleep reason from
7144 // full to dark already recorded in fullToDarkReason.
7145
7146 if (lowBatteryCondition) {
7147 newSleepReason = kIOPMSleepReasonLowPower;
7148 } else {
7149 newSleepReason = fullToDarkReason;
7150 }
7151 } else {
7152 // In dark wake from system sleep.
7153
7154 if (darkWakeSleepService) {
7155 newSleepReason = kIOPMSleepReasonSleepServiceExit;
7156 } else {
7157 newSleepReason = kIOPMSleepReasonMaintenance;
7158 }
7159 }
7160
7161 if (checkSystemCanSleep(newSleepReason)) {
7162 privateSleepSystem(newSleepReason);
7163 }
7164 } else { // non-maintenance (network) dark wake
7165 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
7166 // Release power clamp, and wait for children idle.
7167 adjustPowerState(true);
7168 } else {
7169 changePowerStateToPriv(ON_STATE);
7170 }
7171 }
7172 }
7173
7174 if (systemDarkWake) {
7175 // The rest are irrelevant while system is in dark wake.
7176 flags.u32 = 0;
7177 }
7178
7179 if ((flags.bit.displaySleep) &&
7180 (kFullWakeReasonDisplayOn == fullWakeReason)) {
7181 // kIOPMSleepReasonMaintenance?
7182 DLOG("Display sleep while in notification wake\n");
7183 changePowerStateWithOverrideTo( SLEEP_STATE, kIOPMSleepReasonMaintenance );
7184 }
7185
7186 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
7187 bool cancelQuickSpindown = false;
7188
7189 if (flags.bit.sleepDelayChanged) {
7190 // Cancel existing idle sleep timer and quick disk spindown.
7191 // New settings will be applied by the idleSleepEnabled flag
7192 // handler below if idle sleep is enabled.
7193
7194 DLOG("extra sleep timer changed\n");
7195 cancelIdleSleepTimer();
7196 cancelQuickSpindown = true;
7197 } else {
7198 DLOG("user inactive\n");
7199 }
7200
7201 if (!userIsActive && idleSleepEnabled) {
7202 startIdleSleepTimer(getTimeToIdleSleep());
7203 }
7204
7205 if (cancelQuickSpindown) {
7206 restoreUserSpinDownTimeout();
7207 }
7208 }
7209
7210 if (flags.bit.idleSleepEnabled) {
7211 DLOG("idle sleep timer enabled\n");
7212 if (!wrangler) {
7213 changePowerStateToPriv(ON_STATE);
7214 startIdleSleepTimer( idleSeconds );
7215 } else {
7216 // Start idle timer if prefs now allow system sleep
7217 // and user is already inactive. Disk spindown is
7218 // accelerated upon timer expiration.
7219
7220 if (!userIsActive) {
7221 startIdleSleepTimer(getTimeToIdleSleep());
7222 }
7223 }
7224 }
7225
7226 if (flags.bit.idleSleepDisabled) {
7227 DLOG("idle sleep timer disabled\n");
7228 cancelIdleSleepTimer();
7229 restoreUserSpinDownTimeout();
7230 adjustPowerState();
7231 }
7232
7233 if (flags.bit.adjustPowerState) {
7234 bool sleepASAP = false;
7235
7236 if (!systemBooting && (preventIdleSleepList->getCount() == 0)) {
7237 if (!wrangler) {
7238 changePowerStateToPriv(ON_STATE);
7239 if (idleSleepEnabled) {
7240 // stay awake for at least idleSeconds
7241 startIdleSleepTimer(idleSeconds);
7242 }
7243 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake) {
7244 sleepASAP = true;
7245 }
7246 }
7247
7248 adjustPowerState(sleepASAP);
7249 }
7250 }
7251
7252 //******************************************************************************
7253 // requestFullWake
7254 //
7255 // Request transition from dark wake to full wake
7256 //******************************************************************************
7257
7258 void
7259 IOPMrootDomain::requestFullWake( FullWakeReason reason )
7260 {
7261 uint32_t options = 0;
7262 IOService * pciRoot = 0;
7263 bool promotion = false;
7264
7265 // System must be in dark wake and a valid reason for entering full wake
7266 if ((kFullWakeReasonNone == reason) ||
7267 (kFullWakeReasonNone != fullWakeReason) ||
7268 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
7269 return;
7270 }
7271
7272 // Will clear reason upon exit from full wake
7273 fullWakeReason = reason;
7274
7275 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
7276 kIOPMSystemCapabilityAudio);
7277
7278 if ((kSystemTransitionWake == _systemTransitionType) &&
7279 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7280 !graphicsSuppressed) {
7281 // Promote to full wake while waking up to dark wake due to tickle.
7282 // PM will hold off notifying the graphics subsystem about system wake
7283 // as late as possible, so if a HID tickle does arrive, graphics can
7284 // power up on this same wake cycle. The latency to power up graphics
7285 // on the next cycle can be huge on some systems. However, once any
7286 // graphics suppression has taken effect, it is too late. All other
7287 // graphics devices must be similarly suppressed. But the delay till
7288 // the following cycle should be short.
7289
7290 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
7291 kIOPMSystemCapabilityAudio);
7292
7293 // Immediately bring up audio and graphics
7294 pciRoot = pciHostBridgeDriver;
7295 willEnterFullWake();
7296 promotion = true;
7297 }
7298
7299 // Unsafe to cancel once graphics was powered.
7300 // If system woke from dark wake, the return to sleep can
7301 // be cancelled. "awake -> dark -> sleep" transition
7302 // can be canceled also, during the "dark --> sleep" phase
7303 // *prior* to driver power down.
7304 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
7305 _pendingCapability == 0) {
7306 options |= kIOPMSyncCancelPowerDown;
7307 }
7308
7309 synchronizePowerTree(options, pciRoot);
7310 if (kFullWakeReasonLocalUser == fullWakeReason) {
7311 // IOGraphics doesn't light the display even though graphics is
7312 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
7313 // So, do an explicit activity tickle
7314 if (wrangler) {
7315 wrangler->activityTickle(0, 0);
7316 }
7317 }
7318
7319 // Log a timestamp for the initial full wake request.
7320 // System may not always honor this full wake request.
7321 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7322 AbsoluteTime now;
7323 uint64_t nsec;
7324
7325 clock_get_uptime(&now);
7326 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
7327 absolutetime_to_nanoseconds(now, &nsec);
7328 MSG("full wake %s (reason %u) %u ms\n",
7329 promotion ? "promotion" : "request",
7330 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
7331 }
7332 }
7333
7334 //******************************************************************************
7335 // willEnterFullWake
7336 //
7337 // System will enter full wake from sleep, from dark wake, or from dark
7338 // wake promotion. This function aggregate things that are in common to
7339 // all three full wake transitions.
7340 //
7341 // Assumptions: fullWakeReason was updated
7342 //******************************************************************************
7343
7344 void
7345 IOPMrootDomain::willEnterFullWake( void )
7346 {
7347 hibernateRetry = false;
7348 sleepToStandby = false;
7349 standbyNixed = false;
7350 resetTimers = false;
7351 sleepTimerMaintenance = false;
7352
7353 _systemMessageClientMask = kSystemMessageClientPowerd |
7354 kSystemMessageClientLegacyApp;
7355
7356 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
7357 // Initial graphics full power
7358 _systemMessageClientMask |= kSystemMessageClientKernel;
7359
7360 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
7361 setProperty(gIOPMUserTriggeredFullWakeKey,
7362 (kFullWakeReasonLocalUser == fullWakeReason) ?
7363 kOSBooleanTrue : kOSBooleanFalse);
7364 }
7365 #if HIBERNATION
7366 IOHibernateSetWakeCapabilities(_pendingCapability);
7367 #endif
7368
7369 IOService::setAdvisoryTickleEnable( true );
7370 tellClients(kIOMessageSystemWillPowerOn);
7371 preventTransitionToUserActive(false);
7372 }
7373
7374 //******************************************************************************
7375 // fullWakeDelayedWork
7376 //
7377 // System has already entered full wake. Invoked by a delayed thread call.
7378 //******************************************************************************
7379
7380 void
7381 IOPMrootDomain::fullWakeDelayedWork( void )
7382 {
7383 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
7384 // Not gated, don't modify state
7385 if ((kSystemTransitionNone == _systemTransitionType) &&
7386 CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7387 receivePowerNotification( kLocalEvalClamshellCommand );
7388 }
7389 #endif
7390 }
7391
7392 //******************************************************************************
7393 // evaluateAssertions
7394 //
7395 //******************************************************************************
7396 void
7397 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
7398 {
7399 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
7400
7401 messageClients(kIOPMMessageDriverAssertionsChanged);
7402
7403 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
7404 if (wrangler) {
7405 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
7406
7407 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
7408 wrangler->setIgnoreIdleTimer( value );
7409 }
7410 }
7411
7412 if (changedBits & kIOPMDriverAssertionCPUBit) {
7413 evaluatePolicy(kStimulusDarkWakeEvaluate);
7414 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
7415 AbsoluteTime now;
7416 clock_usec_t microsecs;
7417 clock_get_uptime(&now);
7418 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
7419 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
7420 if (assertOnWakeReport) {
7421 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
7422 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
7423 }
7424 }
7425 }
7426
7427 if (changedBits & kIOPMDriverAssertionReservedBit7) {
7428 bool value = (newAssertions & kIOPMDriverAssertionReservedBit7) ? true : false;
7429 if (value) {
7430 DLOG("Driver assertion ReservedBit7 raised. Legacy IO preventing sleep\n");
7431 updatePreventIdleSleepList(this, true);
7432 } else {
7433 DLOG("Driver assertion ReservedBit7 dropped\n");
7434 updatePreventIdleSleepList(this, false);
7435 }
7436 }
7437 }
7438
7439 // MARK: -
7440 // MARK: Statistics
7441
7442 //******************************************************************************
7443 // pmStats
7444 //
7445 //******************************************************************************
7446
7447 void
7448 IOPMrootDomain::pmStatsRecordEvent(
7449 int eventIndex,
7450 AbsoluteTime timestamp)
7451 {
7452 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
7453 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
7454 uint64_t delta;
7455 uint64_t nsec;
7456 OSData *publishPMStats = NULL;
7457
7458 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
7459
7460 absolutetime_to_nanoseconds(timestamp, &nsec);
7461
7462 switch (eventIndex) {
7463 case kIOPMStatsHibernateImageWrite:
7464 if (starting) {
7465 gPMStats.hibWrite.start = nsec;
7466 } else if (stopping) {
7467 gPMStats.hibWrite.stop = nsec;
7468 }
7469
7470 if (stopping) {
7471 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
7472 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
7473 }
7474 break;
7475 case kIOPMStatsHibernateImageRead:
7476 if (starting) {
7477 gPMStats.hibRead.start = nsec;
7478 } else if (stopping) {
7479 gPMStats.hibRead.stop = nsec;
7480 }
7481
7482 if (stopping) {
7483 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
7484 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
7485
7486 publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats));
7487 setProperty(kIOPMSleepStatisticsKey, publishPMStats);
7488 publishPMStats->release();
7489 bzero(&gPMStats, sizeof(gPMStats));
7490 }
7491 break;
7492 }
7493 }
7494
7495 /*
7496 * Appends a record of the application response to
7497 * IOPMrootDomain::pmStatsAppResponses
7498 */
7499 void
7500 IOPMrootDomain::pmStatsRecordApplicationResponse(
7501 const OSSymbol *response,
7502 const char *name,
7503 int messageType,
7504 uint32_t delay_ms,
7505 uint64_t id,
7506 OSObject *object,
7507 IOPMPowerStateIndex powerState)
7508 {
7509 OSDictionary *responseDescription = NULL;
7510 OSNumber *delayNum = NULL;
7511 OSNumber *powerCaps = NULL;
7512 OSNumber *pidNum = NULL;
7513 OSNumber *msgNum = NULL;
7514 const OSSymbol *appname;
7515 const OSSymbol *sleep = NULL, *wake = NULL;
7516 IOPMServiceInterestNotifier *notify = 0;
7517
7518 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
7519 if (response->isEqualTo(gIOPMStatsResponseTimedOut)) {
7520 notify->ackTimeoutCnt++;
7521 } else {
7522 notify->ackTimeoutCnt = 0;
7523 }
7524 }
7525
7526 if (response->isEqualTo(gIOPMStatsResponsePrompt) ||
7527 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
7528 return;
7529 }
7530
7531
7532 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow)) {
7533 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
7534 } else if (notify) {
7535 // User space app or kernel capability client
7536 if (id) {
7537 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
7538 } else {
7539 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
7540 }
7541 notify->msgType = 0;
7542 }
7543
7544 responseDescription = OSDictionary::withCapacity(5);
7545 if (responseDescription) {
7546 if (response) {
7547 responseDescription->setObject(_statsResponseTypeKey, response);
7548 }
7549
7550 msgNum = OSNumber::withNumber(messageType, 32);
7551 if (msgNum) {
7552 responseDescription->setObject(_statsMessageTypeKey, msgNum);
7553 msgNum->release();
7554 }
7555
7556 if (!name && notify && notify->identifier) {
7557 name = notify->identifier->getCStringNoCopy();
7558 }
7559
7560 if (name && (strlen(name) > 0)) {
7561 appname = OSSymbol::withCString(name);
7562 if (appname) {
7563 responseDescription->setObject(_statsNameKey, appname);
7564 appname->release();
7565 }
7566 }
7567
7568 if (!id && notify) {
7569 id = notify->uuid0;
7570 }
7571 if (id != 0) {
7572 pidNum = OSNumber::withNumber(id, 64);
7573 if (pidNum) {
7574 responseDescription->setObject(_statsPIDKey, pidNum);
7575 pidNum->release();
7576 }
7577 }
7578
7579 delayNum = OSNumber::withNumber(delay_ms, 32);
7580 if (delayNum) {
7581 responseDescription->setObject(_statsTimeMSKey, delayNum);
7582 delayNum->release();
7583 }
7584
7585 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow)) {
7586 powerCaps = OSNumber::withNumber(powerState, 32);
7587
7588 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
7589 IOLog("%s::powerStateChange type(%d) to(%lu) async took %d ms\n",
7590 name, messageType,
7591 powerState, delay_ms);
7592 #endif
7593 } else {
7594 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
7595 }
7596 if (powerCaps) {
7597 responseDescription->setObject(_statsPowerCapsKey, powerCaps);
7598 powerCaps->release();
7599 }
7600
7601 sleep = OSSymbol::withCString("Sleep");
7602 wake = OSSymbol::withCString("Wake");
7603 if (_systemTransitionType == kSystemTransitionSleep) {
7604 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep);
7605 } else if (_systemTransitionType == kSystemTransitionWake) {
7606 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake);
7607 } else if (_systemTransitionType == kSystemTransitionCapability) {
7608 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
7609 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep);
7610 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
7611 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake);
7612 }
7613 }
7614 if (sleep) {
7615 sleep->release();
7616 }
7617 if (wake) {
7618 wake->release();
7619 }
7620
7621
7622
7623 IOLockLock(pmStatsLock);
7624 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
7625 pmStatsAppResponses->setObject(responseDescription);
7626 }
7627 IOLockUnlock(pmStatsLock);
7628
7629 responseDescription->release();
7630 }
7631
7632 return;
7633 }
7634
7635 // MARK: -
7636 // MARK: PMTraceWorker
7637
7638 //******************************************************************************
7639 // TracePoint support
7640 //
7641 //******************************************************************************
7642
7643 #define kIOPMRegisterNVRAMTracePointHandlerKey \
7644 "IOPMRegisterNVRAMTracePointHandler"
7645
7646 IOReturn
7647 IOPMrootDomain::callPlatformFunction(
7648 const OSSymbol * functionName,
7649 bool waitForFunction,
7650 void * param1, void * param2,
7651 void * param3, void * param4 )
7652 {
7653 uint32_t bootFailureCode = 0xffffffff;
7654 if (pmTracer && functionName &&
7655 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
7656 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
7657 uint32_t tracePointPhases, tracePointPCI;
7658 uint64_t statusCode;
7659
7660 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
7661 pmTracer->tracePointTarget = (void *) param2;
7662 tracePointPCI = (uint32_t)(uintptr_t) param3;
7663 tracePointPhases = (uint32_t)(uintptr_t) param4;
7664 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
7665 IORegistryEntry *node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
7666 if (node) {
7667 OSData *data = OSDynamicCast( OSData, node->getProperty(kIOEFIBootRomFailureKey));
7668 if (data && data->getLength() == sizeof(bootFailureCode)) {
7669 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
7670 }
7671 node->release();
7672 }
7673 // Failure code from EFI/BootRom is a four byte structure
7674 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
7675 }
7676 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
7677 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
7678 MSG("Sleep failure code 0x%08x 0x%08x\n",
7679 tracePointPCI, tracePointPhases);
7680 }
7681 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
7682 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
7683
7684 return kIOReturnSuccess;
7685 }
7686 #if HIBERNATION
7687 else if (functionName &&
7688 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
7689 if (gSleepPolicyHandler) {
7690 return kIOReturnExclusiveAccess;
7691 }
7692 if (!param1) {
7693 return kIOReturnBadArgument;
7694 }
7695 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
7696 gSleepPolicyTarget = (void *) param2;
7697 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
7698 return kIOReturnSuccess;
7699 }
7700 #endif
7701
7702 return super::callPlatformFunction(
7703 functionName, waitForFunction, param1, param2, param3, param4);
7704 }
7705
7706 void
7707 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
7708 uintptr_t param1, uintptr_t param2, uintptr_t param3)
7709 {
7710 uint32_t code = IODBG_POWER(event);
7711 uint64_t regId = id;
7712 if (regId == 0) {
7713 regId = getRegistryEntryID();
7714 }
7715 IOTimeStampConstant(code, (uintptr_t) regId, param1, param2, param3);
7716 }
7717
7718
7719 void
7720 IOPMrootDomain::tracePoint( uint8_t point )
7721 {
7722 if (systemBooting) {
7723 return;
7724 }
7725
7726 if (kIOPMTracePointWakeCapabilityClients == point) {
7727 acceptSystemWakeEvents(false);
7728 }
7729
7730 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
7731 pmTracer->tracePoint(point);
7732 }
7733
7734 void
7735 IOPMrootDomain::traceDetail(OSObject *object, bool start)
7736 {
7737 IOPMServiceInterestNotifier *notifier;
7738
7739 if (systemBooting) {
7740 return;
7741 }
7742
7743 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
7744 if (!notifier) {
7745 return;
7746 }
7747
7748 if (start) {
7749 pmTracer->traceDetail( notifier->uuid0 >> 32 );
7750 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(), notifier->msgType, notifier->uuid0, notifier->uuid1);
7751 if (notifier->identifier) {
7752 DLOG("trace point 0x%02x msg 0x%x to %s\n", pmTracer->getTracePhase(), notifier->msgType,
7753 notifier->identifier->getCStringNoCopy());
7754 } else {
7755 DLOG("trace point 0x%02x msg 0x%x\n", pmTracer->getTracePhase(), notifier->msgType);
7756 }
7757 notifierThread = current_thread();
7758 notifierObject = notifier;
7759 notifier->retain();
7760 } else {
7761 notifierThread = NULL;
7762 notifierObject = NULL;
7763 notifier->release();
7764 }
7765 }
7766
7767
7768 void
7769 IOPMrootDomain::traceAckDelay(OSObject *object, uint32_t response, uint32_t delay_ms)
7770 {
7771 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
7772 if (!notifier) {
7773 DLOG("Unknown notifier\n");
7774 return;
7775 }
7776
7777 if (!systemBooting) {
7778 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0, notifier->uuid1, response, delay_ms);
7779 if (notifier->identifier) {
7780 DLOG("Response from %s took %d ms(response:%d)\n",
7781 notifier->identifier->getCStringNoCopy(), delay_ms, response);
7782 } else {
7783 DLOG("Response from kext UUID %llx-%llx took %d ms(response:%d)\n",
7784 notifier->uuid0, notifier->uuid1, delay_ms, response);
7785 }
7786 }
7787 }
7788
7789 void
7790 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
7791 {
7792 if (!systemBooting) {
7793 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
7794 pmTracer->traceDetail( detail );
7795 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
7796 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
7797 }
7798 }
7799
7800
7801 void
7802 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
7803 {
7804 size_t reportSize;
7805 void **report = NULL;
7806 uint32_t bktCnt;
7807 uint32_t bktSize;
7808 uint32_t *clientCnt;
7809
7810 ASSERT_GATED();
7811
7812 report = NULL;
7813 if (channel_id == kAssertDelayChID) {
7814 report = &assertOnWakeReport;
7815 bktCnt = kAssertDelayBcktCnt;
7816 bktSize = kAssertDelayBcktSize;
7817 clientCnt = &assertOnWakeClientCnt;
7818 } else if (channel_id == kSleepDelaysChID) {
7819 report = &sleepDelaysReport;
7820 bktCnt = kSleepDelaysBcktCnt;
7821 bktSize = kSleepDelaysBcktSize;
7822 clientCnt = &sleepDelaysClientCnt;
7823 }
7824
7825 switch (action) {
7826 case kIOReportEnable:
7827
7828 if (*report) {
7829 (*clientCnt)++;
7830 break;
7831 }
7832
7833 reportSize = HISTREPORT_BUFSIZE(bktCnt);
7834 *report = IOMalloc(reportSize);
7835 if (*report == NULL) {
7836 break;
7837 }
7838 bzero(*report, reportSize);
7839 HISTREPORT_INIT(bktCnt, bktSize, *report, reportSize,
7840 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
7841
7842 if (channel_id == kAssertDelayChID) {
7843 assertOnWakeSecs = 0;
7844 }
7845
7846 break;
7847
7848 case kIOReportDisable:
7849 if (*clientCnt == 0) {
7850 break;
7851 }
7852 if (*clientCnt == 1) {
7853 IOFree(*report, HISTREPORT_BUFSIZE(bktCnt));
7854 *report = NULL;
7855 }
7856 (*clientCnt)--;
7857
7858 if (channel_id == kAssertDelayChID) {
7859 assertOnWakeSecs = -1; // Invalid value to prevent updates
7860 }
7861 break;
7862
7863 case kIOReportGetDimensions:
7864 if (*report) {
7865 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
7866 }
7867 break;
7868 }
7869
7870 return;
7871 }
7872
7873 IOReturn
7874 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
7875 IOReportConfigureAction action,
7876 void *result,
7877 void *destination)
7878 {
7879 unsigned cnt;
7880 uint64_t configAction = (uint64_t)action;
7881
7882 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7883 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
7884 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
7885 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
7886 if (action != kIOReportGetDimensions) {
7887 continue;
7888 }
7889 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
7890 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
7891 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
7892 gIOPMWorkLoop->runAction(
7893 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
7894 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
7895 (void *)configAction, (void *)result);
7896 }
7897 }
7898
7899 return super::configureReport(channelList, action, result, destination);
7900 }
7901
7902 IOReturn
7903 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
7904 {
7905 uint32_t size2cpy;
7906 void *data2cpy;
7907 void **report;
7908
7909 ASSERT_GATED();
7910
7911 report = NULL;
7912 if (ch_id == kAssertDelayChID) {
7913 report = &assertOnWakeReport;
7914 } else if (ch_id == kSleepDelaysChID) {
7915 report = &sleepDelaysReport;
7916 }
7917
7918 if (*report == NULL) {
7919 return kIOReturnNotOpen;
7920 }
7921
7922 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
7923 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
7924 return kIOReturnOverrun;
7925 }
7926
7927 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
7928 dest->appendBytes(data2cpy, size2cpy);
7929
7930 return kIOReturnSuccess;
7931 }
7932
7933 IOReturn
7934 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
7935 IOReportUpdateAction action,
7936 void *result,
7937 void *destination)
7938 {
7939 uint32_t size2cpy;
7940 void *data2cpy;
7941 uint8_t buf[SIMPLEREPORT_BUFSIZE];
7942 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
7943 unsigned cnt;
7944 uint64_t ch_id;
7945
7946 if (action != kIOReportCopyChannelData) {
7947 goto exit;
7948 }
7949
7950 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7951 ch_id = channelList->channels[cnt].channel_id;
7952
7953 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
7954 gIOPMWorkLoop->runAction(
7955 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
7956 (OSObject *)this, (void *)ch_id,
7957 (void *)result, (void *)dest);
7958 continue;
7959 } else if ((ch_id == kSleepCntChID) ||
7960 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
7961 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
7962 } else {
7963 continue;
7964 }
7965
7966 if (ch_id == kSleepCntChID) {
7967 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
7968 } else if (ch_id == kDarkWkCntChID) {
7969 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
7970 } else if (ch_id == kUserWkCntChID) {
7971 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
7972 }
7973
7974 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
7975 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
7976 dest->appendBytes(data2cpy, size2cpy);
7977 }
7978
7979 exit:
7980 return super::updateReport(channelList, action, result, destination);
7981 }
7982
7983
7984 //******************************************************************************
7985 // PMTraceWorker Class
7986 //
7987 //******************************************************************************
7988
7989 #undef super
7990 #define super OSObject
7991 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
7992
7993 #define kPMBestGuessPCIDevicesCount 25
7994 #define kPMMaxRTCBitfieldSize 32
7995
7996 PMTraceWorker * PMTraceWorker::tracer(IOPMrootDomain * owner)
7997 {
7998 PMTraceWorker *me;
7999
8000 me = OSTypeAlloc( PMTraceWorker );
8001 if (!me || !me->init()) {
8002 return NULL;
8003 }
8004
8005 DLOG("PMTraceWorker %p\n", OBFUSCATE(me));
8006
8007 // Note that we cannot instantiate the PCI device -> bit mappings here, since
8008 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
8009 // this dictionary lazily.
8010 me->owner = owner;
8011 me->pciDeviceBitMappings = NULL;
8012 me->pmTraceWorkerLock = IOLockAlloc();
8013 me->tracePhase = kIOPMTracePointSystemUp;
8014 me->traceData32 = 0;
8015 me->loginWindowData = 0;
8016 me->coreDisplayData = 0;
8017 me->coreGraphicsData = 0;
8018 return me;
8019 }
8020
8021 void
8022 PMTraceWorker::RTC_TRACE(void)
8023 {
8024 if (tracePointHandler && tracePointTarget) {
8025 uint32_t wordA;
8026
8027 IOLockLock(pmTraceWorkerLock);
8028 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
8029 (coreGraphicsData << 8) | tracePhase;
8030 IOLockUnlock(pmTraceWorkerLock);
8031
8032 tracePointHandler( tracePointTarget, traceData32, wordA );
8033 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
8034 }
8035 }
8036
8037 int
8038 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
8039 {
8040 const OSSymbol * deviceName;
8041 int index = -1;
8042
8043 IOLockLock(pmTraceWorkerLock);
8044
8045 if (!pciDeviceBitMappings) {
8046 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
8047 if (!pciDeviceBitMappings) {
8048 goto exit;
8049 }
8050 }
8051
8052 // Check for bitmask overflow.
8053 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
8054 goto exit;
8055 }
8056
8057 if ((deviceName = pciDevice->copyName()) &&
8058 (pciDeviceBitMappings->getNextIndexOfObject(deviceName, 0) == (unsigned int)-1) &&
8059 pciDeviceBitMappings->setObject(deviceName)) {
8060 index = pciDeviceBitMappings->getCount() - 1;
8061 _LOG("PMTrace PCI array: set object %s => %d\n",
8062 deviceName->getCStringNoCopy(), index);
8063 }
8064 if (deviceName) {
8065 deviceName->release();
8066 }
8067 if (!addedToRegistry && (index >= 0)) {
8068 addedToRegistry = owner->setProperty("PCITopLevel", this);
8069 }
8070
8071 exit:
8072 IOLockUnlock(pmTraceWorkerLock);
8073 return index;
8074 }
8075
8076 bool
8077 PMTraceWorker::serialize(OSSerialize *s) const
8078 {
8079 bool ok = false;
8080 if (pciDeviceBitMappings) {
8081 IOLockLock(pmTraceWorkerLock);
8082 ok = pciDeviceBitMappings->serialize(s);
8083 IOLockUnlock(pmTraceWorkerLock);
8084 }
8085 return ok;
8086 }
8087
8088 void
8089 PMTraceWorker::tracePoint(uint8_t phase)
8090 {
8091 // clear trace detail when phase begins
8092 if (tracePhase != phase) {
8093 traceData32 = 0;
8094 }
8095
8096 tracePhase = phase;
8097
8098 DLOG("trace point 0x%02x\n", tracePhase);
8099 RTC_TRACE();
8100 }
8101
8102 void
8103 PMTraceWorker::traceDetail(uint32_t detail)
8104 {
8105 if (detail == traceData32) {
8106 return;
8107 }
8108 traceData32 = detail;
8109 RTC_TRACE();
8110 }
8111
8112 void
8113 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
8114 {
8115 switch (component) {
8116 case kIOPMLoginWindowProgress:
8117 loginWindowData = data & kIOPMLoginWindowProgressMask;
8118 break;
8119 case kIOPMCoreDisplayProgress:
8120 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
8121 break;
8122 case kIOPMCoreGraphicsProgress:
8123 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
8124 break;
8125 default:
8126 return;
8127 }
8128
8129 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
8130 RTC_TRACE();
8131 }
8132
8133 void
8134 PMTraceWorker::tracePCIPowerChange(
8135 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
8136 {
8137 uint32_t bitMask;
8138 uint32_t expectedFlag;
8139
8140 // Ignore PCI changes outside of system sleep/wake.
8141 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
8142 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
8143 return;
8144 }
8145
8146 // Only record the WillChange transition when going to sleep,
8147 // and the DidChange on the way up.
8148 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
8149 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
8150 kIOPMDomainWillChange : kIOPMDomainDidChange;
8151 if (changeFlags != expectedFlag) {
8152 return;
8153 }
8154
8155 // Mark this device off in our bitfield
8156 if (bitNum < kPMMaxRTCBitfieldSize) {
8157 bitMask = (1 << bitNum);
8158
8159 if (kPowerChangeStart == type) {
8160 traceData32 |= bitMask;
8161 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
8162 service->getName(), bitNum, bitMask, traceData32);
8163 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
8164 } else {
8165 traceData32 &= ~bitMask;
8166 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
8167 service->getName(), bitNum, bitMask, traceData32);
8168 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
8169 }
8170
8171 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
8172 RTC_TRACE();
8173 }
8174 }
8175
8176 uint64_t
8177 PMTraceWorker::getPMStatusCode()
8178 {
8179 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
8180 }
8181
8182 uint8_t
8183 PMTraceWorker::getTracePhase()
8184 {
8185 return tracePhase;
8186 }
8187
8188 uint32_t
8189 PMTraceWorker::getTraceData()
8190 {
8191 return traceData32;
8192 }
8193
8194 // MARK: -
8195 // MARK: PMHaltWorker
8196
8197 //******************************************************************************
8198 // PMHaltWorker Class
8199 //
8200 //******************************************************************************
8201
8202 PMHaltWorker *
8203 PMHaltWorker::worker( void )
8204 {
8205 PMHaltWorker * me;
8206 IOThread thread;
8207
8208 do {
8209 me = OSTypeAlloc( PMHaltWorker );
8210 if (!me || !me->init()) {
8211 break;
8212 }
8213
8214 me->lock = IOLockAlloc();
8215 if (!me->lock) {
8216 break;
8217 }
8218
8219 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
8220 me->retain(); // thread holds extra retain
8221 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
8222 me->release();
8223 break;
8224 }
8225 thread_deallocate(thread);
8226 return me;
8227 } while (false);
8228
8229 if (me) {
8230 me->release();
8231 }
8232 return 0;
8233 }
8234
8235 void
8236 PMHaltWorker::free( void )
8237 {
8238 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
8239 if (lock) {
8240 IOLockFree(lock);
8241 lock = 0;
8242 }
8243 return OSObject::free();
8244 }
8245
8246 void
8247 PMHaltWorker::main( void * arg, wait_result_t waitResult )
8248 {
8249 PMHaltWorker * me = (PMHaltWorker *) arg;
8250
8251 IOLockLock( gPMHaltLock );
8252 gPMHaltBusyCount++;
8253 me->depth = gPMHaltDepth;
8254 IOLockUnlock( gPMHaltLock );
8255
8256 while (me->depth >= 0) {
8257 PMHaltWorker::work( me );
8258
8259 IOLockLock( gPMHaltLock );
8260 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
8261 // This is the last thread to finish work on this level,
8262 // inform everyone to start working on next lower level.
8263 gPMHaltDepth--;
8264 me->depth = gPMHaltDepth;
8265 gPMHaltIdleCount = 0;
8266 thread_wakeup((event_t) &gPMHaltIdleCount);
8267 } else {
8268 // One or more threads are still working on this level,
8269 // this thread must wait.
8270 me->depth = gPMHaltDepth - 1;
8271 do {
8272 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
8273 } while (me->depth != gPMHaltDepth);
8274 }
8275 IOLockUnlock( gPMHaltLock );
8276 }
8277
8278 // No more work to do, terminate thread
8279 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
8280 thread_wakeup( &gPMHaltDepth );
8281 me->release();
8282 }
8283
8284 void
8285 PMHaltWorker::work( PMHaltWorker * me )
8286 {
8287 IOService * service;
8288 OSSet * inner;
8289 AbsoluteTime startTime, elapsedTime;
8290 UInt32 deltaTime;
8291 bool timeout;
8292
8293 while (true) {
8294 service = 0;
8295 timeout = false;
8296
8297 // Claim an unit of work from the shared pool
8298 IOLockLock( gPMHaltLock );
8299 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
8300 if (inner) {
8301 service = OSDynamicCast(IOService, inner->getAnyObject());
8302 if (service) {
8303 service->retain();
8304 inner->removeObject(service);
8305 }
8306 }
8307 IOLockUnlock( gPMHaltLock );
8308 if (!service) {
8309 break; // no more work at this depth
8310 }
8311 clock_get_uptime(&startTime);
8312
8313 if (!service->isInactive() &&
8314 service->setProperty(gPMHaltClientAcknowledgeKey, me)) {
8315 IOLockLock(me->lock);
8316 me->startTime = startTime;
8317 me->service = service;
8318 me->timeout = false;
8319 IOLockUnlock(me->lock);
8320
8321 service->systemWillShutdown( gPMHaltMessageType );
8322
8323 // Wait for driver acknowledgement
8324 IOLockLock(me->lock);
8325 while (service->getProperty(gPMHaltClientAcknowledgeKey)) {
8326 IOLockSleep(me->lock, me, THREAD_UNINT);
8327 }
8328 me->service = 0;
8329 timeout = me->timeout;
8330 IOLockUnlock(me->lock);
8331 }
8332
8333 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
8334 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
8335 LOG("%s driver %s (0x%llx) took %u ms\n",
8336 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
8337 "PowerOff" : "Restart",
8338 service->getName(), service->getRegistryEntryID(),
8339 (uint32_t) deltaTime );
8340 halt_log_enter("PowerOff/Restart handler completed",
8341 OSMemberFunctionCast(const void *, service, &IOService::systemWillShutdown),
8342 elapsedTime);
8343 }
8344
8345 service->release();
8346 me->visits++;
8347 }
8348 }
8349
8350 void
8351 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
8352 {
8353 UInt64 nano;
8354 AbsoluteTime startTime;
8355 AbsoluteTime endTime;
8356
8357 endTime = *now;
8358
8359 IOLockLock(me->lock);
8360 if (me->service && !me->timeout) {
8361 startTime = me->startTime;
8362 nano = 0;
8363 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
8364 SUB_ABSOLUTETIME(&endTime, &startTime);
8365 absolutetime_to_nanoseconds(endTime, &nano);
8366 }
8367 if (nano > 3000000000ULL) {
8368 me->timeout = true;
8369
8370 halt_log_enter("PowerOff/Restart still waiting on handler",
8371 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
8372 endTime);
8373 MSG("%s still waiting on %s\n",
8374 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
8375 me->service->getName());
8376 }
8377 }
8378 IOLockUnlock(me->lock);
8379 }
8380
8381 //******************************************************************************
8382 // acknowledgeSystemWillShutdown
8383 //
8384 // Acknowledgement from drivers that they have prepared for shutdown/restart.
8385 //******************************************************************************
8386
8387 void
8388 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
8389 {
8390 PMHaltWorker * worker;
8391 OSObject * prop;
8392
8393 if (!from) {
8394 return;
8395 }
8396
8397 //DLOG("%s acknowledged\n", from->getName());
8398 prop = from->copyProperty( gPMHaltClientAcknowledgeKey );
8399 if (prop) {
8400 worker = (PMHaltWorker *) prop;
8401 IOLockLock(worker->lock);
8402 from->removeProperty( gPMHaltClientAcknowledgeKey );
8403 thread_wakeup((event_t) worker);
8404 IOLockUnlock(worker->lock);
8405 worker->release();
8406 } else {
8407 DLOG("%s acknowledged without worker property\n",
8408 from->getName());
8409 }
8410 }
8411
8412
8413 //******************************************************************************
8414 // notifySystemShutdown
8415 //
8416 // Notify all objects in PM tree that system will shutdown or restart
8417 //******************************************************************************
8418
8419 static void
8420 notifySystemShutdown( IOService * root, uint32_t messageType )
8421 {
8422 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
8423 IORegistryIterator * iter;
8424 IORegistryEntry * entry;
8425 IOService * node;
8426 OSSet * inner;
8427 PMHaltWorker * workers[kPMHaltMaxWorkers];
8428 AbsoluteTime deadline;
8429 unsigned int totalNodes = 0;
8430 unsigned int depth;
8431 unsigned int rootDepth;
8432 unsigned int numWorkers;
8433 unsigned int count;
8434 int waitResult;
8435 void * baseFunc;
8436 bool ok;
8437
8438 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
8439
8440 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
8441
8442 // Iterate the entire PM tree starting from root
8443
8444 rootDepth = root->getDepth( gIOPowerPlane );
8445 if (!rootDepth) {
8446 goto done;
8447 }
8448
8449 // debug - for repeated test runs
8450 while (PMHaltWorker::metaClass->getInstanceCount()) {
8451 IOSleep(1);
8452 }
8453
8454 if (!gPMHaltArray) {
8455 gPMHaltArray = OSArray::withCapacity(40);
8456 if (!gPMHaltArray) {
8457 goto done;
8458 }
8459 } else { // debug
8460 gPMHaltArray->flushCollection();
8461 }
8462
8463 if (!gPMHaltLock) {
8464 gPMHaltLock = IOLockAlloc();
8465 if (!gPMHaltLock) {
8466 goto done;
8467 }
8468 }
8469
8470 if (!gPMHaltClientAcknowledgeKey) {
8471 gPMHaltClientAcknowledgeKey =
8472 OSSymbol::withCStringNoCopy("PMShutdown");
8473 if (!gPMHaltClientAcknowledgeKey) {
8474 goto done;
8475 }
8476 }
8477
8478 gPMHaltMessageType = messageType;
8479
8480 // Depth-first walk of PM plane
8481
8482 iter = IORegistryIterator::iterateOver(
8483 root, gIOPowerPlane, kIORegistryIterateRecursively);
8484
8485 if (iter) {
8486 while ((entry = iter->getNextObject())) {
8487 node = OSDynamicCast(IOService, entry);
8488 if (!node) {
8489 continue;
8490 }
8491
8492 if (baseFunc ==
8493 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
8494 continue;
8495 }
8496
8497 depth = node->getDepth( gIOPowerPlane );
8498 if (depth <= rootDepth) {
8499 continue;
8500 }
8501
8502 ok = false;
8503
8504 // adjust to zero based depth
8505 depth -= (rootDepth + 1);
8506
8507 // gPMHaltArray is an array of containers, each container
8508 // refers to nodes with the same depth.
8509
8510 count = gPMHaltArray->getCount();
8511 while (depth >= count) {
8512 // expand array and insert placeholders
8513 gPMHaltArray->setObject(PLACEHOLDER);
8514 count++;
8515 }
8516 count = gPMHaltArray->getCount();
8517 if (depth < count) {
8518 inner = (OSSet *)gPMHaltArray->getObject(depth);
8519 if (inner == PLACEHOLDER) {
8520 inner = OSSet::withCapacity(40);
8521 if (inner) {
8522 gPMHaltArray->replaceObject(depth, inner);
8523 inner->release();
8524 }
8525 }
8526
8527 // PM nodes that appear more than once in the tree will have
8528 // the same depth, OSSet will refuse to add the node twice.
8529 if (inner) {
8530 ok = inner->setObject(node);
8531 }
8532 }
8533 if (!ok) {
8534 DLOG("Skipped PM node %s\n", node->getName());
8535 }
8536 }
8537 iter->release();
8538 }
8539
8540 // debug only
8541 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
8542 count = 0;
8543 if (inner != PLACEHOLDER) {
8544 count = inner->getCount();
8545 }
8546 DLOG("Nodes at depth %u = %u\n", i, count);
8547 }
8548
8549 // strip placeholders (not all depths are populated)
8550 numWorkers = 0;
8551 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
8552 if (inner == PLACEHOLDER) {
8553 gPMHaltArray->removeObject(i);
8554 continue;
8555 }
8556 count = inner->getCount();
8557 if (count > numWorkers) {
8558 numWorkers = count;
8559 }
8560 totalNodes += count;
8561 i++;
8562 }
8563
8564 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
8565 goto done;
8566 }
8567
8568 gPMHaltBusyCount = 0;
8569 gPMHaltIdleCount = 0;
8570 gPMHaltDepth = gPMHaltArray->getCount() - 1;
8571
8572 // Create multiple workers (and threads)
8573
8574 if (numWorkers > kPMHaltMaxWorkers) {
8575 numWorkers = kPMHaltMaxWorkers;
8576 }
8577
8578 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
8579 totalNodes, gPMHaltArray->getCount(), numWorkers);
8580
8581 for (unsigned int i = 0; i < numWorkers; i++) {
8582 workers[i] = PMHaltWorker::worker();
8583 }
8584
8585 // Wait for workers to exhaust all available work
8586
8587 IOLockLock(gPMHaltLock);
8588 while (gPMHaltDepth >= 0) {
8589 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
8590
8591 waitResult = IOLockSleepDeadline(
8592 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
8593 if (THREAD_TIMED_OUT == waitResult) {
8594 AbsoluteTime now;
8595 clock_get_uptime(&now);
8596
8597 IOLockUnlock(gPMHaltLock);
8598 for (unsigned int i = 0; i < numWorkers; i++) {
8599 if (workers[i]) {
8600 PMHaltWorker::checkTimeout(workers[i], &now);
8601 }
8602 }
8603 IOLockLock(gPMHaltLock);
8604 }
8605 }
8606 IOLockUnlock(gPMHaltLock);
8607
8608 // Release all workers
8609
8610 for (unsigned int i = 0; i < numWorkers; i++) {
8611 if (workers[i]) {
8612 workers[i]->release();
8613 }
8614 // worker also retained by it's own thread
8615 }
8616
8617 done:
8618 DLOG("%s done\n", __FUNCTION__);
8619 return;
8620 }
8621
8622 // MARK: -
8623 // MARK: Kernel Assertion
8624
8625 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8626
8627 IOPMDriverAssertionID
8628 IOPMrootDomain::createPMAssertion(
8629 IOPMDriverAssertionType whichAssertionBits,
8630 IOPMDriverAssertionLevel assertionLevel,
8631 IOService *ownerService,
8632 const char *ownerDescription)
8633 {
8634 IOReturn ret;
8635 IOPMDriverAssertionID newAssertion;
8636
8637 if (!pmAssertions) {
8638 return 0;
8639 }
8640
8641 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
8642
8643 if (kIOReturnSuccess == ret) {
8644 return newAssertion;
8645 } else {
8646 return 0;
8647 }
8648 }
8649
8650 IOReturn
8651 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
8652 {
8653 if (!pmAssertions) {
8654 return kIOReturnInternalError;
8655 }
8656
8657 return pmAssertions->releaseAssertion(releaseAssertion);
8658 }
8659
8660
8661 IOReturn
8662 IOPMrootDomain::setPMAssertionLevel(
8663 IOPMDriverAssertionID assertionID,
8664 IOPMDriverAssertionLevel assertionLevel)
8665 {
8666 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
8667 }
8668
8669 IOPMDriverAssertionLevel
8670 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
8671 {
8672 IOPMDriverAssertionType sysLevels;
8673
8674 if (!pmAssertions || whichAssertion == 0) {
8675 return kIOPMDriverAssertionLevelOff;
8676 }
8677
8678 sysLevels = pmAssertions->getActivatedAssertions();
8679
8680 // Check that every bit set in argument 'whichAssertion' is asserted
8681 // in the aggregate bits.
8682 if ((sysLevels & whichAssertion) == whichAssertion) {
8683 return kIOPMDriverAssertionLevelOn;
8684 } else {
8685 return kIOPMDriverAssertionLevelOff;
8686 }
8687 }
8688
8689 IOReturn
8690 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
8691 {
8692 if (!pmAssertions) {
8693 return kIOReturnNotFound;
8694 }
8695
8696 return pmAssertions->setUserAssertionLevels(inLevels);
8697 }
8698
8699 bool
8700 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
8701 {
8702 if (pmAssertions) {
8703 pmAssertions->publishProperties();
8704 }
8705 return IOService::serializeProperties(s);
8706 }
8707
8708 OSObject *
8709 IOPMrootDomain::copyProperty( const char * aKey) const
8710 {
8711 OSObject *obj = NULL;
8712 obj = IOService::copyProperty(aKey);
8713
8714 if (obj) {
8715 return obj;
8716 }
8717
8718 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
8719 sizeof(kIOPMSleepWakeWdogRebootKey))) {
8720 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
8721 return kOSBooleanTrue;
8722 } else {
8723 return kOSBooleanFalse;
8724 }
8725 }
8726
8727 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
8728 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
8729 if (swd_flags & SWD_VALID_LOGS) {
8730 return kOSBooleanTrue;
8731 } else {
8732 return kOSBooleanFalse;
8733 }
8734 }
8735
8736 /*
8737 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
8738 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
8739 * issued by DisplayWrangler on darkwake.
8740 */
8741 if (!strcmp(aKey, "DesktopMode")) {
8742 if (desktopMode) {
8743 return kOSBooleanTrue;
8744 } else {
8745 return kOSBooleanFalse;
8746 }
8747 }
8748 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
8749 if (displayIdleForDemandSleep) {
8750 return kOSBooleanTrue;
8751 } else {
8752 return kOSBooleanFalse;
8753 }
8754 }
8755
8756 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
8757 OSArray * array = 0;
8758 WAKEEVENT_LOCK();
8759 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
8760 OSCollection *collection = _systemWakeEventsArray->copyCollection();
8761 if (collection && !(array = OSDynamicCast(OSArray, collection))) {
8762 collection->release();
8763 }
8764 }
8765 WAKEEVENT_UNLOCK();
8766 return array;
8767 }
8768
8769 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
8770 OSArray * array = 0;
8771 IOLockLock(pmStatsLock);
8772 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
8773 OSCollection *collection = pmStatsAppResponses->copyCollection();
8774 if (collection && !(array = OSDynamicCast(OSArray, collection))) {
8775 collection->release();
8776 }
8777 pmStatsAppResponses->flushCollection();
8778 }
8779 IOLockUnlock(pmStatsLock);
8780 return array;
8781 }
8782
8783 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
8784 OSArray *idleSleepList = NULL;
8785 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
8786 return idleSleepList;
8787 }
8788
8789 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
8790 OSArray *systemSleepList = NULL;
8791 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
8792 return systemSleepList;
8793 }
8794
8795 return NULL;
8796 }
8797
8798 // MARK: -
8799 // MARK: Wake Event Reporting
8800
8801 void
8802 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
8803 {
8804 WAKEEVENT_LOCK();
8805 strlcpy(outBuf, gWakeReasonString, bufSize);
8806 WAKEEVENT_UNLOCK();
8807 }
8808
8809 //******************************************************************************
8810 // acceptSystemWakeEvents
8811 //
8812 // Private control for the acceptance of driver wake event claims.
8813 //******************************************************************************
8814
8815 void
8816 IOPMrootDomain::acceptSystemWakeEvents( bool accept )
8817 {
8818 bool logWakeReason = false;
8819
8820 WAKEEVENT_LOCK();
8821 if (accept) {
8822 gWakeReasonString[0] = '\0';
8823 if (!_systemWakeEventsArray) {
8824 _systemWakeEventsArray = OSArray::withCapacity(4);
8825 }
8826 if ((_acceptSystemWakeEvents = (_systemWakeEventsArray != 0))) {
8827 _systemWakeEventsArray->flushCollection();
8828 }
8829 } else {
8830 _acceptSystemWakeEvents = false;
8831 #if CONFIG_EMBEDDED
8832 logWakeReason = gWakeReasonSysctlRegistered;
8833 #if DEVELOPMENT
8834 static int panic_allowed = -1;
8835
8836 if ((panic_allowed == -1) &&
8837 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
8838 panic_allowed = 1;
8839 }
8840
8841 if (panic_allowed) {
8842 size_t i = 0;
8843 // Panic if wake reason is null or empty
8844 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
8845 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
8846 break;
8847 }
8848 }
8849 if (i >= strlen(gWakeReasonString)) {
8850 panic("Wake reason is empty\n");
8851 }
8852 }
8853 #endif
8854 #endif
8855 }
8856 WAKEEVENT_UNLOCK();
8857
8858 if (logWakeReason) {
8859 MSG("system wake events:%s\n", gWakeReasonString);
8860 }
8861 }
8862
8863 //******************************************************************************
8864 // claimSystemWakeEvent
8865 //
8866 // For a driver to claim a device is the source/conduit of a system wake event.
8867 //******************************************************************************
8868
8869 void
8870 IOPMrootDomain::claimSystemWakeEvent(
8871 IOService * device,
8872 IOOptionBits flags,
8873 const char * reason,
8874 OSObject * details )
8875 {
8876 const OSSymbol * deviceName = 0;
8877 OSNumber * deviceRegId = 0;
8878 OSNumber * claimTime = 0;
8879 OSData * flagsData = 0;
8880 OSString * reasonString = 0;
8881 OSDictionary * d = 0;
8882 uint64_t timestamp;
8883 bool ok = false;
8884
8885 pmEventTimeStamp(&timestamp);
8886
8887 if (!device || !reason) {
8888 return;
8889 }
8890
8891 deviceName = device->copyName(gIOServicePlane);
8892 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
8893 claimTime = OSNumber::withNumber(timestamp, 64);
8894 flagsData = OSData::withBytes(&flags, sizeof(flags));
8895 reasonString = OSString::withCString(reason);
8896 d = OSDictionary::withCapacity(5 + (details ? 1 : 0));
8897 if (!deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
8898 goto done;
8899 }
8900
8901 d->setObject(gIONameKey, deviceName);
8902 d->setObject(gIORegistryEntryIDKey, deviceRegId);
8903 d->setObject(kIOPMWakeEventTimeKey, claimTime);
8904 d->setObject(kIOPMWakeEventFlagsKey, flagsData);
8905 d->setObject(kIOPMWakeEventReasonKey, reasonString);
8906 if (details) {
8907 d->setObject(kIOPMWakeEventDetailsKey, details);
8908 }
8909
8910 WAKEEVENT_LOCK();
8911 if (!gWakeReasonSysctlRegistered) {
8912 // Lazy registration until the platform driver stops registering
8913 // the same name.
8914 gWakeReasonSysctlRegistered = true;
8915 #if CONFIG_EMBEDDED
8916 sysctl_register_oid(&sysctl__kern_wakereason);
8917 #endif
8918 }
8919 if (_acceptSystemWakeEvents) {
8920 ok = _systemWakeEventsArray->setObject(d);
8921 if (gWakeReasonString[0] != '\0') {
8922 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
8923 }
8924 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
8925 }
8926 WAKEEVENT_UNLOCK();
8927
8928 done:
8929 if (deviceName) {
8930 deviceName->release();
8931 }
8932 if (deviceRegId) {
8933 deviceRegId->release();
8934 }
8935 if (claimTime) {
8936 claimTime->release();
8937 }
8938 if (flagsData) {
8939 flagsData->release();
8940 }
8941 if (reasonString) {
8942 reasonString->release();
8943 }
8944 if (d) {
8945 d->release();
8946 }
8947 }
8948
8949 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8950
8951 // MARK: -
8952 // MARK: PMSettingHandle
8953
8954 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
8955
8956 void
8957 PMSettingHandle::free( void )
8958 {
8959 if (pmso) {
8960 pmso->clientHandleFreed();
8961 pmso->release();
8962 pmso = 0;
8963 }
8964
8965 OSObject::free();
8966 }
8967
8968 // MARK: -
8969 // MARK: PMSettingObject
8970
8971 #undef super
8972 #define super OSObject
8973 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
8974
8975 /*
8976 * Static constructor/initializer for PMSettingObject
8977 */
8978 PMSettingObject *PMSettingObject::pmSettingObject(
8979 IOPMrootDomain * parent_arg,
8980 IOPMSettingControllerCallback handler_arg,
8981 OSObject * target_arg,
8982 uintptr_t refcon_arg,
8983 uint32_t supportedPowerSources,
8984 const OSSymbol * settings[],
8985 OSObject * *handle_obj)
8986 {
8987 uint32_t settingCount = 0;
8988 PMSettingObject *pmso = 0;
8989 PMSettingHandle *pmsh = 0;
8990
8991 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
8992 return NULL;
8993 }
8994
8995 // count OSSymbol entries in NULL terminated settings array
8996 while (settings[settingCount]) {
8997 settingCount++;
8998 }
8999 if (0 == settingCount) {
9000 return NULL;
9001 }
9002
9003 pmso = new PMSettingObject;
9004 if (!pmso || !pmso->init()) {
9005 goto fail;
9006 }
9007
9008 pmsh = new PMSettingHandle;
9009 if (!pmsh || !pmsh->init()) {
9010 goto fail;
9011 }
9012
9013 queue_init(&pmso->calloutQueue);
9014 pmso->parent = parent_arg;
9015 pmso->func = handler_arg;
9016 pmso->target = target_arg;
9017 pmso->refcon = refcon_arg;
9018 pmso->settingCount = settingCount;
9019
9020 pmso->retain(); // handle holds a retain on pmso
9021 pmsh->pmso = pmso;
9022 pmso->pmsh = pmsh;
9023
9024 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount);
9025 if (pmso->publishedFeatureID) {
9026 for (unsigned int i = 0; i < settingCount; i++) {
9027 // Since there is now at least one listener to this setting, publish
9028 // PM root domain support for it.
9029 parent_arg->publishPMSetting( settings[i],
9030 supportedPowerSources, &pmso->publishedFeatureID[i] );
9031 }
9032 }
9033
9034 *handle_obj = pmsh;
9035 return pmso;
9036
9037 fail:
9038 if (pmso) {
9039 pmso->release();
9040 }
9041 if (pmsh) {
9042 pmsh->release();
9043 }
9044 return NULL;
9045 }
9046
9047 void
9048 PMSettingObject::free( void )
9049 {
9050 if (publishedFeatureID) {
9051 for (uint32_t i = 0; i < settingCount; i++) {
9052 if (publishedFeatureID[i]) {
9053 parent->removePublishedFeature( publishedFeatureID[i] );
9054 }
9055 }
9056
9057 IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount);
9058 }
9059
9060 super::free();
9061 }
9062
9063 void
9064 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
9065 {
9066 (*func)(target, type, object, refcon);
9067 }
9068
9069 void
9070 PMSettingObject::clientHandleFreed( void )
9071 {
9072 parent->deregisterPMSettingObject(this);
9073 }
9074
9075 // MARK: -
9076 // MARK: PMAssertionsTracker
9077
9078 //*********************************************************************************
9079 //*********************************************************************************
9080 //*********************************************************************************
9081 // class PMAssertionsTracker Implementation
9082
9083 #define kAssertUniqueIDStart 500
9084
9085 PMAssertionsTracker *
9086 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
9087 {
9088 PMAssertionsTracker *myself;
9089
9090 myself = new PMAssertionsTracker;
9091
9092 if (myself) {
9093 myself->init();
9094 myself->owner = rootDomain;
9095 myself->issuingUniqueID = kAssertUniqueIDStart;
9096 myself->assertionsArray = OSArray::withCapacity(5);
9097 myself->assertionsKernel = 0;
9098 myself->assertionsUser = 0;
9099 myself->assertionsCombined = 0;
9100 myself->assertionsArrayLock = IOLockAlloc();
9101 myself->tabulateProducerCount = myself->tabulateConsumerCount = 0;
9102
9103 if (!myself->assertionsArray || !myself->assertionsArrayLock) {
9104 myself = NULL;
9105 }
9106 }
9107
9108 return myself;
9109 }
9110
9111 /* tabulate
9112 * - Update assertionsKernel to reflect the state of all
9113 * assertions in the kernel.
9114 * - Update assertionsCombined to reflect both kernel & user space.
9115 */
9116 void
9117 PMAssertionsTracker::tabulate(void)
9118 {
9119 int i;
9120 int count;
9121 PMAssertStruct *_a = NULL;
9122 OSData *_d = NULL;
9123
9124 IOPMDriverAssertionType oldKernel = assertionsKernel;
9125 IOPMDriverAssertionType oldCombined = assertionsCombined;
9126
9127 ASSERT_GATED();
9128
9129 assertionsKernel = 0;
9130 assertionsCombined = 0;
9131
9132 if (!assertionsArray) {
9133 return;
9134 }
9135
9136 if ((count = assertionsArray->getCount())) {
9137 for (i = 0; i < count; i++) {
9138 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
9139 if (_d) {
9140 _a = (PMAssertStruct *)_d->getBytesNoCopy();
9141 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
9142 assertionsKernel |= _a->assertionBits;
9143 }
9144 }
9145 }
9146 }
9147
9148 tabulateProducerCount++;
9149 assertionsCombined = assertionsKernel | assertionsUser;
9150
9151 if ((assertionsKernel != oldKernel) ||
9152 (assertionsCombined != oldCombined)) {
9153 owner->evaluateAssertions(assertionsCombined, oldCombined);
9154 }
9155 }
9156
9157 void
9158 PMAssertionsTracker::publishProperties( void )
9159 {
9160 OSArray *assertionsSummary = NULL;
9161
9162 if (tabulateConsumerCount != tabulateProducerCount) {
9163 IOLockLock(assertionsArrayLock);
9164
9165 tabulateConsumerCount = tabulateProducerCount;
9166
9167 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
9168 */
9169 assertionsSummary = copyAssertionsArray();
9170 if (assertionsSummary) {
9171 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary);
9172 assertionsSummary->release();
9173 } else {
9174 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
9175 }
9176
9177 /* Publish the IOPMrootDomain property "DriverPMAssertions"
9178 */
9179 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
9180
9181 IOLockUnlock(assertionsArrayLock);
9182 }
9183 }
9184
9185 PMAssertionsTracker::PMAssertStruct *
9186 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
9187 {
9188 PMAssertStruct *_a = NULL;
9189 OSData *_d = NULL;
9190 int found = -1;
9191 int count = 0;
9192 int i = 0;
9193
9194 if (assertionsArray
9195 && (count = assertionsArray->getCount())) {
9196 for (i = 0; i < count; i++) {
9197 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
9198 if (_d) {
9199 _a = (PMAssertStruct *)_d->getBytesNoCopy();
9200 if (_a && (_id == _a->id)) {
9201 found = i;
9202 break;
9203 }
9204 }
9205 }
9206 }
9207
9208 if (-1 == found) {
9209 return NULL;
9210 } else {
9211 if (index) {
9212 *index = found;
9213 }
9214 return _a;
9215 }
9216 }
9217
9218 /* PMAssertionsTracker::handleCreateAssertion
9219 * Perform assertion work on the PM workloop. Do not call directly.
9220 */
9221 IOReturn
9222 PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
9223 {
9224 ASSERT_GATED();
9225
9226 if (newAssertion) {
9227 IOLockLock(assertionsArrayLock);
9228 assertionsArray->setObject(newAssertion);
9229 IOLockUnlock(assertionsArrayLock);
9230 newAssertion->release();
9231
9232 tabulate();
9233 }
9234 return kIOReturnSuccess;
9235 }
9236
9237 /* PMAssertionsTracker::createAssertion
9238 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
9239 * appropiate.
9240 */
9241 IOReturn
9242 PMAssertionsTracker::createAssertion(
9243 IOPMDriverAssertionType which,
9244 IOPMDriverAssertionLevel level,
9245 IOService *serviceID,
9246 const char *whoItIs,
9247 IOPMDriverAssertionID *outID)
9248 {
9249 OSData *dataStore = NULL;
9250 PMAssertStruct track;
9251
9252 // Warning: trillions and trillions of created assertions may overflow the unique ID.
9253 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
9254 track.level = level;
9255 track.assertionBits = which;
9256 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs):0;
9257 track.ownerService = serviceID;
9258 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
9259 track.modifiedTime = 0;
9260 pmEventTimeStamp(&track.createdTime);
9261
9262 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
9263 if (!dataStore) {
9264 if (track.ownerString) {
9265 track.ownerString->release();
9266 }
9267 return kIOReturnNoMemory;
9268 }
9269
9270 *outID = track.id;
9271
9272 if (owner && owner->pmPowerStateQueue) {
9273 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore);
9274 }
9275
9276 return kIOReturnSuccess;
9277 }
9278
9279 /* PMAssertionsTracker::handleReleaseAssertion
9280 * Runs in PM workloop. Do not call directly.
9281 */
9282 IOReturn
9283 PMAssertionsTracker::handleReleaseAssertion(
9284 IOPMDriverAssertionID _id)
9285 {
9286 ASSERT_GATED();
9287
9288 int index;
9289 PMAssertStruct *assertStruct = detailsForID(_id, &index);
9290
9291 if (!assertStruct) {
9292 return kIOReturnNotFound;
9293 }
9294
9295 IOLockLock(assertionsArrayLock);
9296 if (assertStruct->ownerString) {
9297 assertStruct->ownerString->release();
9298 }
9299
9300 assertionsArray->removeObject(index);
9301 IOLockUnlock(assertionsArrayLock);
9302
9303 tabulate();
9304 return kIOReturnSuccess;
9305 }
9306
9307 /* PMAssertionsTracker::releaseAssertion
9308 * Releases an assertion and affects system behavior if appropiate.
9309 * Actual work happens on PM workloop.
9310 */
9311 IOReturn
9312 PMAssertionsTracker::releaseAssertion(
9313 IOPMDriverAssertionID _id)
9314 {
9315 if (owner && owner->pmPowerStateQueue) {
9316 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, 0, _id);
9317 }
9318 return kIOReturnSuccess;
9319 }
9320
9321 /* PMAssertionsTracker::handleSetAssertionLevel
9322 * Runs in PM workloop. Do not call directly.
9323 */
9324 IOReturn
9325 PMAssertionsTracker::handleSetAssertionLevel(
9326 IOPMDriverAssertionID _id,
9327 IOPMDriverAssertionLevel _level)
9328 {
9329 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
9330
9331 ASSERT_GATED();
9332
9333 if (!assertStruct) {
9334 return kIOReturnNotFound;
9335 }
9336
9337 IOLockLock(assertionsArrayLock);
9338 pmEventTimeStamp(&assertStruct->modifiedTime);
9339 assertStruct->level = _level;
9340 IOLockUnlock(assertionsArrayLock);
9341
9342 tabulate();
9343 return kIOReturnSuccess;
9344 }
9345
9346 /* PMAssertionsTracker::setAssertionLevel
9347 */
9348 IOReturn
9349 PMAssertionsTracker::setAssertionLevel(
9350 IOPMDriverAssertionID _id,
9351 IOPMDriverAssertionLevel _level)
9352 {
9353 if (owner && owner->pmPowerStateQueue) {
9354 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
9355 (void *)(uintptr_t)_level, _id);
9356 }
9357
9358 return kIOReturnSuccess;
9359 }
9360
9361 IOReturn
9362 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
9363 {
9364 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
9365
9366 ASSERT_GATED();
9367
9368 if (new_user_levels != assertionsUser) {
9369 assertionsUser = new_user_levels;
9370 DLOG("assertionsUser 0x%llx\n", assertionsUser);
9371 }
9372
9373 tabulate();
9374 return kIOReturnSuccess;
9375 }
9376
9377 IOReturn
9378 PMAssertionsTracker::setUserAssertionLevels(
9379 IOPMDriverAssertionType new_user_levels)
9380 {
9381 if (gIOPMWorkLoop) {
9382 gIOPMWorkLoop->runAction(
9383 OSMemberFunctionCast(
9384 IOWorkLoop::Action,
9385 this,
9386 &PMAssertionsTracker::handleSetUserAssertionLevels),
9387 this,
9388 (void *) &new_user_levels, 0, 0, 0);
9389 }
9390
9391 return kIOReturnSuccess;
9392 }
9393
9394
9395 OSArray *
9396 PMAssertionsTracker::copyAssertionsArray(void)
9397 {
9398 int count;
9399 int i;
9400 OSArray *outArray = NULL;
9401
9402 if (!assertionsArray ||
9403 (0 == (count = assertionsArray->getCount())) ||
9404 (NULL == (outArray = OSArray::withCapacity(count)))) {
9405 goto exit;
9406 }
9407
9408 for (i = 0; i < count; i++) {
9409 PMAssertStruct *_a = NULL;
9410 OSData *_d = NULL;
9411 OSDictionary *details = NULL;
9412
9413 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
9414 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy())) {
9415 OSNumber *_n = NULL;
9416
9417 details = OSDictionary::withCapacity(7);
9418 if (!details) {
9419 continue;
9420 }
9421
9422 outArray->setObject(details);
9423 details->release();
9424
9425 _n = OSNumber::withNumber(_a->id, 64);
9426 if (_n) {
9427 details->setObject(kIOPMDriverAssertionIDKey, _n);
9428 _n->release();
9429 }
9430 _n = OSNumber::withNumber(_a->createdTime, 64);
9431 if (_n) {
9432 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n);
9433 _n->release();
9434 }
9435 _n = OSNumber::withNumber(_a->modifiedTime, 64);
9436 if (_n) {
9437 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n);
9438 _n->release();
9439 }
9440 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
9441 if (_n) {
9442 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n);
9443 _n->release();
9444 }
9445 _n = OSNumber::withNumber(_a->level, 64);
9446 if (_n) {
9447 details->setObject(kIOPMDriverAssertionLevelKey, _n);
9448 _n->release();
9449 }
9450 _n = OSNumber::withNumber(_a->assertionBits, 64);
9451 if (_n) {
9452 details->setObject(kIOPMDriverAssertionAssertedKey, _n);
9453 _n->release();
9454 }
9455
9456 if (_a->ownerString) {
9457 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
9458 }
9459 }
9460 }
9461
9462 exit:
9463 return outArray;
9464 }
9465
9466 IOPMDriverAssertionType
9467 PMAssertionsTracker::getActivatedAssertions(void)
9468 {
9469 return assertionsCombined;
9470 }
9471
9472 IOPMDriverAssertionLevel
9473 PMAssertionsTracker::getAssertionLevel(
9474 IOPMDriverAssertionType type)
9475 {
9476 if (type && ((type & assertionsKernel) == assertionsKernel)) {
9477 return kIOPMDriverAssertionLevelOn;
9478 } else {
9479 return kIOPMDriverAssertionLevelOff;
9480 }
9481 }
9482
9483 //*********************************************************************************
9484 //*********************************************************************************
9485 //*********************************************************************************
9486
9487
9488 static void
9489 pmEventTimeStamp(uint64_t *recordTS)
9490 {
9491 clock_sec_t tsec;
9492 clock_usec_t tusec;
9493
9494 if (!recordTS) {
9495 return;
9496 }
9497
9498 // We assume tsec fits into 32 bits; 32 bits holds enough
9499 // seconds for 136 years since the epoch in 1970.
9500 clock_get_calendar_microtime(&tsec, &tusec);
9501
9502
9503 // Pack the sec & microsec calendar time into a uint64_t, for fun.
9504 *recordTS = 0;
9505 *recordTS |= (uint32_t)tusec;
9506 *recordTS |= ((uint64_t)tsec << 32);
9507
9508 return;
9509 }
9510
9511 // MARK: -
9512 // MARK: IORootParent
9513
9514 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9515
9516 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
9517
9518 // The reason that root domain needs a root parent is to facilitate demand
9519 // sleep, since a power change from the root parent cannot be vetoed.
9520 //
9521 // The above statement is no longer true since root domain now performs
9522 // demand sleep using overrides. But root parent remains to avoid changing
9523 // the power tree stacking. Root parent is parked at the max power state.
9524
9525
9526 static IOPMPowerState patriarchPowerStates[2] =
9527 {
9528 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
9529 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
9530 };
9531
9532 void
9533 IORootParent::initialize( void )
9534 {
9535
9536 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
9537 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
9538 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
9539 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
9540 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
9541 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
9542 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
9543 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
9544 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
9545 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
9546 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
9547 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
9548 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
9549 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
9550 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
9551 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
9552 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
9553 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
9554 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
9555 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
9556 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
9557 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
9558 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
9559 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
9560 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
9561 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
9562 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
9563 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
9564 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
9565 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
9566 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
9567 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
9568 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
9569 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
9570 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
9571 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
9572 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
9573 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
9574 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
9575 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
9576 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
9577 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
9578 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
9579 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
9580 }
9581
9582 bool
9583 IORootParent::start( IOService * nub )
9584 {
9585 IOService::start(nub);
9586 attachToParent( getRegistryRoot(), gIOPowerPlane );
9587 PMinit();
9588 registerPowerDriver(this, patriarchPowerStates, 2);
9589 makeUsable();
9590 return true;
9591 }
9592
9593 void
9594 IORootParent::shutDownSystem( void )
9595 {
9596 }
9597
9598 void
9599 IORootParent::restartSystem( void )
9600 {
9601 }
9602
9603 void
9604 IORootParent::sleepSystem( void )
9605 {
9606 }
9607
9608 void
9609 IORootParent::dozeSystem( void )
9610 {
9611 }
9612
9613 void
9614 IORootParent::sleepToDoze( void )
9615 {
9616 }
9617
9618 void
9619 IORootParent::wakeSystem( void )
9620 {
9621 }
9622
9623 OSObject *
9624 IORootParent::copyProperty( const char * aKey) const
9625 {
9626 return IOService::copyProperty(aKey);
9627 }
9628
9629 uint32_t
9630 IOPMrootDomain::getWatchdogTimeout()
9631 {
9632 if (gSwdSleepWakeTimeout) {
9633 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
9634 }
9635 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
9636 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
9637 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
9638 } else {
9639 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
9640 }
9641 }
9642
9643
9644 #if defined(__i386__) || defined(__x86_64__)
9645 IOReturn
9646 IOPMrootDomain::restartWithStackshot()
9647 {
9648 takeStackshot(true, true, false);
9649
9650 return kIOReturnSuccess;
9651 }
9652
9653 void
9654 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
9655 {
9656 takeStackshot(wdogTrigger, false, false);
9657 }
9658
9659 void
9660 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
9661 {
9662 switch (tracePhase) {
9663 case kIOPMTracePointSleepStarted:
9664 *phaseString = "kIOPMTracePointSleepStarted";
9665 *description = "starting sleep";
9666 break;
9667
9668 case kIOPMTracePointSleepApplications:
9669 *phaseString = "kIOPMTracePointSleepApplications";
9670 *description = "notifying applications";
9671 break;
9672
9673 case kIOPMTracePointSleepPriorityClients:
9674 *phaseString = "kIOPMTracePointSleepPriorityClients";
9675 *description = "notifying clients about upcoming system capability changes";
9676 break;
9677
9678 case kIOPMTracePointSleepWillChangeInterests:
9679 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
9680 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
9681 break;
9682
9683 case kIOPMTracePointSleepPowerPlaneDrivers:
9684 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
9685 *description = "calling power state change callbacks";
9686 break;
9687
9688 case kIOPMTracePointSleepDidChangeInterests:
9689 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
9690 *description = "calling rootDomain's clients about rootDomain's state changes";
9691 break;
9692
9693 case kIOPMTracePointSleepCapabilityClients:
9694 *phaseString = "kIOPMTracePointSleepCapabilityClients";
9695 *description = "notifying clients about current system capabilities";
9696 break;
9697
9698 case kIOPMTracePointSleepPlatformActions:
9699 *phaseString = "kIOPMTracePointSleepPlatformActions";
9700 *description = "calling Quiesce/Sleep action callbacks";
9701 break;
9702
9703 case kIOPMTracePointSleepCPUs:
9704 {
9705 *phaseString = "kIOPMTracePointSleepCPUs";
9706 #if defined(__i386__) || defined(__x86_64__)
9707 /*
9708 * We cannot use the getCPUNumber() method to get the cpu number, since
9709 * that cpu number is unrelated to the cpu number we need (we need the cpu
9710 * number as enumerated by the scheduler, NOT the CPU number enumerated
9711 * by ACPIPlatform as the CPUs are enumerated in MADT order).
9712 * Instead, pass the Mach processor pointer associated with the current
9713 * shutdown target so its associated cpu_id can be used in
9714 * processor_to_datastring.
9715 */
9716 if (currentShutdownTarget != NULL &&
9717 currentShutdownTarget->getMachProcessor() != NULL) {
9718 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
9719 currentShutdownTarget->getMachProcessor());
9720 *description = sbuf;
9721 } else {
9722 *description = "halting all non-boot CPUs";
9723 }
9724 #else
9725 *description = "halting all non-boot CPUs";
9726 #endif
9727 break;
9728 }
9729 case kIOPMTracePointSleepPlatformDriver:
9730 *phaseString = "kIOPMTracePointSleepPlatformDriver";
9731 *description = "executing platform specific code";
9732 break;
9733
9734 case kIOPMTracePointHibernate:
9735 *phaseString = "kIOPMTracePointHibernate";
9736 *description = "writing the hibernation image";
9737 break;
9738
9739 case kIOPMTracePointSystemSleep:
9740 *phaseString = "kIOPMTracePointSystemSleep";
9741 *description = "in EFI/Bootrom after last point of entry to sleep";
9742 break;
9743
9744 case kIOPMTracePointWakePlatformDriver:
9745 *phaseString = "kIOPMTracePointWakePlatformDriver";
9746 *description = "executing platform specific code";
9747 break;
9748
9749
9750 case kIOPMTracePointWakePlatformActions:
9751 *phaseString = "kIOPMTracePointWakePlatformActions";
9752 *description = "calling Wake action callbacks";
9753 break;
9754
9755 case kIOPMTracePointWakeCPUs:
9756 *phaseString = "kIOPMTracePointWakeCPUs";
9757 *description = "starting non-boot CPUs";
9758 break;
9759
9760 case kIOPMTracePointWakeWillPowerOnClients:
9761 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
9762 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
9763 break;
9764
9765 case kIOPMTracePointWakeWillChangeInterests:
9766 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
9767 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
9768 break;
9769
9770 case kIOPMTracePointWakeDidChangeInterests:
9771 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
9772 *description = "calling rootDomain's clients about completed rootDomain's state changes";
9773 break;
9774
9775 case kIOPMTracePointWakePowerPlaneDrivers:
9776 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
9777 *description = "calling power state change callbacks";
9778 break;
9779
9780 case kIOPMTracePointWakeCapabilityClients:
9781 *phaseString = "kIOPMTracePointWakeCapabilityClients";
9782 *description = "informing clients about current system capabilities";
9783 break;
9784
9785 case kIOPMTracePointWakeApplications:
9786 *phaseString = "kIOPMTracePointWakeApplications";
9787 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
9788 break;
9789
9790 case kIOPMTracePointDarkWakeEntry:
9791 *phaseString = "kIOPMTracePointDarkWakeEntry";
9792 *description = "entering darkwake on way to sleep";
9793 break;
9794
9795 case kIOPMTracePointDarkWakeExit:
9796 *phaseString = "kIOPMTracePointDarkWakeExit";
9797 *description = "entering fullwake from darkwake";
9798 break;
9799
9800 default:
9801 *phaseString = NULL;
9802 *description = NULL;
9803 }
9804 }
9805
9806 void
9807 IOPMrootDomain::saveFailureData2File()
9808 {
9809 unsigned int len = 0;
9810 char failureStr[512];
9811 errno_t error;
9812 char *outbuf;
9813 bool oswatchdog = false;
9814
9815 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len) &&
9816 !PEReadNVRAMProperty(kIOOSWatchdogFailureString, NULL, &len)) {
9817 DLOG("No SleepWake failure or OSWatchdog failure string to read\n");
9818 return;
9819 }
9820
9821 if (len == 0) {
9822 DLOG("Ignoring zero byte SleepWake failure string\n");
9823 goto exit;
9824 }
9825
9826 if (len > sizeof(failureStr)) {
9827 len = sizeof(failureStr);
9828 }
9829 failureStr[0] = 0;
9830 if (PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len) == false) {
9831 if (PEReadNVRAMProperty(kIOOSWatchdogFailureString, failureStr, &len)) {
9832 oswatchdog = true;
9833 }
9834 }
9835 if (failureStr[0] != 0) {
9836 error = sleepWakeDebugSaveFile(oswatchdog ? kOSWatchdogFailureStringFile : kSleepWakeFailureStringFile,
9837 failureStr, len);
9838 if (error) {
9839 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
9840 } else {
9841 DLOG("Saved SleepWake failure string to file.\n");
9842 }
9843 if (!oswatchdog) {
9844 swd_flags |= SWD_BOOT_BY_SW_WDOG;
9845 }
9846 }
9847
9848 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
9849 goto exit;
9850 }
9851
9852 if (swd_buffer) {
9853 unsigned int len = 0;
9854 errno_t error;
9855 char nvram_var_name_buffer[20];
9856 unsigned int concat_len = 0;
9857 swd_hdr *hdr = NULL;
9858
9859
9860 hdr = (swd_hdr *)swd_buffer;
9861 outbuf = (char *)hdr + hdr->spindump_offset;
9862
9863 for (int i = 0; i < 8; i++) {
9864 snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
9865 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
9866 LOG("No SleepWake blob to read beyond chunk %d\n", i);
9867 break;
9868 }
9869 if (PEReadNVRAMProperty(nvram_var_name_buffer, outbuf + concat_len, &len) == FALSE) {
9870 PERemoveNVRAMProperty(nvram_var_name_buffer);
9871 LOG("Could not read the property :-(\n");
9872 break;
9873 }
9874 PERemoveNVRAMProperty(nvram_var_name_buffer);
9875 concat_len += len;
9876 }
9877 LOG("Concatenated length for the SWD blob %d\n", concat_len);
9878
9879 if (concat_len) {
9880 error = sleepWakeDebugSaveFile(oswatchdog ? kOSWatchdogStacksFilename : kSleepWakeStacksFilename,
9881 outbuf, concat_len);
9882 if (error) {
9883 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
9884 } else {
9885 LOG("Saved SleepWake zipped data to file.\n");
9886 }
9887 }
9888 } else {
9889 LOG("No buffer allocated to save failure stackshot\n");
9890 }
9891
9892
9893 gRootDomain->swd_lock = 0;
9894 exit:
9895 PERemoveNVRAMProperty(oswatchdog ? kIOOSWatchdogFailureString : kIOSleepWakeFailureString);
9896 return;
9897 }
9898
9899
9900 void
9901 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
9902 {
9903 IORegistryIterator * iter;
9904 IORegistryEntry * entry;
9905 IOService * node;
9906 bool nodeFound = false;
9907
9908 const void * callMethod = NULL;
9909 const char * objectName = NULL;
9910 uint32_t timeout = getWatchdogTimeout();
9911 const char * phaseString = NULL;
9912 const char * phaseDescription = NULL;
9913
9914 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject);
9915 uint32_t tracePhase = pmTracer->getTracePhase();
9916
9917 *thread = NULL;
9918 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
9919 snprintf(failureStr, strLen, "%sSleep transition timed out after %d seconds", failureStr, timeout);
9920 } else {
9921 snprintf(failureStr, strLen, "%sWake transition timed out after %d seconds", failureStr, timeout);
9922 }
9923 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
9924
9925 if (notifierThread) {
9926 if (notifier && (notifier->identifier)) {
9927 objectName = notifier->identifier->getCStringNoCopy();
9928 }
9929 *thread = notifierThread;
9930 } else {
9931 iter = IORegistryIterator::iterateOver(
9932 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
9933
9934 if (iter) {
9935 while ((entry = iter->getNextObject())) {
9936 node = OSDynamicCast(IOService, entry);
9937 if (!node) {
9938 continue;
9939 }
9940 if (OSDynamicCast(IOPowerConnection, node)) {
9941 continue;
9942 }
9943
9944 if (node->getBlockingDriverCall(thread, &callMethod)) {
9945 nodeFound = true;
9946 break;
9947 }
9948 }
9949 iter->release();
9950 }
9951 if (nodeFound) {
9952 OSKext *kext = OSKext::lookupKextWithAddress((vm_address_t)callMethod);
9953 if (kext) {
9954 objectName = kext->getIdentifierCString();
9955 }
9956 }
9957 }
9958 if (phaseDescription) {
9959 snprintf(failureStr, strLen, "%s while %s.", failureStr, phaseDescription);
9960 }
9961 if (objectName) {
9962 snprintf(failureStr, strLen, "%s Suspected bundle: %s.", failureStr, objectName);
9963 }
9964 if (*thread) {
9965 snprintf(failureStr, strLen, "%s Thread 0x%llx.", failureStr, thread_tid(*thread));
9966 }
9967
9968 DLOG("%s\n", failureStr);
9969 }
9970
9971 struct swd_stackshot_compressed_data {
9972 z_output_func zoutput;
9973 size_t zipped;
9974 uint64_t totalbytes;
9975 uint64_t lastpercent;
9976 IOReturn error;
9977 unsigned outremain;
9978 unsigned outlen;
9979 unsigned writes;
9980 Bytef * outbuf;
9981 };
9982 struct swd_stackshot_compressed_data swd_zip_var = { };
9983
9984 static void *
9985 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
9986 {
9987 void *result;
9988 LOG("Alloc in zipping %d items of size %d\n", items, size);
9989
9990 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
9991 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
9992 LOG("Offset %zu\n", swd_zs_zoffset);
9993 return result;
9994 }
9995
9996 static int
9997 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
9998 {
9999 unsigned len;
10000
10001 len = strm->avail_in;
10002
10003 if (len > size) {
10004 len = size;
10005 }
10006 if (len == 0) {
10007 return 0;
10008 }
10009
10010 if (strm->next_in != (Bytef *) strm) {
10011 memcpy(buf, strm->next_in, len);
10012 } else {
10013 bzero(buf, len);
10014 }
10015
10016 strm->adler = z_crc32(strm->adler, buf, len);
10017
10018 strm->avail_in -= len;
10019 strm->next_in += len;
10020 strm->total_in += len;
10021
10022 return (int)len;
10023 }
10024
10025 static int
10026 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
10027 {
10028 unsigned int i = 0;
10029 // if outlen > max size don't add to the buffer
10030 if (strm && buf) {
10031 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
10032 LOG("No space to GZIP... not writing to NVRAM\n");
10033 return len;
10034 }
10035 }
10036 for (i = 0; i < len; i++) {
10037 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
10038 }
10039 swd_zip_var.outlen += len;
10040 return len;
10041 }
10042 static void
10043 swd_zs_free(void * __unused ref, void * __unused ptr)
10044 {
10045 }
10046
10047 static int
10048 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
10049 {
10050 int wbits = 12;
10051 int memlevel = 3;
10052
10053 if (!swd_zs.zalloc) {
10054 swd_zs.zalloc = swd_zs_alloc;
10055 swd_zs.zfree = swd_zs_free;
10056 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
10057 // allocation failed
10058 bzero(&swd_zs, sizeof(swd_zs));
10059 // swd_zs_zoffset = 0;
10060 } else {
10061 LOG("PMRD inited the zlib allocation routines\n");
10062 }
10063 }
10064
10065
10066
10067 swd_zip_var.zipped = 0;
10068 swd_zip_var.totalbytes = 0; // should this be the max that we have?
10069 swd_zip_var.lastpercent = 0;
10070 swd_zip_var.error = kIOReturnSuccess;
10071 swd_zip_var.outremain = 0;
10072 swd_zip_var.outlen = 0;
10073 swd_zip_var.writes = 0;
10074 swd_zip_var.outbuf = (Bytef *)outPtr;
10075
10076 swd_zip_var.totalbytes = numBytes;
10077
10078 swd_zs.avail_in = 0;
10079 swd_zs.next_in = NULL;
10080 swd_zs.avail_out = 0;
10081 swd_zs.next_out = NULL;
10082
10083 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
10084
10085 z_stream *zs;
10086 int zr;
10087 zs = &swd_zs;
10088
10089 zr = Z_OK;
10090
10091 while (swd_zip_var.error >= 0) {
10092 if (!zs->avail_in) {
10093 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
10094 zs->avail_in = numBytes;
10095 }
10096 if (!zs->avail_out) {
10097 zs->next_out = (Bytef *)zs;
10098 zs->avail_out = UINT32_MAX;
10099 }
10100 zr = deflate(zs, Z_NO_FLUSH);
10101 if (Z_STREAM_END == zr) {
10102 break;
10103 }
10104 if (zr != Z_OK) {
10105 LOG("ZERR %d\n", zr);
10106 swd_zip_var.error = zr;
10107 } else {
10108 if (zs->total_in == numBytes) {
10109 break;
10110 }
10111 }
10112 }
10113 zr = Z_OK;
10114 //now flush the stream
10115 while (swd_zip_var.error >= 0) {
10116 if (!zs->avail_out) {
10117 zs->next_out = (Bytef *)zs;
10118 zs->avail_out = UINT32_MAX;
10119 }
10120 zr = deflate(zs, Z_FINISH);
10121 if (Z_STREAM_END == zr) {
10122 break;
10123 }
10124 if (zr != Z_OK) {
10125 LOG("ZERR %d\n", zr);
10126 swd_zip_var.error = zr;
10127 } else {
10128 if (zs->total_in == numBytes) {
10129 LOG("Total output size %d\n", swd_zip_var.outlen);
10130 break;
10131 }
10132 }
10133 }
10134
10135 return swd_zip_var.outlen;
10136 }
10137
10138 void
10139 IOPMrootDomain::takeStackshot(bool wdogTrigger, bool isOSXWatchdog, bool isSpinDump)
10140 {
10141 swd_hdr * hdr = NULL;
10142 int wdog_panic = -1;
10143 int cnt = 0;
10144 pid_t pid = 0;
10145 kern_return_t kr = KERN_SUCCESS;
10146 uint32_t flags;
10147
10148 char * dstAddr;
10149 uint32_t size;
10150 uint32_t bytesRemaining;
10151 unsigned bytesWritten = 0;
10152 unsigned totalBytes = 0;
10153 OSString * UUIDstring = NULL;
10154
10155 char failureStr[512];
10156 thread_t thread = NULL;
10157 const char * uuid;
10158
10159
10160 uint32_t bufSize;
10161 uint32_t initialStackSize;
10162
10163
10164
10165 failureStr[0] = 0;
10166 if (isSpinDump) {
10167 if (_systemTransitionType != kSystemTransitionSleep &&
10168 _systemTransitionType != kSystemTransitionWake) {
10169 return;
10170 }
10171
10172 if (gSpinDumpBufferFull) {
10173 return;
10174 }
10175 if (swd_spindump_buffer == NULL) {
10176 sleepWakeDebugSpinDumpMemAlloc();
10177 if (swd_spindump_buffer == NULL) {
10178 return;
10179 }
10180 }
10181
10182 bufSize = SWD_SPINDUMP_SIZE;
10183 initialStackSize = SWD_INITIAL_SPINDUMP_SIZE;
10184 hdr = (swd_hdr *)swd_spindump_buffer;
10185 } else {
10186 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
10187 return;
10188 }
10189
10190 if (isOSXWatchdog) {
10191 snprintf(failureStr, sizeof(failureStr), "Stackshot Reason: ");
10192 snprintf(failureStr, sizeof(failureStr), "%smacOS watchdog triggered failure\n", failureStr);
10193 } else if (wdogTrigger) {
10194 if ((UUIDstring = OSDynamicCast(OSString, getProperty(kIOPMSleepWakeUUIDKey))) != NULL) {
10195 uuid = UUIDstring->getCStringNoCopy();
10196 snprintf(failureStr, sizeof(failureStr), "UUID: %s\n", uuid);
10197 }
10198
10199 snprintf(failureStr, sizeof(failureStr), "%sStackshot Reason: ", failureStr);
10200 getFailureData(&thread, failureStr, sizeof(failureStr));
10201 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
10202 goto skip_stackshot;
10203 }
10204 } else {
10205 snprintf(failureStr, sizeof(failureStr), "%sStackshot triggered for debugging stackshot collection.\n", failureStr);
10206 }
10207 // Take only one stackshot in this case.
10208 cnt = SWD_MAX_STACKSHOTS - 1;
10209
10210 if (swd_buffer == NULL) {
10211 sleepWakeDebugMemAlloc();
10212 if (swd_buffer == NULL) {
10213 return;
10214 }
10215 }
10216 hdr = (swd_hdr *)swd_buffer;
10217
10218 bufSize = hdr->alloc_size;;
10219 initialStackSize = bufSize;
10220 }
10221
10222
10223 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
10224 return;
10225 }
10226
10227
10228 dstAddr = (char*)hdr + hdr->spindump_offset;
10229 bytesRemaining = bufSize - hdr->spindump_offset;
10230
10231 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
10232
10233 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO;
10234 while (kr == KERN_SUCCESS) {
10235 if (cnt == 0) {
10236 /*
10237 * Take stackshot of all process on first sample. Size is restricted
10238 * to SWD_INITIAL_STACK_SIZE
10239 */
10240 pid = -1;
10241 size = (bytesRemaining > initialStackSize) ? initialStackSize : bytesRemaining;
10242 } else {
10243 /* Take sample of kernel threads only */
10244 pid = 0;
10245 size = bytesRemaining;
10246 }
10247
10248 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, &bytesWritten);
10249 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
10250 kr, pid, size, flags, bytesWritten);
10251 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
10252 if (pid == -1) {
10253 // Insufficient buffer when trying to take stackshot of user & kernel space threads.
10254 // Continue to take stackshot of just kernel threads
10255 ++cnt;
10256 kr = KERN_SUCCESS;
10257 continue;
10258 } else if (totalBytes == 0) {
10259 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr, size, flags);
10260 }
10261 }
10262
10263 dstAddr += bytesWritten;
10264 totalBytes += bytesWritten;
10265 bytesRemaining -= bytesWritten;
10266
10267 if (++cnt == SWD_MAX_STACKSHOTS) {
10268 break;
10269 }
10270 IOSleep(10); // 10 ms
10271 }
10272
10273 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
10274
10275 memset(hdr->reason, 0x20, sizeof(hdr->reason));
10276 if (isSpinDump) {
10277 snprintf(hdr->reason, sizeof(hdr->reason), "\nStackshot reason: Power State Change Delay\n\n");
10278 gRootDomain->swd_lock = 0;
10279 gSpinDumpBufferFull = true;
10280 return;
10281 }
10282
10283 // Compress stackshot and save to NVRAM
10284 {
10285 char *outbuf = (char *)swd_compressed_buffer;
10286 int outlen = 0;
10287 int num_chunks = 0;
10288 int max_chunks = 0;
10289 int leftover = 0;
10290 char nvram_var_name_buffer[20];
10291
10292 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
10293
10294 if (outlen) {
10295 max_chunks = outlen / (2096 - 200);
10296 leftover = outlen % (2096 - 200);
10297
10298 if (max_chunks < 8) {
10299 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
10300 snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
10301 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
10302 LOG("Failed to update NVRAM %d\n", num_chunks);
10303 break;
10304 }
10305 }
10306 if (leftover) {
10307 snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
10308 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
10309 LOG("Failed to update NVRAM with leftovers\n");
10310 }
10311 }
10312 } else {
10313 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
10314 }
10315 }
10316 }
10317
10318 if (failureStr[0]) {
10319 if (!isOSXWatchdog) {
10320 // append sleep-wake failure code
10321 snprintf(failureStr, sizeof(failureStr), "%s\nFailure code:: 0x%08x %08x\n",
10322 failureStr, pmTracer->getTraceData(), pmTracer->getTracePhase());
10323 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, strlen(failureStr)) == false) {
10324 DLOG("Failed to write SleepWake failure string\n");
10325 }
10326 } else {
10327 if (PEWriteNVRAMProperty(kIOOSWatchdogFailureString, failureStr, strlen(failureStr)) == false) {
10328 DLOG("Failed to write OSWatchdog failure string\n");
10329 }
10330 }
10331 }
10332 gRootDomain->swd_lock = 0;
10333
10334 skip_stackshot:
10335 if (wdogTrigger) {
10336 PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic));
10337
10338 if ((wdog_panic == 1) || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
10339 if (thread) {
10340 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
10341 } else {
10342 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
10343 }
10344 return;
10345 } else if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10346 // If current boot is due to this watch dog trigger restart in previous boot,
10347 // then don't trigger again until at least 1 successful sleep & wake.
10348 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
10349 LOG("Shutting down due to repeated Sleep/Wake failures\n");
10350 if (!tasksSuspended) {
10351 tasksSuspended = TRUE;
10352 tasks_system_suspend(true);
10353 }
10354 PEHaltRestart(kPEHaltCPU);
10355 return;
10356 }
10357 }
10358 }
10359
10360
10361 if (wdogTrigger) {
10362 LOG("Restarting to collect Sleep wake debug logs\n");
10363 if (!tasksSuspended) {
10364 tasksSuspended = TRUE;
10365 tasks_system_suspend(true);
10366 }
10367
10368 PEHaltRestart(kPERestartCPU);
10369 } else {
10370 saveFailureData2File();
10371 }
10372 }
10373
10374 void
10375 IOPMrootDomain::sleepWakeDebugMemAlloc()
10376 {
10377 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
10378
10379 swd_hdr *hdr = NULL;
10380 void *bufPtr = NULL;
10381
10382 IOBufferMemoryDescriptor *memDesc = NULL;
10383
10384
10385 if (kIOSleepWakeWdogOff & gIOKitDebug) {
10386 return;
10387 }
10388
10389 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
10390 return;
10391 }
10392
10393 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
10394 return;
10395 }
10396
10397 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
10398 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
10399 size);
10400 if (memDesc == NULL) {
10401 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
10402 goto exit;
10403 }
10404
10405 bufPtr = memDesc->getBytesNoCopy();
10406
10407 // Carve out memory for zlib routines
10408 swd_zs_zmem = (vm_offset_t)bufPtr;
10409 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
10410
10411 // Carve out memory for compressed stackshots
10412 swd_compressed_buffer = bufPtr;
10413 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
10414
10415 // Remaining is used for holding stackshot
10416 hdr = (swd_hdr *)bufPtr;
10417 memset(hdr, 0, sizeof(swd_hdr));
10418
10419 hdr->signature = SWD_HDR_SIGNATURE;
10420 hdr->alloc_size = SWD_STACKSHOT_SIZE;
10421
10422 hdr->spindump_offset = sizeof(swd_hdr);
10423 swd_buffer = (void *)hdr;
10424 swd_memDesc = memDesc;
10425 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
10426
10427 exit:
10428 gRootDomain->swd_lock = 0;
10429 }
10430
10431 void
10432 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
10433 {
10434 vm_size_t size = SWD_SPINDUMP_SIZE;
10435
10436 swd_hdr *hdr = NULL;
10437
10438 IOBufferMemoryDescriptor *memDesc = NULL;
10439
10440 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
10441 return;
10442 }
10443
10444 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
10445 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
10446 SWD_SPINDUMP_SIZE);
10447
10448 if (memDesc == NULL) {
10449 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
10450 goto exit;
10451 }
10452
10453
10454 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
10455 memset(hdr, 0, sizeof(swd_hdr));
10456
10457 hdr->signature = SWD_HDR_SIGNATURE;
10458 hdr->alloc_size = size;
10459
10460 hdr->spindump_offset = sizeof(swd_hdr);
10461 swd_spindump_buffer = (void *)hdr;
10462
10463 exit:
10464 gRootDomain->swd_lock = 0;
10465 }
10466
10467 void
10468 IOPMrootDomain::sleepWakeDebugEnableWdog()
10469 {
10470 }
10471
10472 bool
10473 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
10474 {
10475 return !systemBooting && !systemShutdown && !gWillShutdown;
10476 }
10477
10478 void
10479 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
10480 {
10481 swd_hdr *hdr = NULL;
10482 errno_t error = EIO;
10483
10484 if (swd_spindump_buffer && gSpinDumpBufferFull) {
10485 hdr = (swd_hdr *)swd_spindump_buffer;
10486
10487 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
10488 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
10489
10490 if (error) {
10491 return;
10492 }
10493
10494 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
10495 (char*)hdr + offsetof(swd_hdr, UUID),
10496 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
10497
10498 gSpinDumpBufferFull = false;
10499 }
10500 }
10501
10502 errno_t
10503 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
10504 {
10505 struct vnode *vp = NULL;
10506 vfs_context_t ctx = vfs_context_create(vfs_context_current());
10507 kauth_cred_t cred = vfs_context_ucred(ctx);
10508 struct vnode_attr va;
10509 errno_t error = EIO;
10510
10511 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
10512 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
10513 LOG("Failed to open the file %s\n", name);
10514 swd_flags |= SWD_FILEOP_ERROR;
10515 goto exit;
10516 }
10517 VATTR_INIT(&va);
10518 VATTR_WANTED(&va, va_nlink);
10519 /* Don't dump to non-regular files or files with links. */
10520 if (vp->v_type != VREG ||
10521 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
10522 LOG("Bailing as this is not a regular file\n");
10523 swd_flags |= SWD_FILEOP_ERROR;
10524 goto exit;
10525 }
10526 VATTR_INIT(&va);
10527 VATTR_SET(&va, va_data_size, 0);
10528 vnode_setattr(vp, &va, ctx);
10529
10530
10531 if (buf != NULL) {
10532 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
10533 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
10534 if (error != 0) {
10535 LOG("Failed to save sleep wake log. err 0x%x\n", error);
10536 swd_flags |= SWD_FILEOP_ERROR;
10537 } else {
10538 DLOG("Saved %d bytes to file %s\n", len, name);
10539 }
10540 }
10541
10542 exit:
10543 if (vp) {
10544 vnode_close(vp, FWRITE, ctx);
10545 }
10546 if (ctx) {
10547 vfs_context_rele(ctx);
10548 }
10549
10550 return error;
10551 }
10552
10553
10554 #else
10555
10556 void
10557 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
10558 {
10559 uint32_t wdog_panic = 1;
10560
10561 if (restart) {
10562 if (PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic)) &&
10563 (wdog_panic == 0)) {
10564 return;
10565 }
10566 panic("Sleep/Wake hang detected");
10567 return;
10568 }
10569 }
10570
10571 void
10572 IOPMrootDomain::takeStackshot(bool restart, bool isOSXWatchdog, bool isSpinDump)
10573 {
10574 #pragma unused(restart)
10575 #pragma unused(isOSXWatchdog)
10576 }
10577
10578 void
10579 IOPMrootDomain::sleepWakeDebugMemAlloc()
10580 {
10581 }
10582 void
10583 IOPMrootDomain::saveFailureData2File()
10584 {
10585 }
10586
10587 void
10588 IOPMrootDomain::sleepWakeDebugEnableWdog()
10589 {
10590 }
10591
10592 bool
10593 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
10594 {
10595 return false;
10596 }
10597
10598 errno_t
10599 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
10600 {
10601 return 0;
10602 }
10603
10604 #endif
10605