]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOCPU.cpp
xnu-3247.1.106.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCPU.cpp
index 00504e9ebaf1da9f9ed2e964c5ffdf509a083e93..47a17b5a110a396aa9a1fb5ae2723c8d80312e36 100644 (file)
@@ -66,80 +66,35 @@ struct iocpu_platform_action_entry
 };
 typedef struct iocpu_platform_action_entry iocpu_platform_action_entry_t;
 
-queue_head_t * 
-iocpu_get_platform_quiesce_queue(void);
-
-queue_head_t * 
-iocpu_get_platform_active_queue(void);
-
-void
-iocpu_platform_cpu_action_init(queue_head_t * quiesce_queue, queue_head_t * init_queue);
-
-void
-iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry_t * entry);
-
-void
-iocpu_remove_platform_action(iocpu_platform_action_entry_t * entry);
-
-kern_return_t
-iocpu_run_platform_actions(queue_head_t * queue, uint32_t first_priority, uint32_t last_priority,
-                                       void * param1, void * param2, void * param3);
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #define kBootCPUNumber  0
 
-static iocpu_platform_action_entry_t * gIOAllActionsQueue;
-static queue_head_t gIOSleepActionQueue;
-static queue_head_t gIOWakeActionQueue;
-
-static queue_head_t iocpu_quiesce_queue;
-static queue_head_t iocpu_active_queue;
-
-static queue_head_t gIOHaltRestartActionQueue;
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void 
-iocpu_platform_cpu_action_init(queue_head_t * quiesce_queue, __unused queue_head_t * init_queue)
+enum
 {
-#if 0
-    enum { kNumQuiesceActions = 2 };
-    static iocpu_platform_action_entry_t quiesce_actions[kNumQuiesceActions] = 
-    {
-       { { NULL, NULL }, (iocpu_platform_action_t) &clean_mmu_dcache, 97000, 0, 0, NULL },    
-       { { NULL, NULL }, (iocpu_platform_action_t) &arm_sleep, 99000, 0, 0, NULL },    
-    };
-    unsigned int idx;
+    kQueueSleep       = 0,
+    kQueueWake        = 1,
+    kQueueQuiesce     = 2,
+    kQueueActive      = 3,
+    kQueueHaltRestart = 4,
+    kQueuePanic       = 5,
+    kQueueCount       = 6
+};
 
-    for (idx = 0; idx < kNumQuiesceActions; idx++)
-       iocpu_add_platform_action(quiesce_queue, &quiesce_actions[idx]);
-#endif
-}
+const OSSymbol *               gIOPlatformSleepActionKey;
+const OSSymbol *               gIOPlatformWakeActionKey;
+const OSSymbol *               gIOPlatformQuiesceActionKey;
+const OSSymbol *               gIOPlatformActiveActionKey;
+const OSSymbol *               gIOPlatformHaltRestartActionKey;
+const OSSymbol *               gIOPlatformPanicActionKey;
 
-queue_head_t * iocpu_get_platform_quiesce_queue(void)
-{
-    if (!iocpu_quiesce_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_quiesce_queue);
-}
+static queue_head_t            gActionQueues[kQueueCount];
+static const OSSymbol *                gActionSymbols[kQueueCount];
 
-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);
-}
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-void iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry_t * entry)
+static void
+iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry_t * entry)
 {
     iocpu_platform_action_entry_t * next;
 
@@ -154,12 +109,13 @@ void iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry
     queue_enter(queue, entry, iocpu_platform_action_entry_t *, link);  // at tail
 }
 
-void iocpu_remove_platform_action(iocpu_platform_action_entry_t * entry)
+static void
+iocpu_remove_platform_action(iocpu_platform_action_entry_t * entry)
 {
     remque(&entry->link);
 }
 
-kern_return_t
+static kern_return_t
 iocpu_run_platform_actions(queue_head_t * queue, uint32_t first_priority, uint32_t last_priority,
                                        void * param1, void * param2, void * param3)
 {
@@ -186,17 +142,33 @@ iocpu_run_platform_actions(queue_head_t * queue, uint32_t first_priority, uint32
 extern "C" kern_return_t 
 IOCPURunPlatformQuiesceActions(void)
 {
-    return (iocpu_run_platform_actions(iocpu_get_platform_quiesce_queue(), 0, 0U-1,
+    return (iocpu_run_platform_actions(&gActionQueues[kQueueQuiesce], 0, 0U-1,
                                    NULL, NULL, NULL));
 }
 
 extern "C" kern_return_t 
 IOCPURunPlatformActiveActions(void)
 {
-    return (iocpu_run_platform_actions(iocpu_get_platform_active_queue(), 0, 0U-1,
+    return (iocpu_run_platform_actions(&gActionQueues[kQueueActive], 0, 0U-1,
                                    NULL, NULL, NULL));
 }
 
+extern "C" kern_return_t 
+IOCPURunPlatformHaltRestartActions(uint32_t message)
+{
+    return (iocpu_run_platform_actions(&gActionQueues[kQueueHaltRestart], 0, 0U-1,
+                                    (void *)(uintptr_t) message, NULL, NULL));
+}
+
+extern "C" kern_return_t 
+IOCPURunPlatformPanicActions(uint32_t message)
+{
+    return (iocpu_run_platform_actions(&gActionQueues[kQueuePanic], 0, 0U-1,
+                                    (void *)(uintptr_t) message, NULL, NULL));
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
 static kern_return_t 
 IOServicePlatformAction(void * refcon0, void * refcon1, uint32_t priority,
                          void * param1, void * param2, void * param3,
@@ -215,17 +187,39 @@ IOServicePlatformAction(void * refcon0, void * refcon1, uint32_t priority,
 }
 
 static void
-IOInstallServicePlatformAction(IOService * service, 
-                               const OSSymbol * key, queue_head_t * queue,
-                               bool reverse)
+IOInstallServicePlatformAction(IOService * service, uint32_t qidx)
 {
-    OSNumber * num;
     iocpu_platform_action_entry_t * entry;
-    uint32_t priority;
+    OSNumber *       num;
+    uint32_t         priority;
+    const OSSymbol * key = gActionSymbols[qidx]; 
+    queue_head_t *   queue = &gActionQueues[qidx];
+    bool             reverse;
+    bool             uniq;
 
     num = OSDynamicCast(OSNumber, service->getProperty(key));
-    if (!num)
-       return;
+    if (!num) return;
+
+    reverse = false;
+    uniq    = false;
+    switch (qidx)
+    {
+       case kQueueWake:
+       case kQueueActive:
+           reverse = true;
+           break;
+       case kQueueHaltRestart:
+       case kQueuePanic:
+           uniq = true;
+           break;
+    }
+    if (uniq)
+    {
+       queue_iterate(queue, entry, iocpu_platform_action_entry_t *, link)
+       {
+           if (service == entry->refcon0) return;
+       }
+    }
 
     entry = IONew(iocpu_platform_action_entry_t, 1);
     entry->action = &IOServicePlatformAction;
@@ -239,49 +233,66 @@ IOInstallServicePlatformAction(IOService * service,
     entry->refcon1 = (void *) key;
 
     iocpu_add_platform_action(queue, entry);
-    entry->alloc_list = gIOAllActionsQueue;
-    gIOAllActionsQueue = entry;
 }
 
-extern "C" kern_return_t 
-IOCPURunPlatformHaltRestartActions(uint32_t message)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+IOCPUInitialize(void)
 {
-    kern_return_t       ret;
-    IORegistryIterator * iter;
-    OSOrderedSet *       all;
-    IOService *          service;
+    for (uint32_t qidx = kQueueSleep; qidx < kQueueCount; qidx++)
+    {
+       queue_init(&gActionQueues[qidx]);
+    }
+
+    gIOPlatformSleepActionKey       = gActionSymbols[kQueueSleep]
+       = OSSymbol::withCStringNoCopy(kIOPlatformSleepActionKey);
+    gIOPlatformWakeActionKey        = gActionSymbols[kQueueWake]
+       = OSSymbol::withCStringNoCopy(kIOPlatformWakeActionKey);
+    gIOPlatformQuiesceActionKey             = gActionSymbols[kQueueQuiesce]
+       = OSSymbol::withCStringNoCopy(kIOPlatformQuiesceActionKey);
+    gIOPlatformActiveActionKey      = gActionSymbols[kQueueActive]
+       = OSSymbol::withCStringNoCopy(kIOPlatformActiveActionKey);
+    gIOPlatformHaltRestartActionKey  = gActionSymbols[kQueueHaltRestart]
+       = OSSymbol::withCStringNoCopy(kIOPlatformHaltRestartActionKey);
+    gIOPlatformPanicActionKey = gActionSymbols[kQueuePanic]
+       = OSSymbol::withCStringNoCopy(kIOPlatformPanicActionKey);
+}
+
+IOReturn
+IOInstallServicePlatformActions(IOService * service)
+{
+    IOInstallServicePlatformAction(service, kQueueHaltRestart);
+    IOInstallServicePlatformAction(service, kQueuePanic);
+
+    return (kIOReturnSuccess);
+}
 
-    if (!gIOHaltRestartActionQueue.next)
+IOReturn
+IORemoveServicePlatformActions(IOService * service)
+{
+    iocpu_platform_action_entry_t * entry;
+    iocpu_platform_action_entry_t * next;
+
+    for (uint32_t qidx = kQueueSleep; qidx < kQueueCount; qidx++)
     {
-       queue_init(&gIOHaltRestartActionQueue);
-       iter = IORegistryIterator::iterateOver(gIOServicePlane,
-                                               kIORegistryIterateRecursively);
-       if (iter)
+       next = (typeof(entry)) queue_first(&gActionQueues[qidx]);
+       while (!queue_end(&gActionQueues[qidx], &next->link))
        {
-           all = 0;
-           do 
+           entry = next;
+           next = (typeof(entry)) queue_next(&entry->link);
+           if (service == entry->refcon0)
            {
-               if (all) all->release();
-               all = iter->iterateAll();
+               iocpu_remove_platform_action(entry);
+               IODelete(entry, iocpu_platform_action_entry_t, 1);
            }
-           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);
+
+    return (kIOReturnSuccess);
 }
 
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 kern_return_t PE_cpu_start(cpu_id_t target,
@@ -308,6 +319,22 @@ void PE_cpu_signal(cpu_id_t source, cpu_id_t target)
   if (sourceCPU && targetCPU) sourceCPU->signalCPU(targetCPU);
 }
 
+void PE_cpu_signal_deferred(cpu_id_t source, cpu_id_t target)
+{
+  IOCPU *sourceCPU = OSDynamicCast(IOCPU, (OSObject *)source);
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+
+  if (sourceCPU && targetCPU) sourceCPU->signalCPUDeferred(targetCPU);
+}
+
+void PE_cpu_signal_cancel(cpu_id_t source, cpu_id_t target)
+{
+  IOCPU *sourceCPU = OSDynamicCast(IOCPU, (OSObject *)source);
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+
+  if (sourceCPU && targetCPU) sourceCPU->signalCPUCancel(targetCPU);
+}
+
 void PE_cpu_machine_init(cpu_id_t target, boolean_t bootb)
 {
   IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
@@ -358,10 +385,6 @@ void IOCPUSleepKernel(void)
 
     rootDomain->tracePoint( kIOPMTracePointSleepPlatformActions );
 
-    queue_init(&gIOSleepActionQueue);
-    queue_init(&gIOWakeActionQueue);
-    queue_init(&gIOHaltRestartActionQueue);
-
     iter = IORegistryIterator::iterateOver( gIOServicePlane,
                                            kIORegistryIterateRecursively );
     if( iter)
@@ -380,18 +403,17 @@ void IOCPUSleepKernel(void)
        {
            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);
+               for (uint32_t qidx = kQueueSleep; qidx <= kQueueActive; qidx++)
+               {
+                   IOInstallServicePlatformAction(service, qidx);
+               }
                all->removeObject(service);
            }
            all->release();
        }       
     }
 
-    iocpu_run_platform_actions(&gIOSleepActionQueue, 0, 0U-1,
+    iocpu_run_platform_actions(&gActionQueues[kQueueSleep], 0, 0U-1,
                                NULL, NULL, NULL);
 
     rootDomain->tracePoint( kIOPMTracePointSleepCPUs );
@@ -423,22 +445,20 @@ void IOCPUSleepKernel(void)
 
     rootDomain->tracePoint( kIOPMTracePointWakePlatformActions );
 
-    iocpu_run_platform_actions(&gIOWakeActionQueue, 0, 0U-1,
+    iocpu_run_platform_actions(&gActionQueues[kQueueWake], 0, 0U-1,
                                    NULL, NULL, NULL);
 
     iocpu_platform_action_entry_t * entry;
-    while ((entry = gIOAllActionsQueue))
+    for (uint32_t qidx = kQueueSleep; qidx <= kQueueActive; qidx++)
     {
-       gIOAllActionsQueue = entry->alloc_list;
-       iocpu_remove_platform_action(entry);
-       IODelete(entry, iocpu_platform_action_entry_t, 1);
+       while (!(queue_empty(&gActionQueues[qidx])))
+       {
+           entry = (typeof(entry)) queue_first(&gActionQueues[qidx]);
+           iocpu_remove_platform_action(entry);
+           IODelete(entry, iocpu_platform_action_entry_t, 1);
+       }
     }
 
-    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.
@@ -556,6 +576,7 @@ bool IOCPU::serializeProperties(OSSerialize *serialize) const
 {
        bool result;
        OSDictionary *dict = dictionaryWithProperties();
+       if (!dict) return false;
        dict->setObject(gIOCPUStateKey, gIOCPUStateNames[_cpuState]);
        result = dict->serialize(serialize);
        dict->release();  
@@ -587,6 +608,20 @@ void IOCPU::signalCPU(IOCPU */*target*/)
 {
 }
 
+void IOCPU::signalCPUDeferred(IOCPU *target)
+{
+  // Our CPU may not support deferred IPIs,
+  // so send a regular IPI by default
+  signalCPU(target);
+}
+
+void IOCPU::signalCPUCancel(IOCPU */*target*/)
+{
+  // Meant to cancel signals sent by
+  // signalCPUDeferred; unsupported
+  // by default
+}
+
 void IOCPU::enableCPUTimeBase(bool /*enable*/)
 {
 }
@@ -734,7 +769,10 @@ void IOCPUInterruptController::enableCPUInterrupt(IOCPU *cpu)
        // Ensure that the increment is seen by all processors
        OSIncrementAtomic(&enabledCPUs);
 
-       if (enabledCPUs == numCPUs) thread_wakeup(this);
+       if (enabledCPUs == numCPUs) {
+    IOService::cpusRunning();
+    thread_wakeup(this);
+  }
 }
 
 IOReturn IOCPUInterruptController::registerInterrupt(IOService *nub,