X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/593a1d5fd87cdf5b46dd5fcb84467b432cea0f91..0b4c1975fb5e4eccf1012a35081f7e7799b81046:/osfmk/i386/pmCPU.c diff --git a/osfmk/i386/pmCPU.c b/osfmk/i386/pmCPU.c index d2efc8bc9..91e3799bb 100644 --- a/osfmk/i386/pmCPU.c +++ b/osfmk/i386/pmCPU.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2008 Apple Inc. All rights reserved. + * Copyright (c) 2004-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -31,28 +31,23 @@ * * Implements the "wrappers" to the KEXT. */ -#include -#include -#include -#include -#include #include +#include #include +#include #include +#include +#include +#include #include #include +#include #include #include #include #include #include - -/* - * Kernel parameter determining whether threads are halted unconditionally - * in the idle state. This is the default behavior. - * See machine_idle() for use. - */ -int idlehalt = 1; +#include extern int disableConsoleOutput; @@ -98,21 +93,14 @@ machine_idle(void) if (my_cpu == NULL) goto out; - /* - * If idlehalt isn't set, then don't do any power management related - * idle handling. - */ - if (!idlehalt) - goto out; - my_cpu->lcpu.state = LCPU_IDLE; DBGLOG(cpu_handle, cpu_number(), MP_IDLE); MARK_CPU_IDLE(cpu_number()); 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 +150,7 @@ pmCPUHalt(uint32_t reason) default: __asm__ volatile ("cli"); - if (pmInitDone + if (pmInitDone && pmDispatch != NULL && pmDispatch->pmCPUHalt != NULL) { /* @@ -282,7 +270,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 +285,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 +336,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 +535,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 +623,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 +662,37 @@ 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->RTCClockAdjust = rtc_clock_adjust; + 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); + } } }