Loading...
iokit/Kernel/IOPMrootDomain.cpp xnu-12377.121.6 xnu-11215.41.3
--- xnu/xnu-12377.121.6/iokit/Kernel/IOPMrootDomain.cpp
+++ xnu/xnu-11215.41.3/iokit/Kernel/IOPMrootDomain.cpp
@@ -54,9 +54,8 @@
 #include <IOKit/IOCatalogue.h>
 #include <IOKit/IOReportMacros.h>
 #include <IOKit/IOLib.h>
-#include <IOKit/IOKitKeysPrivate.h>
+#include <IOKit/IOKitKeys.h>
 #include <IOKit/IOUserServer.h>
-#include <IOKit/IOBSD.h>
 #include "IOKitKernelInternal.h"
 #if HIBERNATION
 #include <IOKit/IOHibernatePrivate.h>
@@ -69,8 +68,6 @@
 #include <sys/vnode_internal.h>
 #include <sys/fcntl.h>
 #include <os/log.h>
-#include <os/log_private.h>
-#include <pexpert/device_tree.h>
 #include <pexpert/protos.h>
 #include <AssertMacros.h>
 
@@ -82,6 +79,7 @@
 #include <os/cpp_util.h>
 #include <os/atomic_private.h>
 #include <libkern/c++/OSBoundedArrayRef.h>
+#include <libkern/coreanalytics/coreanalytics.h>
 
 #if DEVELOPMENT || DEBUG
 #include <os/system_event_log.h>
@@ -99,8 +97,6 @@
 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
 __END_DECLS
 #endif
-
-#define ARRAY_LEN(x) (sizeof (x) / sizeof (x[0]))
 
 #define kIOPMrootDomainClass    "IOPMrootDomain"
 #define LOG_PREFIX              "PMRD: "
@@ -193,8 +189,7 @@
 	kPowerEventPublishSleepWakeUUID,           // 13
 	kPowerEventSetDisplayPowerOn,              // 14
 	kPowerEventPublishWakeType,                // 15
-	kPowerEventAOTEvaluate,                    // 16
-	kPowerEventRunModeRequest                  // 17
+	kPowerEventAOTEvaluate                     // 16
 };
 
 // For evaluatePolicy()
@@ -324,11 +319,7 @@
 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
 // We impose this minimum to avoid race conditions in the AP wake path where
 // userspace clients are not able to acquire power assertions before the idle timer expires.
-#if XNU_TARGET_OS_IOS
-#define kMinimumTimeBeforeIdleSleep     3000
-#else
 #define kMinimumTimeBeforeIdleSleep     1000
-#endif
 
 #define DISPLAY_WRANGLER_PRESENT    (!NO_KERNEL_HID)
 
@@ -337,6 +328,15 @@
 	kWranglerPowerStateSleep = 2,
 	kWranglerPowerStateDim   = 3,
 	kWranglerPowerStateMax   = 4
+};
+
+enum {
+	OFF_STATE           = 0,
+	RESTART_STATE       = 1,
+	SLEEP_STATE         = 2,
+	AOT_STATE           = 3,
+	ON_STATE            = 4,
+	NUM_POWER_STATES
 };
 
 const char *
@@ -620,7 +620,6 @@
 static char gWakeReasonString[128];
 static char gBootReasonString[80];
 static char gShutdownReasonString[80];
-static uint64_t gShutdownTime;
 static bool gWakeReasonSysctlRegistered = false;
 static bool gBootReasonSysctlRegistered = false;
 static bool gShutdownReasonSysctlRegistered = false;
@@ -767,72 +766,6 @@
 	uint8_t                     loginWindowData;
 	uint8_t                     coreDisplayData;
 	uint8_t                     coreGraphicsData;
-};
-
-struct IOPMAssertionLog {
-	IOPMAssertionLogData data;
-
-	mach_port_t  notificationPort;
-	uint64_t     notificationThreshold;
-
-public:
-	IOReturn
-	setNotificationThreshold(uint64_t threshold)
-	{
-		if (threshold > ARRAY_LEN(data.intervals)) {
-			return kIOReturnBadArgument;
-		}
-		notificationThreshold = threshold;
-		return kIOReturnSuccess;
-	}
-
-	IOReturn
-	setNotificationPort(mach_port_t port)
-	{
-		if (port != MACH_PORT_NULL && notificationPort != MACH_PORT_NULL) {
-			return kIOReturnExclusiveAccess;
-		}
-
-		notificationPort = port;
-		return kIOReturnSuccess;
-	}
-
-	void
-	notify()
-	{
-		if (notificationPort == MACH_PORT_NULL) {
-			return;
-		}
-
-		mach_msg_header_t msg;
-		msg.msgh_bits         = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
-		msg.msgh_id           = 0;
-		msg.msgh_size         = sizeof(mach_msg_header_t);
-		msg.msgh_local_port   = MACH_PORT_NULL;
-		msg.msgh_remote_port  = notificationPort;
-		(void)mach_msg_send_from_kernel_with_options(&msg, msg.msgh_size, MACH64_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
-	}
-
-	void
-	addInterval(IOPMDriverAssertionID id, uint64_t create_timestamp, uint64_t delete_timestamp)
-	{
-		IOPMAssertionLogData::Interval& interval = data.intervals[data.intervals_pos++ % ARRAY_LEN(data.intervals)];
-		interval.id = id;
-		interval.create_timestamp = create_timestamp;
-		interval.delete_timestamp = delete_timestamp;
-
-		if (notificationPort && notificationThreshold == (data.intervals_pos % ARRAY_LEN(data.intervals))) {
-			notify();
-		}
-	}
-
-	void
-	addName(IOPMDriverAssertionID id, const char *name)
-	{
-		IOPMAssertionLogData::Properties& prop = data.props[data.props_pos++ % ARRAY_LEN(data.props)];
-		prop.id = id;
-		strlcpy(prop.name, name, sizeof(prop.name));
-	}
 };
 
 /*
@@ -897,10 +830,6 @@
 	IOPMDriverAssertionType     assertionsKernel;
 	IOPMDriverAssertionType     assertionsUser;
 	IOPMDriverAssertionType     assertionsCombined;
-
-	IOPMAssertionLog            assertionsLog;
-
-	friend class IOPMrootDomain;
 };
 
 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
@@ -1446,26 +1375,6 @@
     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
     NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
 
-// This value is meant to represent the last time the device shut down
-// in a unit of the PMU driver's choosing see rdar://138590268 for details
-static int
-sysctl_shutdowntime SYSCTL_HANDLER_ARGS
-{
-	uint64_t shutdownTime = 0;
-
-	if (gRootDomain && gShutdownReasonSysctlRegistered) {
-		gRootDomain->copyShutdownTime(&shutdownTime);
-	} else {
-		return ENOENT;
-	}
-
-	return SYSCTL_OUT(req, &shutdownTime, sizeof(shutdownTime));
-}
-
-SYSCTL_PROC(_kern, OID_AUTO, shutdowntime,
-    CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    NULL, 0, sysctl_shutdowntime, "Q", "shutdowntime");
-
 static int
 sysctl_targettype SYSCTL_HANDLER_ARGS
 {
@@ -1487,69 +1396,6 @@
 SYSCTL_PROC(_hw, OID_AUTO, targettype,
     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
     NULL, 0, sysctl_targettype, "A", "targettype");
-
-static SECURITY_READ_ONLY_LATE(char*) jetsam_properties_product_type_string = NULL;
-static SECURITY_READ_ONLY_LATE(size_t) jetsam_properties_product_type_string_len = 0;
-
-/*
- * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(),
- * so we load the jetsam_properties_product_type string (if available) in a startup handler.
- */
-__startup_func
-static void
-sysctl_load_jetsam_properties_product_type(void)
-{
-	DTEntry node;
-	void const *value = NULL;
-	unsigned int size = 0;
-
-	if (kSuccess != SecureDTLookupEntry(nullptr, "/product", &node)) {
-		return;
-	}
-
-	if (kSuccess != SecureDTGetProperty(node, "jetsam-properties-product-type", (void const **) &value, &size)) {
-		return;
-	}
-
-	if (size == 0) {
-		return;
-	}
-
-	jetsam_properties_product_type_string = (char *) zalloc_permanent(size, ZALIGN_NONE);
-	if (jetsam_properties_product_type_string == NULL) {
-		return;
-	}
-
-	memcpy(jetsam_properties_product_type_string, value, size);
-	jetsam_properties_product_type_string_len = size;
-}
-STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_jetsam_properties_product_type);
-
-static int
-sysctl_jetsam_properties_product_type SYSCTL_HANDLER_ARGS
-{
-	if (jetsam_properties_product_type_string != NULL) {
-		return SYSCTL_OUT(req, jetsam_properties_product_type_string, jetsam_properties_product_type_string_len);
-	}
-
-	IOService * root;
-	OSSharedPtr<OSObject>  obj;
-	OSData *    data;
-	char        tt[32];
-
-	tt[0] = '\0';
-	root = IOService::getServiceRoot();
-	if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
-		if ((data = OSDynamicCast(OSData, obj.get()))) {
-			strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
-		}
-	}
-	return sysctl_io_string(req, tt, 0, 0, NULL);
-}
-
-SYSCTL_PROC(_hw, OID_AUTO, jetsam_properties_product_type,
-    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    NULL, 0, sysctl_jetsam_properties_product_type, "A", "jetsam_properties_product_type");
 
 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
@@ -1580,8 +1426,6 @@
 	return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
 }
 
-TUNABLE_DT_WRITEABLE(uint32_t, gAOTMode, "/product/iopm",
-    "aot-mode", "aot_mode", 0, TUNABLE_DT_NONE);
 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
     NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
@@ -1598,8 +1442,8 @@
 	result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
 		unsigned int oldCount;
 
-		if (mode && !gRootDomain->_aotMetrics) {
-		        gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
+		if (mode) {
+		        gRootDomain->initAOTMetrics();
 		}
 
 		oldCount = gRootDomain->idleSleepPreventersCount();
@@ -1656,15 +1500,6 @@
 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
     NULL, 0, sysctl_aotmode, "I", "");
-
-TUNABLE_DT(uint32_t, gAOTLingerTimeMS, "/product/iopm",
-    "aot-linger-time-ms", "aot_linger_time_ms", 800, TUNABLE_DT_NONE);
-
-// Low Power Wake tunables
-TUNABLE_DT_WRITEABLE(uint64_t, gLPWFlags, "/product/iopm",
-    "low-power-wake", "low_power_wake", false, TUNABLE_DT_NONE);
-static SYSCTL_QUAD(_kern, OID_AUTO, lowpowerwake, CTLFLAG_RW | CTLFLAG_LOCKED,
-    &gLPWFlags, "Low Power Wake");
 
 //******************************************************************************
 
@@ -1686,7 +1521,7 @@
 //
 //******************************************************************************
 
-#define kRootDomainSettingsCount           21
+#define kRootDomainSettingsCount           20
 #define kRootDomainNoPublishSettingsCount  4
 
 bool
@@ -1732,7 +1567,6 @@
 		gIOPMSettingDebugPowerRelativeKey,
 		OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
 		OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
-		OSSymbol::withCString(kIOPMSettingRestartOnPowerConnectKey),
 		OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
 		OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
 		OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
@@ -1767,10 +1601,6 @@
 	PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
 	PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
 	PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
-
-	_aotMode = gAOTMode;
-	_aotLingerTime = gAOTLingerTimeMS;
-	_aotMetrics = _aotMode ? IOMallocType(IOPMAOTMetrics) : NULL;
 
 	// read noidle setting from Device Tree
 	if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
@@ -1908,9 +1738,6 @@
 	PMinit(); // creates gIOPMWorkLoop
 	gIOPMWorkLoop = getIOPMWorkloop();
 
-	commandGate = IOCommandGate::commandGate(gIOPMWorkLoop);
-	gIOPMWorkLoop->addEventSource(commandGate.get());
-
 	// Create IOPMPowerStateQueue used to queue external power
 	// events, and to handle those events on the PM work loop.
 	pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
@@ -1918,6 +1745,7 @@
 		&IOPMrootDomain::dispatchPowerEvent));
 	gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
 
+	_aotMode = 0;
 	_aotTimerES = IOTimerEventSource::timerEventSource(this,
 	    OSMemberFunctionCast(IOTimerEventSource::Action,
 	    this, &IOPMrootDomain::aotEvaluate));
@@ -2214,79 +2042,6 @@
 
 exit:
 	return return_value;
-}
-
-#if HIBERNATION
-// MARK: -
-// MARK: setLockdownModeHibernation
-// ***************************************************************************
-void
-IOPMrootDomain::setLockdownModeHibernation(uint32_t status)
-{
-	if (!gIOPMWorkLoop->inGate()) {
-		gIOPMWorkLoop->runAction(
-			OSMemberFunctionCast(IOWorkLoop::Action, this,
-			&IOPMrootDomain::setLockdownModeHibernation),
-			this, (void *)(uintptr_t) status);
-		return;
-	}
-
-	ldmHibernateDisable = status;
-	DLOG("ldmHibernateDisable %d\n", status);
-	setProperty("IOPMLDMHibernationDisable", status);
-}
-#endif
-
-IOReturn
-IOPMrootDomain::getAssertionLog(IOPMAssertionLogData *outLog)
-{
-	if (!gIOPMWorkLoop->inGate()) {
-		return gIOPMWorkLoop->runAction(
-			OSMemberFunctionCast(IOWorkLoop::Action, this,
-			&IOPMrootDomain::getAssertionLog),
-			this, (void *)(uintptr_t) outLog);
-	}
-
-	if (!pmAssertions) {
-		return kIOReturnNotFound;
-	}
-
-	*outLog = pmAssertions->assertionsLog.data;
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOPMrootDomain::setAssertionLogNotificationPort(mach_port_t port)
-{
-	if (!gIOPMWorkLoop->inGate()) {
-		return gIOPMWorkLoop->runAction(
-			OSMemberFunctionCast(IOWorkLoop::Action, this,
-			&IOPMrootDomain::setAssertionLogNotificationPort),
-			this, (void *)(uintptr_t) port);
-	}
-
-	if (!pmAssertions) {
-		return kIOReturnNotFound;
-	}
-
-	return pmAssertions->assertionsLog.setNotificationPort(port);
-}
-
-IOReturn
-IOPMrootDomain::setAssertionLogNotificationThreshold(uint64_t threshold)
-{
-	if (!gIOPMWorkLoop->inGate()) {
-		return gIOPMWorkLoop->runAction(
-			OSMemberFunctionCast(IOWorkLoop::Action, this,
-			&IOPMrootDomain::setAssertionLogNotificationThreshold),
-			this, (void *)(uintptr_t) threshold);
-	}
-
-	if (!pmAssertions) {
-		return kIOReturnNotFound;
-	}
-
-	return pmAssertions->assertionsLog.setNotificationThreshold(threshold);
 }
 
 // MARK: -
@@ -3069,19 +2824,6 @@
 	notifierThread = current_thread();
 	switch (getPowerState()) {
 	case SLEEP_STATE: {
-#if defined(__arm64__) && HIBERNATION
-		if (kIOHibernateStateInactive == gIOHibernateState)
-#endif /* defined(__arm64__) && HIBERNATION */
-		{
-			if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceWakeupBit)) {
-				IOLog("accelerate wake for assertion\n");
-				setWakeTime(mach_continuous_time());
-			}
-			if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceFullWakeupBit)) {
-				// Note: The scheduled RTC wakeup will trigger a full wake.
-				scheduleImmediateDebugWake();
-			}
-		}
 		if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
 			secs = 0;
 			microsecs = 0;
@@ -3150,6 +2892,7 @@
 		if (!_aotLastWakeTime) {
 			gIOLastUserSleepTime = gIOLastSleepTime;
 		}
+
 		gIOLastWakeTime.tv_sec = 0;
 		gIOLastWakeTime.tv_usec = 0;
 		gIOLastSleepAbsTime = now;
@@ -3261,11 +3004,9 @@
 
 			if (_aotTestTime) {
 				if (_aotWakeTimeUTC <= secs) {
-					_aotTestTime = mach_continuous_time() + _aotTestInterval;
+					_aotTestTime = _aotTestTime + _aotTestInterval;
 				}
-				if (_aotTestTime < _aotEndTime) {
-					_setWakeTime(_aotTestTime);
-				}
+				setWakeTime(_aotTestTime);
 			}
 		}
 
@@ -3424,16 +3165,9 @@
 		// and before the changePowerStateWithTagToPriv() call below.
 		WAKEEVENT_LOCK();
 		aotShouldExit(false);
-		unsigned long newState = getRUN_STATE();
-		if (AOT_STATE == newState) {
-			if (gLPWFlags) {
-				_aotRunMode = gLPWFlags | _aotWakeEventRunMode;
-			}
-			IOLog("_aotRunMode = 0x%llx|0x%llx\n", gLPWFlags, _aotWakeEventRunMode);
-		}
 		WAKEEVENT_UNLOCK();
 
-		changePowerStateWithTagToPriv(newState, kCPSReasonWake);
+		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
 		break;
 	}
 #if !__i386__ && !__x86_64__
@@ -4439,25 +4173,34 @@
 }
 
 //******************************************************************************
-// willNotifyInterest
+// willNotifyPowerChildren
 //
-// Called after all priority clients have all acknowledged the power change,
-// but before any interested drivers and any power children are informed.
-// Dispatched though a thread call, so it is safe to perform work that might block on a
-// sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
+// Called after all interested drivers have all acknowledged the power change,
+// but before any power children is informed. Dispatched though a thread call,
+// so it is safe to perform work that might block on a sleeping disk. PM state
+// machine (not thread) will block w/o timeout until this function returns.
 //******************************************************************************
 
 void
-IOPMrootDomain::willNotifyInterested( IOPMPowerStateIndex newPowerState )
+IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
 {
 	if (SLEEP_STATE == newPowerState) {
+		notifierThread = current_thread();
+		if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
+			AbsoluteTime deadline;
+
+			clock_interval_to_deadline(10, kSecondScale, &deadline);
+#if defined(XNU_TARGET_OS_OSX)
+			vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
+#endif /* defined(XNU_TARGET_OS_OSX) */
+		}
+
 		_aotReadyToFullWake = false;
 #if 0
 		if (_aotLingerTime) {
-			uint64_t interval, deadline;
+			uint64_t deadline;
 			IOLog("aot linger no return\n");
-			nanoseconds_to_absolutetime(_aotLingerTime * NSEC_PER_MSEC, &interval);
-			clock_absolutetime_interval_to_deadline(interval, &deadline);
+			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
 			clock_delay_until(deadline);
 		}
 #endif
@@ -4475,43 +4218,18 @@
 			_aotLastWakeTime   = 0;
 			bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
 			if (kIOPMAOTModeCycle & _aotMode) {
-				clock_interval_to_absolutetime_interval(10, kSecondScale, &_aotTestInterval);
+				clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
 				_aotTestTime = mach_continuous_time() + _aotTestInterval;
-				AbsoluteTime endInterval;
-				clock_interval_to_absolutetime_interval(60, kSecondScale, &endInterval);
-				_aotEndTime = mach_continuous_time() + endInterval;
-				_setWakeTime(_aotTestTime);
-			}
+				setWakeTime(_aotTestTime);
+			}
+			uint32_t lingerSecs;
+			if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
+				lingerSecs = 0;
+			}
+			clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
 			clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
 			clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
 		}
-
-		if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
-			IOLog("PMRD: tasks suspend\n");
-			AbsoluteTime deadline;
-
-			clock_interval_to_deadline(10, kSecondScale, &deadline);
-#if defined(XNU_TARGET_OS_OSX)
-			vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
-#endif /* defined(XNU_TARGET_OS_OSX) */
-		}
-	}
-}
-
-//******************************************************************************
-// willNotifyPowerChildren
-//
-// Called after all interested drivers have all acknowledged the power change,
-// but before any power children are informed.
-// Dispatched though a thread call, so it is safe to perform work that might block on a
-// sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
-//******************************************************************************
-
-void
-IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
-{
-	if (SLEEP_STATE == newPowerState) {
-		notifierThread = current_thread();
 
 #if HIBERNATION
 		// Adjust watchdog for IOHibernateSystemSleep
@@ -4524,9 +4242,6 @@
 		IOHibernateIOKitSleep();
 #endif
 #if defined(__arm64__) && HIBERNATION
-		if (gIOHibernateState == kIOHibernateStateInactive) {
-			setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
-		}
 		// On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
 		// user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
 		// alarms, which can mess with cycler tools.
@@ -6445,7 +6160,7 @@
 
 #if HIBERNATION && defined(__arm64__)
 	if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
-		if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
+		if (!ml_is_secure_hib_supported()) {
 			// If hibernation is unsupported, reject sleep requests to avoid
 			// racing with system shutdown.
 			*inOutChangeFlags |= kIOPMNotDone;
@@ -6527,22 +6242,21 @@
 	if (changeFlags & kIOPMSynchronize) {
 		if (newPowerState == ON_STATE) {
 			if (changeFlags & kIOPMSyncNoChildNotify) {
-				setSystemTransitionTypeGated(kSystemTransitionNewCapClient);
+				_systemTransitionType = kSystemTransitionNewCapClient;
 			} else {
-				setSystemTransitionTypeGated(kSystemTransitionCapability);
+				_systemTransitionType = kSystemTransitionCapability;
 			}
 		}
 	}
 	// 2. Going to sleep (cancellation still possible).
 	else if (newPowerState < currentPowerState) {
-		setSystemTransitionTypeGated(kSystemTransitionSleep);
+		_systemTransitionType = kSystemTransitionSleep;
 	}
 	// 3. Woke from (idle or demand) sleep.
 	else if (!systemBooting &&
 	    (changeFlags & kIOPMSelfInitiated) &&
 	    (newPowerState > currentPowerState)) {
-		setSystemTransitionTypeGated(kSystemTransitionWake);
-
+		_systemTransitionType = kSystemTransitionWake;
 		_desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
 
 		// Early exit from dark wake to full (e.g. LID open)
@@ -6584,7 +6298,7 @@
 		if ((kSystemTransitionCapability == _systemTransitionType) &&
 		    (_pendingCapability == _currentCapability)) {
 			// Cancel the PM state change.
-			setSystemTransitionTypeGated(kSystemTransitionNone);
+			_systemTransitionType = kSystemTransitionNone;
 			*inOutChangeFlags |= kIOPMNotDone;
 		}
 		if (__builtin_popcount(_pendingCapability) <
@@ -6693,12 +6407,7 @@
 		// Clear stats about sleep
 
 		if (AOT_STATE == newPowerState) {
-			// Temporarily increase the capacity of the log subsystem to buffer logs in AOT.
-			os_log_adjust_buffering_capacity(LOG_BUFFERING_CAPACITY_MAX);
-			_pendingCapability = kIOPMSystemCapabilityAOT;
-		} else {
-			// Restore the maximum capacity of the log subsystem once waking to full wake.
-			os_log_adjust_buffering_capacity(LOG_BUFFERING_CAPACITY_DEFAULT);
+			_pendingCapability = 0;
 		}
 
 		if (AOT_STATE == currentPowerState) {
@@ -6789,38 +6498,6 @@
 }
 
 void
-IOPMrootDomain::setSystemTransitionTypeGated(SystemTransitionType type)
-{
-	assert(gIOPMWorkLoop->inGate());
-	_systemTransitionType = type;
-	commandGate->commandWakeup(&_systemTransitionType);
-}
-
-void
-IOPMrootDomain::waitForSystemTransitionToMinPowerState(IOPMRootDomainPowerState state)
-{
-	while (true) {
-		IOReturn ret = gIOPMWorkLoop->runActionBlock(^{
-			// Block until all in progress transitions have completed.
-			while (_systemTransitionType != kSystemTransitionNone) {
-			        commandGate->commandSleep(&_systemTransitionType);
-			}
-
-			// Check the current power state.
-			if (getPowerState() >= state) {
-			        return kIOReturnSuccess;
-			}
-
-			return kIOReturnError;
-		});
-
-		if (ret == kIOReturnSuccess) {
-			break;
-		}
-	}
-}
-
-void
 IOPMrootDomain::handleOurPowerChangeDone(
 	IOService *             service,
 	IOPMActions *           actions,
@@ -6829,7 +6506,7 @@
 	IOPMPowerChangeFlags    changeFlags )
 {
 	if (kSystemTransitionNewCapClient == _systemTransitionType) {
-		setSystemTransitionTypeGated(kSystemTransitionNone);
+		_systemTransitionType = kSystemTransitionNone;
 		return;
 	}
 
@@ -6994,8 +6671,7 @@
 			tracePoint( kIOPMTracePointSystemUp );
 		}
 
-		setSystemTransitionTypeGated(kSystemTransitionNone);
-
+		_systemTransitionType = kSystemTransitionNone;
 		_systemMessageClientMask = 0;
 		toldPowerdCapWillChange  = false;
 
@@ -7837,7 +7513,20 @@
 		break;
 #endif
 
-		if (_driverKitMatchingAssertionCount != 0 || _driverKitSyncedAssertionCount != 0) {
+		if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
+			break; // always sleep on low battery or when in thermal warning/emergency state
+		}
+
+		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
+			break; // always sleep on dark wake thermal emergencies
+		}
+
+		if (preventSystemSleepList->getCount() != 0) {
+			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
+			break;
+		}
+
+		if (_driverKitMatchingAssertionCount != 0) {
 			err = kPMCPUAssertion;
 			break;
 		}
@@ -7846,33 +7535,17 @@
 		// this is in flight can cause IOServicePH to timeout.
 		if (!IOServicePH::checkPMReady()) {
 #if !defined(XNU_TARGET_OS_OSX)
-			if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
-				// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
-				// in dark wake for long periods of time, which causes issues as apps were
-				// already informed of sleep during the f->9 transition. As a temporary
-				// measure, always full wake if we hit this specific condition.
-				pmPowerStateQueue->submitPowerEvent(
-					kPowerEventPolicyStimulus,
-					(void *) kStimulusDarkWakeActivityTickle);
-			}
+			// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
+			// in dark wake for long periods of time, which causes issues as apps were
+			// already informed of sleep during the f->9 transition. As a temporary
+			// measure, always full wake if we hit this specific condition.
+			pmPowerStateQueue->submitPowerEvent(
+				kPowerEventPolicyStimulus,
+				(void *) kStimulusDarkWakeActivityTickle);
 #endif
 			err = kPMDKNotReady;
 			break;
 		}
-
-		if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
-			break; // always sleep on low battery or when in thermal warning/emergency state
-		}
-
-		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
-			break; // always sleep on dark wake thermal emergencies
-		}
-
-		if (preventSystemSleepList->getCount() != 0) {
-			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
-			break;
-		}
-
 
 		if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
 		    kIOPMDriverAssertionLevelOn) {
@@ -7963,59 +7636,6 @@
 }
 
 //******************************************************************************
-// considerRunMode
-// consider the driver for AOT power on via the runmode mask
-//******************************************************************************
-
-int32_t
-IOPMrootDomain::considerRunMode(IOService * service, uint64_t pmDriverClass)
-{
-	int32_t promote;
-
-	if ((0 == _aotRunMode) || (service == this)) {
-		// neutral
-		return 0;
-	}
-	if (pmDriverClass) {
-		IOLog("considerRunMode: %s 0x%llx 0x%llx\n", service->getName(), pmDriverClass, _aotRunMode);
-	}
-	promote = (0 != (_aotRunMode & pmDriverClass)) ? 1 : -1;
-	if (promote > 0) {
-		IOLog("IOPMRD: %s 0x%llx runmode to %s\n", service->getName(), pmDriverClass, (promote < 0) ? "OFF" : "ON");
-	}
-	return promote;
-}
-
-void
-IOPMrootDomain::handleRegisterPowerDriver(IOService * child)
-{
-	OSNumber * num;
-	IOService * userServer;
-	uint64_t driverClassFlags;
-	OSSharedPtr<OSObject> prop = child->copyProperty(kIOPMAOTAllowKey);
-
-	if (!prop || (NULL == (num = OSDynamicCast(OSNumber, prop.get())))) {
-		return;
-	}
-	driverClassFlags = num->unsigned64BitValue();
-
-	userServer = NULL;
-	if (child->reserved->uvars && (userServer = child->reserved->uvars->userServer)) {
-		WAKEEVENT_LOCK();
-		_aotWakeEventRunModeImpliesStorage |= driverClassFlags;
-		WAKEEVENT_UNLOCK();
-	}
-
-	IOLog("addPMDriverClass %s %llx\n", child->getName(), driverClassFlags);
-	if (driverClassFlags) {
-		child->addPMDriverClass(driverClassFlags);
-		if (userServer) {
-			userServer->addPMDriverClass(driverClassFlags);
-		}
-	}
-}
-
-//******************************************************************************
 // attemptIdleSleepAbort
 //******************************************************************************
 
@@ -8192,42 +7812,8 @@
 	return _aotNow;
 }
 
-bool
-IOPMrootDomain::isLPWMode()
-{
-	return gLPWFlags && currentOrPendingPowerState(AOT_STATE);
-}
-
-bool
-IOPMIsAOTMode(void)
-{
-	return gIOPMRootDomain && gIOPMRootDomain->isAOTMode();
-}
-bool
-IOPMIsLPWMode(void)
-{
-	return gIOPMRootDomain && gIOPMRootDomain->isLPWMode();
-}
-
-void
-IOPMNetworkStackFullWake(uint64_t flags, const char * reason)
-{
-	assert(kIOPMNetworkStackFullWakeFlag == flags);
-	assert(gIOPMRootDomain);
-	gIOPMRootDomain->claimSystemWakeEvent(gIOPMRootDomain, kIOPMWakeEventAOTExit, reason, NULL);
-}
-
 IOReturn
 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
-{
-	if (kIOPMAOTModeCycle & _aotMode) {
-		return kIOReturnSuccess;
-	}
-	return _setWakeTime(wakeContinuousTime);
-}
-
-IOReturn
-IOPMrootDomain::_setWakeTime(uint64_t wakeContinuousTime)
 {
 	clock_sec_t     nowsecs, wakesecs;
 	clock_usec_t    nowmicrosecs, wakemicrosecs;
@@ -8318,7 +7904,6 @@
 
 	ASSERT_GATED();
 	_aotNow = false;
-	_aotRunMode = 0;
 	_aotReadyToFullWake = false;
 	if (_aotTimerScheduled) {
 		_aotTimerES->cancelTimeout();
@@ -8391,8 +7976,8 @@
 void
 IOPMrootDomain::adjustPowerState( bool sleepASAP )
 {
-	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d, _aotNow %d\n",
-	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled, _aotNow);
+	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
+	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
 
 	ASSERT_GATED();
 
@@ -8408,7 +7993,11 @@
 		    && !_aotTimerScheduled
 		    && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
 			_aotTimerScheduled = true;
-			_aotTimerES->setTimeout(_aotLingerTime, kMillisecondScale);
+			if (_aotLingerTime) {
+				_aotTimerES->setTimeout(_aotLingerTime);
+			} else {
+				_aotTimerES->setTimeout(800, kMillisecondScale);
+			}
 		}
 		WAKEEVENT_UNLOCK();
 		if (exitNow) {
@@ -8664,11 +8253,6 @@
 			aotEvaluate(NULL);
 		}
 		break;
-	case kPowerEventRunModeRequest:
-		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
-		// arg1 == runModeMask
-		handleRequestRunMode(arg1);
-		break;
 	}
 }
 
@@ -8865,7 +8449,7 @@
 	if (msg & kIOPMPowerEmergency) {
 		DLOG("Received kIOPMPowerEmergency");
 #if HIBERNATION && defined(__arm64__)
-		if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
+		if (!ml_is_secure_hib_supported()) {
 			// Wait for the next low battery notification if the system state is
 			// in transition.
 			if ((_systemTransitionType == kSystemTransitionNone) &&
@@ -8875,7 +8459,6 @@
 				lowBatteryCondition = true;
 
 				// Notify userspace to initiate system shutdown
-				DLOG("Initiating userspace shutdown ml_is_secure_hib_supported %d lockdownMode %d", ml_is_secure_hib_supported(), ldmHibernateDisable);
 				messageClients(kIOPMMessageRequestSystemShutdown);
 			}
 		} else {
@@ -9425,9 +9008,7 @@
 
 		if (!systemBooting && (0 == idleSleepPreventersCount())) {
 			if (!wrangler) {
-				if (kStimulusNoIdleSleepPreventers != stimulus) {
-					changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
-				}
+				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
 				if (idleSleepEnabled) {
 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
 					if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
@@ -11030,12 +10611,6 @@
 			    serviceName, ownerDescription);
 		}
 #endif /* (DEVELOPMENT || DEBUG) */
-
-		const bool waitForWakeup = (whichAssertionBits & kIOPMDriverAssertionForceWakeupBit);
-		if (waitForWakeup) {
-			waitForSystemTransitionToMinPowerState(AOT_STATE);
-		}
-
 		return newAssertion;
 	} else {
 		return 0;
@@ -11111,7 +10686,7 @@
 		        _driverKitMatchingAssertionCount++;
 		        return kIOReturnSuccess;
 		} else {
-		        if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
+		        if (kSystemTransitionSleep == _systemTransitionType) {
 		                // system going to sleep
 		                return kIOReturnBusy;
 			} else {
@@ -11147,75 +10722,6 @@
 	});
 }
 
-IOReturn
-IOPMrootDomain::acquireDriverKitSyncedAssertion(IOService * from, IOPMDriverAssertionID * assertionID)
-{
-	return gIOPMWorkLoop->runActionBlock(^{
-		if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
-		        // system going to sleep
-		        return kIOReturnBusy;
-		}
-		// createPMAssertion is asynchronous.
-		// we must also set _driverKitSyncedAssertionCount under the PM workloop lock so that we can cancel sleep immediately
-		// only kIOPMDriverAssertionCPUBit is used for "synced" assertion
-		*assertionID = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, from->getName());
-		if (*assertionID != kIOPMUndefinedDriverAssertionID) {
-		        _driverKitSyncedAssertionCount++;
-		        return kIOReturnSuccess;
-		} else {
-		        return kIOReturnBusy;
-		}
-	});
-}
-
-void
-IOPMrootDomain::releaseDriverKitSyncedAssertion(IOPMDriverAssertionID assertionID)
-{
-	gIOPMWorkLoop->runActionBlock(^{
-		if (_driverKitSyncedAssertionCount != 0) {
-		        _driverKitSyncedAssertionCount--;
-		        releasePMAssertion(assertionID);
-		} else {
-		        panic("Over-release of driverkit synced assertion");
-		}
-		return kIOReturnSuccess;
-	});
-}
-
-
-IOReturn
-IOPMrootDomain::createPMAssertionSafe(
-	IOPMDriverAssertionID *assertionID,
-	IOPMDriverAssertionType whichAssertionBits,
-	IOPMDriverAssertionLevel assertionLevel,
-	IOService *ownerService,
-	const char *ownerDescription)
-{
-	IOReturn ret;
-	IOPMDriverAssertionID __block id;
-
-	if (!assertionID) {
-		return kIOReturnBadArgument;
-	}
-
-	// Grab workloop to check current transition
-	ret = gIOPMWorkLoop->runActionBlock(^{
-		if (_systemTransitionType == kSystemTransitionSleep) {
-		        return kIOReturnBusy;
-		}
-		id = createPMAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription);
-		return id ? kIOReturnSuccess : kIOReturnError;
-	});
-
-	if (ret == kIOReturnSuccess) {
-		*assertionID = id;
-	} else if (ret == kIOReturnBusy && (kIOLogPMRootDomain & gIOKitDebug)) {
-		DLOG("assertion denied due to ongoing sleep transition (%s)\n", ownerDescription);
-	}
-
-	return ret;
-}
-
 bool
 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
 {
@@ -11344,14 +10850,6 @@
 	WAKEEVENT_UNLOCK();
 }
 
-void
-IOPMrootDomain::copyShutdownTime( uint64_t * time )
-{
-	WAKEEVENT_LOCK();
-	*time = gShutdownTime;
-	WAKEEVENT_UNLOCK();
-}
-
 //******************************************************************************
 // acceptSystemWakeEvents
 //
@@ -11377,7 +10875,6 @@
 				_systemWakeEventsArray->flushCollection();
 			}
 		}
-		_aotWakeEventRunMode = 0;
 
 		// Remove stale WakeType property before system sleep
 		removeProperty(kIOPMRootDomainWakeTypeKey);
@@ -11467,14 +10964,18 @@
 	IOOptionBits        aotFlags = 0;
 	bool                needAOTEvaluate = FALSE;
 
-	if ((kIOPMAOTModeAddEventFlags & _aotMode) && (!flags || (flags == kIOPMWakeEventSource))) {
-		flags |= kIOPMWakeEventAOTExit;
-
+	if (kIOPMAOTModeAddEventFlags & _aotMode) {
 		// Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
-		if (!strcmp("AOP.OutboxNotEmpty", reason) || !strcmp("spu_gesture", reason)) {
-			flags &= ~kIOPMWakeEventAOTExit;
-		}
-	}
+		if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
+			flags |= kIOPMWakeEventAOTExit;
+		}
+	}
+
+#if DEVELOPMENT || DEBUG
+	if (_aotLingerTime && !strcmp("rtc", reason)) {
+		flags |= kIOPMWakeEventAOTPossibleExit;
+	}
+#endif /* DEVELOPMENT || DEBUG */
 
 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
 	// Publishing the WakeType is serialized by the PM work loop
@@ -11522,15 +11023,19 @@
 	if (_aotNow && aotFlags) {
 		if (kIOPMWakeEventAOTPossibleExit & flags) {
 			_aotMetrics->possibleCount++;
+			_aotAnalytics->possibleCount++;
 		}
 		if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
 			_aotMetrics->confirmedPossibleCount++;
+			_aotAnalytics->confirmedPossibleCount++;
 		}
 		if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
 			_aotMetrics->rejectedPossibleCount++;
+			_aotAnalytics->rejectedPossibleCount++;
 		}
 		if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
 			_aotMetrics->expiredPossibleCount++;
+			_aotAnalytics->expiredPossibleCount++;
 		}
 
 		_aotPendingFlags |= aotFlags;
@@ -11566,17 +11071,6 @@
 			strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
 		}
 		strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
-	}
-
-	if (_aotNow && _acceptSystemWakeEvents) {
-		uint64_t runModeBits = (kIOPMAOTModeRunModeMask & flags) >> kIOPMAOTModeRunModeShift;
-		if (runModeBits) {
-			if (_aotWakeEventRunModeImpliesStorage & runModeBits) {
-				runModeBits |= kIOPMDriverClassStorage;
-			}
-			IOLog("AOT wake event %s -> mode 0x%llx\n", reasonString->getCStringNoCopy(), runModeBits);
-			_aotWakeEventRunMode |= runModeBits;
-		}
 	}
 
 	WAKEEVENT_UNLOCK();
@@ -11638,7 +11132,7 @@
 	IOService *              device,
 	IOOptionBits             flags,
 	const char *             reason,
-	OSObject *               details )
+	__unused OSObject *      details )
 {
 	if (!device || !reason) {
 		return;
@@ -11661,55 +11155,8 @@
 	}
 	strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
 
-	if (details) {
-		OSDictionary *dict = OSDynamicCast(OSDictionary, details);
-		if (dict) {
-			OSSharedPtr<OSString> sharedKey = OSString::withCString(kIOPMRootDomainShutdownTime);
-			if (sharedKey) {
-				OSNumber *num = OSDynamicCast(OSNumber, dict->getObject(sharedKey.get()));
-				if (num) {
-					gShutdownTime = (uint64_t)(num->unsigned64BitValue());
-				}
-			}
-		}
-	}
-
 	gShutdownReasonSysctlRegistered = true;
 	WAKEEVENT_UNLOCK();
-}
-
-//******************************************************************************
-// requestRunMode
-//
-// For clients to request a LPW run mode. Only full wake is supported currently.
-//******************************************************************************
-
-IOReturn
-IOPMrootDomain::requestRunMode(uint64_t runModeMask)
-{
-	// We only support requesting full wake at the moment
-	if (runModeMask == kIOPMRunModeFullWake) {
-		pmPowerStateQueue->submitPowerEvent(kPowerEventRunModeRequest, NULL, runModeMask);
-		return kIOReturnSuccess;
-	}
-	return kIOReturnUnsupported;
-}
-
-IOReturn
-IOPMrootDomain::handleRequestRunMode(uint64_t runModeMask)
-{
-	// TODO: Replace with run mode logic when implemented
-	IOReturn ret = kIOReturnUnsupported;
-
-	// We only support requesting full wake at the moment
-	if (runModeMask == kIOPMRunModeFullWake) {
-		// A simple CPS should suffice for now
-		changePowerStateWithTagToPriv(ON_STATE, kCPSReasonEvaluatePolicy);
-		ret = kIOReturnSuccess;
-	}
-
-	DLOG("%s: mask %llx ret %x\n", __func__, runModeMask, ret);
-	return ret;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -11869,7 +11316,6 @@
 	me->assertionsCombined = 0;
 	me->assertionsArrayLock = IOLockAlloc();
 	me->tabulateProducerCount = me->tabulateConsumerCount = 0;
-	bzero(&me->assertionsLog, sizeof(me->assertionsLog));
 
 	assert(me->assertionsArray);
 	assert(me->assertionsArrayLock);
@@ -11926,7 +11372,7 @@
 void
 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
 {
-	AbsoluteTime now, elapsed;
+	AbsoluteTime now;
 	uint64_t     nsec;
 
 	if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
@@ -11934,11 +11380,9 @@
 		return;
 	}
 
-	now = mach_continuous_time();
-	assertionsLog.addInterval(assertStruct->id, assertStruct->assertCPUStartTime, now);
-
-	elapsed = now - assertStruct->assertCPUStartTime;
-	absolutetime_to_nanoseconds(elapsed, &nsec);
+	now = mach_absolute_time();
+	SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
+	absolutetime_to_nanoseconds(now, &nsec);
 	assertStruct->assertCPUDuration += nsec;
 	assertStruct->assertCPUStartTime = 0;
 
@@ -12065,16 +11509,12 @@
 	ASSERT_GATED();
 
 	if (newAssertion) {
+		IOLockLock(assertionsArrayLock);
 		assertStruct = newAssertion->getMutableBytesNoCopy();
-
 		if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
 		    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
-			assertStruct->assertCPUStartTime = mach_continuous_time();
-		}
-
-		assertionsLog.addName(assertStruct->id, assertStruct->ownerString->getCStringNoCopy());
-
-		IOLockLock(assertionsArrayLock);
+			assertStruct->assertCPUStartTime = mach_absolute_time();
+		}
 		assertionsArray->setObject(newAssertion);
 		IOLockUnlock(assertionsArrayLock);
 		newAssertion->release();
@@ -12203,7 +11643,7 @@
 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
 	    (assertStruct->level != _level)) {
 		if (_level == kIOPMDriverAssertionLevelOn) {
-			assertStruct->assertCPUStartTime = mach_continuous_time();
+			assertStruct->assertCPUStartTime = mach_absolute_time();
 		} else {
 			updateCPUBitAccounting(assertStruct);
 		}
@@ -12393,8 +11833,8 @@
 
 static IOPMPowerState patriarchPowerStates[2] =
 {
-	{.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER },
-	{.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER }
+	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 };
 
 void
@@ -12508,6 +11948,70 @@
 	}
 }
 
+static void
+reportAnalyticsTimerExpired(
+	thread_call_param_t us, thread_call_param_t )
+{
+	((IOPMrootDomain *)us)->reportAnalytics();
+}
+
+void
+IOPMrootDomain::initAOTMetrics()
+{
+	if (!_aotMetrics) {
+		_aotMetrics = IOMallocType(IOPMAOTMetrics);
+	}
+
+	if (!_aotAnalytics) {
+		_aotAnalytics = IOMallocType(IOPMAOTAnalytics);
+		analyticsThreadCall = thread_call_allocate_with_options(reportAnalyticsTimerExpired,
+		    (thread_call_param_t)this, THREAD_CALL_PRIORITY_KERNEL, THREAD_CALL_OPTIONS_ONCE);
+		scheduleAnalyticsThreadCall();
+	}
+}
+
+#define ANALYTICS_PERIOD_HOURS 24
+#define ANALYTICS_LEEWAY_MINUTES 5
+
+void
+IOPMrootDomain::scheduleAnalyticsThreadCall()
+{
+	uint64_t leeway, period, leeway_ns, period_ns, deadline;
+
+	period_ns = ANALYTICS_PERIOD_HOURS * 60 * 60 * NSEC_PER_SEC;
+	leeway_ns = ANALYTICS_LEEWAY_MINUTES * 60 * NSEC_PER_SEC;
+
+	nanoseconds_to_absolutetime(period_ns, &period);
+	nanoseconds_to_absolutetime(leeway_ns, &leeway);
+	deadline = mach_continuous_time() + period;
+	thread_call_enter_delayed_with_leeway(analyticsThreadCall, NULL, deadline, leeway, THREAD_CALL_CONTINUOUS);
+}
+
+CA_EVENT(aot_analytics,
+    CA_INT, possible_count,
+    CA_INT, confirmed_possible_count,
+    CA_INT, rejected_possible_count,
+    CA_INT, expired_possible_count);
+
+void
+IOPMrootDomain::reportAnalytics()
+{
+	if (_aotAnalytics) {
+		IOLog("IOPMAOTAnalytics possibleCount: %u, confirmedPossibleCount: %u, rejectedPossibleCount: %u, expiredPossibleCount: %u\n",
+		    _aotAnalytics->possibleCount, _aotAnalytics->confirmedPossibleCount, _aotAnalytics->rejectedPossibleCount, _aotAnalytics->expiredPossibleCount);
+
+		ca_event_t event = CA_EVENT_ALLOCATE(aot_analytics);
+		CA_EVENT_TYPE(aot_analytics) * e = (CA_EVENT_TYPE(aot_analytics) *)event->data;
+		e->possible_count = _aotAnalytics->possibleCount;
+		e->confirmed_possible_count = _aotAnalytics->confirmedPossibleCount;
+		e->rejected_possible_count = _aotAnalytics->rejectedPossibleCount;
+		e->expired_possible_count = _aotAnalytics->expiredPossibleCount;
+		CA_EVENT_SEND(event);
+
+		bzero(_aotAnalytics, sizeof(IOPMAOTAnalytics));
+		scheduleAnalyticsThreadCall();
+	}
+}
 
 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
 IOReturn
@@ -12820,20 +12324,18 @@
 
 	const void *            callMethod = NULL;
 	const char *            objectName = NULL;
+	uint32_t                timeout = getWatchdogTimeout();
 	const char *            phaseString = NULL;
 	const char *            phaseDescription = NULL;
-	uint64_t                delta;
 
 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
 	uint32_t tracePhase = pmTracer->getTracePhase();
 
 	*thread = NULL;
-
-	delta = get_watchdog_elapsed_time();
 	if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
-		snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
+		snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
 	} else {
-		snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
+		snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
 	}
 	tracePhase2String(tracePhase, &phaseString, &phaseDescription);