#include <IOKit/IOLib.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/pwr_mgt/RootDomain.h>
+#include <IOKit/pwr_mgt/IOPMPrivate.h>
#include <IOKit/IOUserClient.h>
#include <IOKit/IOKitKeysPrivate.h>
#include <IOKit/IOCPU.h>
#include <kern/queue.h>
typedef kern_return_t (*iocpu_platform_action_t)(void * refcon0, void * refcon1, uint32_t priority,
- void * param1, void * param2, void * param3);
+ void * param1, void * param2, void * param3,
+ const char * name);
struct iocpu_platform_action_entry
{
queue_chain_t link;
iocpu_platform_action_t action;
int32_t priority;
+ const char * name;
void * refcon0;
void * refcon1;
struct iocpu_platform_action_entry * alloc_list;
static queue_head_t iocpu_quiesce_queue;
static queue_head_t iocpu_active_queue;
+static queue_head_t gIOHaltRestartActionQueue;
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void
queue_head_t * iocpu_get_platform_active_queue(void)
{
+ if (!iocpu_active_queue.next)
+ {
+ queue_init(&iocpu_quiesce_queue);
+ queue_init(&iocpu_active_queue);
+ iocpu_platform_cpu_action_init(&iocpu_quiesce_queue, &iocpu_active_queue);
+ }
return (&iocpu_active_queue);
}
if ((pri >= first_priority) && (pri <= last_priority))
{
//kprintf("[%p]", next->action);
- ret = (*next->action)(next->refcon0, next->refcon1, pri, param1, param2, param3);
+ ret = (*next->action)(next->refcon0, next->refcon1, pri, param1, param2, param3, next->name);
}
if (KERN_SUCCESS == result)
result = ret;
static kern_return_t
IOServicePlatformAction(void * refcon0, void * refcon1, uint32_t priority,
- void * param1, void * param2, void * param3)
+ void * param1, void * param2, void * param3,
+ const char * service_name)
{
IOReturn ret;
IOService * service = (IOService *) refcon0;
const OSSymbol * function = (const OSSymbol *) refcon1;
- kprintf("%s -> %s\n", function->getCStringNoCopy(), service->getName());
+ kprintf("%s -> %s\n", function->getCStringNoCopy(), service_name);
ret = service->callPlatformFunction(function, false,
- (void *) priority, param1, param2, param3);
+ (void *)(uintptr_t) priority, param1, param2, param3);
return (ret);
}
entry = IONew(iocpu_platform_action_entry_t, 1);
entry->action = &IOServicePlatformAction;
+ entry->name = service->getName();
priority = num->unsigned32BitValue();
if (reverse)
entry->priority = -priority;
gIOAllActionsQueue = entry;
}
+extern "C" kern_return_t
+IOCPURunPlatformHaltRestartActions(uint32_t message)
+{
+ kern_return_t ret;
+ IORegistryIterator * iter;
+ OSOrderedSet * all;
+ IOService * service;
+
+ if (!gIOHaltRestartActionQueue.next)
+ {
+ queue_init(&gIOHaltRestartActionQueue);
+ iter = IORegistryIterator::iterateOver(gIOServicePlane,
+ kIORegistryIterateRecursively);
+ if (iter)
+ {
+ all = 0;
+ do
+ {
+ if (all) all->release();
+ all = iter->iterateAll();
+ }
+ while (!iter->isValid());
+ iter->release();
+ if (all)
+ {
+ while((service = (IOService *) all->getFirstObject()))
+ {
+ IOInstallServicePlatformAction(service, gIOPlatformHaltRestartActionKey, &gIOHaltRestartActionQueue, false);
+ all->removeObject(service);
+ }
+ all->release();
+ }
+ }
+ }
+ ret = iocpu_run_platform_actions(&gIOHaltRestartActionQueue, 0, 0U-1,
+ (void *)(uintptr_t) message, NULL, NULL);
+ return (ret);
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t PE_cpu_start(cpu_id_t target,
long cnt, numCPUs;
IOCPU *target;
IOCPU *bootCPU = NULL;
-
+ IOPMrootDomain *rootDomain = IOService::getPMRootDomain();
+
kprintf("IOCPUSleepKernel\n");
- OSIterator * iter;
- IOService * service;
+ IORegistryIterator * iter;
+ OSOrderedSet * all;
+ IOService * service;
+
+ rootDomain->tracePoint( kIOPMTracePointSleepPlatformActions );
queue_init(&gIOSleepActionQueue);
queue_init(&gIOWakeActionQueue);
+ queue_init(&gIOHaltRestartActionQueue);
iter = IORegistryIterator::iterateOver( gIOServicePlane,
kIORegistryIterateRecursively );
if( iter)
{
- do
+ all = 0;
+ do
{
- iter->reset();
- while((service = (IOService *) iter->getNextObject()))
+ if (all)
+ all->release();
+ all = iter->iterateAll();
+ }
+ while (!iter->isValid());
+ iter->release();
+
+ if (all)
+ {
+ while((service = (IOService *) all->getFirstObject()))
{
IOInstallServicePlatformAction(service, gIOPlatformSleepActionKey, &gIOSleepActionQueue, false);
IOInstallServicePlatformAction(service, gIOPlatformWakeActionKey, &gIOWakeActionQueue, true);
IOInstallServicePlatformAction(service, gIOPlatformQuiesceActionKey, iocpu_get_platform_quiesce_queue(), false);
IOInstallServicePlatformAction(service, gIOPlatformActiveActionKey, iocpu_get_platform_active_queue(), true);
+ IOInstallServicePlatformAction(service, gIOPlatformHaltRestartActionKey, &gIOHaltRestartActionQueue, false);
+ all->removeObject(service);
}
- }
- while( !service && !iter->isValid());
- iter->release();
+ all->release();
+ }
}
iocpu_run_platform_actions(&gIOSleepActionQueue, 0, 0U-1,
NULL, NULL, NULL);
+ rootDomain->tracePoint( kIOPMTracePointSleepCPUs );
+
numCPUs = gIOCPUs->getCount();
// Sleep the CPUs.
cnt = numCPUs;
}
}
+ rootDomain->tracePoint( kIOPMTracePointSleepPlatformDriver );
+
// Now sleep the boot CPU.
if (bootCPU)
bootCPU->haltCPU();
+ rootDomain->tracePoint( kIOPMTracePointWakePlatformActions );
+
iocpu_run_platform_actions(&gIOWakeActionQueue, 0, 0U-1,
NULL, NULL, NULL);
IODelete(entry, iocpu_platform_action_entry_t, 1);
}
- if (!queue_empty(&gIOSleepActionQueue))
- panic("gIOSleepActionQueue");
- if (!queue_empty(&gIOWakeActionQueue))
- panic("gIOWakeActionQueue");
+ if (!queue_empty(&gIOSleepActionQueue)) panic("gIOSleepActionQueue");
+ if (!queue_empty(&gIOWakeActionQueue)) panic("gIOWakeActionQueue");
+ if (!queue_empty(&gIOHaltRestartActionQueue)) panic("gIOHaltRestartActionQueue");
+ gIOHaltRestartActionQueue.next = 0;
+ rootDomain->tracePoint( kIOPMTracePointWakeCPUs );
+
// Wake the other CPUs.
for (cnt = 0; cnt < numCPUs; cnt++)
{
provider->setProperty("timebase-frequency", timebaseFrequency);
timebaseFrequency->release();
- super::setProperty("IOCPUID", (uintptr_t)this, sizeof(uintptr_t)*8);
+ super::setProperty("IOCPUID", getRegistryEntryID(), sizeof(uint64_t)*8);
setCPUNumber(0);
setCPUState(kIOCPUStateUnregistered);
IOInterruptHandler, this, &IOCPUInterruptController::handleInterrupt);
ml_install_interrupt_handler(cpu, cpu->getCPUNumber(), this, handler, 0);
-
- enabledCPUs++;
-
- if (enabledCPUs == numCPUs) thread_wakeup(this);
+
+ // Ensure that the increment is seen by all processors
+ OSIncrementAtomic(&enabledCPUs);
+
+ if (enabledCPUs == numCPUs) thread_wakeup(this);
}
IOReturn IOCPUInterruptController::registerInterrupt(IOService *nub,