]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/pmCPU.c
xnu-1486.2.11.tar.gz
[apple/xnu.git] / osfmk / i386 / pmCPU.c
CommitLineData
0c530ab8 1/*
e2fac8b1 2 * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
0c530ab8 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0c530ab8 5 *
2d21ac55
A
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
0c530ab8 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
0c530ab8
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
0c530ab8 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
0c530ab8
A
27 */
28
29/*
30 * CPU-specific power management support.
31 *
32 * Implements the "wrappers" to the KEXT.
33 */
0c530ab8 34#include <i386/asm.h>
b0d623f7 35#include <i386/machine_cpu.h>
0c530ab8 36#include <i386/mp.h>
b0d623f7 37#include <i386/machine_routines.h>
0c530ab8 38#include <i386/proc_reg.h>
b0d623f7
A
39#include <i386/pmap.h>
40#include <i386/misc_protos.h>
41#include <kern/machine.h>
0c530ab8
A
42#include <kern/pms.h>
43#include <kern/processor.h>
7e4a7d39 44#include <kern/etimer.h>
2d21ac55 45#include <i386/cpu_threads.h>
0c530ab8
A
46#include <i386/pmCPU.h>
47#include <i386/cpuid.h>
48#include <i386/rtclock.h>
593a1d5f 49#include <kern/sched_prim.h>
b0d623f7 50#include <i386/lapic.h>
593a1d5f
A
51
52/*
53 * Kernel parameter determining whether threads are halted unconditionally
54 * in the idle state. This is the default behavior.
55 * See machine_idle() for use.
56 */
57int idlehalt = 1;
0c530ab8
A
58
59extern int disableConsoleOutput;
60
61decl_simple_lock_data(,pm_init_lock);
62
63/*
64 * The following is set when the KEXT loads and initializes.
65 */
66pmDispatch_t *pmDispatch = NULL;
67
2d21ac55
A
68static uint32_t pmInitDone = 0;
69
0c530ab8
A
70
71/*
72 * Initialize the Cstate change code.
73 */
74void
75power_management_init(void)
76{
2d21ac55 77 static boolean_t initialized = FALSE;
0c530ab8
A
78
79 /*
80 * Initialize the lock for the KEXT initialization.
81 */
2d21ac55
A
82 if (!initialized) {
83 simple_lock_init(&pm_init_lock, 0);
84 initialized = TRUE;
85 }
0c530ab8
A
86
87 if (pmDispatch != NULL && pmDispatch->cstateInit != NULL)
88 (*pmDispatch->cstateInit)();
89}
90
0c530ab8 91/*
593a1d5f
A
92 * Called when the CPU is idle. It calls into the power management kext
93 * to determine the best way to idle the CPU.
0c530ab8 94 */
593a1d5f
A
95void
96machine_idle(void)
0c530ab8 97{
593a1d5f 98 cpu_data_t *my_cpu = current_cpu_datap();
0c530ab8 99
593a1d5f
A
100 if (my_cpu == NULL)
101 goto out;
0c530ab8 102
593a1d5f
A
103 /*
104 * If idlehalt isn't set, then don't do any power management related
105 * idle handling.
106 */
107 if (!idlehalt)
108 goto out;
109
110 my_cpu->lcpu.state = LCPU_IDLE;
111 DBGLOG(cpu_handle, cpu_number(), MP_IDLE);
112 MARK_CPU_IDLE(cpu_number());
0c530ab8 113
593a1d5f
A
114 if (pmInitDone
115 && pmDispatch != NULL
116 && pmDispatch->cstateMachineIdle != NULL)
117 (*pmDispatch->cstateMachineIdle)(0x7FFFFFFFFFFFFFFFULL);
118 else {
119 /*
120 * If no power management, re-enable interrupts and halt.
121 * This will keep the CPU from spinning through the scheduler
122 * and will allow at least some minimal power savings (but it
123 * cause problems in some MP configurations w.r.t. the APIC
124 * stopping during a GV3 transition).
125 */
126 __asm__ volatile ("sti; hlt");
0c530ab8 127 }
0c530ab8 128
593a1d5f
A
129 /*
130 * Mark the CPU as running again.
131 */
132 MARK_CPU_ACTIVE(cpu_number());
133 DBGLOG(cpu_handle, cpu_number(), MP_UNIDLE);
134 my_cpu->lcpu.state = LCPU_RUN;
135
136 /*
137 * Re-enable interrupts.
138 */
139 out:
140 __asm__ volatile("sti");
2d21ac55
A
141}
142
143/*
144 * Called when the CPU is to be halted. It will choose the best C-State
145 * to be in.
146 */
147void
148pmCPUHalt(uint32_t reason)
149{
593a1d5f 150 cpu_data_t *cpup = current_cpu_datap();
2d21ac55
A
151
152 switch (reason) {
153 case PM_HALT_DEBUG:
593a1d5f 154 cpup->lcpu.state = LCPU_PAUSE;
2d21ac55
A
155 __asm__ volatile ("wbinvd; hlt");
156 break;
157
158 case PM_HALT_PANIC:
593a1d5f 159 cpup->lcpu.state = LCPU_PAUSE;
2d21ac55
A
160 __asm__ volatile ("cli; wbinvd; hlt");
161 break;
162
163 case PM_HALT_NORMAL:
164 default:
165 __asm__ volatile ("cli");
166
b0d623f7 167 if (pmInitDone
2d21ac55
A
168 && pmDispatch != NULL
169 && pmDispatch->pmCPUHalt != NULL) {
593a1d5f
A
170 /*
171 * Halt the CPU (and put it in a low power state.
172 */
2d21ac55 173 (*pmDispatch->pmCPUHalt)();
2d21ac55 174
593a1d5f
A
175 /*
176 * We've exited halt, so get the the CPU schedulable again.
177 */
178 i386_init_slave_fast();
179
180 panic("init_slave_fast returned");
181 } else {
2d21ac55
A
182 /*
183 * If no power managment and a processor is taken off-line,
184 * then invalidate the cache and halt it (it will not be able
185 * to be brought back on-line without resetting the CPU).
186 */
187 __asm__ volatile ("wbinvd");
593a1d5f 188 cpup->lcpu.state = LCPU_HALT;
2d21ac55 189 __asm__ volatile ( "wbinvd; hlt" );
593a1d5f
A
190
191 panic("back from Halt");
2d21ac55
A
192 }
193 break;
0c530ab8
A
194 }
195}
196
2d21ac55 197void
593a1d5f 198pmMarkAllCPUsOff(void)
2d21ac55 199{
593a1d5f
A
200 if (pmInitDone
201 && pmDispatch != NULL
202 && pmDispatch->markAllCPUsOff != NULL)
203 (*pmDispatch->markAllCPUsOff)();
2d21ac55
A
204}
205
206static void
207pmInitComplete(void)
208{
209 pmInitDone = 1;
210}
211
212static x86_lcpu_t *
213pmGetLogicalCPU(int cpu)
0c530ab8 214{
2d21ac55
A
215 return(cpu_to_lcpu(cpu));
216}
217
218static x86_lcpu_t *
219pmGetMyLogicalCPU(void)
220{
221 cpu_data_t *cpup = current_cpu_datap();
0c530ab8 222
2d21ac55
A
223 return(&cpup->lcpu);
224}
225
226static x86_core_t *
227pmGetCore(int cpu)
228{
229 return(cpu_to_core(cpu));
0c530ab8
A
230}
231
2d21ac55
A
232static x86_core_t *
233pmGetMyCore(void)
0c530ab8 234{
2d21ac55 235 cpu_data_t *cpup = current_cpu_datap();
0c530ab8 236
2d21ac55 237 return(cpup->lcpu.core);
0c530ab8
A
238}
239
593a1d5f
A
240static x86_die_t *
241pmGetDie(int cpu)
242{
243 return(cpu_to_die(cpu));
244}
245
246static x86_die_t *
247pmGetMyDie(void)
248{
249 cpu_data_t *cpup = current_cpu_datap();
250
251 return(cpup->lcpu.die);
252}
253
2d21ac55
A
254static x86_pkg_t *
255pmGetPackage(int cpu)
0c530ab8 256{
2d21ac55
A
257 return(cpu_to_package(cpu));
258}
259
260static x86_pkg_t *
261pmGetMyPackage(void)
262{
263 cpu_data_t *cpup = current_cpu_datap();
264
593a1d5f 265 return(cpup->lcpu.package);
2d21ac55
A
266}
267
268static void
269pmLockCPUTopology(int lock)
270{
271 if (lock) {
272 simple_lock(&x86_topo_lock);
273 } else {
274 simple_unlock(&x86_topo_lock);
275 }
0c530ab8
A
276}
277
278/*
2d21ac55
A
279 * Called to get the next deadline that has been set by the
280 * power management code.
0c530ab8 281 */
2d21ac55
A
282uint64_t
283pmCPUGetDeadline(cpu_data_t *cpu)
284{
285 uint64_t deadline = EndOfAllTime;
0c530ab8 286
b0d623f7 287 if (pmInitDone
2d21ac55
A
288 && pmDispatch != NULL
289 && pmDispatch->GetDeadline != NULL)
290 deadline = (*pmDispatch->GetDeadline)(&cpu->lcpu);
291
292 return(deadline);
0c530ab8
A
293}
294
295/*
2d21ac55
A
296 * Called to determine if the supplied deadline or the power management
297 * deadline is sooner. Returns which ever one is first.
0c530ab8 298 */
2d21ac55
A
299uint64_t
300pmCPUSetDeadline(cpu_data_t *cpu, uint64_t deadline)
0c530ab8 301{
b0d623f7 302 if (pmInitDone
2d21ac55
A
303 && pmDispatch != NULL
304 && pmDispatch->SetDeadline != NULL)
305 deadline = (*pmDispatch->SetDeadline)(&cpu->lcpu, deadline);
306
307 return(deadline);
0c530ab8
A
308}
309
0c530ab8 310/*
2d21ac55 311 * Called when a power management deadline expires.
0c530ab8
A
312 */
313void
2d21ac55 314pmCPUDeadline(cpu_data_t *cpu)
0c530ab8 315{
2d21ac55
A
316 if (pmInitDone
317 && pmDispatch != NULL
318 && pmDispatch->Deadline != NULL)
319 (*pmDispatch->Deadline)(&cpu->lcpu);
320}
321
322/*
323 * Called to get a CPU out of idle.
324 */
325boolean_t
326pmCPUExitIdle(cpu_data_t *cpu)
327{
328 boolean_t do_ipi;
329
330 if (pmInitDone
331 && pmDispatch != NULL
332 && pmDispatch->exitIdle != NULL)
333 do_ipi = (*pmDispatch->exitIdle)(&cpu->lcpu);
334 else
335 do_ipi = TRUE;
336
337 return(do_ipi);
0c530ab8
A
338}
339
593a1d5f
A
340kern_return_t
341pmCPUExitHalt(int cpu)
342{
343 kern_return_t rc = KERN_INVALID_ARGUMENT;
344
345 if (pmInitDone
346 && pmDispatch != NULL
347 && pmDispatch->exitHalt != NULL)
348 rc = pmDispatch->exitHalt(cpu_to_lcpu(cpu));
349
350 return(rc);
351}
352
e2fac8b1
A
353kern_return_t
354pmCPUExitHaltToOff(int cpu)
355{
356 kern_return_t rc = KERN_INVALID_ARGUMENT;
357
358 if (pmInitDone
359 && pmDispatch != NULL
360 && pmDispatch->exitHaltToOff != NULL)
361 rc = pmDispatch->exitHaltToOff(cpu_to_lcpu(cpu));
362
363 return(rc);
364}
365
2d21ac55 366/*
593a1d5f 367 * Called to initialize the power management structures for the CPUs.
2d21ac55 368 */
0c530ab8 369void
593a1d5f 370pmCPUStateInit(void)
0c530ab8 371{
593a1d5f
A
372 if (pmDispatch != NULL && pmDispatch->pmCPUStateInit != NULL)
373 (*pmDispatch->pmCPUStateInit)();
0c530ab8
A
374}
375
2d21ac55 376/*
593a1d5f 377 * Called when a CPU is being restarted after being powered off (as in S3).
2d21ac55 378 */
0c530ab8 379void
593a1d5f 380pmCPUMarkRunning(cpu_data_t *cpu)
0c530ab8 381{
593a1d5f
A
382 cpu_data_t *cpup = current_cpu_datap();
383
2d21ac55
A
384 if (pmInitDone
385 && pmDispatch != NULL
593a1d5f
A
386 && pmDispatch->markCPURunning != NULL)
387 (*pmDispatch->markCPURunning)(&cpu->lcpu);
388 else
389 cpup->lcpu.state = LCPU_RUN;
2d21ac55
A
390}
391
392/*
393 * Called to get/set CPU power management state.
394 */
395int
396pmCPUControl(uint32_t cmd, void *datap)
397{
398 int rc = -1;
399
400 if (pmDispatch != NULL
401 && pmDispatch->pmCPUControl != NULL)
402 rc = (*pmDispatch->pmCPUControl)(cmd, datap);
403
404 return(rc);
0c530ab8
A
405}
406
593a1d5f
A
407/*
408 * Called to save the timer state used by power management prior
409 * to "sleeping".
410 */
411void
412pmTimerSave(void)
413{
414 if (pmDispatch != NULL
415 && pmDispatch->pmTimerStateSave != NULL)
416 (*pmDispatch->pmTimerStateSave)();
417}
418
419/*
420 * Called to restore the timer state used by power management after
421 * waking from "sleep".
422 */
423void
424pmTimerRestore(void)
425{
426 if (pmDispatch != NULL
427 && pmDispatch->pmTimerStateRestore != NULL)
428 (*pmDispatch->pmTimerStateRestore)();
429}
430
2d21ac55
A
431/*
432 * Set the worst-case time for the C4 to C2 transition.
433 * No longer does anything.
434 */
0c530ab8 435void
2d21ac55 436ml_set_maxsnoop(__unused uint32_t maxdelay)
0c530ab8 437{
0c530ab8
A
438}
439
2d21ac55
A
440
441/*
442 * Get the worst-case time for the C4 to C2 transition. Returns nanoseconds.
443 */
444unsigned
445ml_get_maxsnoop(void)
446{
447 uint64_t max_snoop = 0;
448
449 if (pmDispatch != NULL
450 && pmDispatch->getMaxSnoop != NULL)
451 max_snoop = pmDispatch->getMaxSnoop();
452
453 return((unsigned)(max_snoop & 0xffffffff));
454}
455
456
457uint32_t
458ml_get_maxbusdelay(void)
459{
460 uint64_t max_delay = 0;
461
462 if (pmDispatch != NULL
463 && pmDispatch->getMaxBusDelay != NULL)
464 max_delay = pmDispatch->getMaxBusDelay();
465
466 return((uint32_t)(max_delay & 0xffffffff));
467}
468
469/*
470 * Set the maximum delay time allowed for snoop on the bus.
471 *
472 * Note that this value will be compared to the amount of time that it takes
473 * to transition from a non-snooping power state (C4) to a snooping state (C2).
474 * If maxBusDelay is less than C4C2SnoopDelay,
475 * we will not enter the lowest power state.
476 */
0c530ab8 477void
2d21ac55 478ml_set_maxbusdelay(uint32_t mdelay)
0c530ab8 479{
2d21ac55
A
480 uint64_t maxdelay = mdelay;
481
482 if (pmDispatch != NULL
483 && pmDispatch->setMaxBusDelay != NULL)
484 pmDispatch->setMaxBusDelay(maxdelay);
593a1d5f
A
485}
486
487uint64_t
488ml_get_maxintdelay(void)
489{
490 uint64_t max_delay = 0;
491
492 if (pmDispatch != NULL
493 && pmDispatch->getMaxIntDelay != NULL)
494 max_delay = pmDispatch->getMaxIntDelay();
495
496 return(max_delay);
497}
498
499/*
500 * Set the maximum delay allowed for an interrupt.
501 */
502void
503ml_set_maxintdelay(uint64_t mdelay)
504{
505 if (pmDispatch != NULL
506 && pmDispatch->setMaxIntDelay != NULL)
507 pmDispatch->setMaxIntDelay(mdelay);
0c530ab8
A
508}
509
2d21ac55
A
510/*
511 * Put a CPU into "safe" mode with respect to power.
512 *
513 * Some systems cannot operate at a continuous "normal" speed without
514 * exceeding the thermal design. This is called per-CPU to place the
515 * CPUs into a "safe" operating mode.
516 */
0c530ab8 517void
2d21ac55
A
518pmSafeMode(x86_lcpu_t *lcpu, uint32_t flags)
519{
520 if (pmDispatch != NULL
521 && pmDispatch->pmCPUSafeMode != NULL)
522 pmDispatch->pmCPUSafeMode(lcpu, flags);
523 else {
524 /*
525 * Do something reasonable if the KEXT isn't present.
526 *
527 * We only look at the PAUSE and RESUME flags. The other flag(s)
528 * will not make any sense without the KEXT, so just ignore them.
529 *
593a1d5f
A
530 * We set the CPU's state to indicate that it's halted. If this
531 * is the CPU we're currently running on, then spin until the
532 * state becomes non-halted.
2d21ac55
A
533 */
534 if (flags & PM_SAFE_FL_PAUSE) {
593a1d5f 535 lcpu->state = LCPU_PAUSE;
2d21ac55 536 if (lcpu == x86_lcpu()) {
593a1d5f 537 while (lcpu->state == LCPU_PAUSE)
2d21ac55
A
538 cpu_pause();
539 }
540 }
541
542 /*
543 * Clear the halted flag for the specified CPU, that will
544 * get it out of it's spin loop.
545 */
546 if (flags & PM_SAFE_FL_RESUME) {
593a1d5f 547 lcpu->state = LCPU_RUN;
2d21ac55
A
548 }
549 }
550}
551
c910b4d9
A
552static uint32_t saved_run_count = 0;
553
554void
555machine_run_count(uint32_t count)
556{
557 if (pmDispatch != NULL
558 && pmDispatch->pmSetRunCount != NULL)
559 pmDispatch->pmSetRunCount(count);
560 else
561 saved_run_count = count;
562}
563
564boolean_t
565machine_cpu_is_inactive(int cpu)
566{
567 if (pmDispatch != NULL
568 && pmDispatch->pmIsCPUUnAvailable != NULL)
569 return(pmDispatch->pmIsCPUUnAvailable(cpu_to_lcpu(cpu)));
570 else
571 return(FALSE);
572}
573
574static uint32_t
575pmGetSavedRunCount(void)
576{
577 return(saved_run_count);
578}
579
2d21ac55
A
580/*
581 * Returns the root of the package tree.
582 */
583static x86_pkg_t *
584pmGetPkgRoot(void)
585{
586 return(x86_pkgs);
587}
588
589static boolean_t
590pmCPUGetHibernate(int cpu)
0c530ab8 591{
2d21ac55 592 return(cpu_datap(cpu)->cpu_hibernate);
0c530ab8
A
593}
594
2d21ac55
A
595static processor_t
596pmLCPUtoProcessor(int lcpu)
597{
598 return(cpu_datap(lcpu)->cpu_processor);
599}
600
c910b4d9
A
601static void
602pmReSyncDeadlines(int cpu)
603{
604 static boolean_t registered = FALSE;
605
606 if (!registered) {
607 PM_interrupt_register(&etimer_resync_deadlines);
608 registered = TRUE;
609 }
610
611 if ((uint32_t)cpu == current_cpu_datap()->lcpu.cpu_num)
612 etimer_resync_deadlines();
613 else
614 cpu_PM_interrupt(cpu);
615}
616
b0d623f7
A
617static void
618pmSendIPI(int cpu)
619{
620 lapic_send_ipi(cpu, LAPIC_PM_INTERRUPT);
621}
622
7e4a7d39
A
623static rtc_nanotime_t *
624pmGetNanotimeInfo(void)
625{
626 return(&rtc_nanotime_info);
627}
628
2d21ac55
A
629/*
630 * Called by the power management kext to register itself and to get the
631 * callbacks it might need into other kernel functions. This interface
632 * is versioned to allow for slight mis-matches between the kext and the
633 * kernel.
634 */
0c530ab8 635void
2d21ac55
A
636pmKextRegister(uint32_t version, pmDispatch_t *cpuFuncs,
637 pmCallBacks_t *callbacks)
0c530ab8 638{
2d21ac55 639 if (callbacks != NULL && version == PM_DISPATCH_VERSION) {
c910b4d9
A
640 callbacks->setRTCPop = setPop;
641 callbacks->resyncDeadlines = pmReSyncDeadlines;
642 callbacks->initComplete = pmInitComplete;
643 callbacks->GetLCPU = pmGetLogicalCPU;
644 callbacks->GetCore = pmGetCore;
645 callbacks->GetDie = pmGetDie;
646 callbacks->GetPackage = pmGetPackage;
647 callbacks->GetMyLCPU = pmGetMyLogicalCPU;
648 callbacks->GetMyCore = pmGetMyCore;
649 callbacks->GetMyDie = pmGetMyDie;
650 callbacks->GetMyPackage = pmGetMyPackage;
651 callbacks->GetPkgRoot = pmGetPkgRoot;
652 callbacks->LockCPUTopology = pmLockCPUTopology;
653 callbacks->GetHibernate = pmCPUGetHibernate;
654 callbacks->LCPUtoProcessor = pmLCPUtoProcessor;
655 callbacks->ThreadBind = thread_bind;
656 callbacks->GetSavedRunCount = pmGetSavedRunCount;
b0d623f7 657 callbacks->pmSendIPI = pmSendIPI;
7e4a7d39 658 callbacks->GetNanotimeInfo = pmGetNanotimeInfo;
c910b4d9
A
659 callbacks->topoParms = &topoParms;
660 } else {
661 panic("Version mis-match between Kernel and CPU PM");
2d21ac55
A
662 }
663
664 if (cpuFuncs != NULL) {
665 pmDispatch = cpuFuncs;
b0d623f7
A
666
667 if (pmDispatch->pmIPIHandler != NULL) {
668 lapic_set_pm_func((i386_intr_func_t)pmDispatch->pmIPIHandler);
669 }
2d21ac55 670 }
0c530ab8
A
671}
672
2d21ac55
A
673/*
674 * Unregisters the power management functions from the kext.
675 */
0c530ab8 676void
2d21ac55 677pmUnRegister(pmDispatch_t *cpuFuncs)
0c530ab8 678{
2d21ac55
A
679 if (cpuFuncs != NULL && pmDispatch == cpuFuncs) {
680 pmDispatch = NULL;
681 }
0c530ab8 682}
2d21ac55 683
593a1d5f
A
684/******************************************************************************
685 *
686 * All of the following are deprecated interfaces and no longer used.
687 *
688 ******************************************************************************/
689kern_return_t
690pmsControl(__unused uint32_t request, __unused user_addr_t reqaddr,
691 __unused uint32_t reqsize)
692{
693 return(KERN_SUCCESS);
694}
695
696void
697pmsInit(void)
698{
699}
700
701void
702pmsStart(void)
703{
704}
705
706void
707pmsPark(void)
708{
709}
710
711void
712pmsRun(__unused uint32_t nstep)
713{
714}
715
716kern_return_t
717pmsBuild(__unused pmsDef *pd, __unused uint32_t pdsize,
718 __unused pmsSetFunc_t *functab,
719 __unused uint32_t platformData, __unused pmsQueryFunc_t queryFunc)
720{
721 return(KERN_SUCCESS);
722}