xref: /xnu-8020.140.41/osfmk/arm/cpu.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 2007-2016 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_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 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.
14  *
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
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  *	File:	arm/cpu.c
30  *
31  *	cpu specific routines
32  */
33 
34 #include <kern/kalloc.h>
35 #include <kern/machine.h>
36 #include <kern/cpu_number.h>
37 #include <kern/percpu.h>
38 #include <kern/thread.h>
39 #include <kern/timer_queue.h>
40 #include <arm/cpu_data.h>
41 #include <arm/cpuid.h>
42 #include <arm/caches_internal.h>
43 #include <arm/cpu_data_internal.h>
44 #include <arm/cpu_internal.h>
45 #include <arm/misc_protos.h>
46 #include <arm/machine_cpu.h>
47 #include <arm/rtclock.h>
48 #include <arm/proc_reg.h>
49 #include <mach/processor_info.h>
50 #include <vm/pmap.h>
51 #include <vm/vm_kern.h>
52 #include <vm/vm_map.h>
53 #include <pexpert/arm/board_config.h>
54 #include <pexpert/arm/protos.h>
55 #include <sys/kdebug.h>
56 
57 #include <machine/atomic.h>
58 
59 #if KPC
60 #include <kern/kpc.h>
61 #endif
62 
63 extern unsigned int resume_idle_cpu;
64 extern unsigned int start_cpu;
65 
66 unsigned int   start_cpu_paddr;
67 
68 extern boolean_t        idle_enable;
69 extern unsigned int     real_ncpus;
70 extern uint64_t         wake_abstime;
71 
72 extern void* wfi_inst;
73 unsigned wfi_fast = 1;
74 unsigned patch_to_nop = 0xe1a00000;
75 
76 void    *LowExceptionVectorsAddr;
77 #define IOS_STATE               (((vm_offset_t)LowExceptionVectorsAddr + 0x80))
78 #define IOS_STATE_SIZE  (0x08UL)
79 static const uint8_t suspend_signature[] = {'X', 'S', 'O', 'M', 'P', 'S', 'U', 'S'};
80 static const uint8_t running_signature[] = {'X', 'S', 'O', 'M', 'N', 'N', 'U', 'R'};
81 
82 /*
83  *	Routine:	cpu_bootstrap
84  *	Function:
85  */
86 void
cpu_bootstrap(void)87 cpu_bootstrap(void)
88 {
89 }
90 
91 
92 /*
93  *	Routine:	cpu_sleep
94  *	Function:
95  */
96 void
cpu_sleep(void)97 cpu_sleep(void)
98 {
99 	cpu_data_t     *cpu_data_ptr = getCpuDatap();
100 	cpu_data_ptr->cpu_active_thread = current_thread();
101 	cpu_data_ptr->cpu_reset_handler = (vm_offset_t) start_cpu_paddr;
102 	cpu_data_ptr->cpu_flags |= SleepState;
103 
104 	if (cpu_data_ptr->cpu_user_debug != NULL) {
105 		arm_debug_set(NULL);
106 	}
107 
108 	CleanPoC_Dcache();
109 
110 	PE_cpu_machine_quiesce(cpu_data_ptr->cpu_id);
111 }
112 
113 _Atomic uint32_t cpu_idle_count = 0;
114 
115 /*
116  *	Routine:	cpu_idle
117  *	Function:
118  */
119 void __attribute__((noreturn))
cpu_idle(void)120 cpu_idle(void)
121 {
122 	cpu_data_t     *cpu_data_ptr = getCpuDatap();
123 	uint64_t        new_idle_timeout_ticks = 0x0ULL, lastPop;
124 
125 	if ((!idle_enable) || (cpu_data_ptr->cpu_signal & SIGPdisabled)) {
126 		Idle_load_context();
127 	}
128 	if (!SetIdlePop()) {
129 		Idle_load_context();
130 	}
131 	lastPop = cpu_data_ptr->rtcPop;
132 
133 	cpu_data_ptr->cpu_active_thread = current_thread();
134 
135 	if (cpu_data_ptr->cpu_idle_notify != NULL) {
136 		cpu_data_ptr->cpu_idle_notify(cpu_data_ptr->cpu_id, TRUE, &new_idle_timeout_ticks);
137 	}
138 
139 	if (cpu_data_ptr->idle_timer_notify != 0) {
140 		if (new_idle_timeout_ticks == 0x0ULL) {
141 			/* turn off the idle timer */
142 			cpu_data_ptr->idle_timer_deadline = 0x0ULL;
143 		} else {
144 			/* set the new idle timeout */
145 			clock_absolutetime_interval_to_deadline(new_idle_timeout_ticks, &cpu_data_ptr->idle_timer_deadline);
146 		}
147 		timer_resync_deadlines();
148 		if (cpu_data_ptr->rtcPop != lastPop) {
149 			/*
150 			 * Ignore the return value here: this CPU has called idle_notify and
151 			 * committed to going idle.
152 			 */
153 			SetIdlePop();
154 		}
155 	}
156 
157 #if KPC
158 	kpc_idle();
159 #endif /* KPC */
160 
161 	platform_cache_idle_enter();
162 	cpu_idle_wfi((boolean_t) wfi_fast);
163 	platform_cache_idle_exit();
164 
165 	ClearIdlePop(TRUE);
166 	cpu_idle_exit(FALSE);
167 }
168 
169 /*
170  *	Routine:	cpu_idle_exit
171  *	Function:
172  */
173 void
cpu_idle_exit(boolean_t from_reset __unused)174 cpu_idle_exit(boolean_t from_reset __unused)
175 {
176 	uint64_t        new_idle_timeout_ticks = 0x0ULL;
177 	cpu_data_t     *cpu_data_ptr = getCpuDatap();
178 
179 #if KPC
180 	kpc_idle_exit();
181 #endif
182 	if (cpu_data_ptr->cpu_idle_notify != NULL) {
183 		cpu_data_ptr->cpu_idle_notify(cpu_data_ptr->cpu_id, FALSE, &new_idle_timeout_ticks);
184 	}
185 
186 	if (cpu_data_ptr->idle_timer_notify != 0) {
187 		if (new_idle_timeout_ticks == 0x0ULL) {
188 			/* turn off the idle timer */
189 			cpu_data_ptr->idle_timer_deadline = 0x0ULL;
190 		} else {
191 			/* set the new idle timeout */
192 			clock_absolutetime_interval_to_deadline(new_idle_timeout_ticks, &cpu_data_ptr->idle_timer_deadline);
193 		}
194 		timer_resync_deadlines();
195 	}
196 
197 	Idle_load_context();
198 }
199 
200 void
cpu_init(void)201 cpu_init(void)
202 {
203 	cpu_data_t     *cdp = getCpuDatap();
204 	arm_cpu_info_t *cpu_info_p;
205 
206 	if (cdp->cpu_type != CPU_TYPE_ARM) {
207 		cdp->cpu_type = CPU_TYPE_ARM;
208 
209 		timer_call_queue_init(&cdp->rtclock_timer.queue);
210 		cdp->rtclock_timer.deadline = EndOfAllTime;
211 
212 		if (cdp == &BootCpuData) {
213 			do_cpuid();
214 			do_mvfpid();
215 		} else {
216 			/*
217 			 * We initialize non-boot CPUs here; the boot CPU is
218 			 * dealt with as part of pmap_bootstrap.
219 			 */
220 			pmap_cpu_data_init();
221 		}
222 
223 		do_cacheid();
224 
225 		/* ARM_SMP: Assuming identical cpu */
226 		do_debugid();
227 
228 		cpu_info_p = cpuid_info();
229 
230 		/* switch based on CPU's reported architecture */
231 		switch (cpu_info_p->arm_info.arm_arch) {
232 		case CPU_ARCH_ARMv4T:
233 		case CPU_ARCH_ARMv5T:
234 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V4T;
235 			break;
236 		case CPU_ARCH_ARMv5TE:
237 		case CPU_ARCH_ARMv5TEJ:
238 			if (cpu_info_p->arm_info.arm_implementor == CPU_VID_INTEL) {
239 				cdp->cpu_subtype = CPU_SUBTYPE_ARM_XSCALE;
240 			} else {
241 				cdp->cpu_subtype = CPU_SUBTYPE_ARM_V5TEJ;
242 			}
243 			break;
244 		case CPU_ARCH_ARMv6:
245 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V6;
246 			break;
247 		case CPU_ARCH_ARMv7:
248 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7;
249 			break;
250 		case CPU_ARCH_ARMv7f:
251 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7F;
252 			break;
253 		case CPU_ARCH_ARMv7s:
254 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7S;
255 			break;
256 		case CPU_ARCH_ARMv7k:
257 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7K;
258 			break;
259 		default:
260 			cdp->cpu_subtype = CPU_SUBTYPE_ARM_ALL;
261 			break;
262 		}
263 
264 		cdp->cpu_threadtype = CPU_THREADTYPE_NONE;
265 	}
266 	cdp->cpu_stat.irq_ex_cnt_wake = 0;
267 	cdp->cpu_stat.ipi_cnt_wake = 0;
268 	cdp->cpu_running = TRUE;
269 	cdp->cpu_sleep_token_last = cdp->cpu_sleep_token;
270 	cdp->cpu_sleep_token = 0x0UL;
271 }
272 
273 void
cpu_stack_alloc(cpu_data_t * cpu_data_ptr)274 cpu_stack_alloc(cpu_data_t *cpu_data_ptr)
275 {
276 	vm_offset_t             irq_stack = 0;
277 	vm_offset_t             fiq_stack = 0;
278 
279 	kern_return_t kr = kernel_memory_allocate(kernel_map, &irq_stack,
280 	    INTSTACK_SIZE + (2 * PAGE_SIZE),
281 	    PAGE_MASK,
282 	    KMA_GUARD_FIRST | KMA_GUARD_LAST | KMA_KSTACK | KMA_KOBJECT,
283 	    VM_KERN_MEMORY_STACK);
284 	if (kr != KERN_SUCCESS) {
285 		panic("Unable to allocate cpu interrupt stack");
286 	}
287 
288 	cpu_data_ptr->intstack_top = irq_stack + PAGE_SIZE + INTSTACK_SIZE;
289 	cpu_data_ptr->istackptr = cpu_data_ptr->intstack_top;
290 
291 	kr = kernel_memory_allocate(kernel_map, &fiq_stack,
292 	    FIQSTACK_SIZE + (2 * PAGE_SIZE),
293 	    PAGE_MASK,
294 	    KMA_GUARD_FIRST | KMA_GUARD_LAST | KMA_KSTACK | KMA_KOBJECT,
295 	    VM_KERN_MEMORY_STACK);
296 	if (kr != KERN_SUCCESS) {
297 		panic("Unable to allocate cpu exception stack");
298 	}
299 
300 	cpu_data_ptr->fiqstack_top = fiq_stack + PAGE_SIZE + FIQSTACK_SIZE;
301 	cpu_data_ptr->fiqstackptr = cpu_data_ptr->fiqstack_top;
302 }
303 
304 void
cpu_data_free(cpu_data_t * cpu_data_ptr)305 cpu_data_free(cpu_data_t *cpu_data_ptr)
306 {
307 	if ((cpu_data_ptr == NULL) || (cpu_data_ptr == &BootCpuData)) {
308 		return;
309 	}
310 
311 	int cpu_number = cpu_data_ptr->cpu_number;
312 
313 	if (CpuDataEntries[cpu_number].cpu_data_vaddr == cpu_data_ptr) {
314 		OSDecrementAtomic((SInt32*)&real_ncpus);
315 		CpuDataEntries[cpu_number].cpu_data_vaddr = NULL;
316 		CpuDataEntries[cpu_number].cpu_data_paddr = 0;
317 		__builtin_arm_dmb(DMB_ISH); // Ensure prior stores to cpu array are visible
318 	}
319 	kmem_free(kernel_map,
320 	    cpu_data_ptr->intstack_top - INTSTACK_SIZE - PAGE_SIZE,
321 	    INTSTACK_SIZE + 2 * PAGE_SIZE);
322 	kmem_free(kernel_map,
323 	    cpu_data_ptr->fiqstack_top - FIQSTACK_SIZE - PAGE_SIZE,
324 	    FIQSTACK_SIZE + 2 * PAGE_SIZE);
325 }
326 
327 void
cpu_data_init(cpu_data_t * cpu_data_ptr)328 cpu_data_init(cpu_data_t *cpu_data_ptr)
329 {
330 	cpu_data_ptr->cpu_flags = 0;
331 #if     __arm__
332 	cpu_data_ptr->cpu_exc_vectors = (vm_offset_t)&ExceptionVectorsTable;
333 #endif
334 	cpu_data_ptr->cpu_int_state = 0;
335 	cpu_data_ptr->cpu_pending_ast = AST_NONE;
336 	cpu_data_ptr->cpu_cache_dispatch = NULL;
337 	cpu_data_ptr->rtcPop = EndOfAllTime;
338 	cpu_data_ptr->rtclock_datap = &RTClockData;
339 	cpu_data_ptr->cpu_user_debug = NULL;
340 	cpu_data_ptr->cpu_base_timebase_low = 0;
341 	cpu_data_ptr->cpu_base_timebase_high = 0;
342 	cpu_data_ptr->cpu_idle_notify = NULL;
343 	cpu_data_ptr->cpu_idle_latency = 0x0ULL;
344 	cpu_data_ptr->cpu_idle_pop = 0x0ULL;
345 	cpu_data_ptr->cpu_reset_type = 0x0UL;
346 	cpu_data_ptr->cpu_reset_handler = 0x0UL;
347 	cpu_data_ptr->cpu_reset_assist = 0x0UL;
348 	cpu_data_ptr->cpu_regmap_paddr = 0x0ULL;
349 	cpu_data_ptr->cpu_phys_id = 0x0UL;
350 	cpu_data_ptr->cpu_l2_access_penalty = 0;
351 	cpu_data_ptr->cpu_cluster_type = CLUSTER_TYPE_SMP;
352 	cpu_data_ptr->cpu_cluster_id = 0;
353 	cpu_data_ptr->cpu_l2_id = 0;
354 	cpu_data_ptr->cpu_l2_size = 0;
355 	cpu_data_ptr->cpu_l3_id = 0;
356 	cpu_data_ptr->cpu_l3_size = 0;
357 
358 	cpu_data_ptr->cpu_signal = SIGPdisabled;
359 
360 	cpu_data_ptr->cpu_get_fiq_handler = NULL;
361 	cpu_data_ptr->cpu_tbd_hardware_addr = NULL;
362 	cpu_data_ptr->cpu_tbd_hardware_val = NULL;
363 	cpu_data_ptr->cpu_get_decrementer_func = NULL;
364 	cpu_data_ptr->cpu_set_decrementer_func = NULL;
365 	cpu_data_ptr->cpu_sleep_token = ARM_CPU_ON_SLEEP_PATH;
366 	cpu_data_ptr->cpu_sleep_token_last = 0x00000000UL;
367 	cpu_data_ptr->cpu_xcall_p0 = NULL;
368 	cpu_data_ptr->cpu_xcall_p1 = NULL;
369 	cpu_data_ptr->cpu_imm_xcall_p0 = NULL;
370 	cpu_data_ptr->cpu_imm_xcall_p1 = NULL;
371 
372 #if     defined(ARMA7)
373 	cpu_data_ptr->cpu_CLWFlush_req = 0x0ULL;
374 	cpu_data_ptr->cpu_CLWFlush_last = 0x0ULL;
375 	cpu_data_ptr->cpu_CLWClean_req = 0x0ULL;
376 	cpu_data_ptr->cpu_CLWClean_last = 0x0ULL;
377 	cpu_data_ptr->cpu_CLW_active = 0x1UL;
378 #endif
379 
380 #if !XNU_MONITOR
381 	pmap_cpu_data_t * pmap_cpu_data_ptr = &cpu_data_ptr->cpu_pmap_cpu_data;
382 
383 	pmap_cpu_data_ptr->cpu_user_pmap = (struct pmap *) NULL;
384 	pmap_cpu_data_ptr->cpu_user_pmap_stamp = 0;
385 	pmap_cpu_data_ptr->cpu_number = PMAP_INVALID_CPU_NUM;
386 
387 	bzero(&(pmap_cpu_data_ptr->cpu_sw_asids[0]), sizeof(pmap_cpu_data_ptr->cpu_sw_asids));
388 #endif
389 	cpu_data_ptr->halt_status = CPU_NOT_HALTED;
390 }
391 
392 kern_return_t
cpu_data_register(cpu_data_t * cpu_data_ptr)393 cpu_data_register(cpu_data_t *cpu_data_ptr)
394 {
395 	int cpu;
396 
397 	cpu = OSIncrementAtomic((SInt32*)&real_ncpus);
398 	if (real_ncpus > ml_get_cpu_count()) {
399 		return KERN_FAILURE;
400 	}
401 
402 	cpu_data_ptr->cpu_number = cpu;
403 	__builtin_arm_dmb(DMB_ISH); // Ensure prior stores to cpu data are visible
404 	CpuDataEntries[cpu].cpu_data_vaddr = cpu_data_ptr;
405 	CpuDataEntries[cpu].cpu_data_paddr = (void *)ml_vtophys((vm_offset_t)cpu_data_ptr);
406 	return KERN_SUCCESS;
407 }
408 
409 kern_return_t
cpu_start(int cpu)410 cpu_start(int cpu)
411 {
412 	kprintf("cpu_start() cpu: %d\n", cpu);
413 	if (cpu == cpu_number()) {
414 		cpu_machine_init();
415 		return KERN_SUCCESS;
416 	} else {
417 		cpu_data_t      *cpu_data_ptr;
418 		thread_t        first_thread;
419 		processor_t     processor;
420 
421 		cpu_data_ptr = CpuDataEntries[cpu].cpu_data_vaddr;
422 		cpu_data_ptr->cpu_reset_handler = (vm_offset_t) start_cpu_paddr;
423 
424 #if !XNU_MONITOR
425 		cpu_data_ptr->cpu_pmap_cpu_data.cpu_user_pmap = NULL;
426 #endif
427 
428 		processor = PERCPU_GET_RELATIVE(processor, cpu_data, cpu_data_ptr);
429 		if (processor->startup_thread != THREAD_NULL) {
430 			first_thread = processor->startup_thread;
431 		} else {
432 			first_thread = processor->idle_thread;
433 		}
434 		cpu_data_ptr->cpu_active_thread = first_thread;
435 		first_thread->machine.CpuDatap = cpu_data_ptr;
436 		first_thread->machine.pcpu_data_base =
437 		    (vm_address_t)cpu_data_ptr - __PERCPU_ADDR(cpu_data);
438 
439 		flush_dcache((vm_offset_t)&CpuDataEntries[cpu], sizeof(cpu_data_entry_t), FALSE);
440 		flush_dcache((vm_offset_t)cpu_data_ptr, sizeof(cpu_data_t), FALSE);
441 		(void) PE_cpu_start(cpu_data_ptr->cpu_id, (vm_offset_t)NULL, (vm_offset_t)NULL);
442 		return KERN_SUCCESS;
443 	}
444 }
445 
446 void
cpu_timebase_init(boolean_t from_boot __unused)447 cpu_timebase_init(boolean_t from_boot __unused)
448 {
449 	cpu_data_t *cdp = getCpuDatap();
450 
451 	if (cdp->cpu_get_fiq_handler == NULL) {
452 		cdp->cpu_get_fiq_handler = rtclock_timebase_func.tbd_fiq_handler;
453 		cdp->cpu_get_decrementer_func = rtclock_timebase_func.tbd_get_decrementer;
454 		cdp->cpu_set_decrementer_func = rtclock_timebase_func.tbd_set_decrementer;
455 		cdp->cpu_tbd_hardware_addr = (void *)rtclock_timebase_addr;
456 		cdp->cpu_tbd_hardware_val = (void *)rtclock_timebase_val;
457 	}
458 	cdp->cpu_decrementer = 0x7FFFFFFFUL;
459 	cdp->cpu_timebase_low = 0x0UL;
460 	cdp->cpu_timebase_high = 0x0UL;
461 
462 #if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
463 	/* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
464 	 * are 32-bit. */
465 	cdp->cpu_base_timebase_low = rtclock_base_abstime_low;
466 	cdp->cpu_base_timebase_high = rtclock_base_abstime_high;
467 #else
468 	*((uint64_t *) &cdp->cpu_base_timebase_low) = rtclock_base_abstime;
469 #endif
470 }
471 
472 
473 __attribute__((noreturn))
474 void
ml_arm_sleep(void)475 ml_arm_sleep(void)
476 {
477 	cpu_data_t     *cpu_data_ptr = getCpuDatap();
478 
479 	if (cpu_data_ptr == &BootCpuData) {
480 		cpu_data_t      *target_cdp;
481 		unsigned int    cpu;
482 
483 		const unsigned int max_cpu_id = ml_get_max_cpu_number();
484 		for (cpu = 0; cpu <= max_cpu_id; cpu++) {
485 			target_cdp = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
486 			if (target_cdp == (cpu_data_t *)NULL) {
487 				break;
488 			}
489 
490 			if (target_cdp == cpu_data_ptr) {
491 				continue;
492 			}
493 
494 			while (target_cdp->cpu_sleep_token != ARM_CPU_ON_SLEEP_PATH) {
495 				;
496 			}
497 		}
498 
499 		/* Now that the other cores have entered the sleep path, set
500 		 * the abstime fixup we'll use when we resume.*/
501 		rtclock_base_abstime = ml_get_timebase();
502 		wake_abstime = rtclock_base_abstime;
503 	} else {
504 		platform_cache_disable();
505 		CleanPoU_Dcache();
506 	}
507 	cpu_data_ptr->cpu_sleep_token = ARM_CPU_ON_SLEEP_PATH;
508 #if     defined(ARMA7)
509 	cpu_data_ptr->cpu_CLWFlush_req = 0;
510 	cpu_data_ptr->cpu_CLWClean_req = 0;
511 	__builtin_arm_dmb(DMB_ISH);
512 	cpu_data_ptr->cpu_CLW_active = 0;
513 #endif
514 	if (cpu_data_ptr == &BootCpuData) {
515 		platform_cache_disable();
516 		platform_cache_shutdown();
517 		bcopy((const void *)suspend_signature, (void *)(IOS_STATE), IOS_STATE_SIZE);
518 	} else {
519 		CleanPoC_DcacheRegion((vm_offset_t) cpu_data_ptr, sizeof(cpu_data_t));
520 	}
521 
522 	__builtin_arm_dsb(DSB_SY);
523 	while (TRUE) {
524 		__builtin_arm_wfe();
525 	} /* Spin */
526 }
527 
528 TUNABLE(unsigned int, wfi, "wfi", 1);
529 
530 void
cpu_machine_idle_init(boolean_t from_boot)531 cpu_machine_idle_init(boolean_t from_boot)
532 {
533 	static const unsigned int       *BootArgs_paddr = (unsigned int *)NULL;
534 	static const unsigned int       *CpuDataEntries_paddr = (unsigned int *)NULL;
535 	static unsigned int             resume_idle_cpu_paddr = (unsigned int)NULL;
536 	cpu_data_t                      *cpu_data_ptr = getCpuDatap();
537 
538 	if (from_boot) {
539 		unsigned int    jtag = 0;
540 
541 		if (PE_parse_boot_argn("jtag", &jtag, sizeof(jtag))) {
542 			if (jtag != 0) {
543 				idle_enable = FALSE;
544 			} else {
545 				idle_enable = TRUE;
546 			}
547 		} else {
548 			idle_enable = TRUE;
549 		}
550 
551 		if (wfi == 0) {
552 			bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&patch_to_nop),
553 			    (addr64_t)ml_static_vtop((vm_offset_t)&wfi_inst), sizeof(unsigned));
554 		}
555 		if (wfi == 2) {
556 			wfi_fast = 0;
557 		}
558 
559 		LowExceptionVectorsAddr = (void *)ml_io_map(ml_vtophys((vm_offset_t)gPhysBase), PAGE_SIZE);
560 
561 		/* Copy Exception Vectors low, but don't touch the sleep token */
562 		bcopy((void *)&ExceptionLowVectorsBase, (void *)LowExceptionVectorsAddr, 0x90);
563 		bcopy(((void *)(((vm_offset_t)&ExceptionLowVectorsBase) + 0xA0)), ((void *)(((vm_offset_t)LowExceptionVectorsAddr) + 0xA0)), ARM_PGBYTES - 0xA0);
564 
565 		start_cpu_paddr = ml_static_vtop((vm_offset_t)&start_cpu);
566 
567 		BootArgs_paddr = (unsigned int *)ml_static_vtop((vm_offset_t)BootArgs);
568 		bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&BootArgs_paddr),
569 		    (addr64_t)((unsigned int)(gPhysBase) +
570 		    ((unsigned int)&(ResetHandlerData.boot_args) - (unsigned int)&ExceptionLowVectorsBase)),
571 		    4);
572 
573 		CpuDataEntries_paddr = (unsigned int *)ml_static_vtop((vm_offset_t)CpuDataEntries);
574 		bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&CpuDataEntries_paddr),
575 		    (addr64_t)((unsigned int)(gPhysBase) +
576 		    ((unsigned int)&(ResetHandlerData.cpu_data_entries) - (unsigned int)&ExceptionLowVectorsBase)),
577 		    4);
578 
579 		CleanPoC_DcacheRegion((vm_offset_t) phystokv(gPhysBase), PAGE_SIZE);
580 
581 		resume_idle_cpu_paddr = (unsigned int)ml_static_vtop((vm_offset_t)&resume_idle_cpu);
582 	}
583 
584 	if (cpu_data_ptr == &BootCpuData) {
585 		bcopy(((const void *)running_signature), (void *)(IOS_STATE), IOS_STATE_SIZE);
586 	}
587 	;
588 
589 	cpu_data_ptr->cpu_reset_handler = resume_idle_cpu_paddr;
590 	clean_dcache((vm_offset_t)cpu_data_ptr, sizeof(cpu_data_t), FALSE);
591 }
592 
593 void
machine_track_platform_idle(boolean_t entry)594 machine_track_platform_idle(boolean_t entry)
595 {
596 	if (entry) {
597 		os_atomic_inc(&cpu_idle_count, relaxed);
598 	} else {
599 		os_atomic_dec(&cpu_idle_count, relaxed);
600 	}
601 }
602