]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/pmCPU.c
feba09cac0dfcae3ffe9c6dd0eef7feaf70802fa
[apple/xnu.git] / osfmk / i386 / pmCPU.c
1 /*
2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31 /*
32 * CPU-specific power management support.
33 *
34 * Implements the "wrappers" to the KEXT.
35 */
36 #include <i386/machine_routines.h>
37 #include <i386/machine_cpu.h>
38 #include <i386/misc_protos.h>
39 #include <i386/pmap.h>
40 #include <i386/asm.h>
41 #include <i386/mp.h>
42 #include <i386/proc_reg.h>
43 #include <kern/pms.h>
44 #include <kern/processor.h>
45 #include <i386/pmCPU.h>
46 #include <i386/cpuid.h>
47 #include <i386/rtclock.h>
48 #if MACH_KDB
49 #include <i386/db_machdep.h>
50 #include <ddb/db_aout.h>
51 #include <ddb/db_access.h>
52 #include <ddb/db_sym.h>
53 #include <ddb/db_variables.h>
54 #include <ddb/db_command.h>
55 #include <ddb/db_output.h>
56 #include <ddb/db_expr.h>
57 #endif
58
59 extern int disableConsoleOutput;
60
61 decl_simple_lock_data(,pm_init_lock);
62
63 /*
64 * The following is set when the KEXT loads and initializes.
65 */
66 pmDispatch_t *pmDispatch = NULL;
67
68 /*
69 * Current power management states (for use until KEXT is loaded).
70 */
71 static pmInitState_t pmInitState;
72
73 /*
74 * Nap control variables:
75 */
76 uint32_t napCtl = 0; /* Defaults to neither napping
77 nor halting */
78 uint32_t forcenap = 0; /* Force nap (fn) boot-arg controls */
79 uint32_t maxBusDelay = 0xFFFFFFFF; /* Maximum memory bus delay that
80 I/O devices can tolerate
81 before errors (nanoseconds) */
82 uint32_t C4C2SnoopDelay = 0; /* C4 to C2 transition time -
83 time before a C4 system
84 can snoop (nanoseconds) */
85
86 /*
87 * We are being asked to set PState (sel).
88 */
89 void
90 pmsCPUSet(uint32_t sel)
91 {
92 if (pmDispatch != NULL && pmDispatch->pmsCPUSet != NULL)
93 (*pmDispatch->pmsCPUSet)(sel);
94 else
95 pmInitState.PState = sel;
96 }
97
98 /*
99 * This code configures the initial step tables. It should be called after
100 * the timebase frequency is initialized.
101 *
102 * Note that this is not used in normal operation. It is strictly for
103 * debugging/testing purposes.
104 */
105 void
106 pmsCPUConf(void)
107 {
108
109 if (pmDispatch != NULL && pmDispatch->pmsCPUConf != NULL)
110 (*pmDispatch->pmsCPUConf)();
111 }
112
113 /*
114 * Machine-dependent initialization.
115 */
116 void
117 pmsCPUMachineInit(void)
118 {
119 /*
120 * Initialize some of the initial state to "uninitialized" until
121 * it gets set with something more useful. This allows the KEXT
122 * to determine if the initial value was actually set to something.
123 */
124 pmInitState.PState = -1;
125 pmInitState.PLimit = -1;
126
127 if (pmDispatch != NULL && pmDispatch->pmsCPUMachineInit != NULL)
128 (*pmDispatch->pmsCPUMachineInit)();
129 }
130
131 /*
132 * This function should be called once for each processor to force the
133 * processor to the correct initial voltage and frequency.
134 */
135 void
136 pmsCPUInit(void)
137 {
138 pmsCPUMachineInit();
139 if (pmDispatch != NULL && pmDispatch->pmsCPUInit != NULL)
140 (*pmDispatch->pmsCPUInit)();
141 }
142
143 /*
144 * Broadcast a change to all processing including ourselves.
145 */
146 void
147 pmsCPURun(uint32_t nstep)
148 {
149 if (pmDispatch != NULL && pmDispatch->pmsCPURun != NULL)
150 (*pmDispatch->pmsCPURun)(nstep);
151 }
152
153 /*
154 * Return the current state of a core.
155 */
156 uint32_t
157 pmsCPUQuery(void)
158 {
159 if (pmDispatch != NULL && pmDispatch->pmsCPUQuery != NULL)
160 return((*pmDispatch->pmsCPUQuery)());
161
162 /*
163 * Return a non-sense value.
164 */
165 return((~0) << 16);
166 }
167
168 /*
169 * Return the current state of the package.
170 */
171 uint32_t
172 pmsCPUPackageQuery(void)
173 {
174 if (pmDispatch != NULL && pmDispatch->pmsCPUPackageQuery != NULL)
175 return((*pmDispatch->pmsCPUPackageQuery)());
176
177 /*
178 * Return a non-sense value.
179 */
180 return((~0) << 16);
181 }
182
183 /*
184 * Force the CPU package to the lowest power level. This is a low-level
185 * interface meant to be called from the panic or debugger code to bring
186 * the CPU to a safe power level for unmanaged operation.
187 *
188 * Note that while this will bring an entire package to a safe level, it
189 * cannot affect other packages. As a general rule, this should be run on
190 * every code as part of entering the debugger or on the panic path.
191 */
192 void
193 pmsCPUYellowFlag(void)
194 {
195 if (pmDispatch != NULL && pmDispatch->pmsCPUYellowFlag != NULL)
196 (*pmDispatch->pmsCPUYellowFlag)();
197 }
198
199 /*
200 * Restore the CPU to the power state it was in before a yellow flag.
201 */
202 void
203 pmsCPUGreenFlag(void)
204 {
205 if (pmDispatch != NULL && pmDispatch->pmsCPUGreenFlag != NULL)
206 (*pmDispatch->pmsCPUGreenFlag)();
207 }
208
209 /*
210 * Load a new ratio/VID table.
211 *
212 * Note that this interface is specific to the Intel SpeedStep implementation.
213 * It is expected that this will only be called once to override the default
214 * ratio/VID table when the platform starts.
215 *
216 * Normally, the table will need to be replaced at the same time that the
217 * stepper program proper is replaced, as the PState indices from an old
218 * program may no longer be valid. When replacing the default program this
219 * should not be a problem as any new table will have at least two PState
220 * entries and the default program only references P0 and P1.
221 */
222 kern_return_t
223 pmsCPULoadVIDTable(uint16_t *tablep, int nstates)
224 {
225 if (pmDispatch != NULL && pmDispatch->pmsCPULoadVIDTable != NULL)
226 return((*pmDispatch->pmsCPULoadVIDTable)(tablep, nstates));
227 else {
228 int i;
229
230 if (nstates > MAX_PSTATES)
231 return(KERN_FAILURE);
232
233 for (i = 0; i < nstates; i += 1)
234 pmInitState.VIDTable[i] = tablep[i];
235 }
236 return(KERN_SUCCESS);
237 }
238
239 /*
240 * Set the (global) PState limit. CPUs will not be permitted to run at
241 * a lower (more performant) PState than this.
242 */
243 kern_return_t
244 pmsCPUSetPStateLimit(uint32_t limit)
245 {
246 if (pmDispatch != NULL && pmDispatch->pmsCPUSetPStateLimit != NULL)
247 return((*pmDispatch->pmsCPUSetPStateLimit)(limit));
248
249 pmInitState.PLimit = limit;
250 return(KERN_SUCCESS);
251 }
252
253 /*
254 * Initialize the Cstate change code.
255 */
256 void
257 power_management_init(void)
258 {
259 uint32_t cpuModel;
260 uint32_t cpuFamily;
261 uint32_t xcpuid[4];
262
263 /*
264 * Initialize the lock for the KEXT initialization.
265 */
266 simple_lock_init(&pm_init_lock, 0);
267
268 /*
269 * XXX
270 *
271 * The following is a hack to disable power management on some systems
272 * until the KEXT is done. This is strictly temporary!!!
273 */
274 do_cpuid(1, xcpuid);
275 cpuFamily = (xcpuid[eax] >> 8) & 0xf;
276 cpuModel = (xcpuid[eax] >> 4) & 0xf;
277
278 if (cpuFamily != 0x6 || cpuModel < 0xe)
279 pmDispatch = NULL;
280
281 if (pmDispatch != NULL && pmDispatch->cstateInit != NULL)
282 (*pmDispatch->cstateInit)();
283 }
284
285 /*
286 * This function will update the system nap policy. It should be called
287 * whenever conditions change: when the system is ready to being napping
288 * and if something changes the rules (e.g. a sysctl altering the policy
289 * for debugging).
290 */
291 void
292 machine_nap_policy(void)
293 {
294 if (pmDispatch != NULL && pmDispatch->cstateNapPolicy != NULL)
295 napCtl = (*pmDispatch->cstateNapPolicy)(forcenap, napCtl);
296 }
297
298 /*
299 * ACPI calls the following routine to set/update mwait hints. A table
300 * (possibly null) specifies the available Cstates and their hints, all
301 * other states are assumed to be invalid. ACPI may update available
302 * states to change the nap policy (for example, while AC power is
303 * available).
304 */
305 kern_return_t
306 Cstate_table_set(Cstate_hint_t *tablep, unsigned int nstates)
307 {
308 if (forcenap)
309 return(KERN_SUCCESS);
310
311 if (pmDispatch != NULL && pmDispatch->cstateTableSet != NULL)
312 return((*pmDispatch->cstateTableSet)(tablep, nstates));
313 else {
314 unsigned int i;
315
316 for (i = 0; i < nstates; i += 1) {
317 pmInitState.CStates[i].number = tablep[i].number;
318 pmInitState.CStates[i].hint = tablep[i].hint;
319 }
320
321 pmInitState.CStatesCount = nstates;
322 }
323 return(KERN_SUCCESS);
324 }
325
326 static inline void
327 sti(void) {
328 __asm__ volatile ( "sti" : : : "memory");
329 }
330
331 /*
332 * Called when the CPU is idle. It will choose the best C state to
333 * be in.
334 */
335 void
336 machine_idle_cstate(void)
337 {
338 if (pmDispatch != NULL && pmDispatch->cstateMachineIdle != NULL)
339 (*pmDispatch->cstateMachineIdle)(napCtl);
340 else {
341 sti();
342 }
343 }
344
345 static pmStats_t *
346 pmsCPUStats(void)
347 {
348 cpu_data_t *pp;
349
350 pp = current_cpu_datap();
351 return(&pp->cpu_pmStats);
352 }
353
354 static pmsd *
355 pmsCPUStepperData(void)
356 {
357 cpu_data_t *pp;
358
359 pp = current_cpu_datap();
360 return(&pp->pms);
361 }
362
363 static uint64_t *
364 CPUHPETAddr(void)
365 {
366 cpu_data_t *pp;
367 pp = current_cpu_datap();
368 return(pp->cpu_pmHpet);
369 }
370
371 /*
372 * Called by the power management kext to register itself and to get the
373 * callbacks it might need into other power management functions.
374 */
375 void
376 pmRegister(pmDispatch_t *cpuFuncs, pmCallBacks_t *callbacks)
377 {
378 if (callbacks != NULL) {
379 callbacks->Park = pmsPark;
380 callbacks->Run = pmsRun;
381 callbacks->RunLocal = pmsRunLocal;
382 callbacks->SetStep = pmsSetStep;
383 callbacks->NapPolicy = machine_nap_policy;
384 callbacks->Build = pmsBuild;
385 callbacks->Stats = pmsCPUStats;
386 callbacks->StepperData = pmsCPUStepperData;
387 callbacks->HPETAddr = CPUHPETAddr;
388 callbacks->InitState = &pmInitState;
389 callbacks->resetPop = resetPop;
390 }
391
392 if (cpuFuncs != NULL)
393 pmDispatch = cpuFuncs;
394 }
395
396 /*
397 * Unregisters the power management functions from the kext.
398 */
399 void
400 pmUnRegister(pmDispatch_t *cpuFuncs)
401 {
402 if (cpuFuncs != NULL && pmDispatch == cpuFuncs)
403 pmDispatch = NULL;
404 }
405
406 #if MACH_KDB
407 /*
408 * XXX stubs for now
409 */
410 void
411 db_cfg(__unused db_expr_t addr,
412 __unused int have_addr,
413 __unused db_expr_t count,
414 __unused char *modif)
415 {
416 return;
417 }
418
419 void
420 db_display_iokit(__unused db_expr_t addr,
421 __unused int have_addr,
422 __unused db_expr_t count,
423 __unused char *modif)
424 {
425 return;
426 }
427
428 void
429 db_dtimers(__unused db_expr_t addr,
430 __unused int have_addr,
431 __unused db_expr_t count,
432 __unused char *modif)
433 {
434 return;
435 }
436
437 void
438 db_intcnt(__unused db_expr_t addr,
439 __unused int have_addr,
440 __unused db_expr_t count,
441 __unused char *modif)
442 {
443 return;
444 }
445
446 void
447 db_nap(__unused db_expr_t addr,
448 __unused int have_addr,
449 __unused db_expr_t count,
450 __unused char *modif)
451 {
452 return;
453 }
454
455 void
456 db_pmgr(__unused db_expr_t addr,
457 __unused int have_addr,
458 __unused db_expr_t count,
459 __unused char *modif)
460 {
461 return;
462 }
463
464 void
465 db_test(__unused db_expr_t addr,
466 __unused int have_addr,
467 __unused db_expr_t count,
468 __unused char *modif)
469 {
470 return;
471 }
472
473 void
474 db_getpmgr(__unused pmData_t *pmj)
475 {
476 }
477 #endif