1 /*
2 * Copyright (c) 1998-2021 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
29 #define IOKIT_ENABLE_SHARED_PTR
30
31 #include <libkern/c++/OSAllocation.h>
32 #include <libkern/c++/OSKext.h>
33 #include <libkern/c++/OSMetaClass.h>
34 #include <libkern/OSAtomic.h>
35 #include <libkern/OSDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommandGate.h>
38 #include <IOKit/IOTimerEventSource.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOCPU.h>
41 #include <IOKit/IOPlatformActions.h>
42 #include <IOKit/IOKitDebug.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
47 #include <IOKit/IODeviceTreeSupport.h>
48 #include <IOKit/IOMessage.h>
49 #include <IOKit/IOReturn.h>
50 #include <IOKit/IONVRAM.h>
51 #include "RootDomainUserClient.h"
52 #include "IOKit/pwr_mgt/IOPowerConnection.h"
53 #include "IOPMPowerStateQueue.h"
54 #include <IOKit/IOCatalogue.h>
55 #include <IOKit/IOReportMacros.h>
56 #include <IOKit/IOLib.h>
57 #include <IOKit/IOKitKeys.h>
58 #include <IOKit/IOUserServer.h>
59 #include "IOKitKernelInternal.h"
60 #if HIBERNATION
61 #include <IOKit/IOHibernatePrivate.h>
62 #endif /* HIBERNATION */
63 #include <console/video_console.h>
64 #include <sys/syslog.h>
65 #include <sys/sysctl.h>
66 #include <sys/vnode.h>
67 #include <sys/vnode_internal.h>
68 #include <sys/fcntl.h>
69 #include <os/log.h>
70 #include <pexpert/protos.h>
71 #include <AssertMacros.h>
72
73 #include <sys/time.h>
74 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
75 #include "IOServicePMPrivate.h"
76
77 #include <libkern/zlib.h>
78 #include <os/cpp_util.h>
79 #include <os/atomic_private.h>
80 #include <libkern/c++/OSBoundedArrayRef.h>
81
82 #if DEVELOPMENT || DEBUG
83 #include <os/system_event_log.h>
84 #endif /* DEVELOPMENT || DEBUG */
85
86 __BEGIN_DECLS
87 #include <mach/shared_region.h>
88 #include <kern/clock.h>
89 __END_DECLS
90
91 #if defined(__i386__) || defined(__x86_64__)
92 __BEGIN_DECLS
93 #include "IOPMrootDomainInternal.h"
94 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
95 __END_DECLS
96 #endif
97
98 #define kIOPMrootDomainClass "IOPMrootDomain"
99 #define LOG_PREFIX "PMRD: "
100
101
102 #define MSG(x...) \
103 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
104
105 #define LOG(x...) \
106 do { kprintf(LOG_PREFIX x); } while (false)
107
108 #if DEVELOPMENT || DEBUG
109 #define DEBUG_LOG(x...) do { \
110 if (kIOLogPMRootDomain & gIOKitDebug) \
111 kprintf(LOG_PREFIX x); \
112 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
113 } while (false)
114 #else
115 #define DEBUG_LOG(x...)
116 #endif
117
118 #define DLOG(x...) do { \
119 if (kIOLogPMRootDomain & gIOKitDebug) \
120 kprintf(LOG_PREFIX x); \
121 else \
122 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
123 } while (false)
124
125 #define DMSG(x...) do { \
126 if (kIOLogPMRootDomain & gIOKitDebug) { \
127 kprintf(LOG_PREFIX x); \
128 } \
129 } while (false)
130
131
132 #define _LOG(x...)
133
134 #define CHECK_THREAD_CONTEXT
135 #ifdef CHECK_THREAD_CONTEXT
136 static IOWorkLoop * gIOPMWorkLoop = NULL;
137 #define ASSERT_GATED() \
138 do { \
139 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
140 panic("RootDomain: not inside PM gate"); \
141 } \
142 } while(false)
143 #else
144 #define ASSERT_GATED()
145 #endif /* CHECK_THREAD_CONTEXT */
146
147 #define CAP_LOSS(c) \
148 (((_pendingCapability & (c)) == 0) && \
149 ((_currentCapability & (c)) != 0))
150
151 #define CAP_GAIN(c) \
152 (((_currentCapability & (c)) == 0) && \
153 ((_pendingCapability & (c)) != 0))
154
155 #define CAP_CHANGE(c) \
156 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
157
158 #define CAP_CURRENT(c) \
159 ((_currentCapability & (c)) != 0)
160
161 #define CAP_HIGHEST(c) \
162 ((_highestCapability & (c)) != 0)
163
164 #define CAP_PENDING(c) \
165 ((_pendingCapability & (c)) != 0)
166
167 // rdar://problem/9157444
168 #if defined(__i386__) || defined(__x86_64__)
169 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
170 #endif
171
172 // Event types for IOPMPowerStateQueue::submitPowerEvent()
173 enum {
174 kPowerEventFeatureChanged = 1, // 1
175 kPowerEventReceivedPowerNotification, // 2
176 kPowerEventSystemBootCompleted, // 3
177 kPowerEventSystemShutdown, // 4
178 kPowerEventUserDisabledSleep, // 5
179 kPowerEventRegisterSystemCapabilityClient, // 6
180 kPowerEventRegisterKernelCapabilityClient, // 7
181 kPowerEventPolicyStimulus, // 8
182 kPowerEventAssertionCreate, // 9
183 kPowerEventAssertionRelease, // 10
184 kPowerEventAssertionSetLevel, // 11
185 kPowerEventQueueSleepWakeUUID, // 12
186 kPowerEventPublishSleepWakeUUID, // 13
187 kPowerEventSetDisplayPowerOn, // 14
188 kPowerEventPublishWakeType, // 15
189 kPowerEventAOTEvaluate // 16
190 };
191
192 // For evaluatePolicy()
193 // List of stimuli that affects the root domain policy.
194 enum {
195 kStimulusDisplayWranglerSleep, // 0
196 kStimulusDisplayWranglerWake, // 1
197 kStimulusAggressivenessChanged, // 2
198 kStimulusDemandSystemSleep, // 3
199 kStimulusAllowSystemSleepChanged, // 4
200 kStimulusDarkWakeActivityTickle, // 5
201 kStimulusDarkWakeEntry, // 6
202 kStimulusDarkWakeReentry, // 7
203 kStimulusDarkWakeEvaluate, // 8
204 kStimulusNoIdleSleepPreventers, // 9
205 kStimulusEnterUserActiveState, // 10
206 kStimulusLeaveUserActiveState // 11
207 };
208
209 // Internal power state change reasons
210 // Must be less than kIOPMSleepReasonClamshell=101
211 enum {
212 kCPSReasonNone = 0, // 0
213 kCPSReasonInit, // 1
214 kCPSReasonWake, // 2
215 kCPSReasonIdleSleepPrevent, // 3
216 kCPSReasonIdleSleepAllow, // 4
217 kCPSReasonPowerOverride, // 5
218 kCPSReasonPowerDownCancel, // 6
219 kCPSReasonAOTExit, // 7
220 kCPSReasonAdjustPowerState, // 8
221 kCPSReasonDarkWakeCannotSleep, // 9
222 kCPSReasonIdleSleepEnabled, // 10
223 kCPSReasonEvaluatePolicy, // 11
224 kCPSReasonSustainFullWake, // 12
225 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
226 };
227
228 extern "C" {
229 IOReturn OSKextSystemSleepOrWake( UInt32 );
230 }
231 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
232 extern "C" addr64_t kvtophys(vm_offset_t va);
233 extern "C" boolean_t kdp_has_polled_corefile();
234
235 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
236 static void notifySystemShutdown( IOService * root, uint32_t messageType );
237 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
238 static void pmEventTimeStamp(uint64_t *recordTS);
239 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
240 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
241 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
242
243 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
244 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
245 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
246 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
247
248 // "IOPMSetSleepSupported" callPlatformFunction name
249 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
250 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
251 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
252
253 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey;
254 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey;
255 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey;
256 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey;
257 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey;
258 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey;
259 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey;
260 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey;
261 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey;
262 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey;
263 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey;
264 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey;
265 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey;
266 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey;
267 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey;
268 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey;
269 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey;
270 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey;
271 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey;
272 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey;
273 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey;
274 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey;
275 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey;
276 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey;
277 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey;
278 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey;
279 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey;
280 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey;
281 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey;
282 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey;
283 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey;
284 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey;
285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey;
286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey;
287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey;
288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey;
289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey;
290 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey;
291 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey;
292 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey;
293 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey;
294 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey;
295 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey;
296 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey;
297
298 #define kIOSleepSupportedKey "IOSleepSupported"
299 #define kIOPMSystemCapabilitiesKey "System Capabilities"
300 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
301
302 #define kIORequestWranglerIdleKey "IORequestIdle"
303 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
304
305 #define kIOSleepWakeFailureString "SleepWakeFailureString"
306 #define kIOEFIBootRomFailureKey "wake-failure"
307 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
308
309 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
310 | kIOPMSupportedOnBatt \
311 | kIOPMSupportedOnUPS)
312
313 #define kLocalEvalClamshellCommand (1 << 15)
314 #define kIdleSleepRetryInterval (3 * 60 * 1000)
315
316 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
317 // We impose this minimum to avoid race conditions in the AP wake path where
318 // userspace clients are not able to acquire power assertions before the idle timer expires.
319 #define kMinimumTimeBeforeIdleSleep 1000
320
321 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
322
323 enum {
324 kWranglerPowerStateMin = 0,
325 kWranglerPowerStateSleep = 2,
326 kWranglerPowerStateDim = 3,
327 kWranglerPowerStateMax = 4
328 };
329
330 enum {
331 OFF_STATE = 0,
332 RESTART_STATE = 1,
333 SLEEP_STATE = 2,
334 AOT_STATE = 3,
335 ON_STATE = 4,
336 NUM_POWER_STATES
337 };
338
339 const char *
getPowerStateString(uint32_t state)340 getPowerStateString( uint32_t state )
341 {
342 #define POWER_STATE(x) {(uint32_t) x, #x}
343
344 static const IONamedValue powerStates[] = {
345 POWER_STATE( OFF_STATE ),
346 POWER_STATE( RESTART_STATE ),
347 POWER_STATE( SLEEP_STATE ),
348 POWER_STATE( AOT_STATE ),
349 POWER_STATE( ON_STATE ),
350 { 0, NULL }
351 };
352 return IOFindNameForValue(state, powerStates);
353 }
354
355 #define ON_POWER kIOPMPowerOn
356 #define RESTART_POWER kIOPMRestart
357 #define SLEEP_POWER kIOPMAuxPowerOn
358
359 static IOPMPowerState
360 ourPowerStates[NUM_POWER_STATES] =
361 {
362 { .version = 1,
363 .capabilityFlags = 0,
364 .outputPowerCharacter = 0,
365 .inputPowerRequirement = 0 },
366 { .version = 1,
367 .capabilityFlags = kIOPMRestartCapability,
368 .outputPowerCharacter = kIOPMRestart,
369 .inputPowerRequirement = RESTART_POWER },
370 { .version = 1,
371 .capabilityFlags = kIOPMSleepCapability,
372 .outputPowerCharacter = kIOPMSleep,
373 .inputPowerRequirement = SLEEP_POWER },
374 { .version = 1,
375 .capabilityFlags = kIOPMAOTCapability,
376 .outputPowerCharacter = kIOPMAOTPower,
377 .inputPowerRequirement = ON_POWER },
378 { .version = 1,
379 .capabilityFlags = kIOPMPowerOn,
380 .outputPowerCharacter = kIOPMPowerOn,
381 .inputPowerRequirement = ON_POWER },
382 };
383
384 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
385 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
386 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
387 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
388 #define kIOPMRootDomainWakeTypeUser "User"
389 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
390 #define kIOPMRootDomainWakeTypeNetwork "Network"
391 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
392 #define kIOPMRootDomainWakeTypeNotification "Notification"
393 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
394
395 // Special interest that entitles the interested client from receiving
396 // all system messages. Only used by powerd.
397 //
398 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
399
400 // Entitlement required for root domain clients
401 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
402
403 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
404 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
405
406 /*
407 * Aggressiveness
408 */
409 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
410 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
411
412 #define kAggressivesMinValue 1
413
414 const char *
getAggressivenessTypeString(uint32_t type)415 getAggressivenessTypeString( uint32_t type )
416 {
417 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
418
419 static const IONamedValue aggressivenessTypes[] = {
420 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
421 AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
422 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
423 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
424 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
425 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
426 AGGRESSIVENESS_TYPE( kPMPowerSource),
427 AGGRESSIVENESS_TYPE( kPMMotionSensor ),
428 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
429 { 0, NULL }
430 };
431 return IOFindNameForValue(type, aggressivenessTypes);
432 }
433
434 enum {
435 kAggressivesStateBusy = 0x01,
436 kAggressivesStateQuickSpindown = 0x02
437 };
438
439 struct AggressivesRecord {
440 uint32_t flags;
441 uint32_t type;
442 uint32_t value;
443 };
444
445 struct AggressivesRequest {
446 queue_chain_t chain;
447 uint32_t options;
448 uint32_t dataType;
449 union {
450 OSSharedPtr<IOService> service;
451 AggressivesRecord record;
452 } data;
453 };
454
455 enum {
456 kAggressivesRequestTypeService = 1,
457 kAggressivesRequestTypeRecord
458 };
459
460 enum {
461 kAggressivesOptionSynchronous = 0x00000001,
462 kAggressivesOptionQuickSpindownEnable = 0x00000100,
463 kAggressivesOptionQuickSpindownDisable = 0x00000200,
464 kAggressivesOptionQuickSpindownMask = 0x00000300
465 };
466
467 enum {
468 kAggressivesRecordFlagModified = 0x00000001,
469 kAggressivesRecordFlagMinValue = 0x00000002
470 };
471
472 // System Sleep Preventers
473
474 enum {
475 kPMUserDisabledAllSleep = 1,
476 kPMSystemRestartBootingInProgress,
477 kPMConfigPreventSystemSleep,
478 kPMChildPreventSystemSleep,
479 kPMCPUAssertion,
480 kPMPCIUnsupported,
481 };
482
483 const char *
getSystemSleepPreventerString(uint32_t preventer)484 getSystemSleepPreventerString( uint32_t preventer )
485 {
486 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
487 static const IONamedValue systemSleepPreventers[] = {
488 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
489 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
490 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
491 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
492 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
493 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
494 { 0, NULL }
495 };
496 return IOFindNameForValue(preventer, systemSleepPreventers);
497 }
498
499 // gDarkWakeFlags
500 enum {
501 kDarkWakeFlagPromotionNone = 0x0000,
502 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp
503 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp
504 kDarkWakeFlagPromotionMask = 0x0003,
505 kDarkWakeFlagAlarmIsDark = 0x0100,
506 kDarkWakeFlagAudioNotSuppressed = 0x0200,
507 kDarkWakeFlagUserWakeWorkaround = 0x1000
508 };
509
510 // gClamshellFlags
511 // The workaround for 9157444 is enabled at compile time using the
512 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
513 enum {
514 kClamshell_WAR_38378787 = 0x00000001,
515 kClamshell_WAR_47715679 = 0x00000002,
516 kClamshell_WAR_58009435 = 0x00000004
517 };
518
519 // acceptSystemWakeEvents()
520 enum {
521 kAcceptSystemWakeEvents_Disable = 0,
522 kAcceptSystemWakeEvents_Enable,
523 kAcceptSystemWakeEvents_Reenable
524 };
525
526 static IOPMrootDomain * gRootDomain;
527 static IORootParent * gPatriarch;
528 static IONotifier * gSysPowerDownNotifier = NULL;
529 static UInt32 gSleepOrShutdownPending = 0;
530 static UInt32 gWillShutdown = 0;
531 static UInt32 gPagingOff = 0;
532 static UInt32 gSleepWakeUUIDIsSet = false;
533 static uint32_t gAggressivesState = 0;
534 uint32_t gHaltTimeMaxLog;
535 uint32_t gHaltTimeMaxPanic;
536 IOLock * gHaltLogLock;
537 static char * gHaltLog;
538 enum { kHaltLogSize = 2048 };
539 static size_t gHaltLogPos;
540 static uint64_t gHaltStartTime;
541 static char gKextNameBuf[64];
542 static size_t gKextNamePos;
543 static bool gKextNameEnd;
544
545 uuid_string_t bootsessionuuid_string;
546
547 #if defined(XNU_TARGET_OS_OSX)
548 #if DISPLAY_WRANGLER_PRESENT
549 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
550 #elif defined(__arm64__)
551 // Enable temporary full wake promotion workarounds
552 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
553 #else
554 // Enable full wake promotion workarounds
555 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
556 #endif
557 #else /* !defined(XNU_TARGET_OS_OSX) */
558 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
559 #endif /* !defined(XNU_TARGET_OS_OSX) */
560
561 static uint32_t gNoIdleFlag = 0;
562 static uint32_t gSleepDisabledFlag = 0;
563 static uint32_t gSwdPanic = 1;
564 static uint32_t gSwdSleepTimeout = 0;
565 static uint32_t gSwdWakeTimeout = 0;
566 static uint32_t gSwdSleepWakeTimeout = 0;
567 static PMStatsStruct gPMStats;
568 #if DEVELOPMENT || DEBUG
569 static uint32_t swd_panic_phase;
570 #endif
571
572 static uint32_t gClamshellFlags = 0
573 #if defined(__i386__) || defined(__x86_64__)
574 | kClamshell_WAR_58009435
575 #endif
576 ;
577
578 #if HIBERNATION
579
580 #if defined(__arm64__)
581 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)582 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
583 {
584 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
585
586 assert(vars->signature == kIOPMSystemSleepPolicySignature);
587 assert(vars->version == kIOPMSystemSleepPolicyVersion);
588
589 // Hibernation enabled and either user forced hibernate or low battery sleep
590 if ((vars->hibernateMode & kIOHibernateModeOn) &&
591 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
592 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
593 sleepType = kIOPMSleepTypeHibernate;
594 }
595 params->version = kIOPMSystemSleepParametersVersion;
596 params->sleepType = sleepType;
597 return kIOReturnSuccess;
598 }
599 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
600 #else /* defined(__arm64__) */
601 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
602 #endif /* defined(__arm64__) */
603
604 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
605 static void * gSleepPolicyTarget;
606 #endif
607
608 struct timeval gIOLastSleepTime;
609 struct timeval gIOLastWakeTime;
610 AbsoluteTime gIOLastWakeAbsTime;
611 AbsoluteTime gIOLastSleepAbsTime;
612
613 struct timeval gIOLastUserSleepTime;
614
615 static char gWakeReasonString[128];
616 static char gBootReasonString[80];
617 static char gShutdownReasonString[80];
618 static bool gWakeReasonSysctlRegistered = false;
619 static bool gBootReasonSysctlRegistered = false;
620 static bool gShutdownReasonSysctlRegistered = false;
621 static bool gWillShutdownSysctlRegistered = false;
622 static AbsoluteTime gUserActiveAbsTime;
623 static AbsoluteTime gUserInactiveAbsTime;
624
625 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
626 static bool gSpinDumpBufferFull = false;
627 #endif
628
629 z_stream swd_zs;
630 vm_offset_t swd_zs_zmem;
631 //size_t swd_zs_zsize;
632 size_t swd_zs_zoffset;
633 #if defined(__i386__) || defined(__x86_64__)
634 IOCPU *currentShutdownTarget = NULL;
635 #endif
636
637 static unsigned int gPMHaltBusyCount;
638 static unsigned int gPMHaltIdleCount;
639 static int gPMHaltDepth;
640 static uint32_t gPMHaltMessageType;
641 static IOLock * gPMHaltLock = NULL;
642 static OSSharedPtr<OSArray> gPMHaltArray;
643 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
644 static bool gPMQuiesced;
645
646 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
647 #define kCPUUnknownIndex 9999999
648 enum {
649 kInformAC = 0,
650 kInformLid = 1,
651 kInformableCount = 2
652 };
653
654 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
655 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
656 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
657 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
658 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
659
660 #define kBadPMFeatureID 0
661
662 /*
663 * PMSettingHandle
664 * Opaque handle passed to clients of registerPMSettingController()
665 */
666 class PMSettingHandle : public OSObject
667 {
668 OSDeclareFinalStructors( PMSettingHandle );
669 friend class PMSettingObject;
670
671 private:
672 PMSettingObject *pmso;
673 void free(void) APPLE_KEXT_OVERRIDE;
674 };
675
676 /*
677 * PMSettingObject
678 * Internal object to track each PM setting controller
679 */
680 class PMSettingObject : public OSObject
681 {
682 OSDeclareFinalStructors( PMSettingObject );
683 friend class IOPMrootDomain;
684
685 private:
686 queue_head_t calloutQueue;
687 thread_t waitThread;
688 IOPMrootDomain *parent;
689 PMSettingHandle *pmsh;
690 IOPMSettingControllerCallback func;
691 OSObject *target;
692 uintptr_t refcon;
693 OSDataAllocation<uint32_t> publishedFeatureID;
694 uint32_t settingCount;
695 bool disabled;
696
697 void free(void) APPLE_KEXT_OVERRIDE;
698
699 public:
700 static PMSettingObject *pmSettingObject(
701 IOPMrootDomain *parent_arg,
702 IOPMSettingControllerCallback handler_arg,
703 OSObject *target_arg,
704 uintptr_t refcon_arg,
705 uint32_t supportedPowerSources,
706 const OSSymbol *settings[],
707 OSObject **handle_obj);
708
709 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
710 void clientHandleFreed(void);
711 };
712
713 struct PMSettingCallEntry {
714 queue_chain_t link;
715 thread_t thread;
716 };
717
718 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
719 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
720 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
721 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
722
723 /*
724 * PMTraceWorker
725 * Internal helper object for logging trace points to RTC
726 * IOPMrootDomain and only IOPMrootDomain should instantiate
727 * exactly one of these.
728 */
729
730 typedef void (*IOPMTracePointHandler)(
731 void * target, uint32_t code, uint32_t data );
732
733 class PMTraceWorker : public OSObject
734 {
735 OSDeclareDefaultStructors(PMTraceWorker);
736 public:
737 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
738
739 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
740 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
741 void tracePoint(uint8_t phase);
742 void traceDetail(uint32_t detail);
743 void traceComponentWakeProgress(uint32_t component, uint32_t data);
744 int recordTopLevelPCIDevice(IOService *);
745 void RTC_TRACE(void);
746 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
747
748 IOPMTracePointHandler tracePointHandler;
749 void * tracePointTarget;
750 uint64_t getPMStatusCode();
751 uint8_t getTracePhase();
752 uint32_t getTraceData();
753 private:
754 IOPMrootDomain *owner;
755 IOLock *pmTraceWorkerLock;
756 OSSharedPtr<OSArray> pciDeviceBitMappings;
757
758 uint8_t addedToRegistry;
759 uint8_t tracePhase;
760 uint32_t traceData32;
761 uint8_t loginWindowData;
762 uint8_t coreDisplayData;
763 uint8_t coreGraphicsData;
764 };
765
766 /*
767 * this should be treated as POD, as it's byte-copied around
768 * and we cannot rely on d'tor firing at the right time
769 */
770 struct PMAssertStruct {
771 IOPMDriverAssertionID id;
772 IOPMDriverAssertionType assertionBits;
773 uint64_t createdTime;
774 uint64_t modifiedTime;
775 const OSSymbol *ownerString;
776 IOService *ownerService;
777 uint64_t registryEntryID;
778 IOPMDriverAssertionLevel level;
779 uint64_t assertCPUStartTime;
780 uint64_t assertCPUDuration;
781 };
782 OSDefineValueObjectForDependentType(PMAssertStruct)
783
784 /*
785 * PMAssertionsTracker
786 * Tracks kernel and user space PM assertions
787 */
788 class PMAssertionsTracker : public OSObject
789 {
790 OSDeclareFinalStructors(PMAssertionsTracker);
791 public:
792 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
793
794 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
795 IOReturn releaseAssertion(IOPMDriverAssertionID);
796 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
797 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
798
799 OSSharedPtr<OSArray> copyAssertionsArray(void);
800 IOPMDriverAssertionType getActivatedAssertions(void);
801 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
802
803 IOReturn handleCreateAssertion(OSValueObject<PMAssertStruct> *);
804 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
805 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
806 IOReturn handleSetUserAssertionLevels(void * arg0);
807 void publishProperties(void);
808 void reportCPUBitAccounting(void);
809
810 private:
811 uint32_t tabulateProducerCount;
812 uint32_t tabulateConsumerCount;
813
814 uint64_t maxAssertCPUDuration;
815 uint64_t maxAssertCPUEntryId;
816
817 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
818 void tabulate(void);
819 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
820
821 IOPMrootDomain *owner;
822 OSSharedPtr<OSArray> assertionsArray;
823 IOLock *assertionsArrayLock;
824 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
825 IOPMDriverAssertionType assertionsKernel;
826 IOPMDriverAssertionType assertionsUser;
827 IOPMDriverAssertionType assertionsCombined;
828 };
829
830 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
831
832 /*
833 * PMHaltWorker
834 * Internal helper object for Shutdown/Restart notifications.
835 */
836 #define kPMHaltMaxWorkers 8
837 #define kPMHaltTimeoutMS 100
838
839 class PMHaltWorker : public OSObject
840 {
841 OSDeclareFinalStructors( PMHaltWorker );
842
843 public:
844 IOService * service;// service being worked on
845 AbsoluteTime startTime; // time when work started
846 int depth; // work on nubs at this PM-tree depth
847 int visits; // number of nodes visited (debug)
848 IOLock * lock;
849 bool timeout;// service took too long
850
851 static PMHaltWorker * worker( void );
852 static void main( void * arg, wait_result_t waitResult );
853 static void work( PMHaltWorker * me );
854 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
855 virtual void free( void ) APPLE_KEXT_OVERRIDE;
856 };
857
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)858 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
859
860
861 #define super IOService
862 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
863
864 boolean_t
865 IOPMRootDomainGetWillShutdown(void)
866 {
867 return gWillShutdown != 0;
868 }
869
870 static void
IOPMRootDomainWillShutdown(void)871 IOPMRootDomainWillShutdown(void)
872 {
873 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
874 IOService::willShutdown();
875 for (int i = 0; i < 100; i++) {
876 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
877 break;
878 }
879 IOSleep( 100 );
880 }
881 }
882 }
883
884 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)885 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
886 {
887 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
888 }
889
890 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)891 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
892 {
893 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
894 }
895
896 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)897 acknowledgeSleepWakeNotification(void * PMrefcon)
898 {
899 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
900 }
901
902 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)903 vetoSleepWakeNotification(void * PMrefcon)
904 {
905 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
906 }
907
908 extern "C" IOReturn
rootDomainRestart(void)909 rootDomainRestart( void )
910 {
911 return gRootDomain->restartSystem();
912 }
913
914 extern "C" IOReturn
rootDomainShutdown(void)915 rootDomainShutdown( void )
916 {
917 return gRootDomain->shutdownSystem();
918 }
919
920 static void
halt_log_putc(char c)921 halt_log_putc(char c)
922 {
923 if (gHaltLogPos >= (kHaltLogSize - 2)) {
924 return;
925 }
926 gHaltLog[gHaltLogPos++] = c;
927 }
928
929 extern "C" void
930 _doprnt_log(const char *fmt,
931 va_list *argp,
932 void (*putc)(char),
933 int radix);
934
935 static int
halt_log(const char * fmt,...)936 halt_log(const char *fmt, ...)
937 {
938 va_list listp;
939
940 va_start(listp, fmt);
941 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
942 va_end(listp);
943
944 return 0;
945 }
946
947 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)948 halt_log_enter(const char * what, const void * pc, uint64_t time)
949 {
950 uint64_t nano, millis;
951
952 if (!gHaltLog) {
953 return;
954 }
955 absolutetime_to_nanoseconds(time, &nano);
956 millis = nano / NSEC_PER_MSEC;
957 if (millis < 100) {
958 return;
959 }
960
961 IOLockLock(gHaltLogLock);
962 if (pc) {
963 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
964 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
965 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
966 } else {
967 halt_log("%s: %qd ms\n", what, millis);
968 }
969
970 gHaltLog[gHaltLogPos] = 0;
971 IOLockUnlock(gHaltLogLock);
972 }
973
974 extern uint32_t gFSState;
975
976 extern "C" void
IOSystemShutdownNotification(int howto,int stage)977 IOSystemShutdownNotification(int howto, int stage)
978 {
979 uint64_t startTime;
980
981 if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
982 #if defined(XNU_TARGET_OS_OSX)
983 uint64_t nano, millis;
984 startTime = mach_absolute_time();
985 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
986 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
987 millis = nano / NSEC_PER_MSEC;
988 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
989 printf("waitQuiet() for unmount %qd ms\n", millis);
990 }
991 #endif /* defined(XNU_TARGET_OS_OSX) */
992 return;
993 }
994
995 if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
996 uint64_t nano, millis;
997 startTime = mach_absolute_time();
998 IOServicePH::systemHalt(howto);
999 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1000 millis = nano / NSEC_PER_MSEC;
1001 if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1002 printf("IOServicePH::systemHalt took %qd ms\n", millis);
1003 }
1004 return;
1005 }
1006
1007 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1008
1009 IOLockLock(gHaltLogLock);
1010 if (!gHaltLog) {
1011 gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1012 gHaltStartTime = mach_absolute_time();
1013 if (gHaltLog) {
1014 halt_log_putc('\n');
1015 }
1016 }
1017 IOLockUnlock(gHaltLogLock);
1018
1019 startTime = mach_absolute_time();
1020 IOPMRootDomainWillShutdown();
1021 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1022 #if HIBERNATION
1023 startTime = mach_absolute_time();
1024 IOHibernateSystemPostWake(true);
1025 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1026 #endif
1027 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1028 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1029 }
1030 }
1031
1032 extern "C" int sync_internal(void);
1033
1034 /*
1035 * A device is always in the highest power state which satisfies its driver,
1036 * its policy-maker, and any power children it has, but within the constraint
1037 * of the power state provided by its parent. The driver expresses its desire by
1038 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1039 * changePowerStateToPriv(), and the children express their desires by calling
1040 * requestPowerDomainState().
1041 *
1042 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1043 * It is a power-managed IOService just like the others in the system.
1044 * It implements several power states which map to what we see as Sleep and On.
1045 *
1046 * The sleep policy is as follows:
1047 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1048 * is off and plug/unplug cards.
1049 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1050 * 3. System cannot Sleep if some object in the tree is in a power state marked
1051 * kIOPMPreventSystemSleep.
1052 *
1053 * These three conditions are enforced using the "driver clamp" by calling
1054 * changePowerStateTo(). For example, if the case is opened,
1055 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1056 * of the desires of the children of the root or the state of the other clamp.
1057 *
1058 * Demand Sleep is initiated by pressing the front panel power button, closing
1059 * the clamshell, or selecting the menu item. In this case the root's parent
1060 * actually initiates the power state change so that the root domain has no
1061 * choice and does not give applications the opportunity to veto the change.
1062 *
1063 * Idle Sleep occurs if no objects in the tree are in a state marked
1064 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1065 * the root on, so it sets the "policy-maker clamp" by calling
1066 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1067 * This timer is set for the difference between the sleep timeout slider and the
1068 * display dim timeout slider. When the timer expires, it releases its clamp and
1069 * now nothing is holding it awake, so it falls asleep.
1070 *
1071 * Demand sleep is prevented when the system is booting. When preferences are
1072 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1073 * and this allows subsequent Demand Sleep.
1074 */
1075
1076 //******************************************************************************
1077
1078 IOPMrootDomain *
construct(void)1079 IOPMrootDomain::construct( void )
1080 {
1081 IOPMrootDomain *root;
1082
1083 root = new IOPMrootDomain;
1084 if (root) {
1085 root->init();
1086 }
1087
1088 return root;
1089 }
1090
1091 //******************************************************************************
1092 // updateConsoleUsersCallout
1093 //
1094 //******************************************************************************
1095
1096 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1097 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1098 {
1099 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1100 rootDomain->updateConsoleUsers();
1101 }
1102
1103 void
updateConsoleUsers(void)1104 IOPMrootDomain::updateConsoleUsers(void)
1105 {
1106 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1107 updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1108 }
1109
1110 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1111 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1112 {
1113 bool newSuspend;
1114
1115 WAKEEVENT_LOCK();
1116 if (newTasksSuspended != kTasksSuspendNoChange) {
1117 tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1118 }
1119 if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1120 _aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1121 }
1122 newSuspend = (tasksSuspended || _aotTasksSuspended);
1123 if (newSuspend == tasksSuspendState) {
1124 WAKEEVENT_UNLOCK();
1125 return false;
1126 }
1127 tasksSuspendState = newSuspend;
1128 WAKEEVENT_UNLOCK();
1129 tasks_system_suspend(newSuspend);
1130 return true;
1131 }
1132
1133 //******************************************************************************
1134
1135 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1136 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1137 {
1138 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1139 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1140 uint32_t powerState = rootDomain->getPowerState();
1141
1142 DLOG("disk_sync_callout ps=%u\n", powerState);
1143
1144 if (ON_STATE == powerState) {
1145 sync_internal();
1146
1147 #if HIBERNATION
1148 // Block sleep until trim issued on previous wake path is completed.
1149 IOHibernateSystemPostWake(true);
1150 #endif
1151 }
1152 #if HIBERNATION
1153 else {
1154 IOHibernateSystemPostWake(false);
1155
1156 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1157 }
1158 #endif
1159
1160 rootDomain->allowPowerChange(notifyRef);
1161 DLOG("disk_sync_callout finish\n");
1162 }
1163
1164 //******************************************************************************
1165 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1166 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1167 {
1168 AbsoluteTime endTime;
1169 UInt64 nano = 0;
1170
1171 clock_get_uptime(&endTime);
1172 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1173 *elapsedTime = 0;
1174 } else {
1175 SUB_ABSOLUTETIME(&endTime, startTime);
1176 absolutetime_to_nanoseconds(endTime, &nano);
1177 *elapsedTime = endTime;
1178 }
1179
1180 return (UInt32)(nano / NSEC_PER_MSEC);
1181 }
1182
1183 //******************************************************************************
1184
1185 static int
1186 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1187 {
1188 struct timeval *swt = (struct timeval *)arg1;
1189 struct proc *p = req->p;
1190
1191 if (p == kernproc) {
1192 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1193 } else if (proc_is64bit(p)) {
1194 struct user64_timeval t = {};
1195 t.tv_sec = swt->tv_sec;
1196 t.tv_usec = swt->tv_usec;
1197 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1198 } else {
1199 struct user32_timeval t = {};
1200 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1201 t.tv_usec = swt->tv_usec;
1202 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1203 }
1204 }
1205
1206 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1207 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1208 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1209
1210 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1211 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1212 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1213
1214 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1215 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1216 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1217 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1218
1219 static int
1220 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1221 {
1222 int new_value, changed, error;
1223
1224 if (!gWillShutdownSysctlRegistered) {
1225 return ENOENT;
1226 }
1227
1228 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1229 if (changed) {
1230 if (!gWillShutdown && (new_value == 1)) {
1231 IOPMRootDomainWillShutdown();
1232 } else {
1233 error = EINVAL;
1234 }
1235 }
1236 return error;
1237 }
1238
1239 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1240 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1241 NULL, 0, sysctl_willshutdown, "I", "");
1242
1243 #if defined(XNU_TARGET_OS_OSX)
1244
1245 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1246 sysctl_progressmeterenable
1247 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1248 {
1249 int error;
1250 int new_value, changed;
1251
1252 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1253
1254 if (changed) {
1255 vc_enable_progressmeter(new_value);
1256 }
1257
1258 return error;
1259 }
1260
1261 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1262 sysctl_progressmeter
1263 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1264 {
1265 int error;
1266 int new_value, changed;
1267
1268 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1269
1270 if (changed) {
1271 vc_set_progressmeter(new_value);
1272 }
1273
1274 return error;
1275 }
1276
1277 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1278 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1279 NULL, 0, sysctl_progressmeterenable, "I", "");
1280
1281 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1282 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1283 NULL, 0, sysctl_progressmeter, "I", "");
1284
1285 #endif /* defined(XNU_TARGET_OS_OSX) */
1286
1287
1288
1289 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1290 sysctl_consoleoptions
1291 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1292 {
1293 int error, changed;
1294 uint32_t new_value;
1295
1296 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1297
1298 if (changed) {
1299 vc_user_options.options = new_value;
1300 }
1301
1302 return error;
1303 }
1304
1305 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1306 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1307 NULL, 0, sysctl_consoleoptions, "I", "");
1308
1309
1310 static int
1311 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1312 {
1313 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1314 }
1315
1316 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1317 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1318 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1319
1320
1321 static int
1322 sysctl_wakereason SYSCTL_HANDLER_ARGS
1323 {
1324 char wr[sizeof(gWakeReasonString)];
1325
1326 wr[0] = '\0';
1327 if (gRootDomain && gWakeReasonSysctlRegistered) {
1328 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1329 } else {
1330 return ENOENT;
1331 }
1332
1333 return sysctl_io_string(req, wr, 0, 0, NULL);
1334 }
1335
1336 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1337 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1338 NULL, 0, sysctl_wakereason, "A", "wakereason");
1339
1340 static int
1341 sysctl_bootreason SYSCTL_HANDLER_ARGS
1342 {
1343 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1344 return ENOENT;
1345 }
1346
1347 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1348 }
1349
1350 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1351 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1352 NULL, 0, sysctl_bootreason, "A", "");
1353
1354 static int
1355 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1356 {
1357 char sr[sizeof(gShutdownReasonString)];
1358
1359 sr[0] = '\0';
1360 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1361 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1362 } else {
1363 return ENOENT;
1364 }
1365
1366 return sysctl_io_string(req, sr, 0, 0, NULL);
1367 }
1368
1369 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1370 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1371 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1372
1373 static int
1374 sysctl_targettype SYSCTL_HANDLER_ARGS
1375 {
1376 IOService * root;
1377 OSSharedPtr<OSObject> obj;
1378 OSData * data;
1379 char tt[32];
1380
1381 tt[0] = '\0';
1382 root = IOService::getServiceRoot();
1383 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1384 if ((data = OSDynamicCast(OSData, obj.get()))) {
1385 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1386 }
1387 }
1388 return sysctl_io_string(req, tt, 0, 0, NULL);
1389 }
1390
1391 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1392 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1393 NULL, 0, sysctl_targettype, "A", "targettype");
1394
1395 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1396 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1397 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1398 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1399 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1400 #if DEVELOPMENT || DEBUG
1401 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1402 #if defined(XNU_TARGET_OS_OSX)
1403 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1404 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1405 #endif /* defined(XNU_TARGET_OS_OSX) */
1406 #endif /* DEVELOPMENT || DEBUG */
1407
1408 //******************************************************************************
1409 // AOT
1410
1411 static int
1412 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1413 {
1414 if (NULL == gRootDomain) {
1415 return ENOENT;
1416 }
1417 if (NULL == gRootDomain->_aotMetrics) {
1418 IOPMAOTMetrics nullMetrics = {};
1419 return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1420 }
1421 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1422 }
1423
1424 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1425 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1426 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1427
1428
1429 static int
update_aotmode(uint32_t mode)1430 update_aotmode(uint32_t mode)
1431 {
1432 int result;
1433
1434 if (!gIOPMWorkLoop) {
1435 return ENOENT;
1436 }
1437 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1438 unsigned int oldCount;
1439
1440 if (mode && !gRootDomain->_aotMetrics) {
1441 gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1442 }
1443
1444 oldCount = gRootDomain->idleSleepPreventersCount();
1445 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1446 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1447 return 0;
1448 });
1449 return result;
1450 }
1451
1452 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1453 sysctl_aotmodebits
1454 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1455 {
1456 int error, changed;
1457 uint32_t new_value;
1458
1459 if (NULL == gRootDomain) {
1460 return ENOENT;
1461 }
1462 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1463 if (changed && gIOPMWorkLoop) {
1464 error = update_aotmode(new_value);
1465 }
1466
1467 return error;
1468 }
1469
1470 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1471 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1472 NULL, 0, sysctl_aotmodebits, "I", "");
1473
1474 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1475 sysctl_aotmode
1476 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1477 {
1478 int error, changed;
1479 uint32_t new_value;
1480
1481 if (NULL == gRootDomain) {
1482 return ENOENT;
1483 }
1484 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1485 if (changed && gIOPMWorkLoop) {
1486 if (new_value) {
1487 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1488 }
1489 error = update_aotmode(new_value);
1490 }
1491
1492 return error;
1493 }
1494
1495 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1496 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1497 NULL, 0, sysctl_aotmode, "I", "");
1498
1499 //******************************************************************************
1500
1501 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1502 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1503 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1504 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1505 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1506 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1507 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1508 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1513
1514 //******************************************************************************
1515 // start
1516 //
1517 //******************************************************************************
1518
1519 #define kRootDomainSettingsCount 20
1520 #define kRootDomainNoPublishSettingsCount 4
1521
1522 bool
start(IOService * nub)1523 IOPMrootDomain::start( IOService * nub )
1524 {
1525 OSSharedPtr<OSIterator> psIterator;
1526 OSSharedPtr<OSDictionary> tmpDict;
1527
1528 super::start(nub);
1529
1530 gRootDomain = this;
1531 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1532 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1533 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1534 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1535 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1536 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1537 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1538 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1539 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1540 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1541 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1542 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1543
1544 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1545 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1546 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1547 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1548 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1549
1550 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1551 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1552 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1553
1554 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1555 {
1556 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1557 gIOPMSettingAutoWakeSecondsKey,
1558 gIOPMSettingAutoPowerSecondsKey,
1559 gIOPMSettingAutoWakeCalendarKey,
1560 gIOPMSettingAutoPowerCalendarKey,
1561 gIOPMSettingDebugWakeRelativeKey,
1562 gIOPMSettingDebugPowerRelativeKey,
1563 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1564 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1565 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1566 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1567 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1568 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1569 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1570 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1571 OSSymbol::withCString(kIOPMStateConsoleShutdown),
1572 OSSymbol::withCString(kIOPMSettingProModeControl),
1573 OSSymbol::withCString(kIOPMSettingProModeDefer),
1574 gIOPMSettingSilentRunningKey,
1575 gIOPMSettingLowLatencyAudioModeKey,
1576 };
1577
1578 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1579 {
1580 OSSymbol::withCString(kIOPMSettingProModeControl),
1581 OSSymbol::withCString(kIOPMSettingProModeDefer),
1582 gIOPMSettingSilentRunningKey,
1583 gIOPMSettingLowLatencyAudioModeKey,
1584 };
1585
1586 #if DEVELOPMENT || DEBUG
1587 #if defined(XNU_TARGET_OS_OSX)
1588 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1589 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1590 #endif /* defined(XNU_TARGET_OS_OSX) */
1591 #endif /* DEVELOPMENT || DEBUG */
1592
1593 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1594 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1595 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1596 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1597 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1598 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1599
1600 // read noidle setting from Device Tree
1601 if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1602 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1603 }
1604
1605 queue_init(&aggressivesQueue);
1606 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1607 aggressivesData = OSData::withCapacity(
1608 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1609
1610 featuresDictLock = IOLockAlloc();
1611 settingsCtrlLock = IOLockAlloc();
1612 wakeEventLock = IOLockAlloc();
1613 gHaltLogLock = IOLockAlloc();
1614 setPMRootDomain(this);
1615
1616 extraSleepTimer = thread_call_allocate(
1617 idleSleepTimerExpired,
1618 (thread_call_param_t) this);
1619
1620 powerButtonDown = thread_call_allocate(
1621 powerButtonDownCallout,
1622 (thread_call_param_t) this);
1623
1624 powerButtonUp = thread_call_allocate(
1625 powerButtonUpCallout,
1626 (thread_call_param_t) this);
1627
1628 diskSyncCalloutEntry = thread_call_allocate(
1629 &disk_sync_callout,
1630 (thread_call_param_t) this);
1631 updateConsoleUsersEntry = thread_call_allocate(
1632 &updateConsoleUsersCallout,
1633 (thread_call_param_t) this);
1634
1635 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1636 fullWakeThreadCall = thread_call_allocate_with_options(
1637 OSMemberFunctionCast(thread_call_func_t, this,
1638 &IOPMrootDomain::fullWakeDelayedWork),
1639 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1640 THREAD_CALL_OPTIONS_ONCE);
1641 #endif
1642
1643 setProperty(kIOSleepSupportedKey, true);
1644
1645 bzero(&gPMStats, sizeof(gPMStats));
1646
1647 pmTracer = PMTraceWorker::tracer(this);
1648
1649 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1650
1651 userDisabledAllSleep = false;
1652 systemBooting = true;
1653 idleSleepEnabled = false;
1654 sleepSlider = 0;
1655 idleSleepTimerPending = false;
1656 wrangler = NULL;
1657 clamshellClosed = false;
1658 clamshellExists = false;
1659 #if DISPLAY_WRANGLER_PRESENT
1660 clamshellDisabled = true;
1661 #else
1662 clamshellDisabled = false;
1663 #endif
1664 clamshellIgnoreClose = false;
1665 acAdaptorConnected = true;
1666 clamshellSleepDisableMask = 0;
1667 gWakeReasonString[0] = '\0';
1668
1669 // Initialize to user active.
1670 // Will never transition to user inactive w/o wrangler.
1671 fullWakeReason = kFullWakeReasonLocalUser;
1672 userIsActive = userWasActive = true;
1673 clock_get_uptime(&gUserActiveAbsTime);
1674 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1675
1676 // Set the default system capabilities at boot.
1677 _currentCapability = kIOPMSystemCapabilityCPU |
1678 kIOPMSystemCapabilityGraphics |
1679 kIOPMSystemCapabilityAudio |
1680 kIOPMSystemCapabilityNetwork;
1681
1682 _pendingCapability = _currentCapability;
1683 _desiredCapability = _currentCapability;
1684 _highestCapability = _currentCapability;
1685 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1686
1687 queuedSleepWakeUUIDString = NULL;
1688 initializeBootSessionUUID();
1689 pmStatsAppResponses = OSArray::withCapacity(5);
1690 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
1691 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
1692 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1693 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1694 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1695 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1696 assertOnWakeSecs = -1;// Invalid value to prevent updates
1697
1698 pmStatsLock = IOLockAlloc();
1699 idxPMCPUClamshell = kCPUUnknownIndex;
1700 idxPMCPULimitedPower = kCPUUnknownIndex;
1701
1702 tmpDict = OSDictionary::withCapacity(1);
1703 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1704
1705 // Set a default "SystemPowerProfileOverrideDict" for platform
1706 // drivers without any overrides.
1707 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1708 tmpDict = OSDictionary::withCapacity(1);
1709 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1710 }
1711
1712 settingsCallbacks = OSDictionary::withCapacity(1);
1713
1714 // Create a list of the valid PM settings that we'll relay to
1715 // interested clients in setProperties() => setPMSetting()
1716 allowedPMSettings = OSArray::withObjects(
1717 (const OSObject **)settingsArr,
1718 kRootDomainSettingsCount,
1719 0);
1720
1721 // List of PM settings that should not automatically publish itself
1722 // as a feature when registered by a listener.
1723 noPublishPMSettings = OSArray::withObjects(
1724 (const OSObject **)noPublishSettingsArr,
1725 kRootDomainNoPublishSettingsCount,
1726 0);
1727
1728 fPMSettingsDict = OSDictionary::withCapacity(5);
1729 preventIdleSleepList = OSSet::withCapacity(8);
1730 preventSystemSleepList = OSSet::withCapacity(2);
1731
1732 PMinit(); // creates gIOPMWorkLoop
1733 gIOPMWorkLoop = getIOPMWorkloop();
1734
1735 // Create IOPMPowerStateQueue used to queue external power
1736 // events, and to handle those events on the PM work loop.
1737 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1738 this, OSMemberFunctionCast(IOEventSource::Action, this,
1739 &IOPMrootDomain::dispatchPowerEvent));
1740 gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1741
1742 _aotMode = 0;
1743 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1744 OSMemberFunctionCast(IOTimerEventSource::Action,
1745 this, &IOPMrootDomain::aotEvaluate));
1746 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1747
1748 // Avoid publishing service early so gIOPMWorkLoop is
1749 // guaranteed to be initialized by rootDomain.
1750 publishPMRootDomain();
1751
1752 // create our power parent
1753 gPatriarch = new IORootParent;
1754 gPatriarch->init();
1755 gPatriarch->attach(this);
1756 gPatriarch->start(this);
1757 gPatriarch->addPowerChild(this);
1758
1759 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1760 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1761
1762 // install power change handler
1763 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1764
1765 #if DISPLAY_WRANGLER_PRESENT
1766 wranglerIdleSettings = OSDictionary::withCapacity(1);
1767 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1768
1769 if (wranglerIdleSettings && wranglerIdlePeriod) {
1770 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1771 wranglerIdlePeriod.get());
1772 }
1773
1774 #endif /* DISPLAY_WRANGLER_PRESENT */
1775
1776 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2);
1777 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState");
1778 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1779 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32);
1780 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1781
1782 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1783 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1784 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1785 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1786 }
1787
1788 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1789 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1790
1791 // IOBacklightDisplay can take a long time to load at boot, or it may
1792 // not load at all if you're booting with clamshell closed. We publish
1793 // 'DisplayDims' here redundantly to get it published early and at all.
1794 OSSharedPtr<OSDictionary> matching;
1795 matching = serviceMatching("IOPMPowerSource");
1796 psIterator = getMatchingServices(matching.get());
1797
1798 if (psIterator && psIterator->getNextObject()) {
1799 // There's at least one battery on the system, so we publish
1800 // 'DisplayDims' support for the LCD.
1801 publishFeature("DisplayDims");
1802 }
1803
1804 // read swd_panic boot-arg
1805 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1806 gWillShutdownSysctlRegistered = true;
1807
1808 #if HIBERNATION
1809 #if defined(__arm64__)
1810 #endif /* defined(__arm64__) */
1811 IOHibernateSystemInit(this);
1812 #endif
1813
1814 registerService(); // let clients find us
1815
1816 return true;
1817 }
1818
1819 //******************************************************************************
1820 // setProperties
1821 //
1822 // Receive a setProperty call
1823 // The "System Boot" property means the system is completely booted.
1824 //******************************************************************************
1825
1826 IOReturn
setProperties(OSObject * props_obj)1827 IOPMrootDomain::setProperties( OSObject * props_obj )
1828 {
1829 IOReturn return_value = kIOReturnSuccess;
1830 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1831 OSBoolean *b = NULL;
1832 OSNumber *n = NULL;
1833 const OSSymbol *key = NULL;
1834 OSObject *obj = NULL;
1835 OSSharedPtr<OSCollectionIterator> iter;
1836
1837 if (!dict) {
1838 return kIOReturnBadArgument;
1839 }
1840
1841 bool clientEntitled = false;
1842 {
1843 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1844 clientEntitled = (obj == kOSBooleanTrue);
1845 }
1846
1847 if (!clientEntitled) {
1848 const char * errorSuffix = NULL;
1849
1850 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1851 // That API can set 6 possible keys that are checked below.
1852 if ((dict->getCount() == 1) &&
1853 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1854 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1855 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1856 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1857 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1858 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1859 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1860 if (return_value != kIOReturnSuccess) {
1861 errorSuffix = "privileged";
1862 }
1863 } else {
1864 return_value = kIOReturnNotPermitted;
1865 errorSuffix = "entitled";
1866 }
1867
1868 if (return_value != kIOReturnSuccess) {
1869 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1870 DLOG("%s failed, process %s is not %s\n", __func__,
1871 procName ? procName->getCStringNoCopy() : "", errorSuffix);
1872 return return_value;
1873 }
1874 }
1875
1876 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries");
1877 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete");
1878 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown");
1879 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt");
1880 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled");
1881 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds");
1882 OSSharedPtr<const OSSymbol> idle_milliseconds_string = OSSymbol::withCString("System Idle Milliseconds");
1883 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled");
1884 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1885 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1886 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1887 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1888 #if DEBUG || DEVELOPMENT
1889 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose");
1890 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen");
1891 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach");
1892 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach");
1893 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet");
1894 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1895 #endif
1896
1897 #if HIBERNATION
1898 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey);
1899 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey);
1900 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1901 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1902 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1903 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1904 #endif
1905
1906 iter = OSCollectionIterator::withCollection(dict);
1907 if (!iter) {
1908 return_value = kIOReturnNoMemory;
1909 goto exit;
1910 }
1911
1912 while ((key = (const OSSymbol *) iter->getNextObject()) &&
1913 (obj = dict->getObject(key))) {
1914 if (key->isEqualTo(publish_simulated_battery_string.get())) {
1915 if (OSDynamicCast(OSBoolean, obj)) {
1916 publishResource(key, kOSBooleanTrue);
1917 }
1918 } else if (key->isEqualTo(idle_seconds_string.get())) {
1919 if ((n = OSDynamicCast(OSNumber, obj))) {
1920 setProperty(key, n);
1921 idleMilliSeconds = n->unsigned32BitValue() * 1000;
1922 }
1923 } else if (key->isEqualTo(idle_milliseconds_string.get())) {
1924 if ((n = OSDynamicCast(OSNumber, obj))) {
1925 setProperty(key, n);
1926 idleMilliSeconds = n->unsigned32BitValue();
1927 }
1928 } else if (key->isEqualTo(boot_complete_string.get())) {
1929 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1930 } else if (key->isEqualTo(sys_shutdown_string.get())) {
1931 if ((b = OSDynamicCast(OSBoolean, obj))) {
1932 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1933 }
1934 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1935 setProperty(key, obj);
1936 }
1937 #if HIBERNATION
1938 else if (key->isEqualTo(hibernatemode_string.get()) ||
1939 key->isEqualTo(hibernatefilemin_string.get()) ||
1940 key->isEqualTo(hibernatefilemax_string.get()) ||
1941 key->isEqualTo(hibernatefreeratio_string.get()) ||
1942 key->isEqualTo(hibernatefreetime_string.get())) {
1943 if ((n = OSDynamicCast(OSNumber, obj))) {
1944 setProperty(key, n);
1945 }
1946 } else if (key->isEqualTo(hibernatefile_string.get())) {
1947 OSString * str = OSDynamicCast(OSString, obj);
1948 if (str) {
1949 setProperty(key, str);
1950 }
1951 }
1952 #endif
1953 else if (key->isEqualTo(sleepdisabled_string.get())) {
1954 if ((b = OSDynamicCast(OSBoolean, obj))) {
1955 setProperty(key, b);
1956 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1957 }
1958 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1959 obj->retain();
1960 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1961 } else if (key->isEqualTo(loginwindow_progress_string.get())) {
1962 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1963 uint32_t data = n->unsigned32BitValue();
1964 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1965 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1966 }
1967 } else if (key->isEqualTo(coredisplay_progress_string.get())) {
1968 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1969 uint32_t data = n->unsigned32BitValue();
1970 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1971 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1972 }
1973 } else if (key->isEqualTo(coregraphics_progress_string.get())) {
1974 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1975 uint32_t data = n->unsigned32BitValue();
1976 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1977 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1978 }
1979 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1980 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1981 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1982 key->isEqualTo(stall_halt_string.get())) {
1983 if ((b = OSDynamicCast(OSBoolean, obj))) {
1984 setProperty(key, b);
1985 }
1986 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1987 key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1988 key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1989 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1990 if ((n = OSDynamicCast(OSNumber, obj))) {
1991 setProperty(key, n);
1992 }
1993 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1994 if (kOSBooleanTrue == obj) {
1995 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1996 } else {
1997 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1998 }
1999 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2000 }
2001 #if DEBUG || DEVELOPMENT
2002 else if (key->isEqualTo(clamshell_close_string.get())) {
2003 DLOG("SetProperties: setting clamshell close\n");
2004 UInt32 msg = kIOPMClamshellClosed;
2005 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2006 } else if (key->isEqualTo(clamshell_open_string.get())) {
2007 DLOG("SetProperties: setting clamshell open\n");
2008 UInt32 msg = kIOPMClamshellOpened;
2009 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2010 } else if (key->isEqualTo(ac_detach_string.get())) {
2011 DLOG("SetProperties: setting ac detach\n");
2012 UInt32 msg = kIOPMSetACAdaptorConnected;
2013 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2014 } else if (key->isEqualTo(ac_attach_string.get())) {
2015 DLOG("SetProperties: setting ac attach\n");
2016 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2017 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2018 } else if (key->isEqualTo(desktopmode_set_string.get())) {
2019 DLOG("SetProperties: setting desktopmode");
2020 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2021 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2022 } else if (key->isEqualTo(desktopmode_remove_string.get())) {
2023 DLOG("SetProperties: removing desktopmode\n");
2024 UInt32 msg = kIOPMSetDesktopMode;
2025 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2026 }
2027 #endif
2028 // Relay our allowed PM settings onto our registered PM clients
2029 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2030 return_value = setPMSetting(key, obj);
2031 if (kIOReturnSuccess != return_value) {
2032 break;
2033 }
2034 } else {
2035 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2036 }
2037 }
2038
2039 exit:
2040 return return_value;
2041 }
2042
2043 // MARK: -
2044 // MARK: Aggressiveness
2045
2046 //******************************************************************************
2047 // setAggressiveness
2048 //
2049 // Override IOService::setAggressiveness()
2050 //******************************************************************************
2051
2052 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2053 IOPMrootDomain::setAggressiveness(
2054 unsigned long type,
2055 unsigned long value )
2056 {
2057 return setAggressiveness( type, value, 0 );
2058 }
2059
2060 /*
2061 * Private setAggressiveness() with an internal options argument.
2062 */
2063 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2064 IOPMrootDomain::setAggressiveness(
2065 unsigned long type,
2066 unsigned long value,
2067 IOOptionBits options )
2068 {
2069 AggressivesRequest * entry;
2070 AggressivesRequest * request;
2071 bool found = false;
2072
2073 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2074 return kIOReturnBadArgument;
2075 }
2076
2077 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2078 DLOG("setAggressiveness(%x) %s = %u\n",
2079 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2080 } else {
2081 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2082 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2083 }
2084
2085 request = IOMallocType(AggressivesRequest);
2086 request->options = options;
2087 request->dataType = kAggressivesRequestTypeRecord;
2088 request->data.record.type = (uint32_t) type;
2089 request->data.record.value = (uint32_t) value;
2090
2091 AGGRESSIVES_LOCK();
2092
2093 // Update disk quick spindown flag used by getAggressiveness().
2094 // Never merge requests with quick spindown flags set.
2095
2096 if (options & kAggressivesOptionQuickSpindownEnable) {
2097 gAggressivesState |= kAggressivesStateQuickSpindown;
2098 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2099 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2100 } else {
2101 // Coalesce requests with identical aggressives types.
2102 // Deal with callers that calls us too "aggressively".
2103
2104 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2105 {
2106 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2107 (entry->data.record.type == type) &&
2108 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2109 entry->data.record.value = (uint32_t) value;
2110 found = true;
2111 break;
2112 }
2113 }
2114 }
2115
2116 if (!found) {
2117 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2118 }
2119
2120 AGGRESSIVES_UNLOCK();
2121
2122 if (found) {
2123 IOFreeType(request, AggressivesRequest);
2124 }
2125
2126 if (options & kAggressivesOptionSynchronous) {
2127 handleAggressivesRequests(); // not truly synchronous
2128 } else {
2129 thread_call_enter(aggressivesThreadCall);
2130 }
2131
2132 return kIOReturnSuccess;
2133 }
2134
2135 //******************************************************************************
2136 // getAggressiveness
2137 //
2138 // Override IOService::setAggressiveness()
2139 // Fetch the aggressiveness factor with the given type.
2140 //******************************************************************************
2141
2142 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2143 IOPMrootDomain::getAggressiveness(
2144 unsigned long type,
2145 unsigned long * outLevel )
2146 {
2147 uint32_t value = 0;
2148 int source = 0;
2149
2150 if (!outLevel || (type > UINT_MAX)) {
2151 return kIOReturnBadArgument;
2152 }
2153
2154 AGGRESSIVES_LOCK();
2155
2156 // Disk quick spindown in effect, report value = 1
2157
2158 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2159 (type == kPMMinutesToSpinDown)) {
2160 value = kAggressivesMinValue;
2161 source = 1;
2162 }
2163
2164 // Consult the pending request queue.
2165
2166 if (!source) {
2167 AggressivesRequest * entry;
2168
2169 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2170 {
2171 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2172 (entry->data.record.type == type) &&
2173 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2174 value = entry->data.record.value;
2175 source = 2;
2176 break;
2177 }
2178 }
2179 }
2180
2181 // Consult the backend records.
2182
2183 if (!source && aggressivesData) {
2184 AggressivesRecord * record;
2185 int i, count;
2186
2187 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2188 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2189
2190 for (i = 0; i < count; i++, record++) {
2191 if (record->type == type) {
2192 value = record->value;
2193 source = 3;
2194 break;
2195 }
2196 }
2197 }
2198
2199 AGGRESSIVES_UNLOCK();
2200
2201 if (source) {
2202 *outLevel = (unsigned long) value;
2203 return kIOReturnSuccess;
2204 } else {
2205 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2206 *outLevel = 0; // default return = 0, driver may not check for error
2207 return kIOReturnInvalid;
2208 }
2209 }
2210
2211 //******************************************************************************
2212 // joinAggressiveness
2213 //
2214 // Request from IOService to join future aggressiveness broadcasts.
2215 //******************************************************************************
2216
2217 IOReturn
joinAggressiveness(IOService * service)2218 IOPMrootDomain::joinAggressiveness(
2219 IOService * service )
2220 {
2221 AggressivesRequest * request;
2222
2223 if (!service || (service == this)) {
2224 return kIOReturnBadArgument;
2225 }
2226
2227 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2228
2229 request = IOMallocType(AggressivesRequest);
2230 request->dataType = kAggressivesRequestTypeService;
2231 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2232
2233 AGGRESSIVES_LOCK();
2234 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2235 AGGRESSIVES_UNLOCK();
2236
2237 thread_call_enter(aggressivesThreadCall);
2238
2239 return kIOReturnSuccess;
2240 }
2241
2242 //******************************************************************************
2243 // handleAggressivesRequests
2244 //
2245 // Backend thread processes all incoming aggressiveness requests in the queue.
2246 //******************************************************************************
2247
2248 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2249 handleAggressivesFunction(
2250 thread_call_param_t param1,
2251 thread_call_param_t param2 )
2252 {
2253 if (param1) {
2254 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2255 }
2256 }
2257
2258 void
handleAggressivesRequests(void)2259 IOPMrootDomain::handleAggressivesRequests( void )
2260 {
2261 AggressivesRecord * start;
2262 AggressivesRecord * record;
2263 AggressivesRequest * request;
2264 queue_head_t joinedQueue;
2265 int i, count;
2266 bool broadcast;
2267 bool found;
2268 bool pingSelf = false;
2269
2270 AGGRESSIVES_LOCK();
2271
2272 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2273 queue_empty(&aggressivesQueue)) {
2274 goto unlock_done;
2275 }
2276
2277 gAggressivesState |= kAggressivesStateBusy;
2278 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2279 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2280
2281 do{
2282 broadcast = false;
2283 queue_init(&joinedQueue);
2284
2285 do{
2286 // Remove request from the incoming queue in FIFO order.
2287 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2288 switch (request->dataType) {
2289 case kAggressivesRequestTypeRecord:
2290 // Update existing record if found.
2291 found = false;
2292 for (i = 0, record = start; i < count; i++, record++) {
2293 if (record->type == request->data.record.type) {
2294 found = true;
2295
2296 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2297 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2298 broadcast = true;
2299 record->flags |= (kAggressivesRecordFlagMinValue |
2300 kAggressivesRecordFlagModified);
2301 DLOG("disk spindown accelerated, was %u min\n",
2302 record->value);
2303 }
2304 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2305 if (record->flags & kAggressivesRecordFlagMinValue) {
2306 broadcast = true;
2307 record->flags |= kAggressivesRecordFlagModified;
2308 record->flags &= ~kAggressivesRecordFlagMinValue;
2309 DLOG("disk spindown restored to %u min\n",
2310 record->value);
2311 }
2312 } else if (record->value != request->data.record.value) {
2313 record->value = request->data.record.value;
2314 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2315 broadcast = true;
2316 record->flags |= kAggressivesRecordFlagModified;
2317 }
2318 }
2319 break;
2320 }
2321 }
2322
2323 // No matching record, append a new record.
2324 if (!found &&
2325 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2326 AggressivesRecord newRecord;
2327
2328 newRecord.flags = kAggressivesRecordFlagModified;
2329 newRecord.type = request->data.record.type;
2330 newRecord.value = request->data.record.value;
2331 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2332 newRecord.flags |= kAggressivesRecordFlagMinValue;
2333 DLOG("disk spindown accelerated\n");
2334 }
2335
2336 aggressivesData->appendValue(newRecord);
2337
2338 // OSData may have switched to another (larger) buffer.
2339 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2340 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2341 broadcast = true;
2342 }
2343
2344 // Finished processing the request, release it.
2345 IOFreeType(request, AggressivesRequest);
2346 break;
2347
2348 case kAggressivesRequestTypeService:
2349 // synchronizeAggressives() will free request.
2350 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2351 break;
2352
2353 default:
2354 panic("bad aggressives request type %x", request->dataType);
2355 break;
2356 }
2357 } while (!queue_empty(&aggressivesQueue));
2358
2359 // Release the lock to perform work, with busy flag set.
2360 if (!queue_empty(&joinedQueue) || broadcast) {
2361 AGGRESSIVES_UNLOCK();
2362 if (!queue_empty(&joinedQueue)) {
2363 synchronizeAggressives(&joinedQueue, start, count);
2364 }
2365 if (broadcast) {
2366 broadcastAggressives(start, count);
2367 }
2368 AGGRESSIVES_LOCK();
2369 }
2370
2371 // Remove the modified flag from all records.
2372 for (i = 0, record = start; i < count; i++, record++) {
2373 if ((record->flags & kAggressivesRecordFlagModified) &&
2374 ((record->type == kPMMinutesToDim) ||
2375 (record->type == kPMMinutesToSleep))) {
2376 pingSelf = true;
2377 }
2378
2379 record->flags &= ~kAggressivesRecordFlagModified;
2380 }
2381
2382 // Check the incoming queue again since new entries may have been
2383 // added while lock was released above.
2384 } while (!queue_empty(&aggressivesQueue));
2385
2386 gAggressivesState &= ~kAggressivesStateBusy;
2387
2388 unlock_done:
2389 AGGRESSIVES_UNLOCK();
2390
2391 // Root domain is interested in system and display sleep slider changes.
2392 // Submit a power event to handle those changes on the PM work loop.
2393
2394 if (pingSelf && pmPowerStateQueue) {
2395 pmPowerStateQueue->submitPowerEvent(
2396 kPowerEventPolicyStimulus,
2397 (void *) kStimulusAggressivenessChanged );
2398 }
2399 }
2400
2401 //******************************************************************************
2402 // synchronizeAggressives
2403 //
2404 // Push all known aggressiveness records to one or more IOService.
2405 //******************************************************************************
2406
2407 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2408 IOPMrootDomain::synchronizeAggressives(
2409 queue_head_t * joinedQueue,
2410 const AggressivesRecord * array,
2411 int count )
2412 {
2413 OSSharedPtr<IOService> service;
2414 AggressivesRequest * request;
2415 const AggressivesRecord * record;
2416 IOPMDriverCallEntry callEntry;
2417 uint32_t value;
2418 int i;
2419
2420 while (!queue_empty(joinedQueue)) {
2421 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2422 if (request->dataType == kAggressivesRequestTypeService) {
2423 // retained by joinAggressiveness(), so take ownership
2424 service = os::move(request->data.service);
2425 } else {
2426 service.reset();
2427 }
2428
2429 IOFreeType(request, AggressivesRequest);
2430 request = NULL;
2431
2432 if (service) {
2433 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2434 for (i = 0, record = array; i < count; i++, record++) {
2435 value = record->value;
2436 if (record->flags & kAggressivesRecordFlagMinValue) {
2437 value = kAggressivesMinValue;
2438 }
2439
2440 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2441 record->type, value, service->getName());
2442 service->setAggressiveness(record->type, value);
2443 }
2444 service->deassertPMDriverCall(&callEntry);
2445 }
2446 }
2447 }
2448 }
2449
2450 //******************************************************************************
2451 // broadcastAggressives
2452 //
2453 // Traverse PM tree and call setAggressiveness() for records that have changed.
2454 //******************************************************************************
2455
2456 void
broadcastAggressives(const AggressivesRecord * array,int count)2457 IOPMrootDomain::broadcastAggressives(
2458 const AggressivesRecord * array,
2459 int count )
2460 {
2461 OSSharedPtr<IORegistryIterator> iter;
2462 IORegistryEntry *entry;
2463 OSSharedPtr<IORegistryEntry> child;
2464 IOPowerConnection *connect;
2465 IOService *service;
2466 const AggressivesRecord *record;
2467 IOPMDriverCallEntry callEntry;
2468 uint32_t value;
2469 int i;
2470
2471 iter = IORegistryIterator::iterateOver(
2472 this, gIOPowerPlane, kIORegistryIterateRecursively);
2473 if (iter) {
2474 do{
2475 // !! reset the iterator
2476 iter->reset();
2477 while ((entry = iter->getNextObject())) {
2478 connect = OSDynamicCast(IOPowerConnection, entry);
2479 if (!connect || !connect->getReadyFlag()) {
2480 continue;
2481 }
2482
2483 child = connect->copyChildEntry(gIOPowerPlane);
2484 if (child) {
2485 if ((service = OSDynamicCast(IOService, child.get()))) {
2486 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2487 for (i = 0, record = array; i < count; i++, record++) {
2488 if (record->flags & kAggressivesRecordFlagModified) {
2489 value = record->value;
2490 if (record->flags & kAggressivesRecordFlagMinValue) {
2491 value = kAggressivesMinValue;
2492 }
2493 _LOG("broadcastAggressives %x = %u to %s\n",
2494 record->type, value, service->getName());
2495 service->setAggressiveness(record->type, value);
2496 }
2497 }
2498 service->deassertPMDriverCall(&callEntry);
2499 }
2500 }
2501 }
2502 }
2503 }while (!entry && !iter->isValid());
2504 }
2505 }
2506
2507 //*****************************************
2508 // stackshot on power button press
2509 // ***************************************
2510 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2511 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2512 {
2513 /* Power button pressed during wake
2514 * Take a stackshot
2515 */
2516 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2517 ((IOPMrootDomain *)us)->takeStackshot(false);
2518 }
2519
2520 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2521 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2522 {
2523 /* Power button released.
2524 * Delete any stackshot data
2525 */
2526 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2527 ((IOPMrootDomain *)us)->deleteStackshot();
2528 }
2529 //*************************************************************************
2530 //
2531
2532 // MARK: -
2533 // MARK: System Sleep
2534
2535 //******************************************************************************
2536 // startIdleSleepTimer
2537 //
2538 //******************************************************************************
2539
2540 void
startIdleSleepTimer(uint32_t inMilliSeconds)2541 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2542 {
2543 AbsoluteTime deadline;
2544
2545 ASSERT_GATED();
2546 if (gNoIdleFlag) {
2547 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2548 return;
2549 }
2550 if (inMilliSeconds) {
2551 if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2552 AbsoluteTime now;
2553 uint64_t nsec_since_wake;
2554 uint64_t msec_since_wake;
2555
2556 // Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2557 // after the most recent AP wake.
2558 clock_get_uptime(&now);
2559 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2560 absolutetime_to_nanoseconds(now, &nsec_since_wake);
2561 msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2562
2563 if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2564 uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2565
2566 // Ensure that our new idle timer is not less than inMilliSeconds,
2567 // as we should only be increasing the timer duration, not decreasing it
2568 if (newIdleTimer > inMilliSeconds) {
2569 DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2570 inMilliSeconds = newIdleTimer;
2571 }
2572 }
2573 }
2574 clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2575 thread_call_enter_delayed(extraSleepTimer, deadline);
2576 idleSleepTimerPending = true;
2577 } else {
2578 thread_call_enter(extraSleepTimer);
2579 }
2580 DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2581 }
2582
2583 //******************************************************************************
2584 // cancelIdleSleepTimer
2585 //
2586 //******************************************************************************
2587
2588 void
cancelIdleSleepTimer(void)2589 IOPMrootDomain::cancelIdleSleepTimer( void )
2590 {
2591 ASSERT_GATED();
2592 if (idleSleepTimerPending) {
2593 DLOG("idle timer cancelled\n");
2594 thread_call_cancel(extraSleepTimer);
2595 idleSleepTimerPending = false;
2596
2597 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2598 AbsoluteTime now;
2599 clock_usec_t microsecs;
2600 clock_get_uptime(&now);
2601 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2602 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
2603 if (assertOnWakeReport) {
2604 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2605 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2606 }
2607 }
2608 }
2609 }
2610
2611 //******************************************************************************
2612 // idleSleepTimerExpired
2613 //
2614 //******************************************************************************
2615
2616 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2617 idleSleepTimerExpired(
2618 thread_call_param_t us, thread_call_param_t )
2619 {
2620 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2621 }
2622
2623 //******************************************************************************
2624 // handleSleepTimerExpiration
2625 //
2626 // The time between the sleep idle timeout and the next longest one has elapsed.
2627 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2628 //******************************************************************************
2629
2630 void
handleSleepTimerExpiration(void)2631 IOPMrootDomain::handleSleepTimerExpiration( void )
2632 {
2633 if (!gIOPMWorkLoop->inGate()) {
2634 gIOPMWorkLoop->runAction(
2635 OSMemberFunctionCast(IOWorkLoop::Action, this,
2636 &IOPMrootDomain::handleSleepTimerExpiration),
2637 this);
2638 return;
2639 }
2640
2641 DLOG("sleep timer expired\n");
2642 ASSERT_GATED();
2643
2644 idleSleepTimerPending = false;
2645 setQuickSpinDownTimeout();
2646 adjustPowerState(true);
2647 }
2648
2649 //******************************************************************************
2650 // getTimeToIdleSleep
2651 //
2652 // Returns number of milliseconds left before going into idle sleep.
2653 // Caller has to make sure that idle sleep is allowed at the time of calling
2654 // this function
2655 //******************************************************************************
2656
2657 uint32_t
getTimeToIdleSleep(void)2658 IOPMrootDomain::getTimeToIdleSleep( void )
2659 {
2660 AbsoluteTime now, lastActivityTime;
2661 uint64_t nanos;
2662 uint32_t minutesSinceUserInactive = 0;
2663 uint32_t sleepDelay = 0;
2664
2665 if (!idleSleepEnabled) {
2666 return 0xffffffff;
2667 }
2668
2669 if (userActivityTime) {
2670 lastActivityTime = userActivityTime;
2671 } else {
2672 lastActivityTime = userBecameInactiveTime;
2673 }
2674
2675 // Ignore any lastActivityTime that predates the last system wake.
2676 // The goal is to avoid a sudden idle sleep right after a dark wake
2677 // due to sleepDelay=0 computed below. The alternative 60s minimum
2678 // timeout should be large enough to allow dark wake to complete,
2679 // at which point the idle timer will be promptly cancelled.
2680 clock_get_uptime(&now);
2681 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2682 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2683 SUB_ABSOLUTETIME(&now, &lastActivityTime);
2684 absolutetime_to_nanoseconds(now, &nanos);
2685 minutesSinceUserInactive = nanos / (60000000000ULL);
2686
2687 if (minutesSinceUserInactive >= sleepSlider) {
2688 sleepDelay = 0;
2689 } else {
2690 sleepDelay = sleepSlider - minutesSinceUserInactive;
2691 }
2692 } else {
2693 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2694 lastActivityTime, now, gIOLastWakeAbsTime);
2695 sleepDelay = sleepSlider;
2696 }
2697
2698 DLOG("user inactive %u min, time to idle sleep %u min\n",
2699 minutesSinceUserInactive, sleepDelay);
2700
2701 return sleepDelay * 60 * 1000;
2702 }
2703
2704 //******************************************************************************
2705 // setQuickSpinDownTimeout
2706 //
2707 //******************************************************************************
2708
2709 void
setQuickSpinDownTimeout(void)2710 IOPMrootDomain::setQuickSpinDownTimeout( void )
2711 {
2712 ASSERT_GATED();
2713 setAggressiveness(
2714 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2715 }
2716
2717 //******************************************************************************
2718 // restoreUserSpinDownTimeout
2719 //
2720 //******************************************************************************
2721
2722 void
restoreUserSpinDownTimeout(void)2723 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2724 {
2725 ASSERT_GATED();
2726 setAggressiveness(
2727 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2728 }
2729
2730 //******************************************************************************
2731 // sleepSystem
2732 //
2733 //******************************************************************************
2734
2735 /* public */
2736 IOReturn
sleepSystem(void)2737 IOPMrootDomain::sleepSystem( void )
2738 {
2739 return sleepSystemOptions(NULL);
2740 }
2741
2742 /* private */
2743 IOReturn
sleepSystemOptions(OSDictionary * options)2744 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2745 {
2746 OSObject *obj = NULL;
2747 OSString *reason = NULL;
2748 /* sleepSystem is a public function, and may be called by any kernel driver.
2749 * And that's bad - drivers should sleep the system by calling
2750 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2751 *
2752 * Note that user space app calls to IOPMSleepSystem() will also travel
2753 * this code path and thus be correctly identified as software sleeps.
2754 */
2755
2756 if (options && options->getObject("OSSwitch")) {
2757 // Log specific sleep cause for OS Switch hibernation
2758 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2759 }
2760
2761 if (options && (obj = options->getObject("Sleep Reason"))) {
2762 reason = OSDynamicCast(OSString, obj);
2763 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2764 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2765 }
2766 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2767 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2768 }
2769 }
2770
2771 return privateSleepSystem( kIOPMSleepReasonSoftware);
2772 }
2773
2774 /* private */
2775 IOReturn
privateSleepSystem(uint32_t sleepReason)2776 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2777 {
2778 /* Called from both gated and non-gated context */
2779
2780 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2781 return kIOReturnNotPermitted;
2782 }
2783
2784 pmPowerStateQueue->submitPowerEvent(
2785 kPowerEventPolicyStimulus,
2786 (void *) kStimulusDemandSystemSleep,
2787 sleepReason);
2788
2789 return kIOReturnSuccess;
2790 }
2791
2792 //******************************************************************************
2793 // powerChangeDone
2794 //
2795 // This overrides powerChangeDone in IOService.
2796 //******************************************************************************
2797 void
powerChangeDone(unsigned long previousPowerState)2798 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2799 {
2800 #if !__i386__ && !__x86_64__
2801 uint64_t timeSinceReset = 0;
2802 #endif
2803 uint64_t now;
2804 unsigned long newState;
2805 clock_sec_t secs;
2806 clock_usec_t microsecs;
2807 uint32_t lastDebugWakeSeconds;
2808 clock_sec_t adjWakeTime;
2809 IOPMCalendarStruct nowCalendar;
2810
2811 ASSERT_GATED();
2812 newState = getPowerState();
2813 DLOG("PowerChangeDone: %s->%s\n",
2814 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2815
2816 if (previousPowerState == newState) {
2817 return;
2818 }
2819
2820 notifierThread = current_thread();
2821 switch (getPowerState()) {
2822 case SLEEP_STATE: {
2823 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2824 secs = 0;
2825 microsecs = 0;
2826 PEGetUTCTimeOfDay(&secs, µsecs);
2827
2828 adjWakeTime = 0;
2829 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2830 IOLog("use _calendarWakeAlarmUTC\n");
2831 adjWakeTime = _calendarWakeAlarmUTC;
2832 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2833 IOLog("accelerate _aotWakeTime for exit\n");
2834 adjWakeTime = secs;
2835 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2836 IOLog("accelerate _aotWakeTime for assertion\n");
2837 adjWakeTime = secs;
2838 }
2839 if (adjWakeTime) {
2840 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2841 }
2842
2843 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2844 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2845
2846 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2847 assert(kIOReturnSuccess == ret);
2848 }
2849 if (_aotLastWakeTime) {
2850 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2851 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2852 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2853 gWakeReasonString,
2854 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2855 }
2856 }
2857 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2858 if (_aotTimerScheduled) {
2859 _aotTimerES->cancelTimeout();
2860 _aotTimerScheduled = false;
2861 }
2862 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2863
2864 // re-enable this timer for next sleep
2865 cancelIdleSleepTimer();
2866
2867 if (clamshellExists) {
2868 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2869 if (gClamshellFlags & kClamshell_WAR_58009435) {
2870 // Disable clamshell sleep until system has completed full wake.
2871 // This prevents a system sleep request (due to a clamshell close)
2872 // from being queued until the end of system full wake - even if
2873 // other clamshell disable bits outside of our control is wrong.
2874 setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2875 }
2876 #endif
2877
2878 // Log the last known clamshell state before system sleep
2879 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2880 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2881 desktopMode, acAdaptorConnected);
2882 }
2883
2884 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now);
2885 logtime(secs);
2886 gIOLastSleepTime.tv_sec = secs;
2887 gIOLastSleepTime.tv_usec = microsecs;
2888 if (!_aotLastWakeTime) {
2889 gIOLastUserSleepTime = gIOLastSleepTime;
2890 }
2891
2892 gIOLastWakeTime.tv_sec = 0;
2893 gIOLastWakeTime.tv_usec = 0;
2894 gIOLastSleepAbsTime = now;
2895
2896 if (wake2DarkwakeDelay && sleepDelaysReport) {
2897 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2898 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2899
2900 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2901 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs);
2902 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs);
2903 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2904 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2905
2906 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2907 wake2DarkwakeDelay = 0;
2908 }
2909 #if HIBERNATION
2910 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2911 #if (DEVELOPMENT || DEBUG)
2912 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2913 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2914 "System State",
2915 gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2916 );
2917 #endif /* DEVELOPMENT || DEBUG */
2918 IOHibernateSystemHasSlept();
2919
2920 evaluateSystemSleepPolicyFinal();
2921 #else
2922 LOG("System Sleep\n");
2923 #if (DEVELOPMENT || DEBUG)
2924 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2925 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2926 "System State", "Enter Sleep");
2927 #endif /* DEVELOPMENT || DEBUG */
2928 #endif
2929 if (thermalWarningState) {
2930 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2931 if (event) {
2932 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2933 }
2934 }
2935 assertOnWakeSecs = 0;
2936 lowBatteryCondition = false;
2937 thermalEmergencyState = false;
2938
2939 #if DEVELOPMENT || DEBUG
2940 extern int g_should_log_clock_adjustments;
2941 if (g_should_log_clock_adjustments) {
2942 clock_sec_t secs = 0;
2943 clock_usec_t microsecs = 0;
2944 uint64_t now_b = mach_absolute_time();
2945
2946 secs = 0;
2947 microsecs = 0;
2948 PEGetUTCTimeOfDay(&secs, µsecs);
2949
2950 uint64_t now_a = mach_absolute_time();
2951 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2952 __func__, (unsigned long)secs, microsecs, now_b, now_a);
2953 }
2954 #endif
2955
2956 getPlatform()->sleepKernel();
2957
2958 // The CPU(s) are off at this point,
2959 // Code will resume execution here upon wake.
2960
2961 clock_get_uptime(&gIOLastWakeAbsTime);
2962 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2963 #if DEVELOPMENT || DEBUG
2964 record_system_event(SYSTEM_EVENT_TYPE_INFO,
2965 SYSTEM_EVENT_SUBSYSTEM_PMRD,
2966 "System State", "Waking Up"
2967 );
2968 #endif /* DEVELOPMENT || DEBUG */
2969 _highestCapability = 0;
2970
2971 #if HIBERNATION
2972 IOHibernateSystemWake();
2973 #endif
2974
2975 // sleep transition complete
2976 gSleepOrShutdownPending = 0;
2977
2978 // trip the reset of the calendar clock
2979 clock_wakeup_calendar();
2980 clock_get_calendar_microtime(&secs, µsecs);
2981 gIOLastWakeTime.tv_sec = secs;
2982 gIOLastWakeTime.tv_usec = microsecs;
2983
2984 // aot
2985 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2986 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2987 secs = 0;
2988 microsecs = 0;
2989 PEGetUTCTimeOfDay(&secs, µsecs);
2990 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2991 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2992 _aotMetrics->sleepCount++;
2993 _aotLastWakeTime = gIOLastWakeAbsTime;
2994 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
2995 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
2996 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
2997 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
2998 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
2999 }
3000
3001 if (_aotTestTime) {
3002 if (_aotWakeTimeUTC <= secs) {
3003 _aotTestTime = _aotTestTime + _aotTestInterval;
3004 }
3005 setWakeTime(_aotTestTime);
3006 }
3007 }
3008
3009 #if HIBERNATION
3010 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3011 #endif
3012
3013 lastSleepReason = 0;
3014
3015 lastDebugWakeSeconds = _debugWakeSeconds;
3016 _debugWakeSeconds = 0;
3017 _scheduledAlarmMask = 0;
3018 _nextScheduledAlarmType = NULL;
3019
3020 darkWakeExit = false;
3021 darkWakePowerClamped = false;
3022 darkWakePostTickle = false;
3023 darkWakeHibernateError = false;
3024 darkWakeToSleepASAP = true;
3025 darkWakeLogClamp = true;
3026 sleepTimerMaintenance = false;
3027 sleepToStandby = false;
3028 wranglerTickled = false;
3029 userWasActive = false;
3030 isRTCAlarmWake = false;
3031 clamshellIgnoreClose = false;
3032 fullWakeReason = kFullWakeReasonNone;
3033
3034 #if defined(__i386__) || defined(__x86_64__)
3035 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3036
3037 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey);
3038 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3039 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3040 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3041
3042 if (wakeReason && (wakeReason->getLength() >= 2) &&
3043 gWakeReasonString[0] == '\0') {
3044 WAKEEVENT_LOCK();
3045 // Until the platform driver can claim its wake reasons
3046 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3047 sizeof(gWakeReasonString));
3048 if (!gWakeReasonSysctlRegistered) {
3049 gWakeReasonSysctlRegistered = true;
3050 }
3051 WAKEEVENT_UNLOCK();
3052 }
3053
3054 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3055 lowBatteryCondition = true;
3056 darkWakeMaintenance = true;
3057 } else {
3058 #if HIBERNATION
3059 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3060 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get());
3061 if (hibernateAborted || ((hibOptions &&
3062 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3063 // Hibernate aborted, or EFI brought up graphics
3064 darkWakeExit = true;
3065 if (hibernateAborted) {
3066 DLOG("Hibernation aborted\n");
3067 } else {
3068 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3069 }
3070 } else
3071 #endif
3072 if (wakeType && (
3073 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3074 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3075 // User wake or RTC alarm
3076 darkWakeExit = true;
3077 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3078 isRTCAlarmWake = true;
3079 }
3080 } else if (wakeType &&
3081 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3082 // SMC standby timer trumps SleepX
3083 darkWakeMaintenance = true;
3084 sleepTimerMaintenance = true;
3085 } else if ((lastDebugWakeSeconds != 0) &&
3086 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3087 // SleepX before maintenance
3088 darkWakeExit = true;
3089 } else if (wakeType &&
3090 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3091 darkWakeMaintenance = true;
3092 } else if (wakeType &&
3093 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3094 darkWakeMaintenance = true;
3095 darkWakeSleepService = true;
3096 #if HIBERNATION
3097 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3098 sleepToStandby = true;
3099 }
3100 #endif
3101 } else if (wakeType &&
3102 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3103 darkWakeMaintenance = true;
3104 darkWakeHibernateError = true;
3105 } else {
3106 // Unidentified wake source, resume to full wake if debug
3107 // alarm is pending.
3108
3109 if (lastDebugWakeSeconds &&
3110 (!wakeReason || wakeReason->isEqualTo(""))) {
3111 darkWakeExit = true;
3112 }
3113 }
3114 }
3115
3116 if (darkWakeExit) {
3117 darkWakeToSleepASAP = false;
3118 fullWakeReason = kFullWakeReasonLocalUser;
3119 reportUserInput();
3120 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3121 handleSetDisplayPowerOn(true);
3122 } else if (!darkWakeMaintenance) {
3123 // Early/late tickle for non-maintenance wake.
3124 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3125 darkWakePostTickle = true;
3126 }
3127 }
3128 #else /* !__i386__ && !__x86_64__ */
3129 timeSinceReset = ml_get_time_since_reset();
3130 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3131
3132 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3133 wranglerTickled = true;
3134 fullWakeReason = kFullWakeReasonLocalUser;
3135 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3136 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3137 isRTCAlarmWake = true;
3138 fullWakeReason = kFullWakeReasonLocalUser;
3139 requestUserActive(this, "RTC debug alarm");
3140 } else {
3141 #if HIBERNATION
3142 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3143 OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3144 if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3145 fullWakeReason = kFullWakeReasonLocalUser;
3146 requestUserActive(this, "hibernate user wake");
3147 }
3148 #endif
3149 }
3150
3151 // stay awake for at least 30 seconds
3152 startIdleSleepTimer(30 * 1000);
3153 #endif
3154 sleepCnt++;
3155
3156 thread_call_enter(updateConsoleUsersEntry);
3157
3158 // Skip AOT_STATE if we are waking up from an RTC timer.
3159 // This check needs to be done after the epoch change is processed
3160 // and before the changePowerStateWithTagToPriv() call below.
3161 WAKEEVENT_LOCK();
3162 aotShouldExit(false, false);
3163 WAKEEVENT_UNLOCK();
3164
3165 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3166 break;
3167 }
3168 #if !__i386__ && !__x86_64__
3169 case ON_STATE:
3170 case AOT_STATE:
3171 {
3172 DLOG("Force re-evaluating aggressiveness\n");
3173 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3174 pmPowerStateQueue->submitPowerEvent(
3175 kPowerEventPolicyStimulus,
3176 (void *) kStimulusNoIdleSleepPreventers );
3177
3178 // After changing to ON_STATE, invalidate any previously queued
3179 // request to change to a state less than ON_STATE. This isn't
3180 // necessary for AOT_STATE or if the device has only one running
3181 // state since the changePowerStateToPriv() issued at the tail
3182 // end of SLEEP_STATE case should take care of that.
3183 if (getPowerState() == ON_STATE) {
3184 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3185 }
3186 break;
3187 }
3188 #endif /* !__i386__ && !__x86_64__ */
3189 }
3190 notifierThread = NULL;
3191 }
3192
3193 //******************************************************************************
3194 // requestPowerDomainState
3195 //
3196 // Extend implementation in IOService. Running on PM work loop thread.
3197 //******************************************************************************
3198
3199 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3200 IOPMrootDomain::requestPowerDomainState(
3201 IOPMPowerFlags childDesire,
3202 IOPowerConnection * childConnection,
3203 unsigned long specification )
3204 {
3205 // Idle and system sleep prevention flags affects driver desire.
3206 // Children desire are irrelevant so they are cleared.
3207
3208 return super::requestPowerDomainState(0, childConnection, specification);
3209 }
3210
3211
3212 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3213 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3214 {
3215 if (!preventers->getCount()) {
3216 return;
3217 }
3218
3219 char *buf_iter = buf + strlen(buf);
3220 char *buf_end = buf + buf_size;
3221
3222 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3223 OSObject *obj = NULL;
3224
3225 while ((obj = iterator->getNextObject())) {
3226 IOService *srv = OSDynamicCast(IOService, obj);
3227 if (buf_iter < buf_end) {
3228 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3229 } else {
3230 DLOG("Print buffer exhausted for sleep preventers list\n");
3231 break;
3232 }
3233 }
3234 }
3235
3236 //******************************************************************************
3237 // updatePreventIdleSleepList
3238 //
3239 // Called by IOService on PM work loop.
3240 // Returns true if PM policy recognized the driver's desire to prevent idle
3241 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3242 //******************************************************************************
3243
3244 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3245 IOPMrootDomain::updatePreventIdleSleepList(
3246 IOService * service, bool addNotRemove)
3247 {
3248 unsigned int oldCount;
3249
3250 oldCount = idleSleepPreventersCount();
3251 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3252 }
3253
3254 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3255 IOPMrootDomain::updatePreventIdleSleepListInternal(
3256 IOService * service, bool addNotRemove, unsigned int oldCount)
3257 {
3258 unsigned int newCount;
3259
3260 ASSERT_GATED();
3261
3262 #if defined(XNU_TARGET_OS_OSX)
3263 // Only the display wrangler and no-idle-sleep kernel assertions
3264 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3265 // reported by drivers in their power state table is ignored.
3266 if (service && (service != wrangler) && (service != this)) {
3267 return false;
3268 }
3269 #endif
3270
3271 if (service) {
3272 if (addNotRemove) {
3273 preventIdleSleepList->setObject(service);
3274 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3275 service->getName(), preventIdleSleepList->getCount());
3276 } else if (preventIdleSleepList->member(service)) {
3277 preventIdleSleepList->removeObject(service);
3278 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3279 service->getName(), preventIdleSleepList->getCount());
3280 }
3281
3282 if (preventIdleSleepList->getCount()) {
3283 char buf[256] = "Idle Sleep Preventers:";
3284 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3285 DLOG("%s\n", buf);
3286 }
3287 }
3288
3289 newCount = idleSleepPreventersCount();
3290
3291 if ((oldCount == 0) && (newCount != 0)) {
3292 // Driver added to empty prevent list.
3293 // Update the driver desire to prevent idle sleep.
3294 // Driver desire does not prevent demand sleep.
3295
3296 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3297 } else if ((oldCount != 0) && (newCount == 0)) {
3298 // Last driver removed from prevent list.
3299 // Drop the driver clamp to allow idle sleep.
3300
3301 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3302 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3303 }
3304 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3305 &newCount, sizeof(newCount));
3306
3307 #if defined(XNU_TARGET_OS_OSX)
3308 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3309 DLOG("Cannot cancel idle sleep\n");
3310 return false; // do not idle-cancel
3311 }
3312 #endif
3313
3314 return true;
3315 }
3316
3317 //******************************************************************************
3318 // startSpinDump
3319 //******************************************************************************
3320
3321 void
startSpinDump(uint32_t spindumpKind)3322 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3323 {
3324 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3325 }
3326
3327 //******************************************************************************
3328 // preventSystemSleepListUpdate
3329 //
3330 // Called by IOService on PM work loop.
3331 //******************************************************************************
3332
3333 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3334 IOPMrootDomain::updatePreventSystemSleepList(
3335 IOService * service, bool addNotRemove )
3336 {
3337 unsigned int oldCount, newCount;
3338
3339 ASSERT_GATED();
3340 if (this == service) {
3341 return;
3342 }
3343
3344 oldCount = preventSystemSleepList->getCount();
3345 if (addNotRemove) {
3346 preventSystemSleepList->setObject(service);
3347 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3348 service->getName(), preventSystemSleepList->getCount());
3349 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3350 AbsoluteTime now;
3351 clock_usec_t microsecs;
3352 clock_get_uptime(&now);
3353 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3354 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
3355 if (assertOnWakeReport) {
3356 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3357 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3358 }
3359 }
3360 } else if (preventSystemSleepList->member(service)) {
3361 preventSystemSleepList->removeObject(service);
3362 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3363 service->getName(), preventSystemSleepList->getCount());
3364
3365 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3366 // Lost all system sleep preventers.
3367 // Send stimulus if system sleep was blocked, and is in dark wake.
3368 evaluatePolicy( kStimulusDarkWakeEvaluate );
3369 }
3370 }
3371
3372 newCount = preventSystemSleepList->getCount();
3373 if (newCount) {
3374 char buf[256] = "System Sleep Preventers:";
3375 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3376 DLOG("%s\n", buf);
3377 }
3378
3379 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3380 &newCount, sizeof(newCount));
3381 }
3382
3383 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3384 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3385 {
3386 OSSharedPtr<OSCollectionIterator> iterator;
3387 OSObject *object = NULL;
3388 OSSharedPtr<OSArray> array;
3389
3390 if (!gIOPMWorkLoop->inGate()) {
3391 gIOPMWorkLoop->runAction(
3392 OSMemberFunctionCast(IOWorkLoop::Action, this,
3393 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3394 this, (void *)idleSleepList, (void *)systemSleepList);
3395 return;
3396 }
3397
3398 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3399 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3400 array = OSArray::withCapacity(5);
3401
3402 if (iterator && array) {
3403 while ((object = iterator->getNextObject())) {
3404 IOService *service = OSDynamicCast(IOService, object);
3405 if (service) {
3406 OSSharedPtr<const OSSymbol> name = service->copyName();
3407 if (name) {
3408 array->setObject(name.get());
3409 }
3410 }
3411 }
3412 }
3413 *idleSleepList = array.detach();
3414 }
3415
3416 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3417 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3418 array = OSArray::withCapacity(5);
3419
3420 if (iterator && array) {
3421 while ((object = iterator->getNextObject())) {
3422 IOService *service = OSDynamicCast(IOService, object);
3423 if (service) {
3424 OSSharedPtr<const OSSymbol> name = service->copyName();
3425 if (name) {
3426 array->setObject(name.get());
3427 }
3428 }
3429 }
3430 }
3431 *systemSleepList = array.detach();
3432 }
3433 }
3434
3435 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3436 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3437 {
3438 OSSharedPtr<OSCollectionIterator> iterator;
3439 OSObject *object = NULL;
3440 OSSharedPtr<OSArray> array;
3441
3442 if (!gIOPMWorkLoop->inGate()) {
3443 gIOPMWorkLoop->runAction(
3444 OSMemberFunctionCast(IOWorkLoop::Action, this,
3445 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3446 this, (void *)idleSleepList, (void *)systemSleepList);
3447 return;
3448 }
3449
3450 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3451 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3452 array = OSArray::withCapacity(5);
3453
3454 if (iterator && array) {
3455 while ((object = iterator->getNextObject())) {
3456 IOService *service = OSDynamicCast(IOService, object);
3457 if (service) {
3458 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3459 OSSharedPtr<const OSSymbol> name = service->copyName();
3460 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3461 if (dict && name && id) {
3462 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3463 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3464 array->setObject(dict.get());
3465 }
3466 }
3467 }
3468 }
3469 *idleSleepList = array.detach();
3470 }
3471
3472 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3473 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3474 array = OSArray::withCapacity(5);
3475
3476 if (iterator && array) {
3477 while ((object = iterator->getNextObject())) {
3478 IOService *service = OSDynamicCast(IOService, object);
3479 if (service) {
3480 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3481 OSSharedPtr<const OSSymbol> name = service->copyName();
3482 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3483 if (dict && name && id) {
3484 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3485 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3486 array->setObject(dict.get());
3487 }
3488 }
3489 }
3490 }
3491 *systemSleepList = array.detach();
3492 }
3493 }
3494
3495 //******************************************************************************
3496 // tellChangeDown
3497 //
3498 // Override the superclass implementation to send a different message type.
3499 //******************************************************************************
3500
3501 bool
tellChangeDown(unsigned long stateNum)3502 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3503 {
3504 DLOG("tellChangeDown %s->%s\n",
3505 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3506
3507 if (SLEEP_STATE == stateNum) {
3508 // Legacy apps were already told in the full->dark transition
3509 if (!ignoreTellChangeDown) {
3510 tracePoint( kIOPMTracePointSleepApplications );
3511 } else {
3512 tracePoint( kIOPMTracePointSleepPriorityClients );
3513 }
3514 }
3515
3516 if (!ignoreTellChangeDown) {
3517 userActivityAtSleep = userActivityCount;
3518 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3519
3520 if (SLEEP_STATE == stateNum) {
3521 hibernateAborted = false;
3522
3523 // Direct callout into OSKext so it can disable kext unloads
3524 // during sleep/wake to prevent deadlocks.
3525 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3526
3527 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3528
3529 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3530 // But tellClientsWithResponse() must be called for both.
3531 ignoreTellChangeDown = true;
3532 }
3533 }
3534
3535 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3536 }
3537
3538 //******************************************************************************
3539 // askChangeDown
3540 //
3541 // Override the superclass implementation to send a different message type.
3542 // This must be idle sleep since we don't ask during any other power change.
3543 //******************************************************************************
3544
3545 bool
askChangeDown(unsigned long stateNum)3546 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3547 {
3548 DLOG("askChangeDown %s->%s\n",
3549 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3550
3551 // Don't log for dark wake entry
3552 if (kSystemTransitionSleep == _systemTransitionType) {
3553 tracePoint( kIOPMTracePointSleepApplications );
3554 }
3555
3556 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3557 }
3558
3559 //******************************************************************************
3560 // askChangeDownDone
3561 //
3562 // An opportunity for root domain to cancel the power transition,
3563 // possibily due to an assertion created by powerd in response to
3564 // kIOMessageCanSystemSleep.
3565 //
3566 // Idle sleep:
3567 // full -> dark wake transition
3568 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3569 // 2. askChangeDownDone()
3570 // dark -> sleep transition
3571 // 1. Notify powerd with kIOMessageCanSystemSleep
3572 // 2. askChangeDownDone()
3573 //
3574 // Demand sleep:
3575 // full -> dark wake transition
3576 // 1. Notify powerd with kIOMessageCanSystemSleep
3577 // 2. askChangeDownDone()
3578 // dark -> sleep transition
3579 // 1. Notify powerd with kIOMessageCanSystemSleep
3580 // 2. askChangeDownDone()
3581 //******************************************************************************
3582
3583 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3584 IOPMrootDomain::askChangeDownDone(
3585 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3586 {
3587 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3588 *inOutChangeFlags, *cancel,
3589 _systemTransitionType,
3590 _currentCapability, _pendingCapability);
3591
3592 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3593 // Dark->Sleep transition.
3594 // Check if there are any deny sleep assertions.
3595 // lastSleepReason already set by handleOurPowerChangeStart()
3596
3597 if (!checkSystemCanSleep(lastSleepReason)) {
3598 // Cancel dark wake to sleep transition.
3599 // Must re-scan assertions upon entering dark wake.
3600
3601 *cancel = true;
3602 DLOG("cancel dark->sleep\n");
3603 }
3604 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3605 uint64_t now = mach_continuous_time();
3606 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3607 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3608 *cancel = true;
3609 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3610 }
3611 }
3612 }
3613 }
3614
3615 //******************************************************************************
3616 // systemDidNotSleep
3617 //
3618 // Work common to both canceled or aborted sleep.
3619 //******************************************************************************
3620
3621 void
systemDidNotSleep(void)3622 IOPMrootDomain::systemDidNotSleep( void )
3623 {
3624 // reset console lock state
3625 thread_call_enter(updateConsoleUsersEntry);
3626
3627 if (idleSleepEnabled) {
3628 if (!wrangler) {
3629 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3630 startIdleSleepTimer(kIdleSleepRetryInterval);
3631 #else
3632 startIdleSleepTimer(idleMilliSeconds);
3633 #endif
3634 } else if (!userIsActive) {
3635 // Manually start the idle sleep timer besides waiting for
3636 // the user to become inactive.
3637 startIdleSleepTimer(kIdleSleepRetryInterval);
3638 }
3639 }
3640
3641 preventTransitionToUserActive(false);
3642 IOService::setAdvisoryTickleEnable( true );
3643
3644 // After idle revert and cancel, send a did-change message to powerd
3645 // to balance the previous will-change message. Kernel clients do not
3646 // need this since sleep cannot be canceled once they are notified.
3647
3648 if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3649 (_pendingCapability != _currentCapability) &&
3650 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3651 // Differs from a real capability gain change where notifyRef != 0,
3652 // but it is zero here since no response is expected.
3653
3654 IOPMSystemCapabilityChangeParameters params;
3655
3656 bzero(¶ms, sizeof(params));
3657 params.fromCapabilities = _pendingCapability;
3658 params.toCapabilities = _currentCapability;
3659 params.changeFlags = kIOPMSystemCapabilityDidChange;
3660
3661 DLOG("MESG cap %x->%x did change\n",
3662 params.fromCapabilities, params.toCapabilities);
3663 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3664 ¶ms, sizeof(params));
3665 }
3666 }
3667
3668 //******************************************************************************
3669 // tellNoChangeDown
3670 //
3671 // Notify registered applications and kernel clients that we are not dropping
3672 // power.
3673 //
3674 // We override the superclass implementation so we can send a different message
3675 // type to the client or application being notified.
3676 //
3677 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3678 //******************************************************************************
3679
3680 void
tellNoChangeDown(unsigned long stateNum)3681 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3682 {
3683 DLOG("tellNoChangeDown %s->%s\n",
3684 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3685
3686 // Sleep canceled, clear the sleep trace point.
3687 tracePoint(kIOPMTracePointSystemUp);
3688
3689 systemDidNotSleep();
3690 return tellClients( kIOMessageSystemWillNotSleep );
3691 }
3692
3693 //******************************************************************************
3694 // tellChangeUp
3695 //
3696 // Notify registered applications and kernel clients that we are raising power.
3697 //
3698 // We override the superclass implementation so we can send a different message
3699 // type to the client or application being notified.
3700 //******************************************************************************
3701
3702 void
tellChangeUp(unsigned long stateNum)3703 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3704 {
3705 DLOG("tellChangeUp %s->%s\n",
3706 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3707
3708 ignoreTellChangeDown = false;
3709
3710 if (stateNum == ON_STATE) {
3711 // Direct callout into OSKext so it can disable kext unloads
3712 // during sleep/wake to prevent deadlocks.
3713 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3714
3715 // Notify platform that sleep was cancelled or resumed.
3716 getPlatform()->callPlatformFunction(
3717 sleepMessagePEFunction.get(), false,
3718 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3719 NULL, NULL, NULL);
3720
3721 if (getPowerState() == ON_STATE) {
3722 // Sleep was cancelled by idle cancel or revert
3723 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3724 // rdar://problem/50363791
3725 // If system is in dark wake and sleep is cancelled, do not
3726 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3727 // priority clients. They haven't yet seen a SystemWillSleep
3728 // message before the cancellation. So make sure the kernel
3729 // client bit is cleared in _systemMessageClientMask before
3730 // invoking the tellClients() below. This bit may have been
3731 // set by handleOurPowerChangeStart() anticipating a successful
3732 // sleep and setting the filter mask ahead of time allows the
3733 // SystemWillSleep message to go through.
3734 _systemMessageClientMask &= ~kSystemMessageClientKernel;
3735 }
3736
3737 systemDidNotSleep();
3738 tellClients( kIOMessageSystemWillPowerOn );
3739 }
3740
3741 tracePoint( kIOPMTracePointWakeApplications );
3742 tellClients( kIOMessageSystemHasPoweredOn );
3743 } else if (stateNum == AOT_STATE) {
3744 if (getPowerState() == AOT_STATE) {
3745 // Sleep was cancelled by idle cancel or revert
3746 startIdleSleepTimer(idleMilliSeconds);
3747 }
3748 }
3749 }
3750
3751 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3752 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3753 ((params)->fromCapabilities & (flag)) && \
3754 (((params)->toCapabilities & (flag)) == 0))
3755
3756 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3757 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3758 ((params)->toCapabilities & (flag)) && \
3759 (((params)->fromCapabilities & (flag)) == 0))
3760
3761 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3762 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3763 ((params)->fromCapabilities & (flag)) && \
3764 (((params)->toCapabilities & (flag)) == 0))
3765
3766 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3767 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3768 ((params)->toCapabilities & (flag)) && \
3769 (((params)->fromCapabilities & (flag)) == 0))
3770
3771 //******************************************************************************
3772 // sysPowerDownHandler
3773 //
3774 // Perform a vfs sync before system sleep.
3775 //******************************************************************************
3776
3777 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3778 IOPMrootDomain::sysPowerDownHandler(
3779 void * target, void * refCon,
3780 UInt32 messageType, IOService * service,
3781 void * messageArgs, vm_size_t argSize )
3782 {
3783 static UInt32 lastSystemMessageType = 0;
3784 IOReturn ret = 0;
3785
3786 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3787
3788 // rdar://problem/50363791
3789 // Sanity check to make sure the SystemWill/Has message types are
3790 // received in the expected order for all kernel priority clients.
3791 if (messageType == kIOMessageSystemWillSleep ||
3792 messageType == kIOMessageSystemWillPowerOn ||
3793 messageType == kIOMessageSystemHasPoweredOn) {
3794 switch (messageType) {
3795 case kIOMessageSystemWillPowerOn:
3796 assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3797 break;
3798 case kIOMessageSystemHasPoweredOn:
3799 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3800 break;
3801 }
3802
3803 lastSystemMessageType = messageType;
3804 }
3805
3806 if (!gRootDomain) {
3807 return kIOReturnUnsupported;
3808 }
3809
3810 if (messageType == kIOMessageSystemCapabilityChange) {
3811 IOPMSystemCapabilityChangeParameters * params =
3812 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3813
3814 // Interested applications have been notified of an impending power
3815 // change and have acked (when applicable).
3816 // This is our chance to save whatever state we can before powering
3817 // down.
3818 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3819 // via callout
3820
3821 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3822 params->fromCapabilities, params->toCapabilities,
3823 params->changeFlags);
3824
3825 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3826 // We will ack within 20 seconds
3827 params->maxWaitForReply = 20 * 1000 * 1000;
3828
3829 #if HIBERNATION
3830 gRootDomain->evaluateSystemSleepPolicyEarly();
3831
3832 // add in time we could spend freeing pages
3833 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3834 params->maxWaitForReply = kCapabilityClientMaxWait;
3835 }
3836 DLOG("sysPowerDownHandler max wait %d s\n",
3837 (int) (params->maxWaitForReply / 1000 / 1000));
3838 #endif
3839
3840 // Notify platform that sleep has begun, after the early
3841 // sleep policy evaluation.
3842 getPlatform()->callPlatformFunction(
3843 sleepMessagePEFunction.get(), false,
3844 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3845 NULL, NULL, NULL);
3846
3847 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3848 // Purposely delay the ack and hope that shutdown occurs quickly.
3849 // Another option is not to schedule the thread and wait for
3850 // ack timeout...
3851 AbsoluteTime deadline;
3852 clock_interval_to_deadline( 30, kSecondScale, &deadline );
3853 thread_call_enter1_delayed(
3854 gRootDomain->diskSyncCalloutEntry,
3855 (thread_call_param_t)(uintptr_t) params->notifyRef,
3856 deadline );
3857 } else {
3858 thread_call_enter1(
3859 gRootDomain->diskSyncCalloutEntry,
3860 (thread_call_param_t)(uintptr_t) params->notifyRef);
3861 }
3862 }
3863 #if HIBERNATION
3864 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3865 // We will ack within 110 seconds
3866 params->maxWaitForReply = 110 * 1000 * 1000;
3867
3868 thread_call_enter1(
3869 gRootDomain->diskSyncCalloutEntry,
3870 (thread_call_param_t)(uintptr_t) params->notifyRef);
3871 }
3872 #endif
3873 ret = kIOReturnSuccess;
3874 }
3875
3876 return ret;
3877 }
3878
3879 //******************************************************************************
3880 // handleQueueSleepWakeUUID
3881 //
3882 // Called from IOPMrootDomain when we're initiating a sleep,
3883 // or indirectly from PM configd when PM decides to clear the UUID.
3884 // PM clears the UUID several minutes after successful wake from sleep,
3885 // so that we might associate App spindumps with the immediately previous
3886 // sleep/wake.
3887 //
3888 // @param obj has a retain on it. We're responsible for releasing that retain.
3889 //******************************************************************************
3890
3891 void
handleQueueSleepWakeUUID(OSObject * obj)3892 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3893 {
3894 OSSharedPtr<OSString> str;
3895
3896 if (kOSBooleanFalse == obj) {
3897 handlePublishSleepWakeUUID(false);
3898 } else {
3899 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3900 if (str) {
3901 // This branch caches the UUID for an upcoming sleep/wake
3902 queuedSleepWakeUUIDString = str;
3903 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3904 }
3905 }
3906 }
3907 //******************************************************************************
3908 // handlePublishSleepWakeUUID
3909 //
3910 // Called from IOPMrootDomain when we're initiating a sleep,
3911 // or indirectly from PM configd when PM decides to clear the UUID.
3912 // PM clears the UUID several minutes after successful wake from sleep,
3913 // so that we might associate App spindumps with the immediately previous
3914 // sleep/wake.
3915 //******************************************************************************
3916
3917 void
handlePublishSleepWakeUUID(bool shouldPublish)3918 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3919 {
3920 ASSERT_GATED();
3921
3922 /*
3923 * Clear the current UUID
3924 */
3925 if (gSleepWakeUUIDIsSet) {
3926 DLOG("SleepWake UUID cleared\n");
3927
3928 gSleepWakeUUIDIsSet = false;
3929
3930 removeProperty(kIOPMSleepWakeUUIDKey);
3931 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3932 }
3933
3934 /*
3935 * Optionally, publish a new UUID
3936 */
3937 if (queuedSleepWakeUUIDString && shouldPublish) {
3938 OSSharedPtr<OSString> publishThisUUID;
3939
3940 publishThisUUID = queuedSleepWakeUUIDString;
3941
3942 if (publishThisUUID) {
3943 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3944 }
3945
3946 gSleepWakeUUIDIsSet = true;
3947 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3948
3949 queuedSleepWakeUUIDString.reset();
3950 }
3951 }
3952
3953 //******************************************************************************
3954 // IOPMGetSleepWakeUUIDKey
3955 //
3956 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3957 // To get the full key -- a C string -- the buffer must large enough for
3958 // the end-of-string character.
3959 // The key is expected to be an UUID string
3960 //******************************************************************************
3961
3962 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3963 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3964 {
3965 if (!gSleepWakeUUIDIsSet) {
3966 return false;
3967 }
3968
3969 if (buffer != NULL) {
3970 OSSharedPtr<OSString> string =
3971 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3972
3973 if (!string) {
3974 *buffer = '\0';
3975 } else {
3976 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3977 }
3978 }
3979
3980 return true;
3981 }
3982
3983 //******************************************************************************
3984 // lowLatencyAudioNotify
3985 //
3986 // Used to send an update about low latency audio activity to interested
3987 // clients. To keep the overhead minimal the OSDictionary used here
3988 // is initialized at boot.
3989 //******************************************************************************
3990
3991 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)3992 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3993 {
3994 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
3995 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
3996 lowLatencyAudioNotifyTimestampVal->setValue(time);
3997 lowLatencyAudioNotifyStateVal->setValue(state);
3998 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
3999 } else {
4000 DLOG("LowLatencyAudioNotify error\n");
4001 }
4002 return;
4003 }
4004
4005 //******************************************************************************
4006 // IOPMrootDomainRTNotifier
4007 //
4008 // Used by performance controller to update the timestamp and state associated
4009 // with low latency audio activity in the system.
4010 //******************************************************************************
4011
4012 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4013 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4014 {
4015 gRootDomain->lowLatencyAudioNotify(time, state);
4016 return;
4017 }
4018
4019 //******************************************************************************
4020 // initializeBootSessionUUID
4021 //
4022 // Initialize the boot session uuid at boot up and sets it into registry.
4023 //******************************************************************************
4024
4025 void
initializeBootSessionUUID(void)4026 IOPMrootDomain::initializeBootSessionUUID(void)
4027 {
4028 uuid_t new_uuid;
4029 uuid_string_t new_uuid_string;
4030
4031 uuid_generate(new_uuid);
4032 uuid_unparse_upper(new_uuid, new_uuid_string);
4033 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4034
4035 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4036 }
4037
4038 //******************************************************************************
4039 // Root domain uses the private and tagged changePowerState methods for
4040 // tracking and logging purposes.
4041 //******************************************************************************
4042
4043 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
4044
4045 static uint32_t
nextRequestTag(IOPMRequestTag tag)4046 nextRequestTag( IOPMRequestTag tag )
4047 {
4048 static SInt16 msb16 = 1;
4049 uint16_t id = OSAddAtomic16(1, &msb16);
4050 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4051 }
4052
4053 // TODO: remove this shim function and exported symbol
4054 IOReturn
changePowerStateTo(unsigned long ordinal)4055 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4056 {
4057 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4058 }
4059
4060 // TODO: remove this shim function and exported symbol
4061 IOReturn
changePowerStateToPriv(unsigned long ordinal)4062 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4063 {
4064 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4065 }
4066
4067 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4068 IOPMrootDomain::changePowerStateWithOverrideTo(
4069 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4070 {
4071 uint32_t tag = nextRequestTag(reason);
4072 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4073
4074 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4075 return kIOReturnUnsupported;
4076 }
4077
4078 return super::changePowerStateWithOverrideTo(ordinal, tag);
4079 }
4080
4081 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4082 IOPMrootDomain::changePowerStateWithTagTo(
4083 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4084 {
4085 uint32_t tag = nextRequestTag(reason);
4086 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4087
4088 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4089 return kIOReturnUnsupported;
4090 }
4091
4092 return super::changePowerStateWithTagTo(ordinal, tag);
4093 }
4094
4095 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4096 IOPMrootDomain::changePowerStateWithTagToPriv(
4097 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4098 {
4099 uint32_t tag = nextRequestTag(reason);
4100 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4101
4102 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4103 return kIOReturnUnsupported;
4104 }
4105
4106 return super::changePowerStateWithTagToPriv(ordinal, tag);
4107 }
4108
4109 //******************************************************************************
4110 // activity detect
4111 //
4112 //******************************************************************************
4113
4114 bool
activitySinceSleep(void)4115 IOPMrootDomain::activitySinceSleep(void)
4116 {
4117 return userActivityCount != userActivityAtSleep;
4118 }
4119
4120 bool
abortHibernation(void)4121 IOPMrootDomain::abortHibernation(void)
4122 {
4123 #if __arm64__
4124 // don't allow hibernation to be aborted on ARM due to user activity
4125 // since once ApplePMGR decides we're hibernating, we can't turn back
4126 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4127 return false;
4128 #else
4129 bool ret = activitySinceSleep();
4130
4131 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4132 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4133 hibernateAborted = true;
4134 }
4135 return ret;
4136 #endif
4137 }
4138
4139 extern "C" int
hibernate_should_abort(void)4140 hibernate_should_abort(void)
4141 {
4142 if (gRootDomain) {
4143 return gRootDomain->abortHibernation();
4144 } else {
4145 return 0;
4146 }
4147 }
4148
4149 //******************************************************************************
4150 // willNotifyPowerChildren
4151 //
4152 // Called after all interested drivers have all acknowledged the power change,
4153 // but before any power children is informed. Dispatched though a thread call,
4154 // so it is safe to perform work that might block on a sleeping disk. PM state
4155 // machine (not thread) will block w/o timeout until this function returns.
4156 //******************************************************************************
4157
4158 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4159 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4160 {
4161 OSSharedPtr<OSDictionary> dict;
4162 OSSharedPtr<OSNumber> secs;
4163
4164 if (SLEEP_STATE == newPowerState) {
4165 notifierThread = current_thread();
4166 if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4167 AbsoluteTime deadline;
4168
4169 clock_interval_to_deadline(10, kSecondScale, &deadline);
4170 #if defined(XNU_TARGET_OS_OSX)
4171 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4172 #endif /* defined(XNU_TARGET_OS_OSX) */
4173 }
4174
4175 _aotReadyToFullWake = false;
4176 #if 0
4177 if (_aotLingerTime) {
4178 uint64_t deadline;
4179 IOLog("aot linger no return\n");
4180 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4181 clock_delay_until(deadline);
4182 }
4183 #endif
4184 if (!_aotMode) {
4185 _aotTestTime = 0;
4186 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4187 _aotLastWakeTime = 0;
4188 if (_aotMetrics) {
4189 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4190 }
4191 } else if (!_aotNow && !_debugWakeSeconds) {
4192 _aotNow = true;
4193 _aotPendingFlags = 0;
4194 _aotTasksSuspended = true;
4195 _aotLastWakeTime = 0;
4196 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4197 if (kIOPMAOTModeCycle & _aotMode) {
4198 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4199 _aotTestTime = mach_continuous_time() + _aotTestInterval;
4200 setWakeTime(_aotTestTime);
4201 }
4202 uint32_t lingerSecs;
4203 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4204 lingerSecs = 0;
4205 }
4206 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4207 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4208 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4209 }
4210
4211 #if HIBERNATION
4212 IOHibernateSystemSleep();
4213 IOHibernateIOKitSleep();
4214 #endif
4215 if (gRootDomain->activitySinceSleep()) {
4216 dict = OSDictionary::withCapacity(1);
4217 secs = OSNumber::withNumber(1, 32);
4218
4219 if (dict && secs) {
4220 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4221 gRootDomain->setProperties(dict.get());
4222 MSG("Reverting sleep with relative wake\n");
4223 }
4224 }
4225
4226 notifierThread = NULL;
4227 }
4228 }
4229
4230 //******************************************************************************
4231 // willTellSystemCapabilityDidChange
4232 //
4233 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4234 // domain is raising its power state, immediately after notifying interested
4235 // drivers and power children.
4236 //******************************************************************************
4237
4238 void
willTellSystemCapabilityDidChange(void)4239 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4240 {
4241 if ((_systemTransitionType == kSystemTransitionWake) &&
4242 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4243 // After powering up drivers, dark->full promotion on the current wake
4244 // transition is no longer possible. That is because the next machine
4245 // state will issue the system capability change messages.
4246 // The darkWakePowerClamped flag may already be set if the system has
4247 // at least one driver that was power clamped due to dark wake.
4248 // This function sets the darkWakePowerClamped flag in case there
4249 // is no power-clamped driver in the system.
4250 //
4251 // Last opportunity to exit dark wake using:
4252 // requestFullWake( kFullWakeReasonLocalUser );
4253
4254 if (!darkWakePowerClamped) {
4255 if (darkWakeLogClamp) {
4256 AbsoluteTime now;
4257 uint64_t nsec;
4258
4259 clock_get_uptime(&now);
4260 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4261 absolutetime_to_nanoseconds(now, &nsec);
4262 DLOG("dark wake promotion disabled at %u ms\n",
4263 ((int)((nsec) / NSEC_PER_MSEC)));
4264 }
4265 darkWakePowerClamped = true;
4266 }
4267 }
4268 }
4269
4270 //******************************************************************************
4271 // sleepOnClamshellClosed
4272 //
4273 // contains the logic to determine if the system should sleep when the clamshell
4274 // is closed.
4275 //******************************************************************************
4276
4277 bool
shouldSleepOnClamshellClosed(void)4278 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4279 {
4280 if (!clamshellExists) {
4281 return false;
4282 }
4283
4284 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4285 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4286
4287 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4288 }
4289
4290 bool
shouldSleepOnRTCAlarmWake(void)4291 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4292 {
4293 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4294 // closed && battery
4295 if (!clamshellExists) {
4296 return false;
4297 }
4298
4299 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4300 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4301
4302 return !acAdaptorConnected && !clamshellSleepDisableMask;
4303 }
4304
4305 void
sendClientClamshellNotification(void)4306 IOPMrootDomain::sendClientClamshellNotification( void )
4307 {
4308 /* Only broadcast clamshell alert if clamshell exists. */
4309 if (!clamshellExists) {
4310 return;
4311 }
4312
4313 setProperty(kAppleClamshellStateKey,
4314 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4315
4316 setProperty(kAppleClamshellCausesSleepKey,
4317 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4318
4319 /* Argument to message is a bitfiel of
4320 * ( kClamshellStateBit | kClamshellSleepBit )
4321 */
4322 messageClients(kIOPMMessageClamshellStateChange,
4323 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4324 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4325 }
4326
4327 //******************************************************************************
4328 // getSleepSupported
4329 //
4330 // Deprecated
4331 //******************************************************************************
4332
4333 IOOptionBits
getSleepSupported(void)4334 IOPMrootDomain::getSleepSupported( void )
4335 {
4336 return platformSleepSupport;
4337 }
4338
4339 //******************************************************************************
4340 // setSleepSupported
4341 //
4342 // Deprecated
4343 //******************************************************************************
4344
4345 void
setSleepSupported(IOOptionBits flags)4346 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4347 {
4348 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4349 OSBitOrAtomic(flags, &platformSleepSupport);
4350 }
4351
4352 //******************************************************************************
4353 // setClamShellSleepDisable
4354 //
4355 //******************************************************************************
4356
4357 void
setClamShellSleepDisable(bool disable,uint32_t bitmask)4358 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4359 {
4360 uint32_t oldMask;
4361
4362 // User client calls this in non-gated context
4363 if (gIOPMWorkLoop->inGate() == false) {
4364 gIOPMWorkLoop->runAction(
4365 OSMemberFunctionCast(IOWorkLoop::Action, this,
4366 &IOPMrootDomain::setClamShellSleepDisable),
4367 (OSObject *) this,
4368 (void *) disable, (void *)(uintptr_t) bitmask);
4369 return;
4370 }
4371
4372 oldMask = clamshellSleepDisableMask;
4373 if (disable) {
4374 clamshellSleepDisableMask |= bitmask;
4375 } else {
4376 clamshellSleepDisableMask &= ~bitmask;
4377 }
4378 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4379
4380 if (clamshellExists && clamshellClosed &&
4381 (clamshellSleepDisableMask != oldMask) &&
4382 (clamshellSleepDisableMask == 0)) {
4383 handlePowerNotification(kLocalEvalClamshellCommand);
4384 }
4385 }
4386
4387 //******************************************************************************
4388 // wakeFromDoze
4389 //
4390 // Deprecated.
4391 //******************************************************************************
4392
4393 void
wakeFromDoze(void)4394 IOPMrootDomain::wakeFromDoze( void )
4395 {
4396 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4397 }
4398
4399 //******************************************************************************
4400 // recordRTCAlarm
4401 //
4402 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4403 // should be a dark wake or a full wake. Both Maintenance and SleepService
4404 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4405 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4406 // PMSettings are ignored.
4407 //
4408 // Caller serialized using settingsCtrlLock.
4409 //******************************************************************************
4410
4411 void
recordRTCAlarm(const OSSymbol * type,OSObject * object)4412 IOPMrootDomain::recordRTCAlarm(
4413 const OSSymbol *type,
4414 OSObject *object )
4415 {
4416 uint32_t previousAlarmMask = _scheduledAlarmMask;
4417
4418 if (type == gIOPMSettingDebugWakeRelativeKey) {
4419 OSNumber * n = OSDynamicCast(OSNumber, object);
4420 if (n) {
4421 // Debug wake has highest scheduling priority so it overrides any
4422 // pre-existing alarm.
4423 uint32_t debugSecs = n->unsigned32BitValue();
4424 _nextScheduledAlarmType.reset(type, OSRetain);
4425 _nextScheduledAlarmUTC = debugSecs;
4426
4427 _debugWakeSeconds = debugSecs;
4428 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4429 DLOG("next alarm (%s) in %u secs\n",
4430 type->getCStringNoCopy(), debugSecs);
4431 }
4432 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4433 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4434 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4435 OSData * data = OSDynamicCast(OSData, object);
4436 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4437 const IOPMCalendarStruct * cs;
4438 bool replaceNextAlarm = false;
4439 clock_sec_t secs;
4440
4441 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4442 secs = IOPMConvertCalendarToSeconds(cs);
4443 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4444
4445 // Update the next scheduled alarm type
4446 if ((_nextScheduledAlarmType == NULL) ||
4447 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4448 (secs < _nextScheduledAlarmUTC))) {
4449 replaceNextAlarm = true;
4450 }
4451
4452 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4453 if (cs->year) {
4454 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4455 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4456 } else {
4457 // TODO: can this else-block be removed?
4458 _calendarWakeAlarmUTC = 0;
4459 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4460 }
4461 }
4462 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4463 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4464 }
4465 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4466 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4467 }
4468
4469 if (replaceNextAlarm) {
4470 _nextScheduledAlarmType.reset(type, OSRetain);
4471 _nextScheduledAlarmUTC = secs;
4472 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4473 }
4474 }
4475 }
4476
4477 if (_scheduledAlarmMask != previousAlarmMask) {
4478 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4479 }
4480 }
4481
4482 // MARK: -
4483 // MARK: Features
4484
4485 //******************************************************************************
4486 // publishFeature
4487 //
4488 // Adds a new feature to the supported features dictionary
4489 //******************************************************************************
4490
4491 void
publishFeature(const char * feature)4492 IOPMrootDomain::publishFeature( const char * feature )
4493 {
4494 publishFeature(feature, kRD_AllPowerSources, NULL);
4495 }
4496
4497 //******************************************************************************
4498 // publishFeature (with supported power source specified)
4499 //
4500 // Adds a new feature to the supported features dictionary
4501 //******************************************************************************
4502
4503 void
publishFeature(const char * feature,uint32_t supportedWhere,uint32_t * uniqueFeatureID)4504 IOPMrootDomain::publishFeature(
4505 const char *feature,
4506 uint32_t supportedWhere,
4507 uint32_t *uniqueFeatureID)
4508 {
4509 static uint16_t next_feature_id = 500;
4510
4511 OSSharedPtr<OSNumber> new_feature_data;
4512 OSNumber *existing_feature = NULL;
4513 OSArray *existing_feature_arr_raw = NULL;
4514 OSSharedPtr<OSArray> existing_feature_arr;
4515 OSObject *osObj = NULL;
4516 uint32_t feature_value = 0;
4517
4518 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4519
4520 if (!supportedWhere) {
4521 // Feature isn't supported anywhere!
4522 return;
4523 }
4524
4525 if (next_feature_id > 5000) {
4526 // Far, far too many features!
4527 return;
4528 }
4529
4530 if (featuresDictLock) {
4531 IOLockLock(featuresDictLock);
4532 }
4533
4534 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4535 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4536 OSSharedPtr<OSDictionary> features;
4537
4538 // Create new features dict if necessary
4539 if (origFeatures) {
4540 features = OSDictionary::withDictionary(origFeatures);
4541 } else {
4542 features = OSDictionary::withCapacity(1);
4543 }
4544
4545 // Create OSNumber to track new feature
4546
4547 next_feature_id += 1;
4548 if (uniqueFeatureID) {
4549 // We don't really mind if the calling kext didn't give us a place
4550 // to stash their unique id. Many kexts don't plan to unload, and thus
4551 // have no need to remove themselves later.
4552 *uniqueFeatureID = next_feature_id;
4553 }
4554
4555 feature_value = (uint32_t)next_feature_id;
4556 feature_value <<= 16;
4557 feature_value += supportedWhere;
4558
4559 new_feature_data = OSNumber::withNumber(
4560 (unsigned long long)feature_value, 32);
4561
4562 // Does features object already exist?
4563 if ((osObj = features->getObject(feature))) {
4564 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4565 // We need to create an OSArray to hold the now 2 elements.
4566 existing_feature_arr = OSArray::withObjects(
4567 (const OSObject **)&existing_feature, 1, 2);
4568 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4569 // Add object to existing array
4570 existing_feature_arr = OSArray::withArray(
4571 existing_feature_arr_raw,
4572 existing_feature_arr_raw->getCount() + 1);
4573 }
4574
4575 if (existing_feature_arr) {
4576 existing_feature_arr->setObject(new_feature_data.get());
4577 features->setObject(feature, existing_feature_arr.get());
4578 }
4579 } else {
4580 // The easy case: no previously existing features listed. We simply
4581 // set the OSNumber at key 'feature' and we're on our way.
4582 features->setObject(feature, new_feature_data.get());
4583 }
4584
4585 setProperty(kRootDomainSupportedFeatures, features.get());
4586
4587 if (featuresDictLock) {
4588 IOLockUnlock(featuresDictLock);
4589 }
4590
4591 // Notify EnergySaver and all those in user space so they might
4592 // re-populate their feature specific UI
4593 if (pmPowerStateQueue) {
4594 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4595 }
4596 }
4597
4598 //******************************************************************************
4599 // removePublishedFeature
4600 //
4601 // Removes previously published feature
4602 //******************************************************************************
4603
4604 IOReturn
removePublishedFeature(uint32_t removeFeatureID)4605 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4606 {
4607 IOReturn ret = kIOReturnError;
4608 uint32_t feature_value = 0;
4609 uint16_t feature_id = 0;
4610 bool madeAChange = false;
4611
4612 OSSymbol *dictKey = NULL;
4613 OSSharedPtr<OSCollectionIterator> dictIterator;
4614 OSArray *arrayMember = NULL;
4615 OSNumber *numberMember = NULL;
4616 OSObject *osObj = NULL;
4617 OSNumber *osNum = NULL;
4618 OSSharedPtr<OSArray> arrayMemberCopy;
4619
4620 if (kBadPMFeatureID == removeFeatureID) {
4621 return kIOReturnNotFound;
4622 }
4623
4624 if (featuresDictLock) {
4625 IOLockLock(featuresDictLock);
4626 }
4627
4628 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4629 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4630 OSSharedPtr<OSDictionary> features;
4631
4632 if (origFeatures) {
4633 // Any modifications to the dictionary are made to the copy to prevent
4634 // races & crashes with userland clients. Dictionary updated
4635 // automically later.
4636 features = OSDictionary::withDictionary(origFeatures);
4637 } else {
4638 features = NULL;
4639 ret = kIOReturnNotFound;
4640 goto exit;
4641 }
4642
4643 // We iterate 'features' dictionary looking for an entry tagged
4644 // with 'removeFeatureID'. If found, we remove it from our tracking
4645 // structures and notify the OS via a general interest message.
4646
4647 dictIterator = OSCollectionIterator::withCollection(features.get());
4648 if (!dictIterator) {
4649 goto exit;
4650 }
4651
4652 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4653 osObj = features->getObject(dictKey);
4654
4655 // Each Feature is either tracked by an OSNumber
4656 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4657 feature_value = numberMember->unsigned32BitValue();
4658 feature_id = (uint16_t)(feature_value >> 16);
4659
4660 if (feature_id == (uint16_t)removeFeatureID) {
4661 // Remove this node
4662 features->removeObject(dictKey);
4663 madeAChange = true;
4664 break;
4665 }
4666
4667 // Or tracked by an OSArray of OSNumbers
4668 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4669 unsigned int arrayCount = arrayMember->getCount();
4670
4671 for (unsigned int i = 0; i < arrayCount; i++) {
4672 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4673 if (!osNum) {
4674 continue;
4675 }
4676
4677 feature_value = osNum->unsigned32BitValue();
4678 feature_id = (uint16_t)(feature_value >> 16);
4679
4680 if (feature_id == (uint16_t)removeFeatureID) {
4681 // Remove this node
4682 if (1 == arrayCount) {
4683 // If the array only contains one element, remove
4684 // the whole thing.
4685 features->removeObject(dictKey);
4686 } else {
4687 // Otherwise remove the element from a copy of the array.
4688 arrayMemberCopy = OSArray::withArray(arrayMember);
4689 if (arrayMemberCopy) {
4690 arrayMemberCopy->removeObject(i);
4691 features->setObject(dictKey, arrayMemberCopy.get());
4692 }
4693 }
4694
4695 madeAChange = true;
4696 break;
4697 }
4698 }
4699 }
4700 }
4701
4702 if (madeAChange) {
4703 ret = kIOReturnSuccess;
4704
4705 setProperty(kRootDomainSupportedFeatures, features.get());
4706
4707 // Notify EnergySaver and all those in user space so they might
4708 // re-populate their feature specific UI
4709 if (pmPowerStateQueue) {
4710 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4711 }
4712 } else {
4713 ret = kIOReturnNotFound;
4714 }
4715
4716 exit:
4717 if (featuresDictLock) {
4718 IOLockUnlock(featuresDictLock);
4719 }
4720 return ret;
4721 }
4722
4723 //******************************************************************************
4724 // publishPMSetting (private)
4725 //
4726 // Should only be called by PMSettingObject to publish a PM Setting as a
4727 // supported feature.
4728 //******************************************************************************
4729
4730 void
publishPMSetting(const OSSymbol * feature,uint32_t where,uint32_t * featureID)4731 IOPMrootDomain::publishPMSetting(
4732 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4733 {
4734 if (noPublishPMSettings &&
4735 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4736 // Setting found in noPublishPMSettings array
4737 *featureID = kBadPMFeatureID;
4738 return;
4739 }
4740
4741 publishFeature(
4742 feature->getCStringNoCopy(), where, featureID);
4743 }
4744
4745 //******************************************************************************
4746 // setPMSetting (private)
4747 //
4748 // Internal helper to relay PM settings changes from user space to individual
4749 // drivers. Should be called only by IOPMrootDomain::setProperties.
4750 //******************************************************************************
4751
4752 IOReturn
setPMSetting(const OSSymbol * type,OSObject * object)4753 IOPMrootDomain::setPMSetting(
4754 const OSSymbol *type,
4755 OSObject *object )
4756 {
4757 PMSettingCallEntry *entries = NULL;
4758 OSSharedPtr<OSArray> chosen;
4759 const OSArray *array;
4760 PMSettingObject *pmso;
4761 thread_t thisThread;
4762 int i, j, count, capacity;
4763 bool ok = false;
4764 IOReturn ret;
4765
4766 if (NULL == type) {
4767 return kIOReturnBadArgument;
4768 }
4769
4770 PMSETTING_LOCK();
4771
4772 // Update settings dict so changes are visible from copyPMSetting().
4773 fPMSettingsDict->setObject(type, object);
4774
4775 // Prep all PMSetting objects with the given 'type' for callout.
4776 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4777 if (!array || ((capacity = array->getCount()) == 0)) {
4778 goto unlock_exit;
4779 }
4780
4781 // Array to retain PMSetting objects targeted for callout.
4782 chosen = OSArray::withCapacity(capacity);
4783 if (!chosen) {
4784 goto unlock_exit; // error
4785 }
4786 entries = IONew(PMSettingCallEntry, capacity);
4787 if (!entries) {
4788 goto unlock_exit; // error
4789 }
4790 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4791
4792 thisThread = current_thread();
4793
4794 for (i = 0, j = 0; i < capacity; i++) {
4795 pmso = (PMSettingObject *) array->getObject(i);
4796 if (pmso->disabled) {
4797 continue;
4798 }
4799 entries[j].thread = thisThread;
4800 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4801 chosen->setObject(pmso);
4802 j++;
4803 }
4804 count = j;
4805 if (!count) {
4806 goto unlock_exit;
4807 }
4808
4809 PMSETTING_UNLOCK();
4810
4811 // Call each pmso in the chosen array.
4812 for (i = 0; i < count; i++) {
4813 pmso = (PMSettingObject *) chosen->getObject(i);
4814 ret = pmso->dispatchPMSetting(type, object);
4815 if (ret == kIOReturnSuccess) {
4816 // At least one setting handler was successful
4817 ok = true;
4818 #if DEVELOPMENT || DEBUG
4819 } else {
4820 // Log the handler and kext that failed
4821 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4822 if (kextName) {
4823 DLOG("PMSetting(%s) error 0x%x from %s\n",
4824 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4825 }
4826 #endif
4827 }
4828 }
4829
4830 PMSETTING_LOCK();
4831 for (i = 0; i < count; i++) {
4832 pmso = (PMSettingObject *) chosen->getObject(i);
4833 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4834 if (pmso->waitThread) {
4835 PMSETTING_WAKEUP(pmso);
4836 }
4837 }
4838
4839 if (ok) {
4840 recordRTCAlarm(type, object);
4841 }
4842 unlock_exit:
4843 PMSETTING_UNLOCK();
4844
4845 if (entries) {
4846 IODelete(entries, PMSettingCallEntry, capacity);
4847 }
4848
4849 return kIOReturnSuccess;
4850 }
4851
4852 //******************************************************************************
4853 // copyPMSetting (public)
4854 //
4855 // Allows kexts to safely read setting values, without being subscribed to
4856 // notifications.
4857 //******************************************************************************
4858
4859 OSSharedPtr<OSObject>
copyPMSetting(OSSymbol * whichSetting)4860 IOPMrootDomain::copyPMSetting(
4861 OSSymbol *whichSetting)
4862 {
4863 OSSharedPtr<OSObject> obj;
4864
4865 if (!whichSetting) {
4866 return NULL;
4867 }
4868
4869 PMSETTING_LOCK();
4870 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4871 PMSETTING_UNLOCK();
4872
4873 return obj;
4874 }
4875
4876 //******************************************************************************
4877 // registerPMSettingController (public)
4878 //
4879 // direct wrapper to registerPMSettingController with uint32_t power source arg
4880 //******************************************************************************
4881
4882 IOReturn
registerPMSettingController(const OSSymbol * settings[],IOPMSettingControllerCallback func,OSObject * target,uintptr_t refcon,OSObject ** handle)4883 IOPMrootDomain::registerPMSettingController(
4884 const OSSymbol * settings[],
4885 IOPMSettingControllerCallback func,
4886 OSObject *target,
4887 uintptr_t refcon,
4888 OSObject **handle)
4889 {
4890 return registerPMSettingController(
4891 settings,
4892 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4893 func, target, refcon, handle);
4894 }
4895
4896 //******************************************************************************
4897 // registerPMSettingController (public)
4898 //
4899 // Kexts may register for notifications when a particular setting is changed.
4900 // A list of settings is available in IOPM.h.
4901 // Arguments:
4902 // * settings - An OSArray containing OSSymbols. Caller should populate this
4903 // array with a list of settings caller wants notifications from.
4904 // * func - A C function callback of the type IOPMSettingControllerCallback
4905 // * target - caller may provide an OSObject *, which PM will pass as an
4906 // target to calls to "func"
4907 // * refcon - caller may provide an void *, which PM will pass as an
4908 // argument to calls to "func"
4909 // * handle - This is a return argument. We will populate this pointer upon
4910 // call success. Hold onto this and pass this argument to
4911 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4912 // Returns:
4913 // kIOReturnSuccess on success
4914 //******************************************************************************
4915
4916 IOReturn
registerPMSettingController(const OSSymbol * settings[],uint32_t supportedPowerSources,IOPMSettingControllerCallback func,OSObject * target,uintptr_t refcon,OSObject ** handle)4917 IOPMrootDomain::registerPMSettingController(
4918 const OSSymbol * settings[],
4919 uint32_t supportedPowerSources,
4920 IOPMSettingControllerCallback func,
4921 OSObject *target,
4922 uintptr_t refcon,
4923 OSObject **handle)
4924 {
4925 PMSettingObject *pmso = NULL;
4926 OSObject *pmsh = NULL;
4927 int i;
4928
4929 if (NULL == settings ||
4930 NULL == func ||
4931 NULL == handle) {
4932 return kIOReturnBadArgument;
4933 }
4934
4935 pmso = PMSettingObject::pmSettingObject(
4936 (IOPMrootDomain *) this, func, target,
4937 refcon, supportedPowerSources, settings, &pmsh);
4938
4939 if (!pmso) {
4940 *handle = NULL;
4941 return kIOReturnInternalError;
4942 }
4943
4944 PMSETTING_LOCK();
4945 for (i = 0; settings[i]; i++) {
4946 OSSharedPtr<OSArray> newList;
4947 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4948 if (!list) {
4949 // New array of callbacks for this setting
4950 newList = OSArray::withCapacity(1);
4951 settingsCallbacks->setObject(settings[i], newList.get());
4952 list = newList.get();
4953 }
4954
4955 // Add caller to the callback list
4956 list->setObject(pmso);
4957 }
4958 PMSETTING_UNLOCK();
4959
4960 // Return handle to the caller, the setting object is private.
4961 *handle = pmsh;
4962
4963 return kIOReturnSuccess;
4964 }
4965
4966 //******************************************************************************
4967 // deregisterPMSettingObject (private)
4968 //
4969 // Only called from PMSettingObject.
4970 //******************************************************************************
4971
4972 void
deregisterPMSettingObject(PMSettingObject * pmso)4973 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4974 {
4975 thread_t thisThread = current_thread();
4976 PMSettingCallEntry *callEntry;
4977 OSSharedPtr<OSCollectionIterator> iter;
4978 OSSymbol *sym;
4979 OSArray *array;
4980 int index;
4981 bool wait;
4982
4983 PMSETTING_LOCK();
4984
4985 pmso->disabled = true;
4986
4987 // Wait for all callout threads to finish.
4988 do {
4989 wait = false;
4990 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
4991 {
4992 if (callEntry->thread != thisThread) {
4993 wait = true;
4994 break;
4995 }
4996 }
4997 if (wait) {
4998 assert(NULL == pmso->waitThread);
4999 pmso->waitThread = thisThread;
5000 PMSETTING_WAIT(pmso);
5001 pmso->waitThread = NULL;
5002 }
5003 } while (wait);
5004
5005 // Search each PM settings array in the kernel.
5006 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5007 if (iter) {
5008 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5009 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5010 index = array->getNextIndexOfObject(pmso, 0);
5011 if (-1 != index) {
5012 array->removeObject(index);
5013 }
5014 }
5015 }
5016
5017 PMSETTING_UNLOCK();
5018
5019 pmso->release();
5020 }
5021
5022 //******************************************************************************
5023 // informCPUStateChange
5024 //
5025 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5026 // running on battery, with the lid closed, etc.
5027 //
5028 // informCPUStateChange is a no-op on non x86 systems
5029 // only x86 has explicit support in the IntelCPUPowerManagement kext
5030 //******************************************************************************
5031
5032 void
informCPUStateChange(uint32_t type,uint32_t value)5033 IOPMrootDomain::informCPUStateChange(
5034 uint32_t type,
5035 uint32_t value )
5036 {
5037 #if defined(__i386__) || defined(__x86_64__)
5038
5039 pmioctlVariableInfo_t varInfoStruct;
5040 int pmCPUret = 0;
5041 const char *varNameStr = NULL;
5042 int32_t *varIndex = NULL;
5043
5044 if (kInformAC == type) {
5045 varNameStr = kIOPMRootDomainBatPowerCString;
5046 varIndex = &idxPMCPULimitedPower;
5047 } else if (kInformLid == type) {
5048 varNameStr = kIOPMRootDomainLidCloseCString;
5049 varIndex = &idxPMCPUClamshell;
5050 } else {
5051 return;
5052 }
5053
5054 // Set the new value!
5055 // pmCPUControl will assign us a new ID if one doesn't exist yet
5056 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5057 varInfoStruct.varID = *varIndex;
5058 varInfoStruct.varType = vBool;
5059 varInfoStruct.varInitValue = value;
5060 varInfoStruct.varCurValue = value;
5061 strlcpy((char *)varInfoStruct.varName,
5062 (const char *)varNameStr,
5063 sizeof(varInfoStruct.varName));
5064
5065 // Set!
5066 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5067
5068 // pmCPU only assigns numerical id's when a new varName is specified
5069 if ((0 == pmCPUret)
5070 && (*varIndex == kCPUUnknownIndex)) {
5071 // pmCPUControl has assigned us a new variable ID.
5072 // Let's re-read the structure we just SET to learn that ID.
5073 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5074
5075 if (0 == pmCPUret) {
5076 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5077 *varIndex = varInfoStruct.varID;
5078 }
5079 }
5080
5081 return;
5082
5083 #endif /* __i386__ || __x86_64__ */
5084 }
5085
5086 // MARK: -
5087 // MARK: Deep Sleep Policy
5088
5089 #if HIBERNATION
5090
5091 //******************************************************************************
5092 // evaluateSystemSleepPolicy
5093 //******************************************************************************
5094
5095 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5096
5097 // Sleep flags
5098 enum {
5099 kIOPMSleepFlagHibernate = 0x00000001,
5100 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5101 };
5102
5103 struct IOPMSystemSleepPolicyEntry {
5104 uint32_t factorMask;
5105 uint32_t factorBits;
5106 uint32_t sleepFlags;
5107 uint32_t wakeEvents;
5108 } __attribute__((packed));
5109
5110 struct IOPMSystemSleepPolicyTable {
5111 uint32_t signature;
5112 uint16_t version;
5113 uint16_t entryCount;
5114 IOPMSystemSleepPolicyEntry entries[];
5115 } __attribute__((packed));
5116
5117 enum {
5118 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5119 kIOPMSleepAttributeHibernateSleep = 0x00000002
5120 };
5121
5122 static uint32_t
getSleepTypeAttributes(uint32_t sleepType)5123 getSleepTypeAttributes( uint32_t sleepType )
5124 {
5125 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5126 {
5127 /* invalid */ 0,
5128 /* abort */ 0,
5129 /* normal */ 0,
5130 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5131 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5132 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5133 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5134 /* deepidle */ 0
5135 };
5136
5137 if (sleepType >= kIOPMSleepTypeLast) {
5138 return 0;
5139 }
5140
5141 return sleepTypeAttributes[sleepType];
5142 }
5143
5144 bool
evaluateSystemSleepPolicy(IOPMSystemSleepParameters * params,int sleepPhase,uint32_t * hibMode)5145 IOPMrootDomain::evaluateSystemSleepPolicy(
5146 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5147 {
5148 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5149
5150 static const IONamedValue factorValues[] = {
5151 SLEEP_FACTOR( SleepTimerWake ),
5152 SLEEP_FACTOR( LidOpen ),
5153 SLEEP_FACTOR( ACPower ),
5154 SLEEP_FACTOR( BatteryLow ),
5155 SLEEP_FACTOR( StandbyNoDelay ),
5156 SLEEP_FACTOR( StandbyForced ),
5157 SLEEP_FACTOR( StandbyDisabled ),
5158 SLEEP_FACTOR( USBExternalDevice ),
5159 SLEEP_FACTOR( BluetoothHIDDevice ),
5160 SLEEP_FACTOR( ExternalMediaMounted ),
5161 SLEEP_FACTOR( ThunderboltDevice ),
5162 SLEEP_FACTOR( RTCAlarmScheduled ),
5163 SLEEP_FACTOR( MagicPacketWakeEnabled ),
5164 SLEEP_FACTOR( HibernateForced ),
5165 SLEEP_FACTOR( AutoPowerOffDisabled ),
5166 SLEEP_FACTOR( AutoPowerOffForced ),
5167 SLEEP_FACTOR( ExternalDisplay ),
5168 SLEEP_FACTOR( NetworkKeepAliveActive ),
5169 SLEEP_FACTOR( LocalUserActivity ),
5170 SLEEP_FACTOR( HibernateFailed ),
5171 SLEEP_FACTOR( ThermalWarning ),
5172 SLEEP_FACTOR( DisplayCaptured ),
5173 { 0, NULL }
5174 };
5175
5176 const IOPMSystemSleepPolicyTable * pt;
5177 OSSharedPtr<OSObject> prop;
5178 OSData * policyData;
5179 uint64_t currentFactors = 0;
5180 char currentFactorsBuf[512];
5181 uint32_t standbyDelay = 0;
5182 uint32_t powerOffDelay = 0;
5183 uint32_t powerOffTimer = 0;
5184 uint32_t standbyTimer = 0;
5185 uint32_t mismatch;
5186 bool standbyEnabled;
5187 bool powerOffEnabled;
5188 bool found = false;
5189
5190 // Get platform's sleep policy table
5191 if (!gSleepPolicyHandler) {
5192 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5193 if (!prop) {
5194 goto done;
5195 }
5196 }
5197
5198 // Fetch additional settings
5199 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5200 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5201 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5202 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5203 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5204 powerOffTimer = powerOffDelay;
5205 }
5206 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5207 standbyTimer = standbyDelay;
5208 }
5209
5210 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5211 sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5212 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5213
5214 currentFactorsBuf[0] = 0;
5215 // pmset level overrides
5216 if ((*hibMode & kIOHibernateModeOn) == 0) {
5217 if (!gSleepPolicyHandler) {
5218 standbyEnabled = false;
5219 powerOffEnabled = false;
5220 }
5221 } else if (!(*hibMode & kIOHibernateModeSleep)) {
5222 // Force hibernate (i.e. mode 25)
5223 // If standby is enabled, force standy.
5224 // If poweroff is enabled, force poweroff.
5225 if (standbyEnabled) {
5226 currentFactors |= kIOPMSleepFactorStandbyForced;
5227 } else if (powerOffEnabled) {
5228 currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5229 } else {
5230 currentFactors |= kIOPMSleepFactorHibernateForced;
5231 }
5232 }
5233
5234 // Current factors based on environment and assertions
5235 if (sleepTimerMaintenance) {
5236 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5237 }
5238 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5239 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5240 }
5241 if (!clamshellClosed) {
5242 currentFactors |= kIOPMSleepFactorLidOpen;
5243 }
5244 if (acAdaptorConnected) {
5245 currentFactors |= kIOPMSleepFactorACPower;
5246 }
5247 if (lowBatteryCondition) {
5248 hibernateMode = 0;
5249 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5250 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5251 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5252 } else {
5253 currentFactors |= kIOPMSleepFactorBatteryLow;
5254 }
5255 }
5256 if (!standbyDelay || !standbyTimer) {
5257 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5258 }
5259 if (standbyNixed || !standbyEnabled) {
5260 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5261 }
5262 if (resetTimers) {
5263 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5264 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5265 }
5266 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5267 kIOPMDriverAssertionLevelOff) {
5268 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5269 }
5270 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5271 kIOPMDriverAssertionLevelOff) {
5272 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5273 }
5274 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5275 kIOPMDriverAssertionLevelOff) {
5276 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5277 }
5278 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5279 kIOPMDriverAssertionLevelOff) {
5280 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5281 }
5282 if (_scheduledAlarmMask != 0) {
5283 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5284 }
5285 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5286 kIOPMDriverAssertionLevelOff) {
5287 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5288 }
5289 #define TCPKEEPALIVE 1
5290 #if TCPKEEPALIVE
5291 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5292 kIOPMDriverAssertionLevelOff) {
5293 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5294 }
5295 #endif
5296 if (!powerOffEnabled) {
5297 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5298 }
5299 if (desktopMode) {
5300 currentFactors |= kIOPMSleepFactorExternalDisplay;
5301 }
5302 if (userWasActive) {
5303 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5304 }
5305 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5306 currentFactors |= kIOPMSleepFactorHibernateFailed;
5307 }
5308 if (thermalWarningState) {
5309 currentFactors |= kIOPMSleepFactorThermalWarning;
5310 }
5311
5312 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5313 uint32_t factor = 1 << factorBit;
5314 if (factor & currentFactors) {
5315 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5316 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5317 }
5318 }
5319 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5320
5321 if (gSleepPolicyHandler) {
5322 uint32_t savedHibernateMode;
5323 IOReturn result;
5324
5325 if (!gSleepPolicyVars) {
5326 gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5327 }
5328 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5329 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion;
5330 gSleepPolicyVars->currentCapability = _currentCapability;
5331 gSleepPolicyVars->highestCapability = _highestCapability;
5332 gSleepPolicyVars->sleepFactors = currentFactors;
5333 gSleepPolicyVars->sleepReason = lastSleepReason;
5334 gSleepPolicyVars->sleepPhase = sleepPhase;
5335 gSleepPolicyVars->standbyDelay = standbyDelay;
5336 gSleepPolicyVars->standbyTimer = standbyTimer;
5337 gSleepPolicyVars->poweroffDelay = powerOffDelay;
5338 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask;
5339 gSleepPolicyVars->poweroffTimer = powerOffTimer;
5340
5341 if (kIOPMSleepPhase0 == sleepPhase) {
5342 // preserve hibernateMode
5343 savedHibernateMode = gSleepPolicyVars->hibernateMode;
5344 gSleepPolicyVars->hibernateMode = *hibMode;
5345 } else if (kIOPMSleepPhase1 == sleepPhase) {
5346 // use original hibernateMode for phase2
5347 gSleepPolicyVars->hibernateMode = *hibMode;
5348 }
5349
5350 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5351
5352 if (kIOPMSleepPhase0 == sleepPhase) {
5353 // restore hibernateMode
5354 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5355 }
5356
5357 if ((result != kIOReturnSuccess) ||
5358 (kIOPMSleepTypeInvalid == params->sleepType) ||
5359 (params->sleepType >= kIOPMSleepTypeLast) ||
5360 (kIOPMSystemSleepParametersVersion != params->version)) {
5361 MSG("sleep policy handler error\n");
5362 goto done;
5363 }
5364
5365 if ((getSleepTypeAttributes(params->sleepType) &
5366 kIOPMSleepAttributeHibernateSetup) &&
5367 ((*hibMode & kIOHibernateModeOn) == 0)) {
5368 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5369 }
5370
5371 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5372 params->version, params->sleepType, params->sleepFlags,
5373 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5374 found = true;
5375 goto done;
5376 }
5377
5378 // Policy table is meaningless without standby enabled
5379 if (!standbyEnabled) {
5380 goto done;
5381 }
5382
5383 // Validate the sleep policy table
5384 policyData = OSDynamicCast(OSData, prop.get());
5385 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5386 goto done;
5387 }
5388
5389 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5390 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5391 (pt->version != 1) || (0 == pt->entryCount)) {
5392 goto done;
5393 }
5394
5395 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5396 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5397 goto done;
5398 }
5399
5400 for (uint32_t i = 0; i < pt->entryCount; i++) {
5401 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5402 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5403
5404 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5405 entry->factorMask, entry->factorBits,
5406 entry->sleepFlags, entry->wakeEvents, mismatch);
5407 if (mismatch) {
5408 continue;
5409 }
5410
5411 DLOG("^ found match\n");
5412 found = true;
5413
5414 params->version = kIOPMSystemSleepParametersVersion;
5415 params->reserved1 = 1;
5416 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5417 params->sleepType = kIOPMSleepTypeStandby;
5418 } else {
5419 params->sleepType = kIOPMSleepTypeNormalSleep;
5420 }
5421
5422 params->ecWakeEvents = entry->wakeEvents;
5423 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5424 if (kIOPMSleepPhase2 == sleepPhase) {
5425 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5426
5427 if (!_standbyTimerResetSeconds ||
5428 (now_secs <= _standbyTimerResetSeconds)) {
5429 // Reset standby timer adjustment
5430 _standbyTimerResetSeconds = now_secs;
5431 DLOG("standby delay %u, reset %u\n",
5432 standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5433 } else if (standbyDelay) {
5434 // Shorten the standby delay timer
5435 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5436 if (standbyDelay > elapsed) {
5437 standbyDelay -= elapsed;
5438 } else {
5439 standbyDelay = 1; // must be > 0
5440 }
5441 DLOG("standby delay %u, elapsed %u\n",
5442 standbyDelay, (uint32_t) elapsed);
5443 }
5444 }
5445 params->ecWakeTimer = standbyDelay;
5446 } else if (kIOPMSleepPhase2 == sleepPhase) {
5447 // A sleep that does not enable the sleep timer will reset
5448 // the standby delay adjustment.
5449 _standbyTimerResetSeconds = 0;
5450 }
5451 break;
5452 }
5453
5454 done:
5455 return found;
5456 }
5457
5458 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5459
5460 void
evaluateSystemSleepPolicyEarly(void)5461 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5462 {
5463 // Evaluate early (priority interest phase), before drivers sleep.
5464
5465 DLOG("%s\n", __FUNCTION__);
5466 removeProperty(kIOPMSystemSleepParametersKey);
5467
5468 // Full wake resets the standby timer delay adjustment
5469 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5470 _standbyTimerResetSeconds = 0;
5471 }
5472
5473 hibernateDisabled = false;
5474 hibernateMode = 0;
5475 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5476
5477 // Save for late evaluation if sleep is aborted
5478 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5479
5480 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5481 &hibernateMode)) {
5482 if (!hibernateRetry &&
5483 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5484 kIOPMSleepAttributeHibernateSetup) == 0)) {
5485 // skip hibernate setup
5486 hibernateDisabled = true;
5487 }
5488 }
5489
5490 // Publish IOPMSystemSleepType
5491 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5492 if (sleepType == kIOPMSleepTypeInvalid) {
5493 // no sleep policy
5494 sleepType = kIOPMSleepTypeNormalSleep;
5495 if (hibernateMode & kIOHibernateModeOn) {
5496 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5497 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5498 }
5499 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5500 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5501 // report the lowest possible sleep state
5502 sleepType = kIOPMSleepTypePowerOff;
5503 }
5504
5505 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5506 }
5507
5508 void
evaluateSystemSleepPolicyFinal(void)5509 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5510 {
5511 IOPMSystemSleepParameters params;
5512 OSSharedPtr<OSData> paramsData;
5513 bool wakeNow;
5514 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5515
5516 DLOG("%s\n", __FUNCTION__);
5517
5518 bzero(¶ms, sizeof(params));
5519 wakeNow = false;
5520 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) {
5521 if ((kIOPMSleepTypeStandby == params.sleepType)
5522 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5523 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5524 & gSleepPolicyVars->sleepFactors))) {
5525 standbyNixed = true;
5526 wakeNow = true;
5527 }
5528 if (wakeNow
5529 || ((hibernateDisabled || hibernateAborted) &&
5530 (getSleepTypeAttributes(params.sleepType) &
5531 kIOPMSleepAttributeHibernateSetup))) {
5532 // Final evaluation picked a state requiring hibernation,
5533 // but hibernate isn't going to proceed. Arm a short sleep using
5534 // the early non-hibernate sleep parameters.
5535 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params));
5536 params.sleepType = kIOPMSleepTypeAbortedSleep;
5537 params.ecWakeTimer = 1;
5538 if (standbyNixed) {
5539 resetTimers = true;
5540 } else {
5541 // Set hibernateRetry flag to force hibernate setup on the
5542 // next sleep.
5543 hibernateRetry = true;
5544 }
5545 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5546 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5547 } else {
5548 hibernateRetry = false;
5549 }
5550
5551 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5552 resetTimers = false;
5553 }
5554
5555 paramsData = OSData::withValue(params);
5556 if (paramsData) {
5557 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5558 }
5559
5560 if (getSleepTypeAttributes(params.sleepType) &
5561 kIOPMSleepAttributeHibernateSleep) {
5562 // Disable sleep to force hibernation
5563 gIOHibernateMode &= ~kIOHibernateModeSleep;
5564 }
5565 }
5566 }
5567
5568 bool
getHibernateSettings(uint32_t * hibernateModePtr,uint32_t * hibernateFreeRatio,uint32_t * hibernateFreeTime)5569 IOPMrootDomain::getHibernateSettings(
5570 uint32_t * hibernateModePtr,
5571 uint32_t * hibernateFreeRatio,
5572 uint32_t * hibernateFreeTime )
5573 {
5574 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5575 // has updated the hibernateDisabled flag.
5576
5577 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5578 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5579 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5580 if (hibernateDisabled) {
5581 *hibernateModePtr = 0;
5582 } else if (gSleepPolicyHandler) {
5583 *hibernateModePtr = hibernateMode;
5584 }
5585 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5586 return ok;
5587 }
5588
5589 bool
getSleepOption(const char * key,uint32_t * option)5590 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5591 {
5592 OSSharedPtr<OSObject> optionsProp;
5593 OSDictionary * optionsDict;
5594 OSSharedPtr<OSObject> obj;
5595 OSNumber * num;
5596 bool ok = false;
5597
5598 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5599 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5600
5601 if (optionsDict) {
5602 obj.reset(optionsDict->getObject(key), OSRetain);
5603 }
5604 if (!obj) {
5605 obj = copyProperty(key);
5606 }
5607 if (obj) {
5608 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5609 *option = num->unsigned32BitValue();
5610 ok = true;
5611 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5612 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5613 ok = true;
5614 }
5615 }
5616
5617 return ok;
5618 }
5619 #endif /* HIBERNATION */
5620
5621 IOReturn
getSystemSleepType(uint32_t * sleepType,uint32_t * standbyTimer)5622 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5623 {
5624 #if HIBERNATION
5625 IOPMSystemSleepParameters params;
5626 uint32_t hibMode = 0;
5627 bool ok;
5628
5629 if (gIOPMWorkLoop->inGate() == false) {
5630 IOReturn ret = gIOPMWorkLoop->runAction(
5631 OSMemberFunctionCast(IOWorkLoop::Action, this,
5632 &IOPMrootDomain::getSystemSleepType),
5633 (OSObject *) this,
5634 (void *) sleepType, (void *) standbyTimer);
5635 return ret;
5636 }
5637
5638 getSleepOption(kIOHibernateModeKey, &hibMode);
5639 bzero(¶ms, sizeof(params));
5640
5641 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode);
5642 if (ok) {
5643 *sleepType = params.sleepType;
5644 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5645 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5646 DLOG("Standby delay is not set\n");
5647 *standbyTimer = 0;
5648 }
5649 return kIOReturnSuccess;
5650 }
5651 #endif
5652
5653 return kIOReturnUnsupported;
5654 }
5655
5656 // MARK: -
5657 // MARK: Shutdown and Restart
5658
5659 //******************************************************************************
5660 // handlePlatformHaltRestart
5661 //
5662 //******************************************************************************
5663
5664 // Phases while performing shutdown/restart
5665 typedef enum {
5666 kNotifyDone = 0x00,
5667 kNotifyPriorityClients = 0x10,
5668 kNotifyPowerPlaneDrivers = 0x20,
5669 kNotifyHaltRestartAction = 0x30,
5670 kQuiescePM = 0x40,
5671 } shutdownPhase_t;
5672
5673
5674 struct HaltRestartApplierContext {
5675 IOPMrootDomain * RootDomain;
5676 unsigned long PowerState;
5677 IOPMPowerFlags PowerFlags;
5678 UInt32 MessageType;
5679 UInt32 Counter;
5680 const char * LogString;
5681 shutdownPhase_t phase;
5682
5683 IOServiceInterestHandler handler;
5684 } gHaltRestartCtx;
5685
5686 const char *
shutdownPhase2String(shutdownPhase_t phase)5687 shutdownPhase2String(shutdownPhase_t phase)
5688 {
5689 switch (phase) {
5690 case kNotifyDone:
5691 return "Notifications completed";
5692 case kNotifyPriorityClients:
5693 return "Notifying priority clients";
5694 case kNotifyPowerPlaneDrivers:
5695 return "Notifying power plane drivers";
5696 case kNotifyHaltRestartAction:
5697 return "Notifying HaltRestart action handlers";
5698 case kQuiescePM:
5699 return "Quiescing PM";
5700 default:
5701 return "Unknown";
5702 }
5703 }
5704
5705 static void
platformHaltRestartApplier(OSObject * object,void * context)5706 platformHaltRestartApplier( OSObject * object, void * context )
5707 {
5708 IOPowerStateChangeNotification notify;
5709 HaltRestartApplierContext * ctx;
5710 AbsoluteTime startTime, elapsedTime;
5711 uint32_t deltaTime;
5712
5713 ctx = (HaltRestartApplierContext *) context;
5714
5715 _IOServiceInterestNotifier * notifier;
5716 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5717 memset(¬ify, 0, sizeof(notify));
5718 notify.powerRef = (void *)(uintptr_t)ctx->Counter;
5719 notify.returnValue = 0;
5720 notify.stateNumber = ctx->PowerState;
5721 notify.stateFlags = ctx->PowerFlags;
5722
5723 if (notifier) {
5724 ctx->handler = notifier->handler;
5725 }
5726
5727 clock_get_uptime(&startTime);
5728 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify );
5729 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5730
5731 if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5732 LOG("%s handler %p took %u ms\n",
5733 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5734 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5735 }
5736
5737 ctx->handler = NULL;
5738 ctx->Counter++;
5739 }
5740
5741 static void
quiescePowerTreeCallback(void * target,void * param)5742 quiescePowerTreeCallback( void * target, void * param )
5743 {
5744 IOLockLock(gPMHaltLock);
5745 gPMQuiesced = true;
5746 thread_wakeup(param);
5747 IOLockUnlock(gPMHaltLock);
5748 }
5749
5750 void
handlePlatformHaltRestart(UInt32 pe_type)5751 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5752 {
5753 AbsoluteTime startTime, elapsedTime;
5754 uint32_t deltaTime;
5755 bool nvramSync = false;
5756
5757 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5758 gHaltRestartCtx.RootDomain = this;
5759
5760 clock_get_uptime(&startTime);
5761 switch (pe_type) {
5762 case kPEHaltCPU:
5763 case kPEUPSDelayHaltCPU:
5764 gHaltRestartCtx.PowerState = OFF_STATE;
5765 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5766 gHaltRestartCtx.LogString = "PowerOff";
5767 nvramSync = true;
5768 break;
5769
5770 case kPERestartCPU:
5771 gHaltRestartCtx.PowerState = RESTART_STATE;
5772 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5773 gHaltRestartCtx.LogString = "Restart";
5774 nvramSync = true;
5775 break;
5776
5777 case kPEPagingOff:
5778 gHaltRestartCtx.PowerState = ON_STATE;
5779 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5780 gHaltRestartCtx.LogString = "PagingOff";
5781 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5782 #if HIBERNATION
5783 IOHibernateSystemRestart();
5784 #endif
5785 break;
5786
5787 default:
5788 return;
5789 }
5790
5791 if (nvramSync) {
5792 PESyncNVRAM();
5793 }
5794
5795 gHaltRestartCtx.phase = kNotifyPriorityClients;
5796 // Notify legacy clients
5797 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5798
5799 // For normal shutdown, turn off File Server Mode.
5800 if (kPEHaltCPU == pe_type) {
5801 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5802 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5803 if (setting && num) {
5804 setPMSetting(setting.get(), num.get());
5805 }
5806 }
5807
5808 if (kPEPagingOff != pe_type) {
5809 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5810 // Notify in power tree order
5811 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5812 }
5813
5814 gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5815 #if defined(XNU_TARGET_OS_OSX)
5816 IOCPURunPlatformHaltRestartActions(pe_type);
5817 #else /* !defined(XNU_TARGET_OS_OSX) */
5818 if (kPEPagingOff != pe_type) {
5819 IOCPURunPlatformHaltRestartActions(pe_type);
5820 }
5821 #endif /* !defined(XNU_TARGET_OS_OSX) */
5822
5823 // Wait for PM to quiesce
5824 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5825 gHaltRestartCtx.phase = kQuiescePM;
5826 AbsoluteTime quiesceTime = mach_absolute_time();
5827
5828 IOLockLock(gPMHaltLock);
5829 gPMQuiesced = false;
5830 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5831 kIOReturnSuccess) {
5832 while (!gPMQuiesced) {
5833 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5834 }
5835 }
5836 IOLockUnlock(gPMHaltLock);
5837 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5838 DLOG("PM quiesce took %u ms\n", deltaTime);
5839 halt_log_enter("Quiesce", NULL, elapsedTime);
5840 }
5841 gHaltRestartCtx.phase = kNotifyDone;
5842
5843 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5844 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5845
5846 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5847
5848 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5849 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5850
5851 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5852 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5853 }
5854
5855 checkShutdownTimeout();
5856 }
5857
5858 bool
checkShutdownTimeout()5859 IOPMrootDomain::checkShutdownTimeout()
5860 {
5861 AbsoluteTime elapsedTime;
5862 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5863
5864 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5865 return true;
5866 }
5867 return false;
5868 }
5869
5870 void
panicWithShutdownLog(uint32_t timeoutInMs)5871 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5872 {
5873 if (gHaltLog) {
5874 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5875 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5876 }
5877 panic("%s timed out in phase '%s'. Total %d ms:%s",
5878 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5879 } else {
5880 panic("%s timed out in phase \'%s\'. Total %d ms",
5881 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5882 }
5883 }
5884
5885 //******************************************************************************
5886 // shutdownSystem
5887 //
5888 //******************************************************************************
5889
5890 IOReturn
shutdownSystem(void)5891 IOPMrootDomain::shutdownSystem( void )
5892 {
5893 return kIOReturnUnsupported;
5894 }
5895
5896 //******************************************************************************
5897 // restartSystem
5898 //
5899 //******************************************************************************
5900
5901 IOReturn
restartSystem(void)5902 IOPMrootDomain::restartSystem( void )
5903 {
5904 return kIOReturnUnsupported;
5905 }
5906
5907 // MARK: -
5908 // MARK: System Capability
5909
5910 //******************************************************************************
5911 // tagPowerPlaneService
5912 //
5913 // Running on PM work loop thread.
5914 //******************************************************************************
5915
5916 void
tagPowerPlaneService(IOService * service,IOPMActions * actions,IOPMPowerStateIndex maxPowerState)5917 IOPMrootDomain::tagPowerPlaneService(
5918 IOService * service,
5919 IOPMActions * actions,
5920 IOPMPowerStateIndex maxPowerState )
5921 {
5922 uint32_t flags = 0;
5923
5924 memset(actions, 0, sizeof(*actions));
5925 actions->target = this;
5926
5927 if (service == this) {
5928 actions->actionPowerChangeStart =
5929 OSMemberFunctionCast(
5930 IOPMActionPowerChangeStart, this,
5931 &IOPMrootDomain::handleOurPowerChangeStart);
5932
5933 actions->actionPowerChangeDone =
5934 OSMemberFunctionCast(
5935 IOPMActionPowerChangeDone, this,
5936 &IOPMrootDomain::handleOurPowerChangeDone);
5937
5938 actions->actionPowerChangeOverride =
5939 OSMemberFunctionCast(
5940 IOPMActionPowerChangeOverride, this,
5941 &IOPMrootDomain::overrideOurPowerChange);
5942 return;
5943 }
5944
5945 #if DISPLAY_WRANGLER_PRESENT
5946 if (NULL != service->metaCast("IODisplayWrangler")) {
5947 // XXX should this really retain?
5948 wrangler.reset(service, OSRetain);
5949 wrangler->registerInterest(gIOGeneralInterest,
5950 &displayWranglerNotification, this, NULL);
5951
5952 // found the display wrangler, check for any display assertions already created
5953 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5954 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5955 wrangler->setIgnoreIdleTimer( true );
5956 }
5957 flags |= kPMActionsFlagIsDisplayWrangler;
5958 }
5959 #endif /* DISPLAY_WRANGLER_PRESENT */
5960
5961 if (service->propertyExists("IOPMStrictTreeOrder")) {
5962 flags |= kPMActionsFlagIsGraphicsDriver;
5963 }
5964 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5965 flags |= kPMActionsFlagIsAudioDriver;
5966 }
5967
5968 // Find the power connection object that is a child of the PCI host
5969 // bridge, and has a graphics/audio device attached below. Mark the
5970 // power branch for delayed child notifications.
5971
5972 if (flags) {
5973 IORegistryEntry * child = service;
5974 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
5975
5976 while (child != this) {
5977 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
5978 // Skip delaying notifications and clamping power on external graphics and audio devices.
5979 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
5980 flags = 0;
5981 break;
5982 }
5983 if ((parent == pciHostBridgeDriver) ||
5984 (parent == this)) {
5985 if (OSDynamicCast(IOPowerConnection, child)) {
5986 IOPowerConnection * conn = (IOPowerConnection *) child;
5987 conn->delayChildNotification = true;
5988 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
5989 }
5990 break;
5991 }
5992 child = parent;
5993 parent = child->getParentEntry(gIOPowerPlane);
5994 }
5995 }
5996
5997 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
5998 if (prop) {
5999 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6000 if (num) {
6001 actions->darkWakePowerState = num->unsigned32BitValue();
6002 if (actions->darkWakePowerState < maxPowerState) {
6003 flags |= kPMActionsFlagHasDarkWakePowerState;
6004 }
6005 }
6006 }
6007
6008
6009 if (flags) {
6010 DLOG("%s tag flags %x\n", service->getName(), flags);
6011 actions->flags |= flags;
6012 actions->actionPowerChangeOverride =
6013 OSMemberFunctionCast(
6014 IOPMActionPowerChangeOverride, this,
6015 &IOPMrootDomain::overridePowerChangeForService);
6016
6017 if (flags & kPMActionsFlagIsDisplayWrangler) {
6018 actions->actionActivityTickle =
6019 OSMemberFunctionCast(
6020 IOPMActionActivityTickle, this,
6021 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6022
6023 actions->actionUpdatePowerClient =
6024 OSMemberFunctionCast(
6025 IOPMActionUpdatePowerClient, this,
6026 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6027 }
6028 return;
6029 }
6030
6031 // Locate the first PCI host bridge for PMTrace.
6032 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6033 IOService * provider = service->getProvider();
6034 if (OSDynamicCast(IOPlatformDevice, provider) &&
6035 provider->inPlane(gIODTPlane)) {
6036 pciHostBridgeDevice.reset(provider, OSNoRetain);
6037 pciHostBridgeDriver.reset(service, OSNoRetain);
6038 DLOG("PMTrace found PCI host bridge %s->%s\n",
6039 provider->getName(), service->getName());
6040 }
6041 }
6042
6043 // Tag top-level PCI devices. The order of PMinit() call does not
6044 // change across boots and is used as the PCI bit number.
6045 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6046 // Would prefer to check built-in property, but tagPowerPlaneService()
6047 // is called before pciDevice->registerService().
6048 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6049 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6050 int bit = pmTracer->recordTopLevelPCIDevice( service );
6051 if (bit >= 0) {
6052 // Save the assigned bit for fast lookup.
6053 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6054
6055 actions->actionPowerChangeStart =
6056 OSMemberFunctionCast(
6057 IOPMActionPowerChangeStart, this,
6058 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6059
6060 actions->actionPowerChangeDone =
6061 OSMemberFunctionCast(
6062 IOPMActionPowerChangeDone, this,
6063 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6064 }
6065 }
6066 }
6067 }
6068
6069 //******************************************************************************
6070 // PM actions for root domain
6071 //******************************************************************************
6072
6073 void
overrideOurPowerChange(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex * inOutPowerState,IOPMPowerChangeFlags * inOutChangeFlags)6074 IOPMrootDomain::overrideOurPowerChange(
6075 IOService * service,
6076 IOPMActions * actions,
6077 const IOPMRequest * request,
6078 IOPMPowerStateIndex * inOutPowerState,
6079 IOPMPowerChangeFlags * inOutChangeFlags )
6080 {
6081 uint32_t changeFlags = *inOutChangeFlags;
6082 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6083 uint32_t currentPowerState = (uint32_t) getPowerState();
6084
6085 if (request->getTag() == 0) {
6086 // Set a tag for any request that originates from IOServicePM
6087 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6088 }
6089
6090 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6091 getPowerStateString(currentPowerState),
6092 getPowerStateString(desiredPowerState),
6093 _currentCapability, changeFlags,
6094 request->getTag());
6095
6096
6097 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6098 /*
6099 * ASBM send lowBattery notifications every 1 second until the device
6100 * enters hibernation. This queues up multiple sleep requests.
6101 * After the device wakes from hibernation, none of these previously
6102 * queued sleep requests are valid.
6103 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6104 * and is cleared at the very last point in sleep.
6105 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6106 * lowBatteryCondition is invalid
6107 */
6108 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6109 if (!lowBatteryCondition) {
6110 DLOG("Duplicate lowBattery sleep");
6111 *inOutChangeFlags |= kIOPMNotDone;
6112 return;
6113 }
6114 }
6115 #endif
6116
6117 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6118 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6119 *inOutChangeFlags |= kIOPMNotDone;
6120 return;
6121 }
6122
6123 if (changeFlags & kIOPMParentInitiated) {
6124 // Root parent is permanently pegged at max power,
6125 // a parent initiated power change is unexpected.
6126 *inOutChangeFlags |= kIOPMNotDone;
6127 return;
6128 }
6129
6130 if (desiredPowerState < currentPowerState) {
6131 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6132 // Root domain is dropping power state from ON->SLEEP.
6133 // If system is in full wake, first enter dark wake by
6134 // converting the power drop to a capability change.
6135 // Once in dark wake, transition to sleep state ASAP.
6136
6137 darkWakeToSleepASAP = true;
6138
6139 // Drop graphics and audio capability
6140 _desiredCapability &= ~(
6141 kIOPMSystemCapabilityGraphics |
6142 kIOPMSystemCapabilityAudio);
6143
6144 // Convert to capability change (ON->ON)
6145 *inOutPowerState = getRUN_STATE();
6146 *inOutChangeFlags |= kIOPMSynchronize;
6147
6148 // Revert device desire from SLEEP to ON
6149 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6150 } else {
6151 // System is already in dark wake, ok to drop power state.
6152 // Broadcast root power down to entire tree.
6153 *inOutChangeFlags |= kIOPMRootChangeDown;
6154 }
6155 } else if (desiredPowerState > currentPowerState) {
6156 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6157 // Broadcast power up when waking from sleep, but not for the
6158 // initial power change at boot by checking for cpu capability.
6159 *inOutChangeFlags |= kIOPMRootChangeUp;
6160 }
6161 }
6162 }
6163
6164 void
handleOurPowerChangeStart(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex newPowerState,IOPMPowerChangeFlags * inOutChangeFlags)6165 IOPMrootDomain::handleOurPowerChangeStart(
6166 IOService * service,
6167 IOPMActions * actions,
6168 const IOPMRequest * request,
6169 IOPMPowerStateIndex newPowerState,
6170 IOPMPowerChangeFlags * inOutChangeFlags )
6171 {
6172 IOPMRequestTag requestTag = request->getTag();
6173 IOPMRequestTag sleepReason;
6174
6175 uint32_t changeFlags = *inOutChangeFlags;
6176 uint32_t currentPowerState = (uint32_t) getPowerState();
6177 bool publishSleepReason = false;
6178
6179 // Check if request has a valid sleep reason
6180 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6181 if (sleepReason < kIOPMSleepReasonClamshell) {
6182 sleepReason = kIOPMSleepReasonIdle;
6183 }
6184
6185 _systemTransitionType = kSystemTransitionNone;
6186 _systemMessageClientMask = 0;
6187 capabilityLoss = false;
6188 toldPowerdCapWillChange = false;
6189
6190 // Emergency notifications may arrive after the initial sleep request
6191 // has been queued. Override the sleep reason so powerd and others can
6192 // treat this as an emergency sleep.
6193 if (lowBatteryCondition) {
6194 sleepReason = kIOPMSleepReasonLowPower;
6195 } else if (thermalEmergencyState) {
6196 sleepReason = kIOPMSleepReasonThermalEmergency;
6197 }
6198
6199 // 1. Explicit capability change.
6200 if (changeFlags & kIOPMSynchronize) {
6201 if (newPowerState == ON_STATE) {
6202 if (changeFlags & kIOPMSyncNoChildNotify) {
6203 _systemTransitionType = kSystemTransitionNewCapClient;
6204 } else {
6205 _systemTransitionType = kSystemTransitionCapability;
6206 }
6207 }
6208 }
6209 // 2. Going to sleep (cancellation still possible).
6210 else if (newPowerState < currentPowerState) {
6211 _systemTransitionType = kSystemTransitionSleep;
6212 }
6213 // 3. Woke from (idle or demand) sleep.
6214 else if (!systemBooting &&
6215 (changeFlags & kIOPMSelfInitiated) &&
6216 (newPowerState > currentPowerState)) {
6217 _systemTransitionType = kSystemTransitionWake;
6218 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6219
6220 // Early exit from dark wake to full (e.g. LID open)
6221 if (kFullWakeReasonNone != fullWakeReason) {
6222 _desiredCapability |= (
6223 kIOPMSystemCapabilityGraphics |
6224 kIOPMSystemCapabilityAudio);
6225
6226 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6227 if (fullWakeReason == kFullWakeReasonLocalUser) {
6228 darkWakeExit = true;
6229 darkWakeToSleepASAP = false;
6230 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6231 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6232 }
6233 #endif
6234 }
6235 #if HIBERNATION
6236 IOHibernateSetWakeCapabilities(_desiredCapability);
6237 #endif
6238 }
6239
6240 // Update pending wake capability at the beginning of every
6241 // state transition (including synchronize). This will become
6242 // the current capability at the end of the transition.
6243
6244 if (kSystemTransitionSleep == _systemTransitionType) {
6245 _pendingCapability = 0;
6246 capabilityLoss = true;
6247 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6248 _pendingCapability = _desiredCapability |
6249 kIOPMSystemCapabilityCPU |
6250 kIOPMSystemCapabilityNetwork;
6251
6252 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6253 _pendingCapability |= kIOPMSystemCapabilityAudio;
6254 }
6255
6256 if ((kSystemTransitionCapability == _systemTransitionType) &&
6257 (_pendingCapability == _currentCapability)) {
6258 // Cancel the PM state change.
6259 _systemTransitionType = kSystemTransitionNone;
6260 *inOutChangeFlags |= kIOPMNotDone;
6261 }
6262 if (__builtin_popcount(_pendingCapability) <
6263 __builtin_popcount(_currentCapability)) {
6264 capabilityLoss = true;
6265 }
6266 }
6267
6268 // 1. Capability change.
6269 if (kSystemTransitionCapability == _systemTransitionType) {
6270 // Dark to Full transition.
6271 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6272 tracePoint( kIOPMTracePointDarkWakeExit );
6273
6274 #if defined(XNU_TARGET_OS_OSX)
6275 // rdar://problem/65627936
6276 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6277 // power state drop, invalidate any request to drop power state already
6278 // in the queue, including the override variant, unless full wake cannot
6279 // be sustained. Any power state drop queued after this SustainFullWake
6280 // request will not be affected.
6281 if (checkSystemCanSustainFullWake()) {
6282 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6283 }
6284 #endif
6285
6286 willEnterFullWake();
6287 }
6288
6289 // Full to Dark transition.
6290 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6291 // Clear previous stats
6292 IOLockLock(pmStatsLock);
6293 if (pmStatsAppResponses) {
6294 pmStatsAppResponses = OSArray::withCapacity(5);
6295 }
6296 IOLockUnlock(pmStatsLock);
6297
6298 tracePoint( kIOPMTracePointDarkWakeEntry );
6299 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6300 _systemMessageClientMask = kSystemMessageClientPowerd |
6301 kSystemMessageClientLegacyApp;
6302
6303 // rdar://15971327
6304 // Prevent user active transitions before notifying clients
6305 // that system will sleep.
6306 preventTransitionToUserActive(true);
6307
6308 IOService::setAdvisoryTickleEnable( false );
6309
6310 // Publish the sleep reason for full to dark wake
6311 publishSleepReason = true;
6312 lastSleepReason = fullToDarkReason = sleepReason;
6313
6314 // Publish a UUID for the Sleep --> Wake cycle
6315 handlePublishSleepWakeUUID(true);
6316 if (sleepDelaysReport) {
6317 clock_get_uptime(&ts_sleepStart);
6318 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6319 }
6320
6321 darkWakeExit = false;
6322 }
6323 }
6324 // 2. System sleep.
6325 else if (kSystemTransitionSleep == _systemTransitionType) {
6326 // Beginning of a system sleep transition.
6327 // Cancellation is still possible.
6328 tracePoint( kIOPMTracePointSleepStarted );
6329
6330 _systemMessageClientMask = kSystemMessageClientAll;
6331 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6332 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6333 }
6334 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6335 // Kernel priority clients are only notified on the initial
6336 // transition to full wake, so don't notify them unless system
6337 // has gained graphics capability since the last system wake.
6338 _systemMessageClientMask &= ~kSystemMessageClientKernel;
6339 } else {
6340 // System was in full wake, but the downwards power transition is driven
6341 // by a request that originates from IOServicePM, so it isn't tagged with
6342 // a valid system sleep reason.
6343 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6344 // Publish the same reason for full to dark
6345 sleepReason = fullToDarkReason;
6346 }
6347 }
6348 #if HIBERNATION
6349 gIOHibernateState = 0;
6350 #endif
6351
6352 // Record the reason for dark wake back to sleep
6353 // System may not have ever achieved full wake
6354
6355 publishSleepReason = true;
6356 lastSleepReason = sleepReason;
6357 if (sleepDelaysReport) {
6358 clock_get_uptime(&ts_sleepStart);
6359 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6360 }
6361 }
6362 // 3. System wake.
6363 else if (kSystemTransitionWake == _systemTransitionType) {
6364 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6365 // Clear stats about sleep
6366
6367 if (AOT_STATE == newPowerState) {
6368 _pendingCapability = 0;
6369 }
6370
6371 if (AOT_STATE == currentPowerState) {
6372 // Wake events are no longer accepted after waking to AOT_STATE.
6373 // Re-enable wake event acceptance to append wake events claimed
6374 // during the AOT to ON_STATE transition.
6375 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6376 }
6377
6378 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6379 willEnterFullWake();
6380 }
6381 }
6382
6383 // The only location where the sleep reason is published. At this point
6384 // sleep can still be cancelled, but sleep reason should be published
6385 // early for logging purposes.
6386
6387 if (publishSleepReason) {
6388 static const char * IOPMSleepReasons[] =
6389 {
6390 kIOPMClamshellSleepKey,
6391 kIOPMPowerButtonSleepKey,
6392 kIOPMSoftwareSleepKey,
6393 kIOPMOSSwitchHibernationKey,
6394 kIOPMIdleSleepKey,
6395 kIOPMLowPowerSleepKey,
6396 kIOPMThermalEmergencySleepKey,
6397 kIOPMMaintenanceSleepKey,
6398 kIOPMSleepServiceExitKey,
6399 kIOPMDarkWakeThermalEmergencyKey,
6400 kIOPMNotificationWakeExitKey
6401 };
6402
6403 // Record sleep cause in IORegistry
6404 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6405 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6406 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6407 #if DEVELOPMENT || DEBUG
6408 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6409 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6410 "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6411 );
6412 #endif /* DEVELOPMENT || DEBUG */
6413 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6414 }
6415 }
6416
6417 if ((kSystemTransitionNone != _systemTransitionType) &&
6418 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6419 _systemStateGeneration++;
6420 systemDarkWake = false;
6421
6422 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6423 getPowerStateString(currentPowerState),
6424 getPowerStateString((uint32_t) newPowerState),
6425 _currentCapability, _pendingCapability,
6426 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6427 requestTag);
6428 #if DEVELOPMENT || DEBUG
6429 if (currentPowerState != (uint32_t) newPowerState) {
6430 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6431 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6432 "Start Power State Trans.",
6433 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6434 getPowerStateString(currentPowerState),
6435 getPowerStateString((uint32_t) newPowerState),
6436 _currentCapability,
6437 _pendingCapability,
6438 *inOutChangeFlags,
6439 _systemStateGeneration,
6440 _systemMessageClientMask,
6441 requestTag
6442 );
6443 }
6444 #endif /* DEVELOPMENT || DEBUG */
6445 }
6446
6447 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6448 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6449 }
6450 if (_aotNow && (ON_STATE == newPowerState)) {
6451 WAKEEVENT_LOCK();
6452 aotShouldExit(false, true);
6453 WAKEEVENT_UNLOCK();
6454 aotExit(false);
6455 }
6456 }
6457
6458 void
handleOurPowerChangeDone(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex oldPowerState,IOPMPowerChangeFlags changeFlags)6459 IOPMrootDomain::handleOurPowerChangeDone(
6460 IOService * service,
6461 IOPMActions * actions,
6462 const IOPMRequest * request,
6463 IOPMPowerStateIndex oldPowerState,
6464 IOPMPowerChangeFlags changeFlags )
6465 {
6466 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6467 _systemTransitionType = kSystemTransitionNone;
6468 return;
6469 }
6470
6471 if (_systemTransitionType != kSystemTransitionNone) {
6472 uint32_t currentPowerState = (uint32_t) getPowerState();
6473
6474 if (changeFlags & kIOPMNotDone) {
6475 // Power down was cancelled or vetoed.
6476 _pendingCapability = _currentCapability;
6477 lastSleepReason = 0;
6478
6479 // When sleep is cancelled or reverted, don't report
6480 // the target (lower) power state as the previous state.
6481 oldPowerState = currentPowerState;
6482
6483 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6484 CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6485 #if defined(XNU_TARGET_OS_OSX)
6486 pmPowerStateQueue->submitPowerEvent(
6487 kPowerEventPolicyStimulus,
6488 (void *) kStimulusDarkWakeReentry,
6489 _systemStateGeneration );
6490 #else /* !defined(XNU_TARGET_OS_OSX) */
6491 // On embedded, there are no factors that can prolong a
6492 // "darkWake" when a power down is vetoed. We need to
6493 // promote to "fullWake" at least once so that factors
6494 // that prevent idle sleep can assert themselves if required
6495 pmPowerStateQueue->submitPowerEvent(
6496 kPowerEventPolicyStimulus,
6497 (void *) kStimulusDarkWakeActivityTickle);
6498 #endif /* !defined(XNU_TARGET_OS_OSX) */
6499 }
6500
6501 // Revert device desire to max.
6502 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6503 } else {
6504 // Send message on dark wake to full wake promotion.
6505 // tellChangeUp() handles the normal SLEEP->ON case.
6506
6507 if (kSystemTransitionCapability == _systemTransitionType) {
6508 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6509 lastSleepReason = 0; // stop logging wrangler tickles
6510 tellClients(kIOMessageSystemHasPoweredOn);
6511 }
6512 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6513 // Going dark, reset full wake state
6514 // userIsActive will be cleared by wrangler powering down
6515 fullWakeReason = kFullWakeReasonNone;
6516
6517 if (ts_sleepStart) {
6518 clock_get_uptime(&wake2DarkwakeDelay);
6519 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6520 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6521 ts_sleepStart = 0;
6522 }
6523 }
6524 }
6525
6526 // Reset state after exiting from dark wake.
6527
6528 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6529 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6530 darkWakeMaintenance = false;
6531 darkWakeToSleepASAP = false;
6532 pciCantSleepValid = false;
6533 darkWakeSleepService = false;
6534
6535 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6536 // Remove the influence of display power assertion
6537 // before next system wake.
6538 if (wrangler) {
6539 wrangler->changePowerStateForRootDomain(
6540 kWranglerPowerStateMin );
6541 }
6542 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6543 }
6544 }
6545
6546 // Entered dark mode.
6547
6548 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6549 (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6550 // Queue an evaluation of whether to remain in dark wake,
6551 // and for how long. This serves the purpose of draining
6552 // any assertions from the queue.
6553
6554 pmPowerStateQueue->submitPowerEvent(
6555 kPowerEventPolicyStimulus,
6556 (void *) kStimulusDarkWakeEntry,
6557 _systemStateGeneration );
6558 }
6559 }
6560
6561 #if DEVELOPMENT || DEBUG
6562 if (currentPowerState != (uint32_t) oldPowerState) {
6563 record_system_event(SYSTEM_EVENT_TYPE_INFO,
6564 SYSTEM_EVENT_SUBSYSTEM_PMRD,
6565 "Finish Power State Trans.",
6566 "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6567 getPowerStateString((uint32_t)oldPowerState),
6568 getPowerStateString(currentPowerState),
6569 _currentCapability,
6570 _pendingCapability,
6571 changeFlags,
6572 _systemStateGeneration,
6573 _systemMessageClientMask,
6574 request->getTag()
6575 );
6576 }
6577 #endif /* DEVELOPMENT || DEBUG */
6578
6579 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6580 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6581 _currentCapability, _pendingCapability,
6582 changeFlags, _systemStateGeneration, _systemMessageClientMask,
6583 request->getTag());
6584
6585 if ((currentPowerState == ON_STATE) && pmAssertions) {
6586 pmAssertions->reportCPUBitAccounting();
6587 }
6588
6589 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6590 displayWakeCnt++;
6591 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6592 if (clamshellExists && fullWakeThreadCall) {
6593 AbsoluteTime deadline;
6594 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6595 thread_call_enter_delayed(fullWakeThreadCall, deadline);
6596 }
6597 #endif
6598 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6599 darkWakeCnt++;
6600 }
6601
6602 // Update current system capability.
6603 if (_currentCapability != _pendingCapability) {
6604 _currentCapability = _pendingCapability;
6605 }
6606
6607 // Update highest system capability.
6608
6609 _highestCapability |= _currentCapability;
6610
6611 if (darkWakePostTickle &&
6612 (kSystemTransitionWake == _systemTransitionType) &&
6613 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6614 kDarkWakeFlagPromotionLate) {
6615 darkWakePostTickle = false;
6616 reportUserInput();
6617 } else if (darkWakeExit) {
6618 requestFullWake( kFullWakeReasonLocalUser );
6619 }
6620
6621 // Reset tracepoint at completion of capability change,
6622 // completion of wake transition, and aborted sleep transition.
6623
6624 if ((_systemTransitionType == kSystemTransitionCapability) ||
6625 (_systemTransitionType == kSystemTransitionWake) ||
6626 ((_systemTransitionType == kSystemTransitionSleep) &&
6627 (changeFlags & kIOPMNotDone))) {
6628 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6629 tracePoint( kIOPMTracePointSystemUp );
6630 }
6631
6632 _systemTransitionType = kSystemTransitionNone;
6633 _systemMessageClientMask = 0;
6634 toldPowerdCapWillChange = false;
6635
6636 darkWakeLogClamp = false;
6637
6638 if (lowBatteryCondition) {
6639 privateSleepSystem(kIOPMSleepReasonLowPower);
6640 } else if (thermalEmergencyState) {
6641 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6642 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6643 // Request for full wake is removed while system is waking up to full wake
6644 DLOG("DisplayOn fullwake request is removed\n");
6645 handleSetDisplayPowerOn(false);
6646 }
6647
6648 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6649 pmPowerStateQueue->submitPowerEvent(
6650 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6651 }
6652 }
6653 }
6654
6655 //******************************************************************************
6656 // PM actions for graphics and audio.
6657 //******************************************************************************
6658
6659 void
overridePowerChangeForService(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex * inOutPowerState,IOPMPowerChangeFlags * inOutChangeFlags)6660 IOPMrootDomain::overridePowerChangeForService(
6661 IOService * service,
6662 IOPMActions * actions,
6663 const IOPMRequest * request,
6664 IOPMPowerStateIndex * inOutPowerState,
6665 IOPMPowerChangeFlags * inOutChangeFlags )
6666 {
6667 uint32_t powerState = (uint32_t) *inOutPowerState;
6668 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6669 const uint32_t actionFlags = actions->flags;
6670
6671 if (kSystemTransitionNone == _systemTransitionType) {
6672 // Not in midst of a system transition.
6673 // Do not set kPMActionsStatePowerClamped.
6674 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6675 bool enableClamp = false;
6676
6677 // For most drivers, enable the clamp during ON->Dark transition
6678 // which has the kIOPMSynchronize flag set in changeFlags.
6679 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6680 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6681 (changeFlags & kIOPMSynchronize)) {
6682 enableClamp = true;
6683 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6684 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6685 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6686 (changeFlags & kIOPMSynchronize)) {
6687 enableClamp = true;
6688 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6689 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6690 (changeFlags & kIOPMSynchronize)) {
6691 enableClamp = true;
6692 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6693 (_systemTransitionType == kSystemTransitionSleep)) {
6694 // For graphics drivers, clamp power when entering
6695 // system sleep. Not when dropping to dark wake.
6696 enableClamp = true;
6697 }
6698
6699 if (enableClamp) {
6700 actions->state |= kPMActionsStatePowerClamped;
6701 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6702 service->getName(), service->getRegistryEntryID(),
6703 _pendingCapability, powerState, changeFlags);
6704 }
6705 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6706 bool disableClamp = false;
6707
6708 if ((actionFlags & (
6709 kPMActionsFlagIsDisplayWrangler |
6710 kPMActionsFlagIsGraphicsDriver)) &&
6711 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6712 disableClamp = true;
6713 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6714 (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6715 disableClamp = true;
6716 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6717 (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6718 disableClamp = true;
6719 }
6720
6721 if (disableClamp) {
6722 actions->state &= ~kPMActionsStatePowerClamped;
6723 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6724 service->getName(), service->getRegistryEntryID(),
6725 _pendingCapability, powerState, changeFlags);
6726 }
6727 }
6728
6729 if (actions->state & kPMActionsStatePowerClamped) {
6730 uint32_t maxPowerState = 0;
6731
6732 // Determine the max power state allowed when clamp is enabled
6733 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6734 // Parent intiated power state changes
6735 if ((service->getPowerState() > maxPowerState) &&
6736 (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6737 maxPowerState++;
6738
6739 // Remove lingering effects of any tickle before entering
6740 // dark wake. It will take a new tickle to return to full
6741 // wake, so the existing tickle state is useless.
6742
6743 if (changeFlags & kIOPMDomainDidChange) {
6744 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6745 }
6746 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6747 maxPowerState++;
6748 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6749 maxPowerState = actions->darkWakePowerState;
6750 }
6751 } else {
6752 // Deny all self-initiated changes when power is limited.
6753 // Wrangler tickle should never defeat the limiter.
6754 maxPowerState = service->getPowerState();
6755 }
6756
6757 if (powerState > maxPowerState) {
6758 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6759 service->getName(), service->getRegistryEntryID(),
6760 powerState, maxPowerState, changeFlags);
6761 *inOutPowerState = maxPowerState;
6762
6763 if (darkWakePostTickle &&
6764 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6765 (changeFlags & kIOPMDomainWillChange) &&
6766 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6767 kDarkWakeFlagPromotionEarly)) {
6768 darkWakePostTickle = false;
6769 reportUserInput();
6770 }
6771 }
6772
6773 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6774 if (darkWakeLogClamp) {
6775 AbsoluteTime now;
6776 uint64_t nsec;
6777
6778 clock_get_uptime(&now);
6779 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6780 absolutetime_to_nanoseconds(now, &nsec);
6781 DLOG("dark wake power clamped after %u ms\n",
6782 ((int)((nsec) / NSEC_PER_MSEC)));
6783 }
6784 darkWakePowerClamped = true;
6785 }
6786 }
6787 }
6788
6789 void
handleActivityTickleForDisplayWrangler(IOService * service,IOPMActions * actions)6790 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6791 IOService * service,
6792 IOPMActions * actions )
6793 {
6794 #if DISPLAY_WRANGLER_PRESENT
6795 // Warning: Not running in PM work loop context - don't modify state !!!
6796 // Trap tickle directed to IODisplayWrangler while running with graphics
6797 // capability suppressed.
6798
6799 assert(service == wrangler);
6800
6801 clock_get_uptime(&userActivityTime);
6802 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6803 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6804 || (lastSleepReason == kIOPMSleepReasonSoftware));
6805 if (aborting) {
6806 userActivityCount++;
6807 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6808 userActivityCount, lastSleepReason);
6809 }
6810
6811 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6812 DLOG("display wrangler tickled\n");
6813 if (kIOLogPMRootDomain & gIOKitDebug) {
6814 OSReportWithBacktrace("Dark wake display tickle");
6815 }
6816 if (pmPowerStateQueue) {
6817 pmPowerStateQueue->submitPowerEvent(
6818 kPowerEventPolicyStimulus,
6819 (void *) kStimulusDarkWakeActivityTickle,
6820 true /* set wake type */ );
6821 }
6822 }
6823 #endif /* DISPLAY_WRANGLER_PRESENT */
6824 }
6825
6826 void
handleUpdatePowerClientForDisplayWrangler(IOService * service,IOPMActions * actions,const OSSymbol * powerClient,IOPMPowerStateIndex oldPowerState,IOPMPowerStateIndex newPowerState)6827 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6828 IOService * service,
6829 IOPMActions * actions,
6830 const OSSymbol * powerClient,
6831 IOPMPowerStateIndex oldPowerState,
6832 IOPMPowerStateIndex newPowerState )
6833 {
6834 #if DISPLAY_WRANGLER_PRESENT
6835 assert(service == wrangler);
6836
6837 // This function implements half of the user active detection
6838 // by monitoring changes to the display wrangler's device desire.
6839 //
6840 // User becomes active when either:
6841 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6842 // in max power state. This desire change in absence of a power state
6843 // change is detected within. This handles the case when user becomes
6844 // active while the display is already lit by setDisplayPowerOn().
6845 //
6846 // 2. Power state change to max, and DeviceDesire is also at max.
6847 // Handled by displayWranglerNotification().
6848 //
6849 // User becomes inactive when DeviceDesire drops to sleep state or below.
6850
6851 DLOG("wrangler %s (ps %u, %u->%u)\n",
6852 powerClient->getCStringNoCopy(),
6853 (uint32_t) service->getPowerState(),
6854 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6855
6856 if (powerClient == gIOPMPowerClientDevice) {
6857 if ((newPowerState > oldPowerState) &&
6858 (newPowerState == kWranglerPowerStateMax) &&
6859 (service->getPowerState() == kWranglerPowerStateMax)) {
6860 evaluatePolicy( kStimulusEnterUserActiveState );
6861 } else if ((newPowerState < oldPowerState) &&
6862 (newPowerState <= kWranglerPowerStateSleep)) {
6863 evaluatePolicy( kStimulusLeaveUserActiveState );
6864 }
6865 }
6866
6867 if (newPowerState <= kWranglerPowerStateSleep) {
6868 evaluatePolicy( kStimulusDisplayWranglerSleep );
6869 } else if (newPowerState == kWranglerPowerStateMax) {
6870 evaluatePolicy( kStimulusDisplayWranglerWake );
6871 }
6872 #endif /* DISPLAY_WRANGLER_PRESENT */
6873 }
6874
6875 //******************************************************************************
6876 // User active state management
6877 //******************************************************************************
6878
6879 void
preventTransitionToUserActive(bool prevent)6880 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6881 {
6882 #if DISPLAY_WRANGLER_PRESENT
6883 _preventUserActive = prevent;
6884 if (wrangler && !_preventUserActive) {
6885 // Allowing transition to user active, but the wrangler may have
6886 // already powered ON in case of sleep cancel/revert. Poll the
6887 // same conditions checked for in displayWranglerNotification()
6888 // to bring the user active state up to date.
6889
6890 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6891 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6892 kWranglerPowerStateMax)) {
6893 evaluatePolicy( kStimulusEnterUserActiveState );
6894 }
6895 }
6896 #endif /* DISPLAY_WRANGLER_PRESENT */
6897 }
6898
6899 //******************************************************************************
6900 // Approve usage of delayed child notification by PM.
6901 //******************************************************************************
6902
6903 bool
shouldDelayChildNotification(IOService * service)6904 IOPMrootDomain::shouldDelayChildNotification(
6905 IOService * service )
6906 {
6907 if ((kFullWakeReasonNone == fullWakeReason) &&
6908 (kSystemTransitionWake == _systemTransitionType)) {
6909 DLOG("%s: delay child notify\n", service->getName());
6910 return true;
6911 }
6912 return false;
6913 }
6914
6915 //******************************************************************************
6916 // PM actions for PCI device.
6917 //******************************************************************************
6918
6919 void
handlePowerChangeStartForPCIDevice(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex powerState,IOPMPowerChangeFlags * inOutChangeFlags)6920 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6921 IOService * service,
6922 IOPMActions * actions,
6923 const IOPMRequest * request,
6924 IOPMPowerStateIndex powerState,
6925 IOPMPowerChangeFlags * inOutChangeFlags )
6926 {
6927 pmTracer->tracePCIPowerChange(
6928 PMTraceWorker::kPowerChangeStart,
6929 service, *inOutChangeFlags,
6930 (actions->flags & kPMActionsPCIBitNumberMask));
6931 }
6932
6933 void
handlePowerChangeDoneForPCIDevice(IOService * service,IOPMActions * actions,const IOPMRequest * request,IOPMPowerStateIndex powerState,IOPMPowerChangeFlags changeFlags)6934 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6935 IOService * service,
6936 IOPMActions * actions,
6937 const IOPMRequest * request,
6938 IOPMPowerStateIndex powerState,
6939 IOPMPowerChangeFlags changeFlags )
6940 {
6941 pmTracer->tracePCIPowerChange(
6942 PMTraceWorker::kPowerChangeCompleted,
6943 service, changeFlags,
6944 (actions->flags & kPMActionsPCIBitNumberMask));
6945 }
6946
6947 //******************************************************************************
6948 // registerInterest
6949 //
6950 // Override IOService::registerInterest() for root domain clients.
6951 //******************************************************************************
6952
6953 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6954 {
6955 friend class IOPMrootDomain;
6956 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6957
6958 protected:
6959 uint32_t ackTimeoutCnt;
6960 uint32_t msgType; // Last type seen by the message filter
6961 uint32_t lastSleepWakeMsgType;
6962 uint32_t msgIndex;
6963 uint32_t maxMsgDelayMS;
6964 uint32_t maxAckDelayMS;
6965 uint64_t msgAbsTime;
6966 uint64_t uuid0;
6967 uint64_t uuid1;
6968 OSSharedPtr<const OSSymbol> identifier;
6969 OSSharedPtr<const OSSymbol> clientName;
6970 };
6971
OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier,_IOServiceInterestNotifier)6972 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
6973
6974 OSSharedPtr<IONotifier>
6975 IOPMrootDomain::registerInterest(
6976 const OSSymbol * typeOfInterest,
6977 IOServiceInterestHandler handler,
6978 void * target, void * ref )
6979 {
6980 IOPMServiceInterestNotifier* notifier;
6981 bool isSystemCapabilityClient;
6982 bool isKernelCapabilityClient;
6983 IOReturn rc = kIOReturnError;
6984
6985 isSystemCapabilityClient = typeOfInterest &&
6986 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
6987
6988 isKernelCapabilityClient = typeOfInterest &&
6989 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
6990
6991 if (isSystemCapabilityClient) {
6992 typeOfInterest = gIOAppPowerStateInterest;
6993 }
6994
6995 notifier = new IOPMServiceInterestNotifier;
6996 if (!notifier) {
6997 return NULL;
6998 }
6999
7000 if (notifier->init()) {
7001 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7002 }
7003 if (rc != kIOReturnSuccess) {
7004 OSSafeReleaseNULL(notifier);
7005 return NULL;
7006 }
7007
7008 notifier->ackTimeoutCnt = 0;
7009
7010 if (pmPowerStateQueue) {
7011 if (isSystemCapabilityClient) {
7012 notifier->retain();
7013 if (pmPowerStateQueue->submitPowerEvent(
7014 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7015 notifier->release();
7016 }
7017 }
7018
7019 if (isKernelCapabilityClient) {
7020 notifier->retain();
7021 if (pmPowerStateQueue->submitPowerEvent(
7022 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7023 notifier->release();
7024 }
7025 }
7026 }
7027
7028 OSSharedPtr<OSData> data;
7029 uint8_t *uuid = NULL;
7030 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7031 if (kext) {
7032 data = kext->copyUUID();
7033 }
7034 if (data && (data->getLength() == sizeof(uuid_t))) {
7035 uuid = (uint8_t *)(data->getBytesNoCopy());
7036
7037 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7038 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7039 ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7040 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7041 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7042 ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7043
7044 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7045 }
7046 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7047 }
7048
7049 //******************************************************************************
7050 // systemMessageFilter
7051 //
7052 //******************************************************************************
7053
7054 bool
systemMessageFilter(void * object,void * arg1,void * arg2,void * arg3)7055 IOPMrootDomain::systemMessageFilter(
7056 void * object, void * arg1, void * arg2, void * arg3 )
7057 {
7058 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7059 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7060 bool isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7061 bool isCapClient = false;
7062 bool allow = false;
7063 OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7064 IOPMServiceInterestNotifier *notifier;
7065
7066 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7067
7068 do {
7069 // When powerd and kernel priority clients register capability interest,
7070 // the power tree is sync'ed to inform those clients about the current
7071 // system capability. Only allow capability change messages during sync.
7072 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7073 (!isCapMsg || !_joinedCapabilityClients ||
7074 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7075 break;
7076 }
7077
7078 // Capability change message for powerd and kernel clients
7079 if (isCapMsg) {
7080 // Kernel priority clients
7081 if ((context->notifyType == kNotifyPriority) ||
7082 (context->notifyType == kNotifyCapabilityChangePriority)) {
7083 isCapClient = true;
7084 }
7085
7086 // powerd will maintain two client registrations with root domain.
7087 // isCapPowerd will be TRUE for any message targeting the powerd
7088 // exclusive (capability change) interest registration.
7089 if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7090 isCapClient = true;
7091 }
7092 }
7093
7094 if (isCapClient) {
7095 IOPMSystemCapabilityChangeParameters * capArgs =
7096 (IOPMSystemCapabilityChangeParameters *) arg2;
7097
7098 if (kSystemTransitionNewCapClient == _systemTransitionType) {
7099 capArgs->fromCapabilities = 0;
7100 capArgs->toCapabilities = _currentCapability;
7101 capArgs->changeFlags = 0;
7102 } else {
7103 capArgs->fromCapabilities = _currentCapability;
7104 capArgs->toCapabilities = _pendingCapability;
7105
7106 if (context->isPreChange) {
7107 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7108 } else {
7109 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7110 }
7111
7112 if (isCapPowerd && context->isPreChange) {
7113 toldPowerdCapWillChange = true;
7114 }
7115 }
7116
7117 // App level capability change messages must only go to powerd.
7118 // Wait for response post-change if capabilitiy is increasing.
7119 // Wait for response pre-change if capability is decreasing.
7120
7121 if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7122 ((capabilityLoss && context->isPreChange) ||
7123 (!capabilityLoss && !context->isPreChange))) {
7124 *waitForReply = kOSBooleanTrue;
7125 }
7126
7127 allow = true;
7128 break;
7129 }
7130
7131 // powerd will always receive CanSystemSleep, even for a demand sleep.
7132 // It will also have a final chance to veto sleep after all clients
7133 // have responded to SystemWillSleep
7134
7135 if ((kIOMessageCanSystemSleep == context->messageType) ||
7136 (kIOMessageSystemWillNotSleep == context->messageType)) {
7137 if (isCapPowerd) {
7138 allow = true;
7139 break;
7140 }
7141
7142 // Demand sleep, don't ask apps for permission
7143 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7144 break;
7145 }
7146 }
7147
7148 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7149 if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7150 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7151 allow = true;
7152 }
7153 break;
7154 }
7155
7156 // Drop capability change messages for legacy clients.
7157 // Drop legacy system sleep messages for powerd capability interest.
7158 if (isCapMsg || isCapPowerd) {
7159 break;
7160 }
7161
7162 // Not a capability change message.
7163 // Perform message filtering based on _systemMessageClientMask.
7164
7165 if ((context->notifyType == kNotifyApps) &&
7166 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7167 if (!notifier) {
7168 break;
7169 }
7170
7171 if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7172 (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7173 break; // drop any duplicate WillPowerOn for AOT devices
7174 }
7175
7176 allow = true;
7177
7178 if (waitForReply) {
7179 if (notifier->ackTimeoutCnt >= 3) {
7180 *waitForReply = kOSBooleanFalse;
7181 } else {
7182 *waitForReply = kOSBooleanTrue;
7183 }
7184 }
7185 } else if ((context->notifyType == kNotifyPriority) &&
7186 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7187 allow = true;
7188 }
7189
7190 // Check sleep/wake message ordering
7191 if (allow) {
7192 if (context->messageType == kIOMessageSystemWillSleep ||
7193 context->messageType == kIOMessageSystemWillPowerOn ||
7194 context->messageType == kIOMessageSystemHasPoweredOn) {
7195 notifier->lastSleepWakeMsgType = context->messageType;
7196 }
7197 }
7198 } while (false);
7199
7200 if (allow && isCapMsg && _joinedCapabilityClients) {
7201 _joinedCapabilityClients->removeObject((OSObject *) object);
7202 if (_joinedCapabilityClients->getCount() == 0) {
7203 DMSG("destroyed capability client set %p\n",
7204 OBFUSCATE(_joinedCapabilityClients.get()));
7205 _joinedCapabilityClients.reset();
7206 }
7207 }
7208 if (notifier) {
7209 // Record the last seen message type even if the message is dropped
7210 // for traceFilteredNotification().
7211 notifier->msgType = context->messageType;
7212 }
7213
7214 return allow;
7215 }
7216
7217 //******************************************************************************
7218 // setMaintenanceWakeCalendar
7219 //
7220 //******************************************************************************
7221
7222 IOReturn
setMaintenanceWakeCalendar(const IOPMCalendarStruct * calendar)7223 IOPMrootDomain::setMaintenanceWakeCalendar(
7224 const IOPMCalendarStruct * calendar )
7225 {
7226 OSSharedPtr<OSData> data;
7227 IOReturn ret = 0;
7228
7229 if (!calendar) {
7230 return kIOReturnBadArgument;
7231 }
7232
7233 data = OSData::withValue(*calendar);
7234 if (!data) {
7235 return kIOReturnNoMemory;
7236 }
7237
7238 if (kPMCalendarTypeMaintenance == calendar->selector) {
7239 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7240 } else if (kPMCalendarTypeSleepService == calendar->selector) {
7241 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7242 }
7243
7244 return ret;
7245 }
7246
7247 // MARK: -
7248 // MARK: Display Wrangler
7249
7250 //******************************************************************************
7251 // displayWranglerNotification
7252 //
7253 // Handle the notification when the IODisplayWrangler changes power state.
7254 //******************************************************************************
7255
7256 IOReturn
displayWranglerNotification(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgument,vm_size_t argSize)7257 IOPMrootDomain::displayWranglerNotification(
7258 void * target, void * refCon,
7259 UInt32 messageType, IOService * service,
7260 void * messageArgument, vm_size_t argSize )
7261 {
7262 #if DISPLAY_WRANGLER_PRESENT
7263 IOPMPowerStateIndex displayPowerState;
7264 IOPowerStateChangeNotification * params =
7265 (IOPowerStateChangeNotification *) messageArgument;
7266
7267 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7268 (messageType != kIOMessageDeviceHasPoweredOn)) {
7269 return kIOReturnUnsupported;
7270 }
7271
7272 ASSERT_GATED();
7273 if (!gRootDomain) {
7274 return kIOReturnUnsupported;
7275 }
7276
7277 displayPowerState = params->stateNumber;
7278 DLOG("wrangler %s ps %d\n",
7279 getIOMessageString(messageType), (uint32_t) displayPowerState);
7280
7281 switch (messageType) {
7282 case kIOMessageDeviceWillPowerOff:
7283 // Display wrangler has dropped power due to display idle
7284 // or force system sleep.
7285 //
7286 // 4 Display ON kWranglerPowerStateMax
7287 // 3 Display Dim kWranglerPowerStateDim
7288 // 2 Display Sleep kWranglerPowerStateSleep
7289 // 1 Not visible to user
7290 // 0 Not visible to user kWranglerPowerStateMin
7291
7292 if (displayPowerState <= kWranglerPowerStateSleep) {
7293 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7294 }
7295 break;
7296
7297 case kIOMessageDeviceHasPoweredOn:
7298 // Display wrangler has powered on due to user activity
7299 // or wake from sleep.
7300
7301 if (kWranglerPowerStateMax == displayPowerState) {
7302 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7303
7304 // See comment in handleUpdatePowerClientForDisplayWrangler
7305 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7306 kWranglerPowerStateMax) {
7307 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7308 }
7309 }
7310 break;
7311 }
7312 #endif /* DISPLAY_WRANGLER_PRESENT */
7313 return kIOReturnUnsupported;
7314 }
7315
7316 //******************************************************************************
7317 // reportUserInput
7318 //
7319 //******************************************************************************
7320
7321 void
updateUserActivity(void)7322 IOPMrootDomain::updateUserActivity( void )
7323 {
7324 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7325 clock_get_uptime(&userActivityTime);
7326 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware)
7327 || (lastSleepReason == kIOPMSleepReasonIdle)
7328 || (lastSleepReason == kIOPMSleepReasonMaintenance));
7329 if (aborting) {
7330 userActivityCount++;
7331 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7332 }
7333 #endif
7334 }
7335 void
reportUserInput(void)7336 IOPMrootDomain::reportUserInput( void )
7337 {
7338 if (wrangler) {
7339 wrangler->activityTickle(0, 0);
7340 }
7341 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7342 // Update user activity
7343 updateUserActivity();
7344
7345 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7346 // update user active abs time
7347 clock_get_uptime(&gUserActiveAbsTime);
7348 pmPowerStateQueue->submitPowerEvent(
7349 kPowerEventPolicyStimulus,
7350 (void *) kStimulusDarkWakeActivityTickle,
7351 true /* set wake type */ );
7352 }
7353 #endif
7354 }
7355
7356 void
requestUserActive(IOService * device,const char * reason)7357 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7358 {
7359 #if DISPLAY_WRANGLER_PRESENT
7360 if (wrangler) {
7361 wrangler->activityTickle(0, 0);
7362 }
7363 #else
7364 if (!device) {
7365 DLOG("requestUserActive: device is null\n");
7366 return;
7367 }
7368 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7369 uint64_t registryID = device->getRegistryEntryID();
7370
7371 if (!deviceName || !registryID) {
7372 DLOG("requestUserActive: no device name or registry entry\n");
7373 return;
7374 }
7375 const char *name = deviceName->getCStringNoCopy();
7376 char payload[128];
7377 snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7378 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7379 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7380 #endif
7381 }
7382
7383 //******************************************************************************
7384 // latchDisplayWranglerTickle
7385 //******************************************************************************
7386
7387 bool
latchDisplayWranglerTickle(bool latch)7388 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7389 {
7390 #if DISPLAY_WRANGLER_PRESENT
7391 if (latch) {
7392 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7393 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7394 !checkSystemCanSustainFullWake()) {
7395 // Currently in dark wake, and not transitioning to full wake.
7396 // Full wake is unsustainable, so latch the tickle to prevent
7397 // the display from lighting up momentarily.
7398 wranglerTickled = true;
7399 } else {
7400 wranglerTickled = false;
7401 }
7402 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7403 wranglerTickled = false;
7404
7405 pmPowerStateQueue->submitPowerEvent(
7406 kPowerEventPolicyStimulus,
7407 (void *) kStimulusDarkWakeActivityTickle );
7408 }
7409
7410 return wranglerTickled;
7411 #else /* ! DISPLAY_WRANGLER_PRESENT */
7412 return false;
7413 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7414 }
7415
7416 //******************************************************************************
7417 // setDisplayPowerOn
7418 //
7419 // For root domain user client
7420 //******************************************************************************
7421
7422 void
setDisplayPowerOn(uint32_t options)7423 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7424 {
7425 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7426 (void *) NULL, options );
7427 }
7428
7429 // MARK: -
7430 // MARK: System PM Policy
7431
7432 //******************************************************************************
7433 // checkSystemSleepAllowed
7434 //
7435 //******************************************************************************
7436
7437 bool
checkSystemSleepAllowed(IOOptionBits options,uint32_t sleepReason)7438 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7439 uint32_t sleepReason )
7440 {
7441 uint32_t err = 0;
7442
7443 // Conditions that prevent idle and demand system sleep.
7444
7445 do {
7446 if (gSleepDisabledFlag) {
7447 err = kPMConfigPreventSystemSleep;
7448 break;
7449 }
7450
7451 if (userDisabledAllSleep) {
7452 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7453 break;
7454 }
7455
7456 if (systemBooting || systemShutdown || gWillShutdown) {
7457 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7458 break;
7459 }
7460
7461 if (options == 0) {
7462 break;
7463 }
7464
7465 // Conditions above pegs the system at full wake.
7466 // Conditions below prevent system sleep but does not prevent
7467 // dark wake, and must be called from gated context.
7468
7469 #if !CONFIG_SLEEP
7470 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7471 break;
7472 #endif
7473
7474 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7475 break; // always sleep on low battery or when in thermal warning/emergency state
7476 }
7477
7478 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7479 break; // always sleep on dark wake thermal emergencies
7480 }
7481
7482 if (preventSystemSleepList->getCount() != 0) {
7483 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7484 break;
7485 }
7486
7487 if (_driverKitMatchingAssertionCount != 0) {
7488 err = kPMCPUAssertion;
7489 break;
7490 }
7491
7492 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7493 kIOPMDriverAssertionLevelOn) {
7494 err = kPMCPUAssertion; // 5. CPU assertion
7495 break;
7496 }
7497
7498 if (pciCantSleepValid) {
7499 if (pciCantSleepFlag) {
7500 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7501 }
7502 break;
7503 } else if (sleepSupportedPEFunction &&
7504 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7505 IOReturn ret;
7506 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7507 ret = getPlatform()->callPlatformFunction(
7508 sleepSupportedPEFunction.get(), false,
7509 NULL, NULL, NULL, NULL);
7510 pciCantSleepValid = true;
7511 pciCantSleepFlag = false;
7512 if ((platformSleepSupport & kPCICantSleep) ||
7513 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7514 err = 6; // 6. PCI card does not support PM
7515 pciCantSleepFlag = true;
7516 break;
7517 }
7518 }
7519 }while (false);
7520
7521 if (err) {
7522 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7523 return false;
7524 }
7525 return true;
7526 }
7527
7528 bool
checkSystemSleepEnabled(void)7529 IOPMrootDomain::checkSystemSleepEnabled( void )
7530 {
7531 return checkSystemSleepAllowed(0, 0);
7532 }
7533
7534 bool
checkSystemCanSleep(uint32_t sleepReason)7535 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7536 {
7537 ASSERT_GATED();
7538 return checkSystemSleepAllowed(1, sleepReason);
7539 }
7540
7541 //******************************************************************************
7542 // checkSystemCanSustainFullWake
7543 //******************************************************************************
7544
7545 bool
checkSystemCanSustainFullWake(void)7546 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7547 {
7548 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7549 // Low battery wake, or received a low battery notification
7550 // while system is awake. This condition will persist until
7551 // the following wake.
7552 return false;
7553 }
7554
7555 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7556 // Graphics state is unknown and external display might not be probed.
7557 // Do not incorporate state that requires graphics to be in max power
7558 // such as desktopMode or clamshellDisabled.
7559
7560 if (!acAdaptorConnected) {
7561 DLOG("full wake check: no AC\n");
7562 return false;
7563 }
7564 }
7565 return true;
7566 }
7567
7568 //******************************************************************************
7569 // mustHibernate
7570 //******************************************************************************
7571
7572 #if HIBERNATION
7573
7574 bool
mustHibernate(void)7575 IOPMrootDomain::mustHibernate( void )
7576 {
7577 return lowBatteryCondition || thermalWarningState;
7578 }
7579
7580 #endif /* HIBERNATION */
7581
7582 //******************************************************************************
7583 // AOT
7584 //******************************************************************************
7585
7586 // Tables for accumulated days in year by month, latter used for leap years
7587
7588 static const unsigned int daysbymonth[] =
7589 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7590
7591 static const unsigned int lydaysbymonth[] =
7592 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7593
7594 static int __unused
IOPMConvertSecondsToCalendar(clock_sec_t secs,IOPMCalendarStruct * dt)7595 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7596 {
7597 const unsigned int * dbm = daysbymonth;
7598 clock_sec_t n, x, y, z;
7599
7600 // Calculate seconds, minutes and hours
7601
7602 n = secs % (24 * 3600);
7603 dt->second = n % 60;
7604 n /= 60;
7605 dt->minute = n % 60;
7606 dt->hour = (typeof(dt->hour))(n / 60);
7607
7608 // Calculate day of week
7609
7610 n = secs / (24 * 3600);
7611 // dt->dayWeek = (n + 4) % 7;
7612
7613 // Calculate year
7614 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7615 // to days since 1/1/1968 to start on 4 year cycle, beginning
7616 // on a leap year.
7617
7618 n += (366 + 365);
7619
7620 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7621 // Valid before 2100, since 2100 is not a leap year.
7622
7623 x = n / 1461; // number of 4 year cycles
7624 y = n % 1461; // days into current 4 year cycle
7625 z = 1968 + (4 * x);
7626
7627 // Add in years in the current 4 year cycle
7628
7629 if (y >= 366) {
7630 y -= 366; // days after the leap year
7631 n = y % 365; // days into the current year
7632 z += (1 + y / 365); // years after the past 4-yr cycle
7633 } else {
7634 n = y;
7635 dbm = lydaysbymonth;
7636 }
7637 if (z > 2099) {
7638 return 0;
7639 }
7640
7641 dt->year = (typeof(dt->year))z;
7642
7643 // Adjust remaining days value to start at 1
7644
7645 n += 1;
7646
7647 // Calculate month
7648
7649 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7650 continue;
7651 }
7652 dt->month = (typeof(dt->month))x;
7653
7654 // Calculate day of month
7655
7656 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7657
7658 return 1;
7659 }
7660
7661 static clock_sec_t
IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)7662 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7663 {
7664 const unsigned int * dbm = daysbymonth;
7665 long y, secs, days;
7666
7667 if (dt->year < 1970 || dt->month > 12) {
7668 return 0;
7669 }
7670
7671 // Seconds elapsed in the current day
7672
7673 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7674
7675 // Number of days from 1/1/70 to beginning of current year
7676 // Account for extra day every 4 years starting at 1973
7677
7678 y = dt->year - 1970;
7679 days = (y * 365) + ((y + 1) / 4);
7680
7681 // Change table if current year is a leap year
7682
7683 if ((dt->year % 4) == 0) {
7684 dbm = lydaysbymonth;
7685 }
7686
7687 // Add in days elapsed in the current year
7688
7689 days += (dt->day - 1) + dbm[dt->month - 1];
7690
7691 // Add accumulated days to accumulated seconds
7692
7693 secs += 24 * 3600 * days;
7694
7695 return secs;
7696 }
7697
7698 unsigned long
getRUN_STATE(void)7699 IOPMrootDomain::getRUN_STATE(void)
7700 {
7701 return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7702 }
7703
7704 bool
isAOTMode()7705 IOPMrootDomain::isAOTMode()
7706 {
7707 return _aotNow;
7708 }
7709
7710 IOReturn
setWakeTime(uint64_t wakeContinuousTime)7711 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7712 {
7713 clock_sec_t nowsecs, wakesecs;
7714 clock_usec_t nowmicrosecs, wakemicrosecs;
7715 uint64_t nowAbs, wakeAbs;
7716
7717 if (!_aotMode) {
7718 return kIOReturnNotReady;
7719 }
7720
7721 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7722 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7723 if (wakeAbs < nowAbs) {
7724 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7725 wakeAbs = nowAbs;
7726 }
7727 wakeAbs -= nowAbs;
7728 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7729
7730 wakesecs += nowsecs;
7731 wakemicrosecs += nowmicrosecs;
7732 if (wakemicrosecs >= USEC_PER_SEC) {
7733 wakesecs++;
7734 wakemicrosecs -= USEC_PER_SEC;
7735 }
7736 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7737 wakesecs++;
7738 }
7739
7740 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7741
7742 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7743 _aotWakeTimeContinuous = wakeContinuousTime;
7744 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7745 }
7746 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7747 _aotWakeTimeUTC = wakesecs;
7748
7749 return kIOReturnSuccess;
7750 }
7751
7752 // assumes WAKEEVENT_LOCK
7753 bool
aotShouldExit(bool checkTimeSet,bool software)7754 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
7755 {
7756 bool exitNow = false;
7757 const char * reason = "";
7758
7759 if (!_aotNow) {
7760 return false;
7761 }
7762
7763 if (software) {
7764 exitNow = true;
7765 _aotMetrics->softwareRequestCount++;
7766 reason = "software request";
7767 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7768 exitNow = true;
7769 reason = gWakeReasonString;
7770 } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
7771 exitNow = true;
7772 _aotMetrics->noTimeSetCount++;
7773 reason = "flipbook expired";
7774 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7775 clock_sec_t sec;
7776 clock_usec_t usec;
7777 clock_get_calendar_microtime(&sec, &usec);
7778 if (_calendarWakeAlarmUTC <= sec) {
7779 exitNow = true;
7780 _aotMetrics->rtcAlarmsCount++;
7781 reason = "user alarm";
7782 }
7783 }
7784 if (exitNow) {
7785 _aotPendingFlags |= kIOPMWakeEventAOTExit;
7786 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7787 reason,
7788 _aotMetrics->sleepCount,
7789 _aotMetrics->possibleCount,
7790 _aotMetrics->confirmedPossibleCount,
7791 _aotMetrics->rejectedPossibleCount,
7792 _aotMetrics->expiredPossibleCount,
7793 _aotMetrics->noTimeSetCount,
7794 _aotMetrics->rtcAlarmsCount);
7795 }
7796 return exitNow;
7797 }
7798
7799 void
aotExit(bool cps)7800 IOPMrootDomain::aotExit(bool cps)
7801 {
7802 uint32_t savedMessageMask;
7803
7804 ASSERT_GATED();
7805 _aotNow = false;
7806 _aotReadyToFullWake = false;
7807 if (_aotTimerScheduled) {
7808 _aotTimerES->cancelTimeout();
7809 _aotTimerScheduled = false;
7810 }
7811 updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7812
7813 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7814 _aotLastWakeTime = 0;
7815 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7816 WAKEEVENT_LOCK();
7817 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7818 gWakeReasonString,
7819 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7820 WAKEEVENT_UNLOCK();
7821 }
7822
7823 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7824
7825 // Preserve the message mask since a system wake transition
7826 // may have already started and initialized the mask.
7827 savedMessageMask = _systemMessageClientMask;
7828 _systemMessageClientMask = kSystemMessageClientLegacyApp;
7829 tellClients(kIOMessageSystemWillPowerOn);
7830 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7831
7832 if (cps) {
7833 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7834 }
7835 }
7836
7837 void
aotEvaluate(IOTimerEventSource * timer)7838 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7839 {
7840 bool exitNow;
7841
7842 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7843
7844 WAKEEVENT_LOCK();
7845 exitNow = aotShouldExit(false, false);
7846 if (timer != NULL) {
7847 _aotTimerScheduled = false;
7848 }
7849 WAKEEVENT_UNLOCK();
7850 if (exitNow) {
7851 aotExit(true);
7852 } else {
7853 #if 0
7854 if (_aotLingerTime) {
7855 uint64_t deadline;
7856 IOLog("aot linger before sleep\n");
7857 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7858 clock_delay_until(deadline);
7859 }
7860 #endif
7861 privateSleepSystem(kIOPMSleepReasonSoftware);
7862 }
7863 }
7864
7865 //******************************************************************************
7866 // adjustPowerState
7867 //
7868 // Conditions that affect our wake/sleep decision has changed.
7869 // If conditions dictate that the system must remain awake, clamp power
7870 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7871 // is TRUE, then remove the power clamp and allow the power state to drop
7872 // to SLEEP_STATE.
7873 //******************************************************************************
7874
7875 void
adjustPowerState(bool sleepASAP)7876 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7877 {
7878 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7879 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7880
7881 ASSERT_GATED();
7882
7883 if (_aotNow) {
7884 bool exitNow;
7885
7886 if (AOT_STATE != getPowerState()) {
7887 return;
7888 }
7889 WAKEEVENT_LOCK();
7890 exitNow = aotShouldExit(true, false);
7891 if (!exitNow
7892 && !_aotTimerScheduled
7893 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7894 _aotTimerScheduled = true;
7895 if (_aotLingerTime) {
7896 _aotTimerES->setTimeout(_aotLingerTime);
7897 } else {
7898 _aotTimerES->setTimeout(800, kMillisecondScale);
7899 }
7900 }
7901 WAKEEVENT_UNLOCK();
7902 if (exitNow) {
7903 aotExit(true);
7904 } else {
7905 _aotReadyToFullWake = true;
7906 if (!_aotTimerScheduled) {
7907 if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
7908 // Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
7909 // Doing so will result in the sleep being cancelled anyway,
7910 // but this check avoids unnecessary thrashing in the power state engine.
7911 return;
7912 }
7913 privateSleepSystem(kIOPMSleepReasonSoftware);
7914 }
7915 }
7916 return;
7917 }
7918
7919 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
7920 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
7921 } else if (sleepASAP) {
7922 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
7923 }
7924 }
7925
7926 void
handleSetDisplayPowerOn(bool powerOn)7927 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
7928 {
7929 if (powerOn) {
7930 if (!checkSystemCanSustainFullWake()) {
7931 DLOG("System cannot sustain full wake\n");
7932 return;
7933 }
7934
7935 // Force wrangler to max power state. If system is in dark wake
7936 // this alone won't raise the wrangler's power state.
7937 if (wrangler) {
7938 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
7939 }
7940
7941 // System in dark wake, always requesting full wake should
7942 // not have any bad side-effects, even if the request fails.
7943
7944 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7945 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
7946 requestFullWake( kFullWakeReasonDisplayOn );
7947 }
7948 } else {
7949 // Relenquish desire to power up display.
7950 // Must first transition to state 1 since wrangler doesn't
7951 // power off the displays at state 0. At state 0 the root
7952 // domain is removed from the wrangler's power client list.
7953 if (wrangler) {
7954 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
7955 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
7956 }
7957 }
7958 }
7959
7960 //******************************************************************************
7961 // dispatchPowerEvent
7962 //
7963 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7964 //******************************************************************************
7965
7966 void
dispatchPowerEvent(uint32_t event,void * arg0,uint64_t arg1)7967 IOPMrootDomain::dispatchPowerEvent(
7968 uint32_t event, void * arg0, uint64_t arg1 )
7969 {
7970 ASSERT_GATED();
7971
7972 switch (event) {
7973 case kPowerEventFeatureChanged:
7974 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7975 messageClients(kIOPMMessageFeatureChange, this);
7976 break;
7977
7978 case kPowerEventReceivedPowerNotification:
7979 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7980 handlePowerNotification((UInt32)(uintptr_t) arg0 );
7981 break;
7982
7983 case kPowerEventSystemBootCompleted:
7984 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7985 if (systemBooting) {
7986 systemBooting = false;
7987
7988 if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
7989 DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
7990 }
7991 if (lowBatteryCondition || thermalEmergencyState) {
7992 if (lowBatteryCondition) {
7993 privateSleepSystem(kIOPMSleepReasonLowPower);
7994 } else {
7995 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
7996 }
7997 // The rest is unnecessary since the system is expected
7998 // to sleep immediately. The following wake will update
7999 // everything.
8000 break;
8001 }
8002
8003 sleepWakeDebugMemAlloc();
8004 saveFailureData2File();
8005
8006 // If lid is closed, re-send lid closed notification
8007 // now that booting is complete.
8008 if (clamshellClosed) {
8009 handlePowerNotification(kLocalEvalClamshellCommand);
8010 }
8011 evaluatePolicy( kStimulusAllowSystemSleepChanged );
8012 }
8013 break;
8014
8015 case kPowerEventSystemShutdown:
8016 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8017 if (kOSBooleanTrue == (OSBoolean *) arg0) {
8018 /* We set systemShutdown = true during shutdown
8019 * to prevent sleep at unexpected times while loginwindow is trying
8020 * to shutdown apps and while the OS is trying to transition to
8021 * complete power of.
8022 *
8023 * Set to true during shutdown, as soon as loginwindow shows
8024 * the "shutdown countdown dialog", through individual app
8025 * termination, and through black screen kernel shutdown.
8026 */
8027 systemShutdown = true;
8028 } else {
8029 /*
8030 * A shutdown was initiated, but then the shutdown
8031 * was cancelled, clearing systemShutdown to false here.
8032 */
8033 systemShutdown = false;
8034 }
8035 break;
8036
8037 case kPowerEventUserDisabledSleep:
8038 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8039 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8040 break;
8041
8042 case kPowerEventRegisterSystemCapabilityClient:
8043 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8044
8045 // reset() handles the arg0 == nullptr case for us
8046 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8047 /* intentional fall-through */
8048 [[clang::fallthrough]];
8049
8050 case kPowerEventRegisterKernelCapabilityClient:
8051 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8052 if (!_joinedCapabilityClients) {
8053 _joinedCapabilityClients = OSSet::withCapacity(8);
8054 }
8055 if (arg0) {
8056 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8057 if (_joinedCapabilityClients) {
8058 _joinedCapabilityClients->setObject(notify.get());
8059 synchronizePowerTree( kIOPMSyncNoChildNotify );
8060 }
8061 }
8062 break;
8063
8064 case kPowerEventPolicyStimulus:
8065 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8066 if (arg0) {
8067 int stimulus = (int)(uintptr_t) arg0;
8068 evaluatePolicy(stimulus, (uint32_t) arg1);
8069 }
8070 break;
8071
8072 case kPowerEventAssertionCreate:
8073 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8074 if (pmAssertions) {
8075 pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8076 }
8077 break;
8078
8079
8080 case kPowerEventAssertionRelease:
8081 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8082 if (pmAssertions) {
8083 pmAssertions->handleReleaseAssertion(arg1);
8084 }
8085 break;
8086
8087 case kPowerEventAssertionSetLevel:
8088 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8089 if (pmAssertions) {
8090 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8091 }
8092 break;
8093
8094 case kPowerEventQueueSleepWakeUUID:
8095 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8096 handleQueueSleepWakeUUID((OSObject *)arg0);
8097 break;
8098 case kPowerEventPublishSleepWakeUUID:
8099 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8100 handlePublishSleepWakeUUID((bool)arg0);
8101 break;
8102
8103 case kPowerEventSetDisplayPowerOn:
8104 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8105 if (arg1 != 0) {
8106 displayPowerOnRequested = true;
8107 } else {
8108 displayPowerOnRequested = false;
8109 }
8110 handleSetDisplayPowerOn(displayPowerOnRequested);
8111 break;
8112
8113 case kPowerEventPublishWakeType:
8114 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8115
8116 // Don't replace wake type property if already set
8117 if ((arg0 == gIOPMWakeTypeUserKey) ||
8118 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8119 const char * wakeType = NULL;
8120
8121 if (arg0 == gIOPMWakeTypeUserKey) {
8122 requestUserActive(this, "WakeTypeUser");
8123 wakeType = kIOPMRootDomainWakeTypeUser;
8124 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8125 requestUserActive(this, "WakeTypeAlarm");
8126 wakeType = kIOPMRootDomainWakeTypeAlarm;
8127 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8128 darkWakeSleepService = true;
8129 wakeType = kIOPMRootDomainWakeTypeSleepService;
8130 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8131 wakeType = kIOPMRootDomainWakeTypeMaintenance;
8132 }
8133
8134 if (wakeType) {
8135 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8136 }
8137 }
8138 break;
8139
8140 case kPowerEventAOTEvaluate:
8141 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8142 if (_aotReadyToFullWake) {
8143 aotEvaluate(NULL);
8144 }
8145 break;
8146 }
8147 }
8148
8149 //******************************************************************************
8150 // systemPowerEventOccurred
8151 //
8152 // The power controller is notifying us of a hardware-related power management
8153 // event that we must handle.
8154 //
8155 // systemPowerEventOccurred covers the same functionality that
8156 // receivePowerNotification does; it simply provides a richer API for conveying
8157 // more information.
8158 //******************************************************************************
8159
8160 IOReturn
systemPowerEventOccurred(const OSSymbol * event,uint32_t intValue)8161 IOPMrootDomain::systemPowerEventOccurred(
8162 const OSSymbol *event,
8163 uint32_t intValue)
8164 {
8165 IOReturn attempt = kIOReturnSuccess;
8166 OSSharedPtr<OSNumber> newNumber;
8167
8168 if (!event) {
8169 return kIOReturnBadArgument;
8170 }
8171
8172 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8173 if (!newNumber) {
8174 return kIOReturnInternalError;
8175 }
8176
8177 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8178
8179 return attempt;
8180 }
8181
8182 void
setThermalState(OSObject * value)8183 IOPMrootDomain::setThermalState(OSObject *value)
8184 {
8185 OSNumber * num;
8186
8187 if (gIOPMWorkLoop->inGate() == false) {
8188 gIOPMWorkLoop->runAction(
8189 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8190 (OSObject *)this,
8191 (void *)value);
8192
8193 return;
8194 }
8195 if (value && (num = OSDynamicCast(OSNumber, value))) {
8196 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8197 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8198 }
8199 }
8200
8201 IOReturn
systemPowerEventOccurred(const OSSymbol * event,OSObject * value)8202 IOPMrootDomain::systemPowerEventOccurred(
8203 const OSSymbol *event,
8204 OSObject *value)
8205 {
8206 OSSharedPtr<OSDictionary> thermalsDict;
8207 bool shouldUpdate = true;
8208
8209 if (!event || !value) {
8210 return kIOReturnBadArgument;
8211 }
8212
8213 // LOCK
8214 // We reuse featuresDict Lock because it already exists and guards
8215 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8216 // of stepping on that lock.
8217 if (featuresDictLock) {
8218 IOLockLock(featuresDictLock);
8219 }
8220
8221 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8222 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8223
8224 if (origThermalsDict) {
8225 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8226 } else {
8227 thermalsDict = OSDictionary::withCapacity(1);
8228 }
8229
8230 if (!thermalsDict) {
8231 shouldUpdate = false;
8232 goto exit;
8233 }
8234
8235 thermalsDict->setObject(event, value);
8236
8237 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8238
8239 exit:
8240 // UNLOCK
8241 if (featuresDictLock) {
8242 IOLockUnlock(featuresDictLock);
8243 }
8244
8245 if (shouldUpdate) {
8246 if (event &&
8247 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8248 setThermalState(value);
8249 }
8250 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8251 }
8252
8253 return kIOReturnSuccess;
8254 }
8255
8256 //******************************************************************************
8257 // receivePowerNotification
8258 //
8259 // The power controller is notifying us of a hardware-related power management
8260 // event that we must handle. This may be a result of an 'environment' interrupt
8261 // from the power mgt micro.
8262 //******************************************************************************
8263
8264 IOReturn
receivePowerNotification(UInt32 msg)8265 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8266 {
8267 if (msg & kIOPMPowerButton) {
8268 uint32_t currentPhase = pmTracer->getTracePhase();
8269 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8270 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8271 swd_flags |= SWD_PWR_BTN_STACKSHOT;
8272 thread_call_enter(powerButtonDown);
8273 } else {
8274 DEBUG_LOG("power button pressed when system is up\n");
8275 }
8276 } else if (msg & kIOPMPowerButtonUp) {
8277 if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8278 swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8279 thread_call_enter(powerButtonUp);
8280 }
8281 } else {
8282 pmPowerStateQueue->submitPowerEvent(
8283 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8284 }
8285 return kIOReturnSuccess;
8286 }
8287
8288 void
handlePowerNotification(UInt32 msg)8289 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8290 {
8291 bool eval_clamshell = false;
8292 bool eval_clamshell_alarm = false;
8293
8294 ASSERT_GATED();
8295
8296 /*
8297 * Local (IOPMrootDomain only) eval clamshell command
8298 */
8299 if (msg & kLocalEvalClamshellCommand) {
8300 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8301 eval_clamshell_alarm = true;
8302
8303 // reset isRTCAlarmWake. This evaluation should happen only once
8304 // on RTC/Alarm wake. Any clamshell events after wake should follow
8305 // the regular evaluation
8306 isRTCAlarmWake = false;
8307 } else {
8308 eval_clamshell = true;
8309 }
8310 }
8311
8312 /*
8313 * Overtemp
8314 */
8315 if (msg & kIOPMOverTemp) {
8316 DLOG("Thermal overtemp message received!\n");
8317 thermalEmergencyState = true;
8318 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8319 }
8320
8321 /*
8322 * Forward DW thermal notification to client, if system is not going to sleep
8323 */
8324 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8325 DLOG("DarkWake thermal limits message received!\n");
8326 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8327 }
8328
8329 /*
8330 * Sleep Now!
8331 */
8332 if (msg & kIOPMSleepNow) {
8333 privateSleepSystem(kIOPMSleepReasonSoftware);
8334 }
8335
8336 /*
8337 * Power Emergency
8338 */
8339 if (msg & kIOPMPowerEmergency) {
8340 DLOG("Received kIOPMPowerEmergency");
8341 lowBatteryCondition = true;
8342 privateSleepSystem(kIOPMSleepReasonLowPower);
8343 }
8344
8345 /*
8346 * Clamshell OPEN
8347 */
8348 if (msg & kIOPMClamshellOpened) {
8349 DLOG("Clamshell opened\n");
8350 // Received clamshel open message from clamshell controlling driver
8351 // Update our internal state and tell general interest clients
8352 clamshellClosed = false;
8353 clamshellExists = true;
8354
8355 // Don't issue a hid tickle when lid is open and polled on wake
8356 if (msg & kIOPMSetValue) {
8357 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8358 reportUserInput();
8359 }
8360
8361 // Tell PMCPU
8362 informCPUStateChange(kInformLid, 0);
8363
8364 // Tell general interest clients
8365 sendClientClamshellNotification();
8366
8367 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8368 || (lastSleepReason == kIOPMSleepReasonIdle)
8369 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8370 if (aborting) {
8371 userActivityCount++;
8372 }
8373 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8374 }
8375
8376 /*
8377 * Clamshell CLOSED
8378 * Send the clamshell interest notification since the lid is closing.
8379 */
8380 if (msg & kIOPMClamshellClosed) {
8381 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8382 clamshellClosed && clamshellExists) {
8383 DLOG("Ignoring redundant Clamshell close event\n");
8384 } else {
8385 DLOG("Clamshell closed\n");
8386 // Received clamshel open message from clamshell controlling driver
8387 // Update our internal state and tell general interest clients
8388 clamshellClosed = true;
8389 clamshellExists = true;
8390
8391 // Ignore all following clamshell close events until the clamshell
8392 // is opened or the system sleeps. When a clamshell close triggers
8393 // a system wake, the lid driver may send us two clamshell close
8394 // events, one for the clamshell close event itself, and a second
8395 // close event when the driver polls the lid state on wake.
8396 clamshellIgnoreClose = true;
8397
8398 // Tell PMCPU
8399 informCPUStateChange(kInformLid, 1);
8400
8401 // Tell general interest clients
8402 sendClientClamshellNotification();
8403
8404 // And set eval_clamshell = so we can attempt
8405 eval_clamshell = true;
8406 }
8407 }
8408
8409 /*
8410 * Set Desktop mode (sent from graphics)
8411 *
8412 * -> reevaluate lid state
8413 */
8414 if (msg & kIOPMSetDesktopMode) {
8415 desktopMode = (0 != (msg & kIOPMSetValue));
8416 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8417 DLOG("Desktop mode %d\n", desktopMode);
8418
8419 sendClientClamshellNotification();
8420
8421 // Re-evaluate the lid state
8422 eval_clamshell = true;
8423 }
8424
8425 /*
8426 * AC Adaptor connected
8427 *
8428 * -> reevaluate lid state
8429 */
8430 if (msg & kIOPMSetACAdaptorConnected) {
8431 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8432 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8433
8434 // Tell CPU PM
8435 informCPUStateChange(kInformAC, !acAdaptorConnected);
8436
8437 // Tell BSD if AC is connected
8438 // 0 == external power source; 1 == on battery
8439 post_sys_powersource(acAdaptorConnected ? 0:1);
8440
8441 sendClientClamshellNotification();
8442
8443 IOUserServer::powerSourceChanged(acAdaptorConnected);
8444
8445 // Re-evaluate the lid state
8446 eval_clamshell = true;
8447
8448 // Lack of AC may have latched a display wrangler tickle.
8449 // This mirrors the hardware's USB wake event latch, where a latched
8450 // USB wake event followed by an AC attach will trigger a full wake.
8451 latchDisplayWranglerTickle( false );
8452
8453 #if HIBERNATION
8454 // AC presence will reset the standy timer delay adjustment.
8455 _standbyTimerResetSeconds = 0;
8456 #endif
8457 if (!userIsActive) {
8458 // Reset userActivityTime when power supply is changed(rdr 13789330)
8459 clock_get_uptime(&userActivityTime);
8460 }
8461 }
8462
8463 /*
8464 * Enable Clamshell (external display disappear)
8465 *
8466 * -> reevaluate lid state
8467 */
8468 if (msg & kIOPMEnableClamshell) {
8469 DLOG("Clamshell enabled\n");
8470
8471 // Re-evaluate the lid state
8472 // System should sleep on external display disappearance
8473 // in lid closed operation.
8474 if (true == clamshellDisabled) {
8475 eval_clamshell = true;
8476
8477 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8478 // Also clear kClamshellSleepDisableInternal when graphics enables
8479 // the clamshell during a full wake. When graphics is behaving as
8480 // expected, this will allow clamshell close to be honored earlier
8481 // rather than waiting for the delayed evaluation.
8482 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8483 (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8484 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8485 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8486
8487 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8488 // when timer expires which is harmless but useless.
8489 thread_call_cancel(fullWakeThreadCall);
8490 }
8491 #endif
8492 }
8493
8494 clamshellDisabled = false;
8495 sendClientClamshellNotification();
8496 }
8497
8498 /*
8499 * Disable Clamshell (external display appeared)
8500 * We don't bother re-evaluating clamshell state. If the system is awake,
8501 * the lid is probably open.
8502 */
8503 if (msg & kIOPMDisableClamshell) {
8504 DLOG("Clamshell disabled\n");
8505 clamshellDisabled = true;
8506 sendClientClamshellNotification();
8507 }
8508
8509 /*
8510 * Evaluate clamshell and SLEEP if appropriate
8511 */
8512 if (eval_clamshell_alarm && clamshellClosed) {
8513 if (shouldSleepOnRTCAlarmWake()) {
8514 privateSleepSystem(kIOPMSleepReasonClamshell);
8515 }
8516 } else if (eval_clamshell && clamshellClosed) {
8517 if (shouldSleepOnClamshellClosed()) {
8518 privateSleepSystem(kIOPMSleepReasonClamshell);
8519 } else {
8520 evaluatePolicy( kStimulusDarkWakeEvaluate );
8521 }
8522 }
8523
8524 if (msg & kIOPMProModeEngaged) {
8525 int newState = 1;
8526 DLOG("ProModeEngaged\n");
8527 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8528 }
8529
8530 if (msg & kIOPMProModeDisengaged) {
8531 int newState = 0;
8532 DLOG("ProModeDisengaged\n");
8533 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8534 }
8535 }
8536
8537 //******************************************************************************
8538 // evaluatePolicy
8539 //
8540 // Evaluate root-domain policy in response to external changes.
8541 //******************************************************************************
8542
8543 void
evaluatePolicy(int stimulus,uint32_t arg)8544 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8545 {
8546 union {
8547 struct {
8548 int idleSleepEnabled : 1;
8549 int idleSleepDisabled : 1;
8550 int displaySleep : 1;
8551 int sleepDelayChanged : 1;
8552 int evaluateDarkWake : 1;
8553 int adjustPowerState : 1;
8554 int userBecameInactive : 1;
8555 int displaySleepEntry : 1;
8556 } bit;
8557 uint32_t u32;
8558 } flags;
8559
8560
8561 ASSERT_GATED();
8562 flags.u32 = 0;
8563
8564 switch (stimulus) {
8565 case kStimulusDisplayWranglerSleep:
8566 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8567 if (!wranglerPowerOff) {
8568 // wrangler is in sleep state or lower
8569 flags.bit.displaySleep = true;
8570 }
8571 if (!wranglerAsleep) {
8572 // transition from wrangler wake to wrangler sleep
8573 flags.bit.displaySleepEntry = true;
8574 wranglerAsleep = true;
8575 }
8576 break;
8577
8578 case kStimulusDisplayWranglerWake:
8579 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8580 displayIdleForDemandSleep = false;
8581 wranglerPowerOff = false;
8582 wranglerAsleep = false;
8583 break;
8584
8585 case kStimulusEnterUserActiveState:
8586 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8587 if (_preventUserActive) {
8588 DLOG("user active dropped\n");
8589 break;
8590 }
8591 if (!userIsActive) {
8592 userIsActive = true;
8593 userWasActive = true;
8594 clock_get_uptime(&gUserActiveAbsTime);
8595
8596 // Stay awake after dropping demand for display power on
8597 if (kFullWakeReasonDisplayOn == fullWakeReason) {
8598 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8599 DLOG("User activity while in notification wake\n");
8600 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8601 }
8602
8603 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8604 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8605 messageClients(kIOPMMessageUserIsActiveChanged);
8606 }
8607 flags.bit.idleSleepDisabled = true;
8608 break;
8609
8610 case kStimulusLeaveUserActiveState:
8611 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8612 if (userIsActive) {
8613 clock_get_uptime(&gUserInactiveAbsTime);
8614 userIsActive = false;
8615 clock_get_uptime(&userBecameInactiveTime);
8616 flags.bit.userBecameInactive = true;
8617
8618 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8619 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8620 messageClients(kIOPMMessageUserIsActiveChanged);
8621 }
8622 break;
8623
8624 case kStimulusAggressivenessChanged:
8625 {
8626 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8627 unsigned long aggressiveValue;
8628 uint32_t minutesToIdleSleep = 0;
8629 uint32_t minutesToDisplayDim = 0;
8630 uint32_t minutesDelta = 0;
8631
8632 // Fetch latest display and system sleep slider values.
8633 aggressiveValue = 0;
8634 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8635 minutesToIdleSleep = (uint32_t) aggressiveValue;
8636
8637 aggressiveValue = 0;
8638 getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8639 minutesToDisplayDim = (uint32_t) aggressiveValue;
8640 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8641 sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8642
8643 DLOG("idle time -> %d ms (ena %d)\n",
8644 idleMilliSeconds, (minutesToIdleSleep != 0));
8645
8646 // How long to wait before sleeping the system once
8647 // the displays turns off is indicated by 'extraSleepDelay'.
8648
8649 if (minutesToIdleSleep > minutesToDisplayDim) {
8650 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8651 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8652 minutesDelta = 1;
8653 }
8654
8655 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8656 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8657 }
8658
8659 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8660 flags.bit.idleSleepDisabled = true;
8661 idleSleepEnabled = false;
8662 }
8663 #if !defined(XNU_TARGET_OS_OSX)
8664 if (0x7fffffff == minutesToIdleSleep) {
8665 minutesToIdleSleep = idleMilliSeconds / 1000;
8666 }
8667 #endif /* !defined(XNU_TARGET_OS_OSX) */
8668
8669 if (((minutesDelta != extraSleepDelay) ||
8670 (userActivityTime != userActivityTime_prev)) &&
8671 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8672 flags.bit.sleepDelayChanged = true;
8673 }
8674
8675 if (systemDarkWake && !darkWakeToSleepASAP &&
8676 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8677 // Reconsider decision to remain in dark wake
8678 flags.bit.evaluateDarkWake = true;
8679 }
8680
8681 sleepSlider = minutesToIdleSleep;
8682 extraSleepDelay = minutesDelta;
8683 userActivityTime_prev = userActivityTime;
8684 } break;
8685
8686 case kStimulusDemandSystemSleep:
8687 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8688 displayIdleForDemandSleep = true;
8689 if (wrangler && wranglerIdleSettings) {
8690 // Request wrangler idle only when demand sleep is triggered
8691 // from full wake.
8692 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8693 wrangler->setProperties(wranglerIdleSettings.get());
8694 DLOG("Requested wrangler idle\n");
8695 }
8696 }
8697 // arg = sleepReason
8698 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8699 break;
8700
8701 case kStimulusAllowSystemSleepChanged:
8702 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8703 flags.bit.adjustPowerState = true;
8704 break;
8705
8706 case kStimulusDarkWakeActivityTickle:
8707 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8708 // arg == true implies real and not self generated wrangler tickle.
8709 // Update wake type on PM work loop instead of the tickle thread to
8710 // eliminate the possibility of an early tickle clobbering the wake
8711 // type set by the platform driver.
8712 if (arg == true) {
8713 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8714 }
8715
8716 if (!darkWakeExit) {
8717 if (latchDisplayWranglerTickle(true)) {
8718 DLOG("latched tickle\n");
8719 break;
8720 }
8721
8722 darkWakeExit = true;
8723 DLOG("Requesting full wake due to dark wake activity tickle\n");
8724 requestFullWake( kFullWakeReasonLocalUser );
8725 }
8726 break;
8727
8728 case kStimulusDarkWakeEntry:
8729 case kStimulusDarkWakeReentry:
8730 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8731 // Any system transitions since the last dark wake transition
8732 // will invalid the stimulus.
8733
8734 if (arg == _systemStateGeneration) {
8735 DLOG("dark wake entry\n");
8736 systemDarkWake = true;
8737
8738 // Keep wranglerPowerOff an invariant when wrangler is absent
8739 if (wrangler) {
8740 wranglerPowerOff = true;
8741 }
8742
8743 if (kStimulusDarkWakeEntry == stimulus) {
8744 clock_get_uptime(&userBecameInactiveTime);
8745 flags.bit.evaluateDarkWake = true;
8746 if (activitySinceSleep()) {
8747 DLOG("User activity recorded while going to darkwake\n");
8748 reportUserInput();
8749 }
8750 }
8751
8752 // Always accelerate disk spindown while in dark wake,
8753 // even if system does not support/allow sleep.
8754
8755 cancelIdleSleepTimer();
8756 setQuickSpinDownTimeout();
8757 }
8758 break;
8759
8760 case kStimulusDarkWakeEvaluate:
8761 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8762 if (systemDarkWake) {
8763 flags.bit.evaluateDarkWake = true;
8764 }
8765 break;
8766
8767 case kStimulusNoIdleSleepPreventers:
8768 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8769 flags.bit.adjustPowerState = true;
8770 break;
8771 } /* switch(stimulus) */
8772
8773 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8774 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8775 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8776 if (darkWakeToSleepASAP ||
8777 (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8778 uint32_t newSleepReason;
8779
8780 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8781 // System was previously in full wake. Sleep reason from
8782 // full to dark already recorded in fullToDarkReason.
8783
8784 if (lowBatteryCondition) {
8785 newSleepReason = kIOPMSleepReasonLowPower;
8786 } else if (thermalEmergencyState) {
8787 newSleepReason = kIOPMSleepReasonThermalEmergency;
8788 } else {
8789 newSleepReason = fullToDarkReason;
8790 }
8791 } else {
8792 // In dark wake from system sleep.
8793
8794 if (darkWakeSleepService) {
8795 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8796 } else {
8797 newSleepReason = kIOPMSleepReasonMaintenance;
8798 }
8799 }
8800
8801 if (checkSystemCanSleep(newSleepReason)) {
8802 privateSleepSystem(newSleepReason);
8803 }
8804 } else { // non-maintenance (network) dark wake
8805 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8806 // Release power clamp, and wait for children idle.
8807 adjustPowerState(true);
8808 } else {
8809 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8810 }
8811 }
8812 }
8813
8814 if (systemDarkWake) {
8815 // The rest are irrelevant while system is in dark wake.
8816 flags.u32 = 0;
8817 }
8818
8819 if ((flags.bit.displaySleepEntry) &&
8820 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8821 // kIOPMSleepReasonNotificationWakeExit
8822 DLOG("Display sleep while in notification wake\n");
8823 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8824 }
8825
8826 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8827 bool cancelQuickSpindown = false;
8828
8829 if (flags.bit.sleepDelayChanged) {
8830 // Cancel existing idle sleep timer and quick disk spindown.
8831 // New settings will be applied by the idleSleepEnabled flag
8832 // handler below if idle sleep is enabled.
8833
8834 DLOG("extra sleep timer changed\n");
8835 cancelIdleSleepTimer();
8836 cancelQuickSpindown = true;
8837 } else {
8838 DLOG("user inactive\n");
8839 }
8840
8841 if (!userIsActive && idleSleepEnabled) {
8842 startIdleSleepTimer(getTimeToIdleSleep());
8843 }
8844
8845 if (cancelQuickSpindown) {
8846 restoreUserSpinDownTimeout();
8847 }
8848 }
8849
8850 if (flags.bit.idleSleepEnabled) {
8851 DLOG("idle sleep timer enabled\n");
8852 if (!wrangler) {
8853 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8854 startIdleSleepTimer(getTimeToIdleSleep());
8855 #else
8856 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8857 startIdleSleepTimer( idleMilliSeconds );
8858 #endif
8859 } else {
8860 // Start idle timer if prefs now allow system sleep
8861 // and user is already inactive. Disk spindown is
8862 // accelerated upon timer expiration.
8863
8864 if (!userIsActive) {
8865 startIdleSleepTimer(getTimeToIdleSleep());
8866 }
8867 }
8868 }
8869
8870 if (flags.bit.idleSleepDisabled) {
8871 DLOG("idle sleep timer disabled\n");
8872 cancelIdleSleepTimer();
8873 restoreUserSpinDownTimeout();
8874 adjustPowerState();
8875 }
8876
8877 if (flags.bit.adjustPowerState) {
8878 bool sleepASAP = false;
8879
8880 if (!systemBooting && (0 == idleSleepPreventersCount())) {
8881 if (!wrangler) {
8882 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
8883 if (idleSleepEnabled) {
8884 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8885 if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
8886 sleepASAP = true;
8887 }
8888 #else
8889 // stay awake for at least idleMilliSeconds
8890 startIdleSleepTimer(idleMilliSeconds);
8891 #endif
8892 }
8893 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
8894 sleepASAP = true;
8895 }
8896 }
8897
8898 adjustPowerState(sleepASAP);
8899 }
8900 }
8901
8902 //******************************************************************************
8903
8904 unsigned int
idleSleepPreventersCount()8905 IOPMrootDomain::idleSleepPreventersCount()
8906 {
8907 if (_aotMode) {
8908 unsigned int count __block;
8909 count = 0;
8910 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
8911 {
8912 count += (NULL == obj->metaCast("AppleARMBacklight"));
8913 return false;
8914 });
8915 return count;
8916 }
8917
8918 return preventIdleSleepList->getCount();
8919 }
8920
8921
8922 //******************************************************************************
8923 // requestFullWake
8924 //
8925 // Request transition from dark wake to full wake
8926 //******************************************************************************
8927
8928 void
requestFullWake(FullWakeReason reason)8929 IOPMrootDomain::requestFullWake( FullWakeReason reason )
8930 {
8931 uint32_t options = 0;
8932 IOService * pciRoot = NULL;
8933 bool promotion = false;
8934
8935 // System must be in dark wake and a valid reason for entering full wake
8936 if ((kFullWakeReasonNone == reason) ||
8937 (kFullWakeReasonNone != fullWakeReason) ||
8938 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8939 return;
8940 }
8941
8942 // Will clear reason upon exit from full wake
8943 fullWakeReason = reason;
8944
8945 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
8946 kIOPMSystemCapabilityAudio);
8947
8948 if ((kSystemTransitionWake == _systemTransitionType) &&
8949 !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
8950 !darkWakePowerClamped) {
8951 // Promote to full wake while waking up to dark wake due to tickle.
8952 // PM will hold off notifying the graphics subsystem about system wake
8953 // as late as possible, so if a HID tickle does arrive, graphics can
8954 // power up from this same wake transition. Otherwise, the latency to
8955 // power up graphics on the following transition can be huge on certain
8956 // systems. However, once any power clamping has taken effect, it is
8957 // too late to promote the current dark wake transition to a full wake.
8958 _pendingCapability |= (kIOPMSystemCapabilityGraphics |
8959 kIOPMSystemCapabilityAudio);
8960
8961 // Tell the PCI parent of audio and graphics drivers to stop
8962 // delaying the child notifications. Same for root domain.
8963 pciRoot = pciHostBridgeDriver.get();
8964 willEnterFullWake();
8965 promotion = true;
8966 }
8967
8968 // Unsafe to cancel once graphics was powered.
8969 // If system woke from dark wake, the return to sleep can
8970 // be cancelled. "awake -> dark -> sleep" transition
8971 // can be cancelled also, during the "dark -> sleep" phase
8972 // *prior* to driver power down.
8973 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
8974 _pendingCapability == 0) {
8975 options |= kIOPMSyncCancelPowerDown;
8976 }
8977
8978 synchronizePowerTree(options, pciRoot);
8979
8980 if (kFullWakeReasonLocalUser == fullWakeReason) {
8981 // IOGraphics doesn't light the display even though graphics is
8982 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8983 // So, do an explicit activity tickle
8984 if (wrangler) {
8985 wrangler->activityTickle(0, 0);
8986 }
8987 }
8988
8989 // Log a timestamp for the initial full wake request.
8990 // System may not always honor this full wake request.
8991 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8992 AbsoluteTime now;
8993 uint64_t nsec;
8994
8995 clock_get_uptime(&now);
8996 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
8997 absolutetime_to_nanoseconds(now, &nsec);
8998 MSG("full wake %s (reason %u) %u ms\n",
8999 promotion ? "promotion" : "request",
9000 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9001 }
9002 }
9003
9004 //******************************************************************************
9005 // willEnterFullWake
9006 //
9007 // System will enter full wake from sleep, from dark wake, or from dark
9008 // wake promotion. This function aggregate things that are in common to
9009 // all three full wake transitions.
9010 //
9011 // Assumptions: fullWakeReason was updated
9012 //******************************************************************************
9013
9014 void
willEnterFullWake(void)9015 IOPMrootDomain::willEnterFullWake( void )
9016 {
9017 hibernateRetry = false;
9018 sleepToStandby = false;
9019 standbyNixed = false;
9020 resetTimers = false;
9021 sleepTimerMaintenance = false;
9022
9023 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9024
9025 _systemMessageClientMask = kSystemMessageClientPowerd |
9026 kSystemMessageClientLegacyApp;
9027
9028 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9029 // First time to attain full wake capability since the last wake
9030 _systemMessageClientMask |= kSystemMessageClientKernel;
9031
9032 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9033 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9034 (kFullWakeReasonLocalUser == fullWakeReason) ?
9035 kOSBooleanTrue : kOSBooleanFalse);
9036 }
9037 #if HIBERNATION
9038 IOHibernateSetWakeCapabilities(_pendingCapability);
9039 #endif
9040
9041 IOService::setAdvisoryTickleEnable( true );
9042 tellClients(kIOMessageSystemWillPowerOn);
9043 preventTransitionToUserActive(false);
9044 }
9045
9046 //******************************************************************************
9047 // fullWakeDelayedWork
9048 //
9049 // System has already entered full wake. Invoked by a delayed thread call.
9050 //******************************************************************************
9051
9052 void
fullWakeDelayedWork(void)9053 IOPMrootDomain::fullWakeDelayedWork( void )
9054 {
9055 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9056 if (!gIOPMWorkLoop->inGate()) {
9057 gIOPMWorkLoop->runAction(
9058 OSMemberFunctionCast(IOWorkLoop::Action, this,
9059 &IOPMrootDomain::fullWakeDelayedWork), this);
9060 return;
9061 }
9062
9063 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9064 _currentCapability, _pendingCapability, _highestCapability,
9065 clamshellDisabled, clamshellSleepDisableMask);
9066
9067 if (clamshellExists &&
9068 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9069 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9070 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9071 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9072 } else {
9073 // Not the initial full wake after waking from sleep.
9074 // Evaluate the clamshell for rdar://problem/9157444.
9075 receivePowerNotification(kLocalEvalClamshellCommand);
9076 }
9077 }
9078 #endif
9079 }
9080
9081 //******************************************************************************
9082 // evaluateAssertions
9083 //
9084 //******************************************************************************
9085
9086 // Bitmask of all kernel assertions that prevent system idle sleep.
9087 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9088 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9089 (kIOPMDriverAssertionReservedBit7 | \
9090 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9091
9092 void
evaluateAssertions(IOPMDriverAssertionType newAssertions,IOPMDriverAssertionType oldAssertions)9093 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9094 {
9095 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9096
9097 messageClients(kIOPMMessageDriverAssertionsChanged);
9098
9099 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9100 if (wrangler) {
9101 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9102
9103 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9104 wrangler->setIgnoreIdleTimer( value );
9105 }
9106 }
9107
9108 if (changedBits & kIOPMDriverAssertionCPUBit) {
9109 if (_aotNow) {
9110 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9111 }
9112 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9113 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9114 AbsoluteTime now;
9115 clock_usec_t microsecs;
9116 clock_get_uptime(&now);
9117 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9118 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs);
9119 if (assertOnWakeReport) {
9120 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9121 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9122 }
9123 }
9124 }
9125
9126 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9127 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9128 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9129 DLOG("PreventIdleSleep driver assertion raised\n");
9130 bool ok = updatePreventIdleSleepList(this, true);
9131 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9132 // Cancel idle sleep if there is one in progress
9133 cancelIdlePowerDown(this);
9134 }
9135 }
9136 } else {
9137 DLOG("PreventIdleSleep driver assertion dropped\n");
9138 updatePreventIdleSleepList(this, false);
9139 }
9140 }
9141 }
9142
9143 // MARK: -
9144 // MARK: Statistics
9145
9146 //******************************************************************************
9147 // pmStats
9148 //
9149 //******************************************************************************
9150
9151 void
pmStatsRecordEvent(int eventIndex,AbsoluteTime timestamp)9152 IOPMrootDomain::pmStatsRecordEvent(
9153 int eventIndex,
9154 AbsoluteTime timestamp)
9155 {
9156 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9157 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9158 uint64_t delta;
9159 uint64_t nsec;
9160 OSSharedPtr<OSData> publishPMStats;
9161
9162 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9163
9164 absolutetime_to_nanoseconds(timestamp, &nsec);
9165
9166 switch (eventIndex) {
9167 case kIOPMStatsHibernateImageWrite:
9168 if (starting) {
9169 gPMStats.hibWrite.start = nsec;
9170 } else if (stopping) {
9171 gPMStats.hibWrite.stop = nsec;
9172 }
9173
9174 if (stopping) {
9175 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9176 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9177 }
9178 break;
9179 case kIOPMStatsHibernateImageRead:
9180 if (starting) {
9181 gPMStats.hibRead.start = nsec;
9182 } else if (stopping) {
9183 gPMStats.hibRead.stop = nsec;
9184 }
9185
9186 if (stopping) {
9187 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9188 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9189
9190 publishPMStats = OSData::withValue(gPMStats);
9191 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9192 bzero(&gPMStats, sizeof(gPMStats));
9193 }
9194 break;
9195 }
9196 }
9197
9198 /*
9199 * Appends a record of the application response to
9200 * IOPMrootDomain::pmStatsAppResponses
9201 */
9202 void
pmStatsRecordApplicationResponse(const OSSymbol * response,const char * name,int messageType,uint32_t delay_ms,uint64_t id,OSObject * object,IOPMPowerStateIndex powerState,bool async)9203 IOPMrootDomain::pmStatsRecordApplicationResponse(
9204 const OSSymbol *response,
9205 const char *name,
9206 int messageType,
9207 uint32_t delay_ms,
9208 uint64_t id,
9209 OSObject *object,
9210 IOPMPowerStateIndex powerState,
9211 bool async)
9212 {
9213 OSSharedPtr<OSDictionary> responseDescription;
9214 OSSharedPtr<OSNumber> delayNum;
9215 OSSharedPtr<OSNumber> powerCaps;
9216 OSSharedPtr<OSNumber> pidNum;
9217 OSSharedPtr<OSNumber> msgNum;
9218 OSSharedPtr<const OSSymbol> appname;
9219 OSSharedPtr<const OSSymbol> sleep;
9220 OSSharedPtr<const OSSymbol> wake;
9221 IOPMServiceInterestNotifier *notify = NULL;
9222
9223 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9224 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9225 notify->ackTimeoutCnt++;
9226 } else {
9227 notify->ackTimeoutCnt = 0;
9228 }
9229 }
9230
9231 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9232 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9233 return;
9234 }
9235
9236
9237 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9238 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9239 } else if (notify) {
9240 // User space app or kernel capability client
9241 if (id) {
9242 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9243 } else {
9244 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9245 }
9246 notify->msgType = 0;
9247 }
9248
9249 responseDescription = OSDictionary::withCapacity(5);
9250 if (responseDescription) {
9251 if (response) {
9252 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9253 }
9254
9255 msgNum = OSNumber::withNumber(messageType, 32);
9256 if (msgNum) {
9257 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9258 }
9259
9260 if (!name && notify && notify->identifier) {
9261 name = notify->identifier->getCStringNoCopy();
9262 }
9263
9264 if (name && (strlen(name) > 0)) {
9265 appname = OSSymbol::withCString(name);
9266 if (appname) {
9267 responseDescription->setObject(_statsNameKey.get(), appname.get());
9268 }
9269 }
9270
9271 if (!id && notify) {
9272 id = notify->uuid0;
9273 }
9274 pidNum = OSNumber::withNumber(id, 64);
9275 if (pidNum) {
9276 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9277 }
9278
9279 delayNum = OSNumber::withNumber(delay_ms, 32);
9280 if (delayNum) {
9281 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9282 }
9283
9284 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9285 powerCaps = OSNumber::withNumber(powerState, 32);
9286
9287 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9288 static const char * driverCallTypes[] = {
9289 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9290 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9291 [kDriverCallSetPowerState] = "setPowerState"
9292 };
9293
9294 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9295 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9296 name, id, driverCallTypes[messageType], (uint32_t) powerState,
9297 async ? "async " : "", delay_ms);
9298 }
9299 #endif
9300 } else {
9301 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9302 }
9303 if (powerCaps) {
9304 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9305 }
9306
9307 sleep = OSSymbol::withCString("Sleep");
9308 wake = OSSymbol::withCString("Wake");
9309 if (_systemTransitionType == kSystemTransitionSleep) {
9310 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9311 } else if (_systemTransitionType == kSystemTransitionWake) {
9312 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9313 } else if (_systemTransitionType == kSystemTransitionCapability) {
9314 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9315 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9316 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9317 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9318 }
9319 }
9320
9321 IOLockLock(pmStatsLock);
9322 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9323 pmStatsAppResponses->setObject(responseDescription.get());
9324 }
9325 IOLockUnlock(pmStatsLock);
9326 }
9327
9328 return;
9329 }
9330
9331 // MARK: -
9332 // MARK: PMTraceWorker
9333
9334 //******************************************************************************
9335 // TracePoint support
9336 //
9337 //******************************************************************************
9338
9339 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9340 "IOPMRegisterNVRAMTracePointHandler"
9341
9342 IOReturn
callPlatformFunction(const OSSymbol * functionName,bool waitForFunction,void * param1,void * param2,void * param3,void * param4)9343 IOPMrootDomain::callPlatformFunction(
9344 const OSSymbol * functionName,
9345 bool waitForFunction,
9346 void * param1, void * param2,
9347 void * param3, void * param4 )
9348 {
9349 if (pmTracer && functionName &&
9350 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9351 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9352 uint32_t tracePointPhases, tracePointPCI;
9353 uint64_t statusCode;
9354
9355 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9356 pmTracer->tracePointTarget = (void *) param2;
9357 tracePointPCI = (uint32_t)(uintptr_t) param3;
9358 tracePointPhases = (uint32_t)(uintptr_t) param4;
9359 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9360 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9361 if (node) {
9362 OSSharedPtr<OSObject> bootRomFailureProp;
9363 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9364 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9365 uint32_t bootFailureCode;
9366 if (data && data->getLength() == sizeof(bootFailureCode)) {
9367 // Failure code from EFI/BootRom is a four byte structure
9368 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9369 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9370 }
9371 }
9372 }
9373 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9374 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9375 MSG("Sleep failure code 0x%08x 0x%08x\n",
9376 tracePointPCI, tracePointPhases);
9377 }
9378 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9379 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9380
9381 return kIOReturnSuccess;
9382 }
9383 #if HIBERNATION
9384 else if (functionName &&
9385 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9386 if (gSleepPolicyHandler) {
9387 return kIOReturnExclusiveAccess;
9388 }
9389 if (!param1) {
9390 return kIOReturnBadArgument;
9391 }
9392 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9393 gSleepPolicyTarget = (void *) param2;
9394 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9395 return kIOReturnSuccess;
9396 }
9397 #endif
9398
9399 return super::callPlatformFunction(
9400 functionName, waitForFunction, param1, param2, param3, param4);
9401 }
9402
9403 void
kdebugTrace(uint32_t event,uint64_t id,uintptr_t param1,uintptr_t param2,uintptr_t param3)9404 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9405 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9406 {
9407 uint32_t code = IODBG_POWER(event);
9408 uint64_t regId = id;
9409 if (regId == 0) {
9410 regId = getRegistryEntryID();
9411 }
9412 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9413 }
9414
9415 void
tracePoint(uint8_t point)9416 IOPMrootDomain::tracePoint( uint8_t point )
9417 {
9418 if (systemBooting) {
9419 return;
9420 }
9421
9422 if (kIOPMTracePointWakeCapabilityClients == point) {
9423 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9424 }
9425
9426 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9427 pmTracer->tracePoint(point);
9428 }
9429
9430 static void
kext_log_putc(char c)9431 kext_log_putc(char c)
9432 {
9433 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9434 return;
9435 }
9436 if (c == '(' || c == '[' || c == ' ') {
9437 c = 0;
9438 gKextNameEnd = true;
9439 }
9440
9441 gKextNameBuf[gKextNamePos++] = c;
9442 }
9443
9444 static int
kext_log(const char * fmt,...)9445 kext_log(const char *fmt, ...)
9446 {
9447 va_list listp;
9448
9449 va_start(listp, fmt);
9450 _doprnt(fmt, &listp, &kext_log_putc, 16);
9451 va_end(listp);
9452
9453 return 0;
9454 }
9455
9456 static OSPtr<const OSSymbol>
copyKextIdentifierWithAddress(vm_address_t address)9457 copyKextIdentifierWithAddress(vm_address_t address)
9458 {
9459 OSSharedPtr<const OSSymbol> identifer;
9460
9461 IOLockLock(gHaltLogLock);
9462
9463 gKextNameEnd = false;
9464 gKextNamePos = 0;
9465 gKextNameBuf[0] = 0;
9466
9467 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9468 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9469 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9470
9471 IOLockUnlock(gHaltLogLock);
9472
9473 return identifer;
9474 }
9475
9476 // Caller serialized using PM workloop
9477 const char *
getNotificationClientName(OSObject * object)9478 IOPMrootDomain::getNotificationClientName(OSObject *object)
9479 {
9480 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9481 const char *clientName = "UNKNOWN";
9482
9483 if (!notifier->clientName) {
9484 // Check for user client
9485 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9486 OSNumber *clientID = NULL;
9487 messageClient(kIOMessageCopyClientID, object, &clientID);
9488 if (clientID) {
9489 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9490 if (string) {
9491 notifier->clientName = OSSymbol::withString(string.get());
9492 }
9493 clientID->release();
9494 }
9495 } else if (notifier->identifier) {
9496 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9497 }
9498 }
9499
9500 if (notifier->clientName) {
9501 clientName = notifier->clientName->getCStringNoCopy();
9502 }
9503
9504 return clientName;
9505 }
9506
9507 void
traceNotification(OSObject * object,bool start,uint64_t timestamp,uint32_t msgIndex)9508 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9509 {
9510 IOPMServiceInterestNotifier *notifier;
9511
9512 if (systemBooting) {
9513 return;
9514 }
9515 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9516 if (!notifier) {
9517 return;
9518 }
9519
9520 if (start) {
9521 pmTracer->traceDetail(notifier->uuid0 >> 32);
9522 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9523 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9524
9525 // Update notifier state used for response/ack logging
9526 notifier->msgIndex = msgIndex;
9527 notifier->msgAbsTime = timestamp;
9528
9529 if (msgIndex != UINT_MAX) {
9530 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9531 } else {
9532 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9533 }
9534
9535 assert(notifierObject == NULL);
9536 notifierThread = current_thread();
9537 notifierObject.reset(notifier, OSRetain);
9538 } else {
9539 uint64_t nsec;
9540 uint32_t delayMS;
9541
9542 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime);
9543 absolutetime_to_nanoseconds(timestamp, &nsec);
9544 delayMS = (uint32_t)(nsec / 1000000ULL);
9545 if (delayMS > notifier->maxMsgDelayMS) {
9546 notifier->maxMsgDelayMS = delayMS;
9547 }
9548
9549 assert(notifierObject == notifier);
9550 notifierObject.reset();
9551 notifierThread = NULL;
9552 }
9553 }
9554
9555 void
traceNotificationAck(OSObject * object,uint32_t delay_ms)9556 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9557 {
9558 if (systemBooting) {
9559 return;
9560 }
9561 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9562 if (!notifier) {
9563 return;
9564 }
9565
9566 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9567 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9568
9569 DLOG("%s[%u] ack from %s took %d ms\n",
9570 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9571 if (delay_ms > notifier->maxAckDelayMS) {
9572 notifier->maxAckDelayMS = delay_ms;
9573 }
9574 }
9575
9576 void
traceNotificationResponse(OSObject * object,uint32_t delay_ms,uint32_t ack_time_us)9577 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9578 {
9579 if (systemBooting) {
9580 return;
9581 }
9582 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9583 if (!notifier) {
9584 return;
9585 }
9586
9587 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9588 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9589
9590 if (ack_time_us == 0) {
9591 // Client work is done and ack will not be forthcoming
9592 DLOG("%s[%u] response from %s took %d ms\n",
9593 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9594 } else {
9595 // Client needs more time and it must ack within ack_time_us
9596 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9597 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9598 }
9599 }
9600
9601 void
traceFilteredNotification(OSObject * object)9602 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9603 {
9604 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9605 return;
9606 }
9607 if (systemBooting) {
9608 return;
9609 }
9610 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9611 if (!notifier) {
9612 return;
9613 }
9614
9615 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9616 }
9617
9618 void
traceDetail(uint32_t msgType,uint32_t msgIndex,uint32_t delay)9619 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9620 {
9621 if (!systemBooting) {
9622 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9623 pmTracer->traceDetail( detail );
9624 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9625 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9626 }
9627 }
9628
9629 void
configureReportGated(uint64_t channel_id,uint64_t action,void * result)9630 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9631 {
9632 size_t reportSize;
9633 void **report = NULL;
9634 uint32_t bktCnt;
9635 uint32_t bktSize;
9636 uint32_t *clientCnt;
9637
9638 ASSERT_GATED();
9639
9640 report = NULL;
9641 if (channel_id == kAssertDelayChID) {
9642 report = &assertOnWakeReport;
9643 bktCnt = kAssertDelayBcktCnt;
9644 bktSize = kAssertDelayBcktSize;
9645 clientCnt = &assertOnWakeClientCnt;
9646 } else if (channel_id == kSleepDelaysChID) {
9647 report = &sleepDelaysReport;
9648 bktCnt = kSleepDelaysBcktCnt;
9649 bktSize = kSleepDelaysBcktSize;
9650 clientCnt = &sleepDelaysClientCnt;
9651 } else {
9652 assert(false);
9653 return;
9654 }
9655
9656 switch (action) {
9657 case kIOReportEnable:
9658
9659 if (*report) {
9660 (*clientCnt)++;
9661 break;
9662 }
9663
9664 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9665 *report = IOMallocZeroData(reportSize);
9666 if (*report == NULL) {
9667 break;
9668 }
9669 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9670 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9671
9672 if (channel_id == kAssertDelayChID) {
9673 assertOnWakeSecs = 0;
9674 }
9675
9676 break;
9677
9678 case kIOReportDisable:
9679 if (*clientCnt == 0) {
9680 break;
9681 }
9682 if (*clientCnt == 1) {
9683 IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9684 *report = NULL;
9685 }
9686 (*clientCnt)--;
9687
9688 if (channel_id == kAssertDelayChID) {
9689 assertOnWakeSecs = -1; // Invalid value to prevent updates
9690 }
9691 break;
9692
9693 case kIOReportGetDimensions:
9694 if (*report) {
9695 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9696 }
9697 break;
9698 }
9699
9700 return;
9701 }
9702
9703 IOReturn
configureReport(IOReportChannelList * channelList,IOReportConfigureAction action,void * result,void * destination)9704 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9705 IOReportConfigureAction action,
9706 void *result,
9707 void *destination)
9708 {
9709 unsigned cnt;
9710 uint64_t configAction = (uint64_t)action;
9711
9712 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9713 if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9714 (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9715 (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9716 if (action != kIOReportGetDimensions) {
9717 continue;
9718 }
9719 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9720 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9721 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9722 gIOPMWorkLoop->runAction(
9723 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9724 (OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9725 (void *)configAction, (void *)result);
9726 }
9727 }
9728
9729 return super::configureReport(channelList, action, result, destination);
9730 }
9731
9732 IOReturn
updateReportGated(uint64_t ch_id,void * result,IOBufferMemoryDescriptor * dest)9733 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9734 {
9735 uint32_t size2cpy;
9736 void *data2cpy;
9737 void **report;
9738
9739 ASSERT_GATED();
9740
9741 report = NULL;
9742 if (ch_id == kAssertDelayChID) {
9743 report = &assertOnWakeReport;
9744 } else if (ch_id == kSleepDelaysChID) {
9745 report = &sleepDelaysReport;
9746 } else {
9747 assert(false);
9748 return kIOReturnBadArgument;
9749 }
9750
9751 if (*report == NULL) {
9752 return kIOReturnNotOpen;
9753 }
9754
9755 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9756 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9757 return kIOReturnOverrun;
9758 }
9759
9760 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9761 dest->appendBytes(data2cpy, size2cpy);
9762
9763 return kIOReturnSuccess;
9764 }
9765
9766 IOReturn
updateReport(IOReportChannelList * channelList,IOReportUpdateAction action,void * result,void * destination)9767 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9768 IOReportUpdateAction action,
9769 void *result,
9770 void *destination)
9771 {
9772 uint32_t size2cpy;
9773 void *data2cpy;
9774 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9775 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9776 unsigned cnt;
9777 uint64_t ch_id;
9778
9779 if (action != kIOReportCopyChannelData) {
9780 goto exit;
9781 }
9782
9783 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9784 ch_id = channelList->channels[cnt].channel_id;
9785
9786 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9787 gIOPMWorkLoop->runAction(
9788 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9789 (OSObject *)this, (void *)ch_id,
9790 (void *)result, (void *)dest);
9791 continue;
9792 } else if ((ch_id == kSleepCntChID) ||
9793 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9794 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9795 } else {
9796 continue;
9797 }
9798
9799 if (ch_id == kSleepCntChID) {
9800 SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9801 } else if (ch_id == kDarkWkCntChID) {
9802 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9803 } else if (ch_id == kUserWkCntChID) {
9804 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9805 }
9806
9807 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9808 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9809 dest->appendBytes(data2cpy, size2cpy);
9810 }
9811
9812 exit:
9813 return super::updateReport(channelList, action, result, destination);
9814 }
9815
9816
9817 //******************************************************************************
9818 // PMTraceWorker Class
9819 //
9820 //******************************************************************************
9821
9822 #undef super
9823 #define super OSObject
OSDefineMetaClassAndStructors(PMTraceWorker,OSObject)9824 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9825
9826 #define kPMBestGuessPCIDevicesCount 25
9827 #define kPMMaxRTCBitfieldSize 32
9828
9829 OSPtr<PMTraceWorker>
9830 PMTraceWorker::tracer(IOPMrootDomain * owner)
9831 {
9832 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9833 if (!me || !me->init()) {
9834 return NULL;
9835 }
9836
9837 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9838
9839 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9840 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9841 // this dictionary lazily.
9842 me->owner = owner;
9843 me->pciDeviceBitMappings = NULL;
9844 me->pmTraceWorkerLock = IOLockAlloc();
9845 me->tracePhase = kIOPMTracePointSystemUp;
9846 me->traceData32 = 0;
9847 me->loginWindowData = 0;
9848 me->coreDisplayData = 0;
9849 me->coreGraphicsData = 0;
9850 return me;
9851 }
9852
9853 void
RTC_TRACE(void)9854 PMTraceWorker::RTC_TRACE(void)
9855 {
9856 if (tracePointHandler && tracePointTarget) {
9857 uint32_t wordA;
9858
9859 IOLockLock(pmTraceWorkerLock);
9860 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9861 (coreGraphicsData << 8) | tracePhase;
9862 IOLockUnlock(pmTraceWorkerLock);
9863
9864 tracePointHandler( tracePointTarget, traceData32, wordA );
9865 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9866 }
9867 #if DEVELOPMENT || DEBUG
9868 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
9869 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
9870 IOLock *l = IOLockAlloc();
9871 IOLockLock(l);
9872 IOLockLock(l);
9873 }
9874 #endif /* DEVELOPMENT || DEBUG */
9875 }
9876
9877 int
recordTopLevelPCIDevice(IOService * pciDevice)9878 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
9879 {
9880 OSSharedPtr<const OSSymbol> deviceName;
9881 int index = -1;
9882
9883 IOLockLock(pmTraceWorkerLock);
9884
9885 if (!pciDeviceBitMappings) {
9886 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
9887 if (!pciDeviceBitMappings) {
9888 goto exit;
9889 }
9890 }
9891
9892 // Check for bitmask overflow.
9893 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
9894 goto exit;
9895 }
9896
9897 if ((deviceName = pciDevice->copyName()) &&
9898 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
9899 pciDeviceBitMappings->setObject(deviceName.get())) {
9900 index = pciDeviceBitMappings->getCount() - 1;
9901 _LOG("PMTrace PCI array: set object %s => %d\n",
9902 deviceName->getCStringNoCopy(), index);
9903 }
9904
9905 if (!addedToRegistry && (index >= 0)) {
9906 addedToRegistry = owner->setProperty("PCITopLevel", this);
9907 }
9908
9909 exit:
9910 IOLockUnlock(pmTraceWorkerLock);
9911 return index;
9912 }
9913
9914 bool
serialize(OSSerialize * s) const9915 PMTraceWorker::serialize(OSSerialize *s) const
9916 {
9917 bool ok = false;
9918 if (pciDeviceBitMappings) {
9919 IOLockLock(pmTraceWorkerLock);
9920 ok = pciDeviceBitMappings->serialize(s);
9921 IOLockUnlock(pmTraceWorkerLock);
9922 }
9923 return ok;
9924 }
9925
9926 void
tracePoint(uint8_t phase)9927 PMTraceWorker::tracePoint(uint8_t phase)
9928 {
9929 // clear trace detail when phase begins
9930 if (tracePhase != phase) {
9931 traceData32 = 0;
9932 }
9933
9934 tracePhase = phase;
9935
9936 DLOG("trace point 0x%02x\n", tracePhase);
9937 RTC_TRACE();
9938 }
9939
9940 void
traceDetail(uint32_t detail)9941 PMTraceWorker::traceDetail(uint32_t detail)
9942 {
9943 if (detail == traceData32) {
9944 return;
9945 }
9946 traceData32 = detail;
9947 RTC_TRACE();
9948 }
9949
9950 void
traceComponentWakeProgress(uint32_t component,uint32_t data)9951 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
9952 {
9953 switch (component) {
9954 case kIOPMLoginWindowProgress:
9955 loginWindowData = data & kIOPMLoginWindowProgressMask;
9956 break;
9957 case kIOPMCoreDisplayProgress:
9958 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
9959 break;
9960 case kIOPMCoreGraphicsProgress:
9961 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
9962 break;
9963 default:
9964 return;
9965 }
9966
9967 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
9968 RTC_TRACE();
9969 }
9970
9971 void
tracePCIPowerChange(change_t type,IOService * service,uint32_t changeFlags,uint32_t bitNum)9972 PMTraceWorker::tracePCIPowerChange(
9973 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
9974 {
9975 uint32_t bitMask;
9976 uint32_t expectedFlag;
9977
9978 // Ignore PCI changes outside of system sleep/wake.
9979 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
9980 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
9981 return;
9982 }
9983
9984 // Only record the WillChange transition when going to sleep,
9985 // and the DidChange on the way up.
9986 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
9987 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
9988 kIOPMDomainWillChange : kIOPMDomainDidChange;
9989 if (changeFlags != expectedFlag) {
9990 return;
9991 }
9992
9993 // Mark this device off in our bitfield
9994 if (bitNum < kPMMaxRTCBitfieldSize) {
9995 bitMask = (1 << bitNum);
9996
9997 if (kPowerChangeStart == type) {
9998 traceData32 |= bitMask;
9999 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
10000 service->getName(), bitNum, bitMask, traceData32);
10001 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10002 } else {
10003 traceData32 &= ~bitMask;
10004 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10005 service->getName(), bitNum, bitMask, traceData32);
10006 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10007 }
10008
10009 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10010 RTC_TRACE();
10011 }
10012 }
10013
10014 uint64_t
getPMStatusCode()10015 PMTraceWorker::getPMStatusCode()
10016 {
10017 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10018 }
10019
10020 uint8_t
getTracePhase()10021 PMTraceWorker::getTracePhase()
10022 {
10023 return tracePhase;
10024 }
10025
10026 uint32_t
getTraceData()10027 PMTraceWorker::getTraceData()
10028 {
10029 return traceData32;
10030 }
10031
10032 // MARK: -
10033 // MARK: PMHaltWorker
10034
10035 //******************************************************************************
10036 // PMHaltWorker Class
10037 //
10038 //******************************************************************************
10039
10040 PMHaltWorker *
worker(void)10041 PMHaltWorker::worker( void )
10042 {
10043 PMHaltWorker * me;
10044 IOThread thread;
10045
10046 do {
10047 me = OSTypeAlloc( PMHaltWorker );
10048 if (!me || !me->init()) {
10049 break;
10050 }
10051
10052 me->lock = IOLockAlloc();
10053 if (!me->lock) {
10054 break;
10055 }
10056
10057 DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10058 me->retain(); // thread holds extra retain
10059 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10060 me->release();
10061 break;
10062 }
10063 thread_deallocate(thread);
10064 return me;
10065 } while (false);
10066
10067 if (me) {
10068 me->release();
10069 }
10070 return NULL;
10071 }
10072
10073 void
free(void)10074 PMHaltWorker::free( void )
10075 {
10076 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10077 if (lock) {
10078 IOLockFree(lock);
10079 lock = NULL;
10080 }
10081 return OSObject::free();
10082 }
10083
10084 void
main(void * arg,wait_result_t waitResult)10085 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10086 {
10087 PMHaltWorker * me = (PMHaltWorker *) arg;
10088
10089 IOLockLock( gPMHaltLock );
10090 gPMHaltBusyCount++;
10091 me->depth = gPMHaltDepth;
10092 IOLockUnlock( gPMHaltLock );
10093
10094 while (me->depth >= 0) {
10095 PMHaltWorker::work( me );
10096
10097 IOLockLock( gPMHaltLock );
10098 if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10099 // This is the last thread to finish work on this level,
10100 // inform everyone to start working on next lower level.
10101 gPMHaltDepth--;
10102 me->depth = gPMHaltDepth;
10103 gPMHaltIdleCount = 0;
10104 thread_wakeup((event_t) &gPMHaltIdleCount);
10105 } else {
10106 // One or more threads are still working on this level,
10107 // this thread must wait.
10108 me->depth = gPMHaltDepth - 1;
10109 do {
10110 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10111 } while (me->depth != gPMHaltDepth);
10112 }
10113 IOLockUnlock( gPMHaltLock );
10114 }
10115
10116 // No more work to do, terminate thread
10117 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10118 thread_wakeup( &gPMHaltDepth );
10119 me->release();
10120 }
10121
10122 void
work(PMHaltWorker * me)10123 PMHaltWorker::work( PMHaltWorker * me )
10124 {
10125 OSSharedPtr<IOService> service;
10126 OSSet * inner;
10127 AbsoluteTime startTime, elapsedTime;
10128 UInt32 deltaTime;
10129 bool timeout;
10130
10131 while (true) {
10132 timeout = false;
10133
10134 // Claim an unit of work from the shared pool
10135 IOLockLock( gPMHaltLock );
10136 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10137 if (inner) {
10138 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10139 if (service) {
10140 inner->removeObject(service.get());
10141 }
10142 }
10143 IOLockUnlock( gPMHaltLock );
10144 if (!service) {
10145 break; // no more work at this depth
10146 }
10147 clock_get_uptime(&startTime);
10148
10149 if (!service->isInactive() &&
10150 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10151 IOLockLock(me->lock);
10152 me->startTime = startTime;
10153 me->service = service.get();
10154 me->timeout = false;
10155 IOLockUnlock(me->lock);
10156
10157 service->systemWillShutdown( gPMHaltMessageType);
10158
10159 // Wait for driver acknowledgement
10160 IOLockLock(me->lock);
10161 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10162 IOLockSleep(me->lock, me, THREAD_UNINT);
10163 }
10164 me->service = NULL;
10165 timeout = me->timeout;
10166 IOLockUnlock(me->lock);
10167 }
10168
10169 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10170 if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10171 LOG("%s driver %s (0x%llx) took %u ms\n",
10172 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10173 "PowerOff" : "Restart",
10174 service->getName(), service->getRegistryEntryID(),
10175 (uint32_t) deltaTime );
10176 halt_log_enter("PowerOff/Restart handler completed",
10177 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10178 elapsedTime);
10179 }
10180
10181 me->visits++;
10182 }
10183 }
10184
10185 void
checkTimeout(PMHaltWorker * me,AbsoluteTime * now)10186 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10187 {
10188 UInt64 nano;
10189 AbsoluteTime startTime;
10190 AbsoluteTime endTime;
10191
10192 endTime = *now;
10193
10194 IOLockLock(me->lock);
10195 if (me->service && !me->timeout) {
10196 startTime = me->startTime;
10197 nano = 0;
10198 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10199 SUB_ABSOLUTETIME(&endTime, &startTime);
10200 absolutetime_to_nanoseconds(endTime, &nano);
10201 }
10202 if (nano > 3000000000ULL) {
10203 me->timeout = true;
10204
10205 halt_log_enter("PowerOff/Restart still waiting on handler",
10206 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10207 endTime);
10208 MSG("%s still waiting on %s\n",
10209 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10210 me->service->getName());
10211 }
10212 }
10213 IOLockUnlock(me->lock);
10214 }
10215
10216 //******************************************************************************
10217 // acknowledgeSystemWillShutdown
10218 //
10219 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10220 //******************************************************************************
10221
10222 void
acknowledgeSystemWillShutdown(IOService * from)10223 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10224 {
10225 PMHaltWorker * worker;
10226 OSSharedPtr<OSObject> prop;
10227
10228 if (!from) {
10229 return;
10230 }
10231
10232 //DLOG("%s acknowledged\n", from->getName());
10233 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10234 if (prop) {
10235 worker = (PMHaltWorker *) prop.get();
10236 IOLockLock(worker->lock);
10237 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10238 thread_wakeup((event_t) worker);
10239 IOLockUnlock(worker->lock);
10240 } else {
10241 DLOG("%s acknowledged without worker property\n",
10242 from->getName());
10243 }
10244 }
10245
10246
10247 //******************************************************************************
10248 // notifySystemShutdown
10249 //
10250 // Notify all objects in PM tree that system will shutdown or restart
10251 //******************************************************************************
10252
10253 static void
notifySystemShutdown(IOService * root,uint32_t messageType)10254 notifySystemShutdown( IOService * root, uint32_t messageType )
10255 {
10256 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10257 OSSharedPtr<IORegistryIterator> iter;
10258 IORegistryEntry * entry;
10259 IOService * node;
10260 OSSet * inner;
10261 OSSharedPtr<OSSet> newInner;
10262 PMHaltWorker * workers[kPMHaltMaxWorkers];
10263 AbsoluteTime deadline;
10264 unsigned int totalNodes = 0;
10265 unsigned int depth;
10266 unsigned int rootDepth;
10267 unsigned int numWorkers;
10268 unsigned int count;
10269 int waitResult;
10270 void * baseFunc;
10271 bool ok;
10272
10273 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10274
10275 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10276
10277 // Iterate the entire PM tree starting from root
10278
10279 rootDepth = root->getDepth( gIOPowerPlane );
10280 if (!rootDepth) {
10281 goto done;
10282 }
10283
10284 // debug - for repeated test runs
10285 while (PMHaltWorker::metaClass->getInstanceCount()) {
10286 IOSleep(1);
10287 }
10288
10289 if (!gPMHaltArray) {
10290 gPMHaltArray = OSArray::withCapacity(40);
10291 if (!gPMHaltArray) {
10292 goto done;
10293 }
10294 } else { // debug
10295 gPMHaltArray->flushCollection();
10296 }
10297
10298 if (!gPMHaltLock) {
10299 gPMHaltLock = IOLockAlloc();
10300 if (!gPMHaltLock) {
10301 goto done;
10302 }
10303 }
10304
10305 if (!gPMHaltClientAcknowledgeKey) {
10306 gPMHaltClientAcknowledgeKey =
10307 OSSymbol::withCStringNoCopy("PMShutdown");
10308 if (!gPMHaltClientAcknowledgeKey) {
10309 goto done;
10310 }
10311 }
10312
10313 gPMHaltMessageType = messageType;
10314
10315 // Depth-first walk of PM plane
10316
10317 iter = IORegistryIterator::iterateOver(
10318 root, gIOPowerPlane, kIORegistryIterateRecursively);
10319
10320 if (iter) {
10321 while ((entry = iter->getNextObject())) {
10322 node = OSDynamicCast(IOService, entry);
10323 if (!node) {
10324 continue;
10325 }
10326
10327 if (baseFunc ==
10328 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10329 continue;
10330 }
10331
10332 depth = node->getDepth( gIOPowerPlane );
10333 if (depth <= rootDepth) {
10334 continue;
10335 }
10336
10337 ok = false;
10338
10339 // adjust to zero based depth
10340 depth -= (rootDepth + 1);
10341
10342 // gPMHaltArray is an array of containers, each container
10343 // refers to nodes with the same depth.
10344
10345 count = gPMHaltArray->getCount();
10346 while (depth >= count) {
10347 // expand array and insert placeholders
10348 gPMHaltArray->setObject(PLACEHOLDER);
10349 count++;
10350 }
10351 count = gPMHaltArray->getCount();
10352 if (depth < count) {
10353 inner = (OSSet *)gPMHaltArray->getObject(depth);
10354 if (inner == PLACEHOLDER) {
10355 newInner = OSSet::withCapacity(40);
10356 if (newInner) {
10357 gPMHaltArray->replaceObject(depth, newInner.get());
10358 inner = newInner.get();
10359 }
10360 }
10361
10362 // PM nodes that appear more than once in the tree will have
10363 // the same depth, OSSet will refuse to add the node twice.
10364 if (inner) {
10365 ok = inner->setObject(node);
10366 }
10367 }
10368 if (!ok) {
10369 DLOG("Skipped PM node %s\n", node->getName());
10370 }
10371 }
10372 }
10373
10374 // debug only
10375 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10376 count = 0;
10377 if (inner != PLACEHOLDER) {
10378 count = inner->getCount();
10379 }
10380 DLOG("Nodes at depth %u = %u\n", i, count);
10381 }
10382
10383 // strip placeholders (not all depths are populated)
10384 numWorkers = 0;
10385 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10386 if (inner == PLACEHOLDER) {
10387 gPMHaltArray->removeObject(i);
10388 continue;
10389 }
10390 count = inner->getCount();
10391 if (count > numWorkers) {
10392 numWorkers = count;
10393 }
10394 totalNodes += count;
10395 i++;
10396 }
10397
10398 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10399 goto done;
10400 }
10401
10402 gPMHaltBusyCount = 0;
10403 gPMHaltIdleCount = 0;
10404 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10405
10406 // Create multiple workers (and threads)
10407
10408 if (numWorkers > kPMHaltMaxWorkers) {
10409 numWorkers = kPMHaltMaxWorkers;
10410 }
10411
10412 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10413 totalNodes, gPMHaltArray->getCount(), numWorkers);
10414
10415 for (unsigned int i = 0; i < numWorkers; i++) {
10416 workers[i] = PMHaltWorker::worker();
10417 }
10418
10419 // Wait for workers to exhaust all available work
10420
10421 IOLockLock(gPMHaltLock);
10422 while (gPMHaltDepth >= 0) {
10423 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10424
10425 waitResult = IOLockSleepDeadline(
10426 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10427 if (THREAD_TIMED_OUT == waitResult) {
10428 AbsoluteTime now;
10429 clock_get_uptime(&now);
10430
10431 IOLockUnlock(gPMHaltLock);
10432 for (unsigned int i = 0; i < numWorkers; i++) {
10433 if (workers[i]) {
10434 PMHaltWorker::checkTimeout(workers[i], &now);
10435 }
10436 }
10437 IOLockLock(gPMHaltLock);
10438 }
10439 }
10440 IOLockUnlock(gPMHaltLock);
10441
10442 // Release all workers
10443
10444 for (unsigned int i = 0; i < numWorkers; i++) {
10445 if (workers[i]) {
10446 workers[i]->release();
10447 }
10448 // worker also retained by it's own thread
10449 }
10450
10451 done:
10452 DLOG("%s done\n", __FUNCTION__);
10453 return;
10454 }
10455
10456 // MARK: -
10457 // MARK: Kernel Assertion
10458
10459 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10460
10461 IOPMDriverAssertionID
createPMAssertion(IOPMDriverAssertionType whichAssertionBits,IOPMDriverAssertionLevel assertionLevel,IOService * ownerService,const char * ownerDescription)10462 IOPMrootDomain::createPMAssertion(
10463 IOPMDriverAssertionType whichAssertionBits,
10464 IOPMDriverAssertionLevel assertionLevel,
10465 IOService *ownerService,
10466 const char *ownerDescription)
10467 {
10468 IOReturn ret;
10469 IOPMDriverAssertionID newAssertion;
10470
10471 if (!pmAssertions) {
10472 return 0;
10473 }
10474
10475 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10476
10477 if (kIOReturnSuccess == ret) {
10478 #if (DEVELOPMENT || DEBUG)
10479 if (_aotNow) {
10480 OSReportWithBacktrace("IOPMrootDomain::createPMAssertion(0x%qx)", newAssertion);
10481 }
10482 #endif /* (DEVELOPMENT || DEBUG) */
10483 return newAssertion;
10484 } else {
10485 return 0;
10486 }
10487 }
10488
10489 IOReturn
releasePMAssertion(IOPMDriverAssertionID releaseAssertion)10490 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10491 {
10492 #if (DEVELOPMENT || DEBUG)
10493 if (_aotNow) {
10494 OSReportWithBacktrace("IOPMrootDomain::releasePMAssertion(0x%qx)", releaseAssertion);
10495 }
10496 #endif /* (DEVELOPMENT || DEBUG) */
10497 if (!pmAssertions) {
10498 return kIOReturnInternalError;
10499 }
10500 return pmAssertions->releaseAssertion(releaseAssertion);
10501 }
10502
10503
10504 IOReturn
setPMAssertionLevel(IOPMDriverAssertionID assertionID,IOPMDriverAssertionLevel assertionLevel)10505 IOPMrootDomain::setPMAssertionLevel(
10506 IOPMDriverAssertionID assertionID,
10507 IOPMDriverAssertionLevel assertionLevel)
10508 {
10509 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10510 }
10511
10512 IOPMDriverAssertionLevel
getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)10513 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10514 {
10515 IOPMDriverAssertionType sysLevels;
10516
10517 if (!pmAssertions || whichAssertion == 0) {
10518 return kIOPMDriverAssertionLevelOff;
10519 }
10520
10521 sysLevels = pmAssertions->getActivatedAssertions();
10522
10523 // Check that every bit set in argument 'whichAssertion' is asserted
10524 // in the aggregate bits.
10525 if ((sysLevels & whichAssertion) == whichAssertion) {
10526 return kIOPMDriverAssertionLevelOn;
10527 } else {
10528 return kIOPMDriverAssertionLevelOff;
10529 }
10530 }
10531
10532 IOReturn
setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)10533 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10534 {
10535 if (!pmAssertions) {
10536 return kIOReturnNotFound;
10537 }
10538
10539 return pmAssertions->setUserAssertionLevels(inLevels);
10540 }
10541
10542 IOReturn
acquireDriverKitMatchingAssertion()10543 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10544 {
10545 return gIOPMWorkLoop->runActionBlock(^{
10546 if (_driverKitMatchingAssertionCount != 0) {
10547 _driverKitMatchingAssertionCount++;
10548 return kIOReturnSuccess;
10549 } else {
10550 bool fullToDarkTransition = (kSystemTransitionCapability == _systemTransitionType) && CAP_LOSS(kIOPMSystemCapabilityGraphics);
10551 if (kSystemTransitionSleep == _systemTransitionType || fullToDarkTransition) {
10552 // system transitioning from wake to sleep/darkwake
10553 return kIOReturnBusy;
10554 } else {
10555 // createPMAssertion is asynchronous.
10556 // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10557 // The assertion is used so that on release, we reevaluate all assertions
10558 _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10559 if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10560 _driverKitMatchingAssertionCount = 1;
10561 return kIOReturnSuccess;
10562 } else {
10563 return kIOReturnBusy;
10564 }
10565 }
10566 }
10567 });
10568 }
10569
10570 void
releaseDriverKitMatchingAssertion()10571 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10572 {
10573 gIOPMWorkLoop->runActionBlock(^{
10574 if (_driverKitMatchingAssertionCount != 0) {
10575 _driverKitMatchingAssertionCount--;
10576 if (_driverKitMatchingAssertionCount == 0) {
10577 releasePMAssertion(_driverKitMatchingAssertion);
10578 _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10579 }
10580 } else {
10581 panic("Over-release of driverkit matching assertion");
10582 }
10583 return kIOReturnSuccess;
10584 });
10585 }
10586
10587 bool
serializeProperties(OSSerialize * s) const10588 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10589 {
10590 if (pmAssertions) {
10591 pmAssertions->publishProperties();
10592 }
10593 return IOService::serializeProperties(s);
10594 }
10595
10596 OSSharedPtr<OSObject>
copyProperty(const char * aKey) const10597 IOPMrootDomain::copyProperty( const char * aKey) const
10598 {
10599 OSSharedPtr<OSObject> obj;
10600 obj = IOService::copyProperty(aKey);
10601
10602 if (obj) {
10603 return obj;
10604 }
10605
10606 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10607 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10608 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10609 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10610 } else {
10611 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10612 }
10613 }
10614
10615 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10616 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10617 if (swd_flags & SWD_VALID_LOGS) {
10618 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10619 } else {
10620 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10621 }
10622 }
10623
10624 /*
10625 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10626 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10627 * issued by DisplayWrangler on darkwake.
10628 */
10629 if (!strcmp(aKey, "DesktopMode")) {
10630 if (desktopMode) {
10631 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10632 } else {
10633 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10634 }
10635 }
10636 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10637 if (displayIdleForDemandSleep) {
10638 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10639 } else {
10640 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10641 }
10642 }
10643
10644 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10645 OSSharedPtr<OSArray> array;
10646 WAKEEVENT_LOCK();
10647 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10648 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10649 if (collection) {
10650 array = OSDynamicPtrCast<OSArray>(collection);
10651 }
10652 }
10653 WAKEEVENT_UNLOCK();
10654 return os::move(array);
10655 }
10656
10657 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10658 OSSharedPtr<OSArray> array;
10659 IOLockLock(pmStatsLock);
10660 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10661 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10662 if (collection) {
10663 array = OSDynamicPtrCast<OSArray>(collection);
10664 }
10665 }
10666 IOLockUnlock(pmStatsLock);
10667 return os::move(array);
10668 }
10669
10670 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10671 OSArray *idleSleepList = NULL;
10672 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10673 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10674 }
10675
10676 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10677 OSArray *systemSleepList = NULL;
10678 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10679 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10680 }
10681
10682 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10683 OSArray *idleSleepList = NULL;
10684 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10685 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10686 }
10687
10688 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10689 OSArray *systemSleepList = NULL;
10690 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10691 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10692 }
10693 return NULL;
10694 }
10695
10696 // MARK: -
10697 // MARK: Wake Event Reporting
10698
10699 void
copyWakeReasonString(char * outBuf,size_t bufSize)10700 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10701 {
10702 WAKEEVENT_LOCK();
10703 strlcpy(outBuf, gWakeReasonString, bufSize);
10704 WAKEEVENT_UNLOCK();
10705 }
10706
10707 void
copyShutdownReasonString(char * outBuf,size_t bufSize)10708 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10709 {
10710 WAKEEVENT_LOCK();
10711 strlcpy(outBuf, gShutdownReasonString, bufSize);
10712 WAKEEVENT_UNLOCK();
10713 }
10714
10715 //******************************************************************************
10716 // acceptSystemWakeEvents
10717 //
10718 // Private control for the acceptance of driver wake event claims.
10719 //******************************************************************************
10720
10721 void
acceptSystemWakeEvents(uint32_t control)10722 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10723 {
10724 bool logWakeReason = false;
10725
10726 WAKEEVENT_LOCK();
10727 switch (control) {
10728 case kAcceptSystemWakeEvents_Enable:
10729 assert(_acceptSystemWakeEvents == false);
10730 if (!_systemWakeEventsArray) {
10731 _systemWakeEventsArray = OSArray::withCapacity(4);
10732 }
10733 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10734 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10735 gWakeReasonString[0] = '\0';
10736 if (_systemWakeEventsArray) {
10737 _systemWakeEventsArray->flushCollection();
10738 }
10739 }
10740
10741 // Remove stale WakeType property before system sleep
10742 removeProperty(kIOPMRootDomainWakeTypeKey);
10743 removeProperty(kIOPMRootDomainWakeReasonKey);
10744 break;
10745
10746 case kAcceptSystemWakeEvents_Disable:
10747 _acceptSystemWakeEvents = false;
10748 #if defined(XNU_TARGET_OS_OSX)
10749 logWakeReason = (gWakeReasonString[0] != '\0');
10750 #else /* !defined(XNU_TARGET_OS_OSX) */
10751 logWakeReason = gWakeReasonSysctlRegistered;
10752 #if DEVELOPMENT
10753 static int panic_allowed = -1;
10754
10755 if ((panic_allowed == -1) &&
10756 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10757 panic_allowed = 0;
10758 }
10759
10760 if (panic_allowed) {
10761 size_t i = 0;
10762 // Panic if wake reason is null or empty
10763 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10764 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10765 break;
10766 }
10767 }
10768 if (i >= strlen(gWakeReasonString)) {
10769 panic("Wake reason is empty");
10770 }
10771 }
10772 #endif /* DEVELOPMENT */
10773 #endif /* !defined(XNU_TARGET_OS_OSX) */
10774
10775 // publish kIOPMRootDomainWakeReasonKey if not already set
10776 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10777 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10778 }
10779 break;
10780
10781 case kAcceptSystemWakeEvents_Reenable:
10782 assert(_acceptSystemWakeEvents == false);
10783 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10784 removeProperty(kIOPMRootDomainWakeReasonKey);
10785 break;
10786 }
10787 WAKEEVENT_UNLOCK();
10788
10789 if (logWakeReason) {
10790 MSG("system wake events: %s\n", gWakeReasonString);
10791 }
10792 }
10793
10794 //******************************************************************************
10795 // claimSystemWakeEvent
10796 //
10797 // For a driver to claim a device is the source/conduit of a system wake event.
10798 //******************************************************************************
10799
10800 void
claimSystemWakeEvent(IOService * device,IOOptionBits flags,const char * reason,OSObject * details)10801 IOPMrootDomain::claimSystemWakeEvent(
10802 IOService * device,
10803 IOOptionBits flags,
10804 const char * reason,
10805 OSObject * details )
10806 {
10807 OSSharedPtr<const OSSymbol> deviceName;
10808 OSSharedPtr<OSNumber> deviceRegId;
10809 OSSharedPtr<OSNumber> claimTime;
10810 OSSharedPtr<OSData> flagsData;
10811 OSSharedPtr<OSString> reasonString;
10812 OSSharedPtr<OSDictionary> dict;
10813 uint64_t timestamp;
10814 bool addWakeReason;
10815
10816 if (!device || !reason) {
10817 return;
10818 }
10819
10820 pmEventTimeStamp(×tamp);
10821
10822 IOOptionBits aotFlags = 0;
10823 bool needAOTEvaluate = FALSE;
10824
10825 if (kIOPMAOTModeAddEventFlags & _aotMode) {
10826 if (!strcmp("hold", reason)
10827 || !strcmp("help", reason)
10828 || !strcmp("menu", reason)
10829 || !strcmp("stockholm", reason)
10830 || !strcmp("ringer", reason)
10831 || !strcmp("ringerab", reason)
10832 || !strcmp("smc0", reason)
10833 || !strcmp("AOP.RTPWakeupAP", reason)
10834 || !strcmp("AOP.RTP_AP_IRQ", reason)
10835 || !strcmp("BT.OutboxNotEmpty", reason)
10836 || !strcmp("WL.OutboxNotEmpty", reason)) {
10837 flags |= kIOPMWakeEventAOTExit;
10838 }
10839 }
10840
10841 #if DEVELOPMENT || DEBUG
10842 if (_aotLingerTime && !strcmp("rtc", reason)) {
10843 flags |= kIOPMWakeEventAOTPossibleExit;
10844 }
10845 #endif /* DEVELOPMENT || DEBUG */
10846
10847 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10848 // Publishing the WakeType is serialized by the PM work loop
10849 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10850 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10851 (void *) _nextScheduledAlarmType.get());
10852 }
10853
10854 // Workaround for the missing wake HID event
10855 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10856 if (!strcmp("trackpadkeyboard", reason)) {
10857 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10858 (void *) gIOPMWakeTypeUserKey.get());
10859 }
10860 }
10861 #endif
10862
10863 deviceName = device->copyName(gIOServicePlane);
10864 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64);
10865 claimTime = OSNumber::withNumber(timestamp, 64);
10866 flagsData = OSData::withValue(flags);
10867 reasonString = OSString::withCString(reason);
10868 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
10869 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
10870 goto done;
10871 }
10872
10873 dict->setObject(gIONameKey, deviceName.get());
10874 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
10875 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
10876 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
10877 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
10878 if (details) {
10879 dict->setObject(kIOPMWakeEventDetailsKey, details);
10880 }
10881
10882 WAKEEVENT_LOCK();
10883 addWakeReason = _acceptSystemWakeEvents;
10884 if (_aotMode) {
10885 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
10886 }
10887 aotFlags = (kIOPMWakeEventAOTFlags & flags);
10888 aotFlags = (aotFlags & ~_aotPendingFlags);
10889 needAOTEvaluate = false;
10890 if (_aotNow && aotFlags) {
10891 if (kIOPMWakeEventAOTPossibleExit & flags) {
10892 _aotMetrics->possibleCount++;
10893 }
10894 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
10895 _aotMetrics->confirmedPossibleCount++;
10896 }
10897 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
10898 _aotMetrics->rejectedPossibleCount++;
10899 }
10900 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
10901 _aotMetrics->expiredPossibleCount++;
10902 }
10903
10904 _aotPendingFlags |= aotFlags;
10905 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
10906 needAOTEvaluate = _aotReadyToFullWake;
10907 }
10908 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
10909 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
10910 _aotNow, pmTracer->getTracePhase(), addWakeReason);
10911
10912 #if DEVELOPMENT || DEBUG
10913 if (addWakeReason) {
10914 record_system_event(SYSTEM_EVENT_TYPE_INFO,
10915 SYSTEM_EVENT_SUBSYSTEM_PMRD,
10916 "Report System Wake Event",
10917 "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
10918 reason,
10919 (int)flags,
10920 deviceName->getCStringNoCopy(),
10921 device->getRegistryEntryID()
10922 );
10923 }
10924 #endif /* DEVELOPMENT || DEBUG */
10925
10926 if (!gWakeReasonSysctlRegistered) {
10927 // Lazy registration until the platform driver stops registering
10928 // the same name.
10929 gWakeReasonSysctlRegistered = true;
10930 }
10931 if (addWakeReason) {
10932 _systemWakeEventsArray->setObject(dict.get());
10933 if (gWakeReasonString[0] != '\0') {
10934 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
10935 }
10936 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
10937 }
10938
10939 WAKEEVENT_UNLOCK();
10940 if (needAOTEvaluate) {
10941 // Call aotEvaluate() on PM work loop since it may call
10942 // aotExit() which accesses PM state.
10943 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
10944 }
10945
10946 done:
10947 return;
10948 }
10949
10950 //******************************************************************************
10951 // claimSystemBootEvent
10952 //
10953 // For a driver to claim a device is the source/conduit of a system boot event.
10954 //******************************************************************************
10955
10956 void
claimSystemBootEvent(IOService * device,IOOptionBits flags,const char * reason,__unused OSObject * details)10957 IOPMrootDomain::claimSystemBootEvent(
10958 IOService * device,
10959 IOOptionBits flags,
10960 const char * reason,
10961 __unused OSObject * details )
10962 {
10963 if (!device || !reason) {
10964 return;
10965 }
10966
10967 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
10968 #if DEVELOPMENT || DEBUG
10969 record_system_event(SYSTEM_EVENT_TYPE_INFO,
10970 SYSTEM_EVENT_SUBSYSTEM_PMRD,
10971 "Report System Boot Device",
10972 "Reason: %s Flags: 0x%x Device: %s",
10973 reason,
10974 (int)flags,
10975 device->getName()
10976 );
10977 #endif /* DEVELOPMENT || DEBUG */
10978 WAKEEVENT_LOCK();
10979 if (!gBootReasonSysctlRegistered) {
10980 // Lazy sysctl registration after setting gBootReasonString
10981 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
10982 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
10983 }
10984 WAKEEVENT_UNLOCK();
10985 }
10986
10987 //******************************************************************************
10988 // claimSystemShutdownEvent
10989 //
10990 // For drivers to claim a system shutdown event on the ensuing boot.
10991 //******************************************************************************
10992
10993 void
claimSystemShutdownEvent(IOService * device,IOOptionBits flags,const char * reason,__unused OSObject * details)10994 IOPMrootDomain::claimSystemShutdownEvent(
10995 IOService * device,
10996 IOOptionBits flags,
10997 const char * reason,
10998 __unused OSObject * details )
10999 {
11000 if (!device || !reason) {
11001 return;
11002 }
11003
11004 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11005 #if DEVELOPMENT || DEBUG
11006 record_system_event(SYSTEM_EVENT_TYPE_INFO,
11007 SYSTEM_EVENT_SUBSYSTEM_PMRD,
11008 "Report System Shutdown Cause From Previous Boot",
11009 "Reason: %s Flags: 0x%x Device: %s",
11010 reason,
11011 (int)flags,
11012 device->getName()
11013 );
11014 #endif /* DEVELOPMENT || DEBUG */
11015 WAKEEVENT_LOCK();
11016 if (gShutdownReasonString[0] != '\0') {
11017 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11018 }
11019 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11020
11021 gShutdownReasonSysctlRegistered = true;
11022 WAKEEVENT_UNLOCK();
11023 }
11024
11025 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11026
11027 // MARK: -
11028 // MARK: PMSettingHandle
11029
OSDefineMetaClassAndStructors(PMSettingHandle,OSObject)11030 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11031
11032 void
11033 PMSettingHandle::free( void )
11034 {
11035 if (pmso) {
11036 pmso->clientHandleFreed();
11037 pmso->release();
11038 pmso = NULL;
11039 }
11040
11041 OSObject::free();
11042 }
11043
11044 // MARK: -
11045 // MARK: PMSettingObject
11046
11047 #undef super
11048 #define super OSObject
OSDefineMetaClassAndFinalStructors(PMSettingObject,OSObject)11049 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11050
11051 /*
11052 * Static constructor/initializer for PMSettingObject
11053 */
11054 PMSettingObject *PMSettingObject::pmSettingObject(
11055 IOPMrootDomain * parent_arg,
11056 IOPMSettingControllerCallback handler_arg,
11057 OSObject * target_arg,
11058 uintptr_t refcon_arg,
11059 uint32_t supportedPowerSources,
11060 const OSSymbol * settings[],
11061 OSObject * *handle_obj)
11062 {
11063 uint32_t settingCount = 0;
11064 PMSettingObject *pmso = NULL;
11065 PMSettingHandle *pmsh = NULL;
11066
11067 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11068 return NULL;
11069 }
11070
11071 // count OSSymbol entries in NULL terminated settings array
11072 while (settings[settingCount]) {
11073 settingCount++;
11074 }
11075 if (0 == settingCount) {
11076 return NULL;
11077 }
11078
11079 pmso = new PMSettingObject;
11080 if (!pmso || !pmso->init()) {
11081 goto fail;
11082 }
11083
11084 pmsh = new PMSettingHandle;
11085 if (!pmsh || !pmsh->init()) {
11086 goto fail;
11087 }
11088
11089 queue_init(&pmso->calloutQueue);
11090 pmso->parent = parent_arg;
11091 pmso->func = handler_arg;
11092 pmso->target = target_arg;
11093 pmso->refcon = refcon_arg;
11094 pmso->settingCount = settingCount;
11095
11096 pmso->retain(); // handle holds a retain on pmso
11097 pmsh->pmso = pmso;
11098 pmso->pmsh = pmsh;
11099
11100 pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11101 if (pmso->publishedFeatureID) {
11102 for (unsigned int i = 0; i < settingCount; i++) {
11103 // Since there is now at least one listener to this setting, publish
11104 // PM root domain support for it.
11105 parent_arg->publishPMSetting( settings[i],
11106 supportedPowerSources, &pmso->publishedFeatureID[i] );
11107 }
11108 }
11109
11110 *handle_obj = pmsh;
11111 return pmso;
11112
11113 fail:
11114 if (pmso) {
11115 pmso->release();
11116 }
11117 if (pmsh) {
11118 pmsh->release();
11119 }
11120 return NULL;
11121 }
11122
11123 void
free(void)11124 PMSettingObject::free( void )
11125 {
11126 if (publishedFeatureID) {
11127 for (const auto& featureID : publishedFeatureID) {
11128 if (featureID) {
11129 parent->removePublishedFeature( featureID );
11130 }
11131 }
11132
11133 publishedFeatureID = {};
11134 }
11135
11136 super::free();
11137 }
11138
11139 IOReturn
dispatchPMSetting(const OSSymbol * type,OSObject * object)11140 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11141 {
11142 return (*func)(target, type, object, refcon);
11143 }
11144
11145 void
clientHandleFreed(void)11146 PMSettingObject::clientHandleFreed( void )
11147 {
11148 parent->deregisterPMSettingObject(this);
11149 }
11150
11151 // MARK: -
11152 // MARK: PMAssertionsTracker
11153
11154 //*********************************************************************************
11155 //*********************************************************************************
11156 //*********************************************************************************
11157 // class PMAssertionsTracker Implementation
11158
11159 #define kAssertUniqueIDStart 500
11160
11161 PMAssertionsTracker *
pmAssertionsTracker(IOPMrootDomain * rootDomain)11162 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11163 {
11164 PMAssertionsTracker *me;
11165
11166 me = new PMAssertionsTracker;
11167 if (!me || !me->init()) {
11168 if (me) {
11169 me->release();
11170 }
11171 return NULL;
11172 }
11173
11174 me->owner = rootDomain;
11175 me->issuingUniqueID = kAssertUniqueIDStart;
11176 me->assertionsArray = OSArray::withCapacity(5);
11177 me->assertionsKernel = 0;
11178 me->assertionsUser = 0;
11179 me->assertionsCombined = 0;
11180 me->assertionsArrayLock = IOLockAlloc();
11181 me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11182
11183 assert(me->assertionsArray);
11184 assert(me->assertionsArrayLock);
11185
11186 return me;
11187 }
11188
11189 /* tabulate
11190 * - Update assertionsKernel to reflect the state of all
11191 * assertions in the kernel.
11192 * - Update assertionsCombined to reflect both kernel & user space.
11193 */
11194 void
tabulate(void)11195 PMAssertionsTracker::tabulate(void)
11196 {
11197 int i;
11198 int count;
11199 const PMAssertStruct *_a = nullptr;
11200 OSValueObject<PMAssertStruct> *_d = nullptr;
11201
11202 IOPMDriverAssertionType oldKernel = assertionsKernel;
11203 IOPMDriverAssertionType oldCombined = assertionsCombined;
11204
11205 ASSERT_GATED();
11206
11207 assertionsKernel = 0;
11208 assertionsCombined = 0;
11209
11210 if (!assertionsArray) {
11211 return;
11212 }
11213
11214 if ((count = assertionsArray->getCount())) {
11215 for (i = 0; i < count; i++) {
11216 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11217 if (_d) {
11218 _a = _d->getBytesNoCopy();
11219 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11220 assertionsKernel |= _a->assertionBits;
11221 }
11222 }
11223 }
11224 }
11225
11226 tabulateProducerCount++;
11227 assertionsCombined = assertionsKernel | assertionsUser;
11228
11229 if ((assertionsKernel != oldKernel) ||
11230 (assertionsCombined != oldCombined)) {
11231 owner->evaluateAssertions(assertionsCombined, oldCombined);
11232 }
11233 }
11234
11235 void
updateCPUBitAccounting(PMAssertStruct * assertStruct)11236 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11237 {
11238 AbsoluteTime now;
11239 uint64_t nsec;
11240
11241 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11242 (assertStruct->assertCPUStartTime == 0)) {
11243 return;
11244 }
11245
11246 now = mach_absolute_time();
11247 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11248 absolutetime_to_nanoseconds(now, &nsec);
11249 assertStruct->assertCPUDuration += nsec;
11250 assertStruct->assertCPUStartTime = 0;
11251
11252 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11253 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11254 maxAssertCPUEntryId = assertStruct->registryEntryID;
11255 }
11256 }
11257
11258 void
reportCPUBitAccounting(void)11259 PMAssertionsTracker::reportCPUBitAccounting( void )
11260 {
11261 const PMAssertStruct *_a = nullptr;
11262 OSValueObject<PMAssertStruct> *_d = nullptr;
11263 int i, count;
11264 AbsoluteTime now;
11265 uint64_t nsec;
11266
11267 ASSERT_GATED();
11268
11269 // Account for drivers that are still holding the CPU assertion
11270 if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11271 now = mach_absolute_time();
11272 if ((count = assertionsArray->getCount())) {
11273 for (i = 0; i < count; i++) {
11274 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11275 if (_d) {
11276 _a = _d->getBytesNoCopy();
11277 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11278 (_a->level == kIOPMDriverAssertionLevelOn) &&
11279 (_a->assertCPUStartTime != 0)) {
11280 // Don't modify PMAssertStruct, leave that
11281 // for updateCPUBitAccounting()
11282 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11283 absolutetime_to_nanoseconds(now, &nsec);
11284 nsec += _a->assertCPUDuration;
11285 if (nsec > maxAssertCPUDuration) {
11286 maxAssertCPUDuration = nsec;
11287 maxAssertCPUEntryId = _a->registryEntryID;
11288 }
11289 }
11290 }
11291 }
11292 }
11293 }
11294
11295 if (maxAssertCPUDuration) {
11296 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11297 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11298 }
11299
11300 maxAssertCPUDuration = 0;
11301 maxAssertCPUEntryId = 0;
11302 }
11303
11304 void
publishProperties(void)11305 PMAssertionsTracker::publishProperties( void )
11306 {
11307 OSSharedPtr<OSArray> assertionsSummary;
11308
11309 if (tabulateConsumerCount != tabulateProducerCount) {
11310 IOLockLock(assertionsArrayLock);
11311
11312 tabulateConsumerCount = tabulateProducerCount;
11313
11314 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11315 */
11316 assertionsSummary = copyAssertionsArray();
11317 if (assertionsSummary) {
11318 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11319 } else {
11320 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11321 }
11322
11323 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11324 */
11325 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11326
11327 IOLockUnlock(assertionsArrayLock);
11328 }
11329 }
11330
11331 PMAssertStruct *
detailsForID(IOPMDriverAssertionID _id,int * index)11332 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11333 {
11334 PMAssertStruct *_a = NULL;
11335 OSValueObject<PMAssertStruct> *_d = nullptr;
11336 int found = -1;
11337 int count = 0;
11338 int i = 0;
11339
11340 if (assertionsArray
11341 && (count = assertionsArray->getCount())) {
11342 for (i = 0; i < count; i++) {
11343 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11344 if (_d) {
11345 _a = _d->getMutableBytesNoCopy();
11346 if (_a && (_id == _a->id)) {
11347 found = i;
11348 break;
11349 }
11350 }
11351 }
11352 }
11353
11354 if (-1 == found) {
11355 return NULL;
11356 } else {
11357 if (index) {
11358 *index = found;
11359 }
11360 return _a;
11361 }
11362 }
11363
11364 /* PMAssertionsTracker::handleCreateAssertion
11365 * Perform assertion work on the PM workloop. Do not call directly.
11366 */
11367 IOReturn
handleCreateAssertion(OSValueObject<PMAssertStruct> * newAssertion)11368 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11369 {
11370 PMAssertStruct *assertStruct = nullptr;
11371
11372 ASSERT_GATED();
11373
11374 if (newAssertion) {
11375 IOLockLock(assertionsArrayLock);
11376 assertStruct = newAssertion->getMutableBytesNoCopy();
11377 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11378 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11379 assertStruct->assertCPUStartTime = mach_absolute_time();
11380 }
11381 assertionsArray->setObject(newAssertion);
11382 IOLockUnlock(assertionsArrayLock);
11383 newAssertion->release();
11384
11385 tabulate();
11386 }
11387 return kIOReturnSuccess;
11388 }
11389
11390 /* PMAssertionsTracker::createAssertion
11391 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11392 * appropiate.
11393 */
11394 IOReturn
createAssertion(IOPMDriverAssertionType which,IOPMDriverAssertionLevel level,IOService * serviceID,const char * whoItIs,IOPMDriverAssertionID * outID)11395 PMAssertionsTracker::createAssertion(
11396 IOPMDriverAssertionType which,
11397 IOPMDriverAssertionLevel level,
11398 IOService *serviceID,
11399 const char *whoItIs,
11400 IOPMDriverAssertionID *outID)
11401 {
11402 OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11403 PMAssertStruct track;
11404
11405 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11406 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11407 track.level = level;
11408 track.assertionBits = which;
11409
11410 // NB: ownerString is explicitly managed by PMAssertStruct
11411 // it will be released in `handleReleaseAssertion' below
11412 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11413 track.ownerService = serviceID;
11414 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11415 track.modifiedTime = 0;
11416 pmEventTimeStamp(&track.createdTime);
11417 track.assertCPUStartTime = 0;
11418 track.assertCPUDuration = 0;
11419
11420 dataStore = OSValueObjectWithValue(track);
11421 if (!dataStore) {
11422 if (track.ownerString) {
11423 track.ownerString->release();
11424 track.ownerString = NULL;
11425 }
11426 return kIOReturnNoMemory;
11427 }
11428
11429 *outID = track.id;
11430
11431 if (owner && owner->pmPowerStateQueue) {
11432 // queue action is responsible for releasing dataStore
11433 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11434 }
11435
11436 return kIOReturnSuccess;
11437 }
11438
11439 /* PMAssertionsTracker::handleReleaseAssertion
11440 * Runs in PM workloop. Do not call directly.
11441 */
11442 IOReturn
handleReleaseAssertion(IOPMDriverAssertionID _id)11443 PMAssertionsTracker::handleReleaseAssertion(
11444 IOPMDriverAssertionID _id)
11445 {
11446 ASSERT_GATED();
11447
11448 int index;
11449 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11450
11451 if (!assertStruct) {
11452 return kIOReturnNotFound;
11453 }
11454
11455 IOLockLock(assertionsArrayLock);
11456
11457 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11458 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11459 updateCPUBitAccounting(assertStruct);
11460 }
11461
11462 if (assertStruct->ownerString) {
11463 assertStruct->ownerString->release();
11464 assertStruct->ownerString = NULL;
11465 }
11466
11467 assertionsArray->removeObject(index);
11468 IOLockUnlock(assertionsArrayLock);
11469
11470 tabulate();
11471 return kIOReturnSuccess;
11472 }
11473
11474 /* PMAssertionsTracker::releaseAssertion
11475 * Releases an assertion and affects system behavior if appropiate.
11476 * Actual work happens on PM workloop.
11477 */
11478 IOReturn
releaseAssertion(IOPMDriverAssertionID _id)11479 PMAssertionsTracker::releaseAssertion(
11480 IOPMDriverAssertionID _id)
11481 {
11482 if (owner && owner->pmPowerStateQueue) {
11483 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11484 }
11485 return kIOReturnSuccess;
11486 }
11487
11488 /* PMAssertionsTracker::handleSetAssertionLevel
11489 * Runs in PM workloop. Do not call directly.
11490 */
11491 IOReturn
handleSetAssertionLevel(IOPMDriverAssertionID _id,IOPMDriverAssertionLevel _level)11492 PMAssertionsTracker::handleSetAssertionLevel(
11493 IOPMDriverAssertionID _id,
11494 IOPMDriverAssertionLevel _level)
11495 {
11496 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11497
11498 ASSERT_GATED();
11499
11500 if (!assertStruct) {
11501 return kIOReturnNotFound;
11502 }
11503
11504 IOLockLock(assertionsArrayLock);
11505 pmEventTimeStamp(&assertStruct->modifiedTime);
11506 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11507 (assertStruct->level != _level)) {
11508 if (_level == kIOPMDriverAssertionLevelOn) {
11509 assertStruct->assertCPUStartTime = mach_absolute_time();
11510 } else {
11511 updateCPUBitAccounting(assertStruct);
11512 }
11513 }
11514 assertStruct->level = _level;
11515 IOLockUnlock(assertionsArrayLock);
11516
11517 tabulate();
11518 return kIOReturnSuccess;
11519 }
11520
11521 /* PMAssertionsTracker::setAssertionLevel
11522 */
11523 IOReturn
setAssertionLevel(IOPMDriverAssertionID _id,IOPMDriverAssertionLevel _level)11524 PMAssertionsTracker::setAssertionLevel(
11525 IOPMDriverAssertionID _id,
11526 IOPMDriverAssertionLevel _level)
11527 {
11528 if (owner && owner->pmPowerStateQueue) {
11529 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11530 (void *)(uintptr_t)_level, _id);
11531 }
11532
11533 return kIOReturnSuccess;
11534 }
11535
11536 IOReturn
handleSetUserAssertionLevels(void * arg0)11537 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11538 {
11539 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11540
11541 ASSERT_GATED();
11542
11543 if (new_user_levels != assertionsUser) {
11544 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11545 assertionsUser = new_user_levels;
11546 }
11547
11548 tabulate();
11549 return kIOReturnSuccess;
11550 }
11551
11552 IOReturn
setUserAssertionLevels(IOPMDriverAssertionType new_user_levels)11553 PMAssertionsTracker::setUserAssertionLevels(
11554 IOPMDriverAssertionType new_user_levels)
11555 {
11556 if (gIOPMWorkLoop) {
11557 gIOPMWorkLoop->runAction(
11558 OSMemberFunctionCast(
11559 IOWorkLoop::Action,
11560 this,
11561 &PMAssertionsTracker::handleSetUserAssertionLevels),
11562 this,
11563 (void *) &new_user_levels, NULL, NULL, NULL);
11564 }
11565
11566 return kIOReturnSuccess;
11567 }
11568
11569
11570 OSSharedPtr<OSArray>
copyAssertionsArray(void)11571 PMAssertionsTracker::copyAssertionsArray(void)
11572 {
11573 int count;
11574 int i;
11575 OSSharedPtr<OSArray> outArray = NULL;
11576
11577 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11578 goto exit;
11579 }
11580 outArray = OSArray::withCapacity(count);
11581 if (!outArray) {
11582 goto exit;
11583 }
11584
11585 for (i = 0; i < count; i++) {
11586 const PMAssertStruct *_a = nullptr;
11587 OSValueObject<PMAssertStruct> *_d = nullptr;
11588 OSSharedPtr<OSDictionary> details;
11589
11590 _d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11591 if (_d && (_a = _d->getBytesNoCopy())) {
11592 OSSharedPtr<OSNumber> _n;
11593
11594 details = OSDictionary::withCapacity(7);
11595 if (!details) {
11596 continue;
11597 }
11598
11599 outArray->setObject(details.get());
11600
11601 _n = OSNumber::withNumber(_a->id, 64);
11602 if (_n) {
11603 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11604 }
11605 _n = OSNumber::withNumber(_a->createdTime, 64);
11606 if (_n) {
11607 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11608 }
11609 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11610 if (_n) {
11611 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11612 }
11613 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11614 if (_n) {
11615 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11616 }
11617 _n = OSNumber::withNumber(_a->level, 64);
11618 if (_n) {
11619 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11620 }
11621 _n = OSNumber::withNumber(_a->assertionBits, 64);
11622 if (_n) {
11623 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11624 }
11625
11626 if (_a->ownerString) {
11627 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11628 }
11629 }
11630 }
11631
11632 exit:
11633 return os::move(outArray);
11634 }
11635
11636 IOPMDriverAssertionType
getActivatedAssertions(void)11637 PMAssertionsTracker::getActivatedAssertions(void)
11638 {
11639 return assertionsCombined;
11640 }
11641
11642 IOPMDriverAssertionLevel
getAssertionLevel(IOPMDriverAssertionType type)11643 PMAssertionsTracker::getAssertionLevel(
11644 IOPMDriverAssertionType type)
11645 {
11646 // FIXME: unused and also wrong
11647 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11648 return kIOPMDriverAssertionLevelOn;
11649 } else {
11650 return kIOPMDriverAssertionLevelOff;
11651 }
11652 }
11653
11654 //*********************************************************************************
11655 //*********************************************************************************
11656 //*********************************************************************************
11657
11658
11659 static void
pmEventTimeStamp(uint64_t * recordTS)11660 pmEventTimeStamp(uint64_t *recordTS)
11661 {
11662 clock_sec_t tsec;
11663 clock_usec_t tusec;
11664
11665 if (!recordTS) {
11666 return;
11667 }
11668
11669 // We assume tsec fits into 32 bits; 32 bits holds enough
11670 // seconds for 136 years since the epoch in 1970.
11671 clock_get_calendar_microtime(&tsec, &tusec);
11672
11673
11674 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11675 *recordTS = 0;
11676 *recordTS |= (uint32_t)tusec;
11677 *recordTS |= ((uint64_t)tsec << 32);
11678
11679 return;
11680 }
11681
11682 // MARK: -
11683 // MARK: IORootParent
11684
11685 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11686
11687 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11688
11689 // The reason that root domain needs a root parent is to facilitate demand
11690 // sleep, since a power change from the root parent cannot be vetoed.
11691 //
11692 // The above statement is no longer true since root domain now performs
11693 // demand sleep using overrides. But root parent remains to avoid changing
11694 // the power tree stacking. Root parent is parked at the max power state.
11695
11696
11697 static IOPMPowerState patriarchPowerStates[2] =
11698 {
11699 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11700 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11701 };
11702
11703 void
initialize(void)11704 IORootParent::initialize( void )
11705 {
11706
11707 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11708 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11709 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11710 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11711 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11712 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11713 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11714 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11715 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11716 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11717 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11718 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11719 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11720 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11721 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11722 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11723 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11724 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11725 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11726 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11727 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11728 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11729 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11730 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11731 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11732 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11733 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11734 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11735 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11736 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11737 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11738 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11739 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11740 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11741 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11742 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11743 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11744 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11745 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11746 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11747 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11748 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11749 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11750 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11751 }
11752
11753 bool
start(IOService * nub)11754 IORootParent::start( IOService * nub )
11755 {
11756 IOService::start(nub);
11757 attachToParent( getRegistryRoot(), gIOPowerPlane );
11758 PMinit();
11759 registerPowerDriver(this, patriarchPowerStates, 2);
11760 makeUsable();
11761 return true;
11762 }
11763
11764 void
shutDownSystem(void)11765 IORootParent::shutDownSystem( void )
11766 {
11767 }
11768
11769 void
restartSystem(void)11770 IORootParent::restartSystem( void )
11771 {
11772 }
11773
11774 void
sleepSystem(void)11775 IORootParent::sleepSystem( void )
11776 {
11777 }
11778
11779 void
dozeSystem(void)11780 IORootParent::dozeSystem( void )
11781 {
11782 }
11783
11784 void
sleepToDoze(void)11785 IORootParent::sleepToDoze( void )
11786 {
11787 }
11788
11789 void
wakeSystem(void)11790 IORootParent::wakeSystem( void )
11791 {
11792 }
11793
11794 OSSharedPtr<OSObject>
copyProperty(const char * aKey) const11795 IORootParent::copyProperty( const char * aKey) const
11796 {
11797 return IOService::copyProperty(aKey);
11798 }
11799
11800 uint32_t
getWatchdogTimeout()11801 IOPMrootDomain::getWatchdogTimeout()
11802 {
11803 if (gSwdSleepWakeTimeout) {
11804 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11805 }
11806 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11807 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11808 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11809 } else {
11810 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11811 }
11812 }
11813
11814
11815 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11816 IOReturn
restartWithStackshot()11817 IOPMrootDomain::restartWithStackshot()
11818 {
11819 takeStackshot(true);
11820
11821 return kIOReturnSuccess;
11822 }
11823
11824 void
sleepWakeDebugTrig(bool wdogTrigger)11825 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11826 {
11827 takeStackshot(wdogTrigger);
11828 }
11829
11830 void
tracePhase2String(uint32_t tracePhase,const char ** phaseString,const char ** description)11831 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11832 {
11833 switch (tracePhase) {
11834 case kIOPMTracePointSleepStarted:
11835 *phaseString = "kIOPMTracePointSleepStarted";
11836 *description = "starting sleep";
11837 break;
11838
11839 case kIOPMTracePointSleepApplications:
11840 *phaseString = "kIOPMTracePointSleepApplications";
11841 *description = "notifying applications";
11842 break;
11843
11844 case kIOPMTracePointSleepPriorityClients:
11845 *phaseString = "kIOPMTracePointSleepPriorityClients";
11846 *description = "notifying clients about upcoming system capability changes";
11847 break;
11848
11849 case kIOPMTracePointSleepWillChangeInterests:
11850 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11851 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11852 break;
11853
11854 case kIOPMTracePointSleepPowerPlaneDrivers:
11855 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11856 *description = "calling power state change callbacks";
11857 break;
11858
11859 case kIOPMTracePointSleepDidChangeInterests:
11860 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
11861 *description = "calling rootDomain's clients about rootDomain's state changes";
11862 break;
11863
11864 case kIOPMTracePointSleepCapabilityClients:
11865 *phaseString = "kIOPMTracePointSleepCapabilityClients";
11866 *description = "notifying clients about current system capabilities";
11867 break;
11868
11869 case kIOPMTracePointSleepPlatformActions:
11870 *phaseString = "kIOPMTracePointSleepPlatformActions";
11871 *description = "calling Quiesce/Sleep action callbacks";
11872 break;
11873
11874 case kIOPMTracePointSleepCPUs:
11875 {
11876 *phaseString = "kIOPMTracePointSleepCPUs";
11877 #if defined(__i386__) || defined(__x86_64__)
11878 /*
11879 * We cannot use the getCPUNumber() method to get the cpu number, since
11880 * that cpu number is unrelated to the cpu number we need (we need the cpu
11881 * number as enumerated by the scheduler, NOT the CPU number enumerated
11882 * by ACPIPlatform as the CPUs are enumerated in MADT order).
11883 * Instead, pass the Mach processor pointer associated with the current
11884 * shutdown target so its associated cpu_id can be used in
11885 * processor_to_datastring.
11886 */
11887 if (currentShutdownTarget != NULL &&
11888 currentShutdownTarget->getMachProcessor() != NULL) {
11889 const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
11890 currentShutdownTarget->getMachProcessor());
11891 *description = sbuf;
11892 } else {
11893 *description = "halting all non-boot CPUs";
11894 }
11895 #else
11896 *description = "halting all non-boot CPUs";
11897 #endif
11898 break;
11899 }
11900 case kIOPMTracePointSleepPlatformDriver:
11901 *phaseString = "kIOPMTracePointSleepPlatformDriver";
11902 *description = "executing platform specific code";
11903 break;
11904
11905 case kIOPMTracePointHibernate:
11906 *phaseString = "kIOPMTracePointHibernate";
11907 *description = "writing the hibernation image";
11908 break;
11909
11910 case kIOPMTracePointSystemSleep:
11911 *phaseString = "kIOPMTracePointSystemSleep";
11912 *description = "in EFI/Bootrom after last point of entry to sleep";
11913 break;
11914
11915 case kIOPMTracePointWakePlatformDriver:
11916 *phaseString = "kIOPMTracePointWakePlatformDriver";
11917 *description = "executing platform specific code";
11918 break;
11919
11920
11921 case kIOPMTracePointWakePlatformActions:
11922 *phaseString = "kIOPMTracePointWakePlatformActions";
11923 *description = "calling Wake action callbacks";
11924 break;
11925
11926 case kIOPMTracePointWakeCPUs:
11927 *phaseString = "kIOPMTracePointWakeCPUs";
11928 *description = "starting non-boot CPUs";
11929 break;
11930
11931 case kIOPMTracePointWakeWillPowerOnClients:
11932 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
11933 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11934 break;
11935
11936 case kIOPMTracePointWakeWillChangeInterests:
11937 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
11938 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
11939 break;
11940
11941 case kIOPMTracePointWakeDidChangeInterests:
11942 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
11943 *description = "calling rootDomain's clients about completed rootDomain's state changes";
11944 break;
11945
11946 case kIOPMTracePointWakePowerPlaneDrivers:
11947 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
11948 *description = "calling power state change callbacks";
11949 break;
11950
11951 case kIOPMTracePointWakeCapabilityClients:
11952 *phaseString = "kIOPMTracePointWakeCapabilityClients";
11953 *description = "informing clients about current system capabilities";
11954 break;
11955
11956 case kIOPMTracePointWakeApplications:
11957 *phaseString = "kIOPMTracePointWakeApplications";
11958 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11959 break;
11960
11961 case kIOPMTracePointDarkWakeEntry:
11962 *phaseString = "kIOPMTracePointDarkWakeEntry";
11963 *description = "entering darkwake on way to sleep";
11964 break;
11965
11966 case kIOPMTracePointDarkWakeExit:
11967 *phaseString = "kIOPMTracePointDarkWakeExit";
11968 *description = "entering fullwake from darkwake";
11969 break;
11970
11971 default:
11972 *phaseString = NULL;
11973 *description = NULL;
11974 }
11975 }
11976
11977 void
saveFailureData2File()11978 IOPMrootDomain::saveFailureData2File()
11979 {
11980 unsigned int len = 0;
11981 char failureStr[512];
11982 errno_t error;
11983 char *outbuf;
11984 OSNumber *statusCode;
11985 uint64_t pmStatusCode = 0;
11986 uint32_t phaseData = 0;
11987 uint32_t phaseDetail = 0;
11988 bool efiFailure = false;
11989
11990 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
11991 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
11992 if (statusCode) {
11993 pmStatusCode = statusCode->unsigned64BitValue();
11994 phaseData = pmStatusCode & 0xFFFFFFFF;
11995 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
11996 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
11997 LOG("Sleep Wake failure in EFI\n");
11998 efiFailure = true;
11999 failureStr[0] = 0;
12000 snprintf(failureStr, sizeof(failureStr), "Sleep Wake failure in EFI\n\nFailure code:: 0x%08x 0x%08x\n\nPlease IGNORE the below stackshot\n", phaseDetail, phaseData);
12001 len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12002 }
12003 }
12004
12005 if (!efiFailure) {
12006 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12007 swd_flags |= SWD_BOOT_BY_SW_WDOG;
12008 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12009 // dump panic will handle saving nvram data
12010 return;
12011 }
12012
12013 /* Keeping this around for capturing data during power
12014 * button press */
12015
12016 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12017 DLOG("No sleep wake failure string\n");
12018 return;
12019 }
12020 if (len == 0) {
12021 DLOG("Ignoring zero byte SleepWake failure string\n");
12022 goto exit;
12023 }
12024
12025 // if PMStatus code is zero, delete stackshot and return
12026 if (statusCode) {
12027 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12028 // there was no sleep wake failure
12029 // this can happen if delete stackshot was called
12030 // before take stackshot completed. Let us delete any
12031 // sleep wake failure data in nvram
12032 DLOG("Deleting stackshot on successful wake\n");
12033 deleteStackshot();
12034 return;
12035 }
12036 }
12037
12038 if (len > sizeof(failureStr)) {
12039 len = sizeof(failureStr);
12040 }
12041 failureStr[0] = 0;
12042 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12043 }
12044 if (failureStr[0] != 0) {
12045 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12046 if (error) {
12047 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12048 } else {
12049 DLOG("Saved SleepWake failure string to file.\n");
12050 }
12051 }
12052
12053 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12054 goto exit;
12055 }
12056
12057 if (swd_buffer) {
12058 unsigned int len = 0;
12059 errno_t error;
12060 char nvram_var_name_buffer[20];
12061 unsigned int concat_len = 0;
12062 swd_hdr *hdr = NULL;
12063
12064
12065 hdr = (swd_hdr *)swd_buffer;
12066 outbuf = (char *)hdr + hdr->spindump_offset;
12067 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12068
12069 for (int i = 0; i < 8; i++) {
12070 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12071 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12072 LOG("No SleepWake blob to read beyond chunk %d\n", i);
12073 break;
12074 }
12075 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12076 PERemoveNVRAMProperty(nvram_var_name_buffer);
12077 LOG("Could not read the property :-(\n");
12078 break;
12079 }
12080 PERemoveNVRAMProperty(nvram_var_name_buffer);
12081 concat_len += len;
12082 }
12083 LOG("Concatenated length for the SWD blob %d\n", concat_len);
12084
12085 if (concat_len) {
12086 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12087 if (error) {
12088 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12089 } else {
12090 LOG("Saved SleepWake zipped data to file.\n");
12091 }
12092 } else {
12093 // There is a sleep wake failure string but no stackshot
12094 // Write a placeholder stacks file so that swd runs
12095 snprintf(outbuf, 20, "%s", "No stackshot data\n");
12096 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12097 if (error) {
12098 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12099 } else {
12100 LOG("Saved SleepWake zipped data to file.\n");
12101 }
12102 }
12103 } else {
12104 LOG("No buffer allocated to save failure stackshot\n");
12105 }
12106
12107
12108 gRootDomain->swd_lock = 0;
12109 exit:
12110 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12111 return;
12112 }
12113
12114
12115 void
getFailureData(thread_t * thread,char * failureStr,size_t strLen)12116 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12117 {
12118 OSSharedPtr<IORegistryIterator> iter;
12119 OSSharedPtr<const OSSymbol> kextName = NULL;
12120 IORegistryEntry * entry;
12121 IOService * node;
12122 bool nodeFound = false;
12123
12124 const void * callMethod = NULL;
12125 const char * objectName = NULL;
12126 uint32_t timeout = getWatchdogTimeout();
12127 const char * phaseString = NULL;
12128 const char * phaseDescription = NULL;
12129
12130 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12131 uint32_t tracePhase = pmTracer->getTracePhase();
12132
12133 *thread = NULL;
12134 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12135 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
12136 } else {
12137 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
12138 }
12139 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12140
12141 if (notifierThread) {
12142 if (notifier && (notifier->identifier)) {
12143 objectName = notifier->identifier->getCStringNoCopy();
12144 }
12145 *thread = notifierThread;
12146 } else {
12147 iter = IORegistryIterator::iterateOver(
12148 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12149
12150 if (iter) {
12151 while ((entry = iter->getNextObject())) {
12152 node = OSDynamicCast(IOService, entry);
12153 if (!node) {
12154 continue;
12155 }
12156 if (OSDynamicCast(IOPowerConnection, node)) {
12157 continue;
12158 }
12159
12160 if (node->getBlockingDriverCall(thread, &callMethod)) {
12161 nodeFound = true;
12162 break;
12163 }
12164 }
12165 }
12166 if (nodeFound) {
12167 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12168 if (kextName) {
12169 objectName = kextName->getCStringNoCopy();
12170 }
12171 }
12172 }
12173 if (phaseDescription) {
12174 strlcat(failureStr, " while ", strLen);
12175 strlcat(failureStr, phaseDescription, strLen);
12176 strlcat(failureStr, ".", strLen);
12177 }
12178 if (objectName) {
12179 strlcat(failureStr, " Suspected bundle: ", strLen);
12180 strlcat(failureStr, objectName, strLen);
12181 strlcat(failureStr, ".", strLen);
12182 }
12183 if (*thread) {
12184 char threadName[40];
12185 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12186 strlcat(failureStr, threadName, strLen);
12187 }
12188
12189 DLOG("%s\n", failureStr);
12190 }
12191
12192 struct swd_stackshot_compressed_data {
12193 z_output_func zoutput;
12194 size_t zipped;
12195 uint64_t totalbytes;
12196 uint64_t lastpercent;
12197 IOReturn error;
12198 unsigned outremain;
12199 unsigned outlen;
12200 unsigned writes;
12201 Bytef * outbuf;
12202 };
12203 struct swd_stackshot_compressed_data swd_zip_var = { };
12204
12205 static void *
swd_zs_alloc(void * __unused ref,u_int items,u_int size)12206 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12207 {
12208 void *result;
12209 LOG("Alloc in zipping %d items of size %d\n", items, size);
12210
12211 result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12212 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12213 LOG("Offset %zu\n", swd_zs_zoffset);
12214 return result;
12215 }
12216
12217 static int
swd_zinput(z_streamp strm,Bytef * buf,unsigned size)12218 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12219 {
12220 unsigned len;
12221
12222 len = strm->avail_in;
12223
12224 if (len > size) {
12225 len = size;
12226 }
12227 if (len == 0) {
12228 return 0;
12229 }
12230
12231 if (strm->next_in != (Bytef *) strm) {
12232 memcpy(buf, strm->next_in, len);
12233 } else {
12234 bzero(buf, len);
12235 }
12236
12237 strm->adler = z_crc32(strm->adler, buf, len);
12238
12239 strm->avail_in -= len;
12240 strm->next_in += len;
12241 strm->total_in += len;
12242
12243 return (int)len;
12244 }
12245
12246 static int
swd_zoutput(z_streamp strm,Bytef * buf,unsigned len)12247 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12248 {
12249 unsigned int i = 0;
12250 // if outlen > max size don't add to the buffer
12251 assert(buf != NULL);
12252 if (strm && buf) {
12253 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12254 LOG("No space to GZIP... not writing to NVRAM\n");
12255 return len;
12256 }
12257 }
12258 for (i = 0; i < len; i++) {
12259 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12260 }
12261 swd_zip_var.outlen += len;
12262 return len;
12263 }
12264
12265 static void
swd_zs_free(void * __unused ref,void * __unused ptr)12266 swd_zs_free(void * __unused ref, void * __unused ptr)
12267 {
12268 }
12269
12270 static int
swd_compress(char * inPtr,char * outPtr,size_t numBytes)12271 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12272 {
12273 int wbits = 12;
12274 int memlevel = 3;
12275
12276 if (((unsigned int) numBytes) != numBytes) {
12277 return 0;
12278 }
12279
12280 if (!swd_zs.zalloc) {
12281 swd_zs.zalloc = swd_zs_alloc;
12282 swd_zs.zfree = swd_zs_free;
12283 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12284 // allocation failed
12285 bzero(&swd_zs, sizeof(swd_zs));
12286 // swd_zs_zoffset = 0;
12287 } else {
12288 LOG("PMRD inited the zlib allocation routines\n");
12289 }
12290 }
12291
12292 swd_zip_var.zipped = 0;
12293 swd_zip_var.totalbytes = 0; // should this be the max that we have?
12294 swd_zip_var.lastpercent = 0;
12295 swd_zip_var.error = kIOReturnSuccess;
12296 swd_zip_var.outremain = 0;
12297 swd_zip_var.outlen = 0;
12298 swd_zip_var.writes = 0;
12299 swd_zip_var.outbuf = (Bytef *)outPtr;
12300
12301 swd_zip_var.totalbytes = numBytes;
12302
12303 swd_zs.avail_in = 0;
12304 swd_zs.next_in = NULL;
12305 swd_zs.avail_out = 0;
12306 swd_zs.next_out = NULL;
12307
12308 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12309
12310 z_stream *zs;
12311 int zr;
12312 zs = &swd_zs;
12313
12314 while (swd_zip_var.error >= 0) {
12315 if (!zs->avail_in) {
12316 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12317 zs->avail_in = (unsigned int) numBytes;
12318 }
12319 if (!zs->avail_out) {
12320 zs->next_out = (Bytef *)zs;
12321 zs->avail_out = UINT32_MAX;
12322 }
12323 zr = deflate(zs, Z_NO_FLUSH);
12324 if (Z_STREAM_END == zr) {
12325 break;
12326 }
12327 if (zr != Z_OK) {
12328 LOG("ZERR %d\n", zr);
12329 swd_zip_var.error = zr;
12330 } else {
12331 if (zs->total_in == numBytes) {
12332 break;
12333 }
12334 }
12335 }
12336
12337 //now flush the stream
12338 while (swd_zip_var.error >= 0) {
12339 if (!zs->avail_out) {
12340 zs->next_out = (Bytef *)zs;
12341 zs->avail_out = UINT32_MAX;
12342 }
12343 zr = deflate(zs, Z_FINISH);
12344 if (Z_STREAM_END == zr) {
12345 break;
12346 }
12347 if (zr != Z_OK) {
12348 LOG("ZERR %d\n", zr);
12349 swd_zip_var.error = zr;
12350 } else {
12351 if (zs->total_in == numBytes) {
12352 LOG("Total output size %d\n", swd_zip_var.outlen);
12353 break;
12354 }
12355 }
12356 }
12357
12358 return swd_zip_var.outlen;
12359 }
12360
12361 void
deleteStackshot()12362 IOPMrootDomain::deleteStackshot()
12363 {
12364 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12365 // takeStackshot hasn't completed
12366 return;
12367 }
12368 LOG("Deleting any sleepwake failure data in nvram\n");
12369
12370 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12371 char nvram_var_name_buf[20];
12372 for (int i = 0; i < 8; i++) {
12373 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12374 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12375 LOG("Removing %s returned false\n", nvram_var_name_buf);
12376 }
12377 }
12378 // force NVRAM sync
12379 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12380 DLOG("Failed to force nvram sync\n");
12381 }
12382 gRootDomain->swd_lock = 0;
12383 }
12384
12385 void
takeStackshot(bool wdogTrigger)12386 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12387 {
12388 swd_hdr * hdr = NULL;
12389 int cnt = 0;
12390 int max_cnt;
12391 pid_t pid = 0;
12392 kern_return_t kr = KERN_SUCCESS;
12393 uint64_t flags;
12394
12395 char * dstAddr;
12396 uint32_t size;
12397 uint32_t bytesRemaining;
12398 unsigned bytesWritten = 0;
12399
12400 char failureStr[512];
12401 thread_t thread = NULL;
12402 const char * swfPanic = "swfPanic";
12403
12404 uint32_t bufSize;
12405 int success = 0;
12406
12407 #if defined(__i386__) || defined(__x86_64__)
12408 const bool concise = false;
12409 #else
12410 const bool concise = true;
12411 #endif
12412
12413 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12414 return;
12415 }
12416
12417 failureStr[0] = 0;
12418 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12419 return;
12420 }
12421
12422 if (wdogTrigger) {
12423 getFailureData(&thread, failureStr, sizeof(failureStr));
12424
12425 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12426 goto skip_stackshot;
12427 }
12428 } else {
12429 AbsoluteTime now;
12430 uint64_t nsec;
12431 clock_get_uptime(&now);
12432 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12433 absolutetime_to_nanoseconds(now, &nsec);
12434 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12435 }
12436
12437 if (swd_buffer == NULL) {
12438 sleepWakeDebugMemAlloc();
12439 if (swd_buffer == NULL) {
12440 return;
12441 }
12442 }
12443 hdr = (swd_hdr *)swd_buffer;
12444 bufSize = hdr->alloc_size;
12445
12446 dstAddr = (char*)hdr + hdr->spindump_offset;
12447 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO | STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12448
12449 /* If not wdogTrigger only take kernel tasks stackshot
12450 */
12451 if (wdogTrigger) {
12452 pid = -1;
12453 max_cnt = 3;
12454 } else {
12455 pid = 0;
12456 max_cnt = 2;
12457 }
12458
12459 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12460 * If we run out of space, take stackshot with only kernel task
12461 */
12462 while (success == 0 && cnt < max_cnt) {
12463 bytesRemaining = bufSize - hdr->spindump_offset;
12464 cnt++;
12465 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12466
12467 size = bytesRemaining;
12468 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12469 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12470 kr, pid, size, flags, bytesWritten);
12471 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12472 if (pid == -1) {
12473 pid = 0;
12474 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12475 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12476 } else {
12477 LOG("Insufficient buffer size for only kernel task\n");
12478 break;
12479 }
12480 }
12481 if (kr == KERN_SUCCESS) {
12482 if (bytesWritten == 0) {
12483 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12484 continue;
12485 }
12486 bytesRemaining -= bytesWritten;
12487 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12488
12489 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12490
12491 // Compress stackshot and save to NVRAM
12492 {
12493 char *outbuf = (char *)swd_compressed_buffer;
12494 int outlen = 0;
12495 int num_chunks = 0;
12496 int max_chunks = 0;
12497 int leftover = 0;
12498 char nvram_var_name_buffer[20];
12499
12500 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12501
12502 if (outlen) {
12503 max_chunks = outlen / (2096 - 200);
12504 leftover = outlen % (2096 - 200);
12505
12506 if (max_chunks < 8) {
12507 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12508 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12509 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12510 LOG("Failed to update NVRAM %d\n", num_chunks);
12511 break;
12512 }
12513 }
12514 if (leftover) {
12515 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12516 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12517 LOG("Failed to update NVRAM with leftovers\n");
12518 }
12519 }
12520 success = 1;
12521 LOG("Successfully saved stackshot to NVRAM\n");
12522 } else {
12523 if (pid == -1) {
12524 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12525 pid = 0;
12526 } else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12527 LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12528 flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12529 } else {
12530 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12531 break;
12532 }
12533 }
12534 }
12535 }
12536 }
12537 }
12538
12539 if (failureStr[0]) {
12540 // append sleep-wake failure code
12541 char traceCode[80];
12542 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12543 pmTracer->getTraceData(), pmTracer->getTracePhase());
12544 strlcat(failureStr, traceCode, sizeof(failureStr));
12545 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12546 DLOG("Failed to write SleepWake failure string\n");
12547 }
12548 }
12549
12550 // force NVRAM sync
12551 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12552 DLOG("Failed to force nvram sync\n");
12553 }
12554
12555 skip_stackshot:
12556 if (wdogTrigger) {
12557 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12558 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12559 // If current boot is due to this watch dog trigger restart in previous boot,
12560 // then don't trigger again until at least 1 successful sleep & wake.
12561 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12562 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12563 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12564 PEHaltRestart(kPEHaltCPU);
12565 return;
12566 }
12567 }
12568 if (gSwdPanic == 0) {
12569 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12570 updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12571 PEHaltRestart(kPERestartCPU);
12572 }
12573 }
12574 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12575 DLOG("Failed to write SleepWake failure panic key\n");
12576 }
12577 #if defined(__x86_64__)
12578 if (thread) {
12579 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12580 } else
12581 #endif /* defined(__x86_64__) */
12582 {
12583 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12584 }
12585 } else {
12586 gRootDomain->swd_lock = 0;
12587 return;
12588 }
12589 }
12590
12591 void
sleepWakeDebugMemAlloc()12592 IOPMrootDomain::sleepWakeDebugMemAlloc()
12593 {
12594 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12595
12596 swd_hdr *hdr = NULL;
12597 void *bufPtr = NULL;
12598
12599 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12600
12601
12602 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12603 return;
12604 }
12605
12606 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12607 return;
12608 }
12609
12610 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12611 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12612 size);
12613 if (memDesc == NULL) {
12614 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12615 goto exit;
12616 }
12617
12618 bufPtr = memDesc->getBytesNoCopy();
12619
12620 // Carve out memory for zlib routines
12621 swd_zs_zmem = (vm_offset_t)bufPtr;
12622 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12623
12624 // Carve out memory for compressed stackshots
12625 swd_compressed_buffer = bufPtr;
12626 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12627
12628 // Remaining is used for holding stackshot
12629 hdr = (swd_hdr *)bufPtr;
12630 memset(hdr, 0, sizeof(swd_hdr));
12631
12632 hdr->signature = SWD_HDR_SIGNATURE;
12633 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12634
12635 hdr->spindump_offset = sizeof(swd_hdr);
12636 swd_buffer = (void *)hdr;
12637 swd_memDesc = os::move(memDesc);
12638 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12639
12640 exit:
12641 gRootDomain->swd_lock = 0;
12642 }
12643
12644 void
sleepWakeDebugSpinDumpMemAlloc()12645 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12646 {
12647 #if UNUSED
12648 vm_size_t size = SWD_SPINDUMP_SIZE;
12649
12650 swd_hdr *hdr = NULL;
12651
12652 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12653
12654 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12655 return;
12656 }
12657
12658 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12659 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12660 SWD_SPINDUMP_SIZE);
12661
12662 if (memDesc == NULL) {
12663 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12664 goto exit;
12665 }
12666
12667
12668 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12669 memset(hdr, 0, sizeof(swd_hdr));
12670
12671 hdr->signature = SWD_HDR_SIGNATURE;
12672 hdr->alloc_size = size;
12673
12674 hdr->spindump_offset = sizeof(swd_hdr);
12675 swd_spindump_buffer = (void *)hdr;
12676 swd_spindump_memDesc = os::move(memDesc);
12677
12678 exit:
12679 gRootDomain->swd_lock = 0;
12680 #endif /* UNUSED */
12681 }
12682
12683 void
sleepWakeDebugEnableWdog()12684 IOPMrootDomain::sleepWakeDebugEnableWdog()
12685 {
12686 }
12687
12688 bool
sleepWakeDebugIsWdogEnabled()12689 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12690 {
12691 return !systemBooting && !systemShutdown && !gWillShutdown;
12692 }
12693
12694 void
sleepWakeDebugSaveSpinDumpFile()12695 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12696 {
12697 swd_hdr *hdr = NULL;
12698 errno_t error = EIO;
12699
12700 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12701 hdr = (swd_hdr *)swd_spindump_buffer;
12702
12703 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12704 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12705
12706 if (error) {
12707 return;
12708 }
12709
12710 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12711 (char*)hdr + offsetof(swd_hdr, UUID),
12712 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12713
12714 gSpinDumpBufferFull = false;
12715 }
12716 }
12717
12718 errno_t
sleepWakeDebugSaveFile(const char * name,char * buf,int len)12719 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12720 {
12721 struct vnode *vp = NULL;
12722 vfs_context_t ctx = vfs_context_create(vfs_context_current());
12723 kauth_cred_t cred = vfs_context_ucred(ctx);
12724 struct vnode_attr va;
12725 errno_t error = EIO;
12726
12727 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12728 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12729 LOG("Failed to open the file %s\n", name);
12730 swd_flags |= SWD_FILEOP_ERROR;
12731 goto exit;
12732 }
12733 VATTR_INIT(&va);
12734 VATTR_WANTED(&va, va_nlink);
12735 /* Don't dump to non-regular files or files with links. */
12736 if (vp->v_type != VREG ||
12737 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12738 LOG("Bailing as this is not a regular file\n");
12739 swd_flags |= SWD_FILEOP_ERROR;
12740 goto exit;
12741 }
12742 VATTR_INIT(&va);
12743 VATTR_SET(&va, va_data_size, 0);
12744 vnode_setattr(vp, &va, ctx);
12745
12746
12747 if (buf != NULL) {
12748 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12749 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12750 if (error != 0) {
12751 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12752 swd_flags |= SWD_FILEOP_ERROR;
12753 } else {
12754 DLOG("Saved %d bytes to file %s\n", len, name);
12755 }
12756 }
12757
12758 exit:
12759 if (vp) {
12760 vnode_close(vp, FWRITE, ctx);
12761 }
12762 if (ctx) {
12763 vfs_context_rele(ctx);
12764 }
12765
12766 return error;
12767 }
12768
12769 #else /* defined(__i386__) || defined(__x86_64__) */
12770
12771 void
sleepWakeDebugTrig(bool restart)12772 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12773 {
12774 if (restart) {
12775 if (gSwdPanic == 0) {
12776 return;
12777 }
12778 panic("Sleep/Wake hang detected");
12779 return;
12780 }
12781 }
12782
12783 void
takeStackshot(bool restart)12784 IOPMrootDomain::takeStackshot(bool restart)
12785 {
12786 #pragma unused(restart)
12787 }
12788
12789 void
deleteStackshot()12790 IOPMrootDomain::deleteStackshot()
12791 {
12792 }
12793
12794 void
sleepWakeDebugMemAlloc()12795 IOPMrootDomain::sleepWakeDebugMemAlloc()
12796 {
12797 }
12798
12799 void
saveFailureData2File()12800 IOPMrootDomain::saveFailureData2File()
12801 {
12802 }
12803
12804 void
sleepWakeDebugEnableWdog()12805 IOPMrootDomain::sleepWakeDebugEnableWdog()
12806 {
12807 }
12808
12809 bool
sleepWakeDebugIsWdogEnabled()12810 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12811 {
12812 return false;
12813 }
12814
12815 void
sleepWakeDebugSaveSpinDumpFile()12816 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12817 {
12818 }
12819
12820 errno_t
sleepWakeDebugSaveFile(const char * name,char * buf,int len)12821 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12822 {
12823 return 0;
12824 }
12825
12826 #endif /* defined(__i386__) || defined(__x86_64__) */
12827
12828