]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/pmCPU.c
xnu-1504.3.12.tar.gz
[apple/xnu.git] / osfmk / i386 / pmCPU.c
index d2efc8bc9bf03cf7b08296da4861342d5c10e7d2..0efbb917c4609c40fa58e420d71e24afee2cda19 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  *
  * Implements the "wrappers" to the KEXT.
  */
-#include <kern/machine.h>
-#include <i386/machine_routines.h>
-#include <i386/machine_cpu.h>
-#include <i386/misc_protos.h>
-#include <i386/pmap.h>
 #include <i386/asm.h>
+#include <i386/machine_cpu.h>
 #include <i386/mp.h>
+#include <i386/machine_routines.h>
 #include <i386/proc_reg.h>
+#include <i386/pmap.h>
+#include <i386/misc_protos.h>
+#include <kern/machine.h>
 #include <kern/pms.h>
 #include <kern/processor.h>
+#include <kern/etimer.h>
 #include <i386/cpu_threads.h>
 #include <i386/pmCPU.h>
 #include <i386/cpuid.h>
 #include <i386/rtclock.h>
 #include <kern/sched_prim.h>
+#include <i386/lapic.h>
 
 /*
  * Kernel parameter determining whether threads are halted unconditionally
@@ -111,8 +113,8 @@ machine_idle(void)
 
     if (pmInitDone
        && pmDispatch != NULL
-       && pmDispatch->cstateMachineIdle != NULL)
-       (*pmDispatch->cstateMachineIdle)(0x7FFFFFFFFFFFFFFFULL);
+       && pmDispatch->MachineIdle != NULL)
+       (*pmDispatch->MachineIdle)(0x7FFFFFFFFFFFFFFFULL);
     else {
        /*
         * If no power management, re-enable interrupts and halt.
@@ -162,7 +164,7 @@ pmCPUHalt(uint32_t reason)
     default:
        __asm__ volatile ("cli");
 
-       if (pmInitDone
+    if (pmInitDone
            && pmDispatch != NULL
            && pmDispatch->pmCPUHalt != NULL) {
            /*
@@ -282,7 +284,7 @@ pmCPUGetDeadline(cpu_data_t *cpu)
 {
     uint64_t   deadline        = EndOfAllTime;
 
-    if (pmInitDone
+       if (pmInitDone
        && pmDispatch != NULL
        && pmDispatch->GetDeadline != NULL)
        deadline = (*pmDispatch->GetDeadline)(&cpu->lcpu);
@@ -297,7 +299,7 @@ pmCPUGetDeadline(cpu_data_t *cpu)
 uint64_t
 pmCPUSetDeadline(cpu_data_t *cpu, uint64_t deadline)
 {
-    if (pmInitDone
+   if (pmInitDone
        && pmDispatch != NULL
        && pmDispatch->SetDeadline != NULL)
        deadline = (*pmDispatch->SetDeadline)(&cpu->lcpu, deadline);
@@ -348,6 +350,19 @@ pmCPUExitHalt(int cpu)
     return(rc);
 }
 
+kern_return_t
+pmCPUExitHaltToOff(int cpu)
+{
+    kern_return_t      rc      = KERN_INVALID_ARGUMENT;
+
+    if (pmInitDone
+       && pmDispatch != NULL
+       && pmDispatch->exitHaltToOff != NULL)
+       rc = pmDispatch->exitHaltToOff(cpu_to_lcpu(cpu));
+
+    return(rc);
+}
+
 /*
  * Called to initialize the power management structures for the CPUs.
  */
@@ -534,6 +549,73 @@ pmSafeMode(x86_lcpu_t *lcpu, uint32_t flags)
     }
 }
 
+static uint32_t                saved_run_count = 0;
+
+void
+machine_run_count(uint32_t count)
+{
+    if (pmDispatch != NULL
+       && pmDispatch->pmSetRunCount != NULL)
+       pmDispatch->pmSetRunCount(count);
+    else
+       saved_run_count = count;
+}
+
+boolean_t
+machine_processor_is_inactive(processor_t processor)
+{
+    int                cpu = processor->cpu_id;
+
+    if (pmDispatch != NULL
+       && pmDispatch->pmIsCPUUnAvailable != NULL)
+       return(pmDispatch->pmIsCPUUnAvailable(cpu_to_lcpu(cpu)));
+    else
+       return(FALSE);
+}
+
+processor_t
+machine_choose_processor(processor_set_t pset,
+                        processor_t preferred)
+{
+    int                startCPU;
+    int                endCPU;
+    int                preferredCPU;
+    int                chosenCPU;
+
+    if (!pmInitDone)
+       return(preferred);
+
+    if (pset == NULL) {
+       startCPU = -1;
+       endCPU = -1;
+    } else {
+       startCPU = pset->cpu_set_low;
+       endCPU = pset->cpu_set_hi;
+    }
+
+    if (preferred == NULL)
+       preferredCPU = -1;
+    else
+       preferredCPU = preferred->cpu_id;
+
+    if (pmDispatch != NULL
+       && pmDispatch->pmChooseCPU != NULL) {
+       chosenCPU = pmDispatch->pmChooseCPU(startCPU, endCPU, preferredCPU);
+
+       if (chosenCPU == -1)
+           return(NULL);
+       return(cpu_datap(chosenCPU)->cpu_processor);
+    }
+
+    return(preferred);
+}
+
+static uint32_t
+pmGetSavedRunCount(void)
+{
+    return(saved_run_count);
+}
+
 /*
  * Returns the root of the package tree.
  */
@@ -555,6 +637,34 @@ pmLCPUtoProcessor(int lcpu)
     return(cpu_datap(lcpu)->cpu_processor);
 }
 
+static void
+pmReSyncDeadlines(int cpu)
+{
+    static boolean_t   registered      = FALSE;
+
+    if (!registered) {
+       PM_interrupt_register(&etimer_resync_deadlines);
+       registered = TRUE;
+    }
+
+    if ((uint32_t)cpu == current_cpu_datap()->lcpu.cpu_num)
+       etimer_resync_deadlines();
+    else
+       cpu_PM_interrupt(cpu);
+}
+
+static void
+pmSendIPI(int cpu)
+{
+    lapic_send_ipi(cpu, LAPIC_PM_INTERRUPT);
+}
+
+static rtc_nanotime_t *
+pmGetNanotimeInfo(void)
+{
+    return(&rtc_nanotime_info);
+}
+
 /*
  * Called by the power management kext to register itself and to get the
  * callbacks it might need into other kernel functions.  This interface
@@ -566,27 +676,36 @@ pmKextRegister(uint32_t version, pmDispatch_t *cpuFuncs,
               pmCallBacks_t *callbacks)
 {
     if (callbacks != NULL && version == PM_DISPATCH_VERSION) {
-       callbacks->setRTCPop   = setPop;
-       callbacks->resyncDeadlines = etimer_resync_deadlines;
-       callbacks->initComplete= pmInitComplete;
-       callbacks->GetLCPU     = pmGetLogicalCPU;
-       callbacks->GetCore     = pmGetCore;
-       callbacks->GetDie      = pmGetDie;
-       callbacks->GetPackage  = pmGetPackage;
-       callbacks->GetMyLCPU   = pmGetMyLogicalCPU;
-       callbacks->GetMyCore   = pmGetMyCore;
-       callbacks->GetMyDie    = pmGetMyDie;
-       callbacks->GetMyPackage= pmGetMyPackage;
-       callbacks->GetPkgRoot  = pmGetPkgRoot;
-       callbacks->LockCPUTopology = pmLockCPUTopology;
-       callbacks->GetHibernate    = pmCPUGetHibernate;
-       callbacks->LCPUtoProcessor = pmLCPUtoProcessor;
-       callbacks->ThreadBind      = thread_bind;
-       callbacks->topoParms       = &topoParms;
+       callbacks->setRTCPop            = setPop;
+       callbacks->resyncDeadlines      = pmReSyncDeadlines;
+       callbacks->initComplete         = pmInitComplete;
+       callbacks->GetLCPU              = pmGetLogicalCPU;
+       callbacks->GetCore              = pmGetCore;
+       callbacks->GetDie               = pmGetDie;
+       callbacks->GetPackage           = pmGetPackage;
+       callbacks->GetMyLCPU            = pmGetMyLogicalCPU;
+       callbacks->GetMyCore            = pmGetMyCore;
+       callbacks->GetMyDie             = pmGetMyDie;
+       callbacks->GetMyPackage         = pmGetMyPackage;
+       callbacks->GetPkgRoot           = pmGetPkgRoot;
+       callbacks->LockCPUTopology      = pmLockCPUTopology;
+       callbacks->GetHibernate         = pmCPUGetHibernate;
+       callbacks->LCPUtoProcessor      = pmLCPUtoProcessor;
+       callbacks->ThreadBind           = thread_bind;
+       callbacks->GetSavedRunCount     = pmGetSavedRunCount;
+       callbacks->pmSendIPI            = pmSendIPI;
+       callbacks->GetNanotimeInfo      = pmGetNanotimeInfo;
+       callbacks->topoParms            = &topoParms;
+    } else {
+       panic("Version mis-match between Kernel and CPU PM");
     }
 
     if (cpuFuncs != NULL) {
        pmDispatch = cpuFuncs;
+
+       if (pmDispatch->pmIPIHandler != NULL) {
+           lapic_set_pm_func((i386_intr_func_t)pmDispatch->pmIPIHandler);
+       }
     }
 }