]>
Commit | Line | Data |
---|---|---|
5ba3f43e A |
1 | /* |
2 | * Copyright (c) 2007-2009 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 | * @OSF_COPYRIGHT@ | |
30 | */ | |
31 | ||
32 | #include <debug.h> | |
33 | #include <mach_ldebug.h> | |
34 | #include <mach_kdp.h> | |
35 | ||
36 | #include <kern/misc_protos.h> | |
37 | #include <kern/thread.h> | |
38 | #include <kern/timer_queue.h> | |
39 | #include <kern/processor.h> | |
40 | #include <kern/startup.h> | |
41 | #include <kern/debug.h> | |
42 | #include <prng/random.h> | |
43 | #include <machine/machine_routines.h> | |
44 | #include <machine/commpage.h> | |
45 | /* ARM64_TODO unify boot.h */ | |
46 | #if __arm64__ | |
47 | #include <pexpert/arm64/boot.h> | |
48 | #elif __arm__ | |
49 | #include <pexpert/arm/boot.h> | |
50 | #else | |
51 | #error Unsupported arch | |
52 | #endif | |
53 | #include <pexpert/arm/consistent_debug.h> | |
54 | #include <pexpert/device_tree.h> | |
55 | #include <arm/proc_reg.h> | |
56 | #include <arm/pmap.h> | |
57 | #include <arm/caches_internal.h> | |
58 | #include <arm/cpu_internal.h> | |
59 | #include <arm/cpu_data_internal.h> | |
60 | #include <arm/misc_protos.h> | |
61 | #include <arm/machine_cpu.h> | |
62 | #include <arm/rtclock.h> | |
63 | #include <vm/vm_map.h> | |
64 | ||
65 | #include <libkern/kernel_mach_header.h> | |
66 | #include <libkern/stack_protector.h> | |
67 | #include <libkern/section_keywords.h> | |
68 | #include <san/kasan.h> | |
69 | ||
70 | #include <pexpert/pexpert.h> | |
71 | ||
72 | #include <console/serial_protos.h> | |
73 | ||
74 | #if CONFIG_TELEMETRY | |
75 | #include <kern/telemetry.h> | |
76 | #endif | |
77 | #if MONOTONIC | |
78 | #include <kern/monotonic.h> | |
79 | #endif /* MONOTONIC */ | |
80 | ||
0a7de745 A |
81 | extern void patch_low_glo(void); |
82 | extern int serial_init(void); | |
5ba3f43e A |
83 | extern void sleep_token_buffer_init(void); |
84 | ||
85 | extern vm_offset_t intstack_top; | |
5ba3f43e A |
86 | #if __arm64__ |
87 | extern vm_offset_t excepstack_top; | |
cb323159 | 88 | extern uint64_t events_per_sec; |
d9a64523 A |
89 | #else |
90 | extern vm_offset_t fiqstack_top; | |
5ba3f43e A |
91 | #endif |
92 | ||
93 | extern const char version[]; | |
94 | extern const char version_variant[]; | |
95 | extern int disableConsoleOutput; | |
96 | ||
5ba3f43e A |
97 | int pc_trace_buf[PC_TRACE_BUF_SIZE] = {0}; |
98 | int pc_trace_cnt = PC_TRACE_BUF_SIZE; | |
99 | int debug_task; | |
100 | ||
101 | boolean_t up_style_idle_exit = 0; | |
102 | ||
103 | ||
c6bf4f31 A |
104 | #if HAS_NEX_PG |
105 | uint32_t nex_pg = 1; | |
106 | extern void set_nex_pg(void); | |
107 | #endif | |
5ba3f43e | 108 | |
c6bf4f31 A |
109 | #if HAS_BP_RET |
110 | /* Enable both branch target retention (0x2) and branch direction retention (0x1) across sleep */ | |
111 | uint32_t bp_ret = 3; | |
112 | extern void set_bp_ret(void); | |
113 | #endif | |
cb323159 | 114 | |
5ba3f43e A |
115 | #if INTERRUPT_MASKED_DEBUG |
116 | boolean_t interrupt_masked_debug = 1; | |
117 | uint64_t interrupt_masked_timeout = 0xd0000; | |
118 | #endif | |
119 | ||
120 | boot_args const_boot_args __attribute__((section("__DATA, __const"))); | |
121 | boot_args *BootArgs __attribute__((section("__DATA, __const"))); | |
122 | ||
123 | unsigned int arm_diag; | |
0a7de745 | 124 | #ifdef APPLETYPHOON |
5ba3f43e A |
125 | static unsigned cpus_defeatures = 0x0; |
126 | extern void cpu_defeatures_set(unsigned int); | |
127 | #endif | |
128 | ||
129 | #if __arm64__ && __ARM_GLOBAL_SLEEP_BIT__ | |
130 | extern volatile boolean_t arm64_stall_sleep; | |
131 | #endif | |
132 | ||
133 | extern boolean_t force_immediate_debug_halt; | |
134 | ||
5ba3f43e A |
135 | /* |
136 | * Forward definition | |
137 | */ | |
138 | void arm_init(boot_args * args); | |
139 | ||
140 | #if __arm64__ | |
0a7de745 | 141 | unsigned int page_shift_user32; /* for page_size as seen by a 32-bit task */ |
5ba3f43e A |
142 | #endif /* __arm64__ */ |
143 | ||
144 | ||
d9a64523 A |
145 | /* |
146 | * JOP rebasing | |
147 | */ | |
148 | ||
cb323159 A |
149 | #if defined(HAS_APPLE_PAC) |
150 | #include <ptrauth.h> | |
151 | #endif /* defined(HAS_APPLE_PAC) */ | |
d9a64523 A |
152 | |
153 | // Note, the following should come from a header from dyld | |
154 | static void | |
155 | rebase_chain(uintptr_t chainStartAddress, uint64_t stepMultiplier, uintptr_t baseAddress __unused, uint64_t slide) | |
156 | { | |
157 | uint64_t delta = 0; | |
158 | uintptr_t address = chainStartAddress; | |
159 | do { | |
160 | uint64_t value = *(uint64_t*)address; | |
161 | ||
cb323159 A |
162 | #if HAS_APPLE_PAC |
163 | uint16_t diversity = (uint16_t)(value >> 32); | |
164 | bool hasAddressDiversity = (value & (1ULL << 48)) != 0; | |
165 | ptrauth_key key = (ptrauth_key)((value >> 49) & 0x3); | |
166 | #endif | |
d9a64523 A |
167 | bool isAuthenticated = (value & (1ULL << 63)) != 0; |
168 | bool isRebase = (value & (1ULL << 62)) == 0; | |
169 | if (isRebase) { | |
170 | if (isAuthenticated) { | |
171 | // The new value for a rebase is the low 32-bits of the threaded value plus the slide. | |
172 | uint64_t newValue = (value & 0xFFFFFFFF) + slide; | |
173 | // Add in the offset from the mach_header | |
174 | newValue += baseAddress; | |
cb323159 A |
175 | #if HAS_APPLE_PAC |
176 | // We have bits to merge in to the discriminator | |
177 | uintptr_t discriminator = diversity; | |
178 | if (hasAddressDiversity) { | |
179 | // First calculate a new discriminator using the address of where we are trying to store the value | |
180 | // Only blend if we have a discriminator | |
181 | if (discriminator) { | |
182 | discriminator = __builtin_ptrauth_blend_discriminator((void*)address, discriminator); | |
183 | } else { | |
184 | discriminator = address; | |
185 | } | |
186 | } | |
187 | switch (key) { | |
188 | case ptrauth_key_asia: | |
189 | newValue = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)newValue, ptrauth_key_asia, discriminator); | |
190 | break; | |
191 | case ptrauth_key_asib: | |
192 | newValue = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)newValue, ptrauth_key_asib, discriminator); | |
193 | break; | |
194 | case ptrauth_key_asda: | |
195 | newValue = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)newValue, ptrauth_key_asda, discriminator); | |
196 | break; | |
197 | case ptrauth_key_asdb: | |
198 | newValue = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)newValue, ptrauth_key_asdb, discriminator); | |
199 | break; | |
200 | } | |
201 | #endif | |
d9a64523 | 202 | *(uint64_t*)address = newValue; |
0a7de745 | 203 | } else { |
d9a64523 A |
204 | // Regular pointer which needs to fit in 51-bits of value. |
205 | // C++ RTTI uses the top bit, so we'll allow the whole top-byte | |
206 | // and the bottom 43-bits to be fit in to 51-bits. | |
207 | uint64_t top8Bits = value & 0x0007F80000000000ULL; | |
208 | uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL; | |
0a7de745 | 209 | uint64_t targetValue = (top8Bits << 13) | (((intptr_t)(bottom43Bits << 21) >> 21) & 0x00FFFFFFFFFFFFFF); |
d9a64523 A |
210 | targetValue = targetValue + slide; |
211 | *(uint64_t*)address = targetValue; | |
212 | } | |
213 | } | |
214 | ||
215 | // The delta is bits [51..61] | |
216 | // And bit 62 is to tell us if we are a rebase (0) or bind (1) | |
217 | value &= ~(1ULL << 62); | |
0a7de745 | 218 | delta = (value & 0x3FF8000000000000) >> 51; |
d9a64523 | 219 | address += delta * stepMultiplier; |
0a7de745 | 220 | } while (delta != 0); |
d9a64523 A |
221 | } |
222 | ||
223 | // Note, the following method should come from a header from dyld | |
224 | static bool | |
225 | rebase_threaded_starts(uint32_t *threadArrayStart, uint32_t *threadArrayEnd, | |
0a7de745 | 226 | uintptr_t macho_header_addr, uintptr_t macho_header_vmaddr, size_t slide) |
d9a64523 A |
227 | { |
228 | uint32_t threadStartsHeader = *threadArrayStart; | |
229 | uint64_t stepMultiplier = (threadStartsHeader & 1) == 1 ? 8 : 4; | |
230 | for (uint32_t* threadOffset = threadArrayStart + 1; threadOffset != threadArrayEnd; ++threadOffset) { | |
0a7de745 | 231 | if (*threadOffset == 0xFFFFFFFF) { |
d9a64523 | 232 | break; |
0a7de745 | 233 | } |
d9a64523 A |
234 | rebase_chain(macho_header_addr + *threadOffset, stepMultiplier, macho_header_vmaddr, slide); |
235 | } | |
236 | return true; | |
237 | } | |
238 | ||
cb323159 | 239 | |
5ba3f43e A |
240 | /* |
241 | * Routine: arm_init | |
242 | * Function: | |
243 | */ | |
d9a64523 A |
244 | |
245 | extern uint32_t __thread_starts_sect_start[] __asm("section$start$__TEXT$__thread_starts"); | |
246 | extern uint32_t __thread_starts_sect_end[] __asm("section$end$__TEXT$__thread_starts"); | |
247 | ||
5ba3f43e A |
248 | void |
249 | arm_init( | |
0a7de745 | 250 | boot_args *args) |
5ba3f43e A |
251 | { |
252 | unsigned int maxmem; | |
253 | uint32_t memsize; | |
254 | uint64_t xmaxmem; | |
255 | thread_t thread; | |
256 | processor_t my_master_proc; | |
257 | ||
0a7de745 A |
258 | // rebase and sign jops |
259 | if (&__thread_starts_sect_end[0] != &__thread_starts_sect_start[0]) { | |
d9a64523 A |
260 | uintptr_t mh = (uintptr_t) &_mh_execute_header; |
261 | uintptr_t slide = mh - VM_KERNEL_LINK_ADDRESS; | |
262 | rebase_threaded_starts( &__thread_starts_sect_start[0], | |
0a7de745 A |
263 | &__thread_starts_sect_end[0], |
264 | mh, mh - slide, slide); | |
d9a64523 A |
265 | } |
266 | ||
5ba3f43e A |
267 | /* If kernel integrity is supported, use a constant copy of the boot args. */ |
268 | const_boot_args = *args; | |
d9a64523 | 269 | BootArgs = args = &const_boot_args; |
5ba3f43e A |
270 | |
271 | cpu_data_init(&BootCpuData); | |
cb323159 A |
272 | #if defined(HAS_APPLE_PAC) |
273 | /* bootstrap cpu process dependent key for kernel has been loaded by start.s */ | |
274 | BootCpuData.rop_key = KERNEL_ROP_ID; | |
275 | #endif /* defined(HAS_APPLE_PAC) */ | |
5ba3f43e | 276 | |
d9a64523 | 277 | PE_init_platform(FALSE, args); /* Get platform expert set up */ |
5ba3f43e A |
278 | |
279 | #if __arm64__ | |
d9a64523 A |
280 | |
281 | ||
cb323159 A |
282 | #if defined(HAS_APPLE_PAC) |
283 | boolean_t user_jop = TRUE; | |
284 | PE_parse_boot_argn("user_jop", &user_jop, sizeof(user_jop)); | |
285 | if (!user_jop) { | |
286 | args->bootFlags |= kBootFlagsDisableUserJOP; | |
287 | } | |
288 | boolean_t user_ts_jop = TRUE; | |
289 | PE_parse_boot_argn("user_ts_jop", &user_ts_jop, sizeof(user_ts_jop)); | |
290 | if (!user_ts_jop) { | |
291 | args->bootFlags |= kBootFlagsDisableUserThreadStateJOP; | |
292 | } | |
293 | #endif /* defined(HAS_APPLE_PAC) */ | |
294 | ||
5ba3f43e A |
295 | { |
296 | unsigned int tmp_16k = 0; | |
297 | ||
0a7de745 | 298 | #ifdef XXXX |
5ba3f43e A |
299 | /* |
300 | * Select the advertised kernel page size; without the boot-arg | |
301 | * we default to the hardware page size for the current platform. | |
302 | */ | |
0a7de745 | 303 | if (PE_parse_boot_argn("-vm16k", &tmp_16k, sizeof(tmp_16k))) { |
5ba3f43e | 304 | PAGE_SHIFT_CONST = PAGE_MAX_SHIFT; |
0a7de745 | 305 | } else { |
5ba3f43e | 306 | PAGE_SHIFT_CONST = ARM_PGSHIFT; |
0a7de745 | 307 | } |
5ba3f43e A |
308 | #else |
309 | /* | |
310 | * Select the advertised kernel page size; with the boot-arg | |
311 | * use to the hardware page size for the current platform. | |
312 | */ | |
313 | int radar_20804515 = 1; /* default: new mode */ | |
314 | PE_parse_boot_argn("radar_20804515", &radar_20804515, sizeof(radar_20804515)); | |
315 | if (radar_20804515) { | |
0a7de745 | 316 | if (args->memSize > 1ULL * 1024 * 1024 * 1024) { |
5ba3f43e A |
317 | /* |
318 | * arm64 device with > 1GB of RAM: | |
319 | * kernel uses 16KB pages. | |
320 | */ | |
321 | PAGE_SHIFT_CONST = PAGE_MAX_SHIFT; | |
322 | } else { | |
323 | /* | |
324 | * arm64 device with <= 1GB of RAM: | |
325 | * kernel uses hardware page size | |
326 | * (4KB for H6/H7, 16KB for H8+). | |
327 | */ | |
328 | PAGE_SHIFT_CONST = ARM_PGSHIFT; | |
329 | } | |
330 | /* 32-bit apps always see 16KB page size */ | |
331 | page_shift_user32 = PAGE_MAX_SHIFT; | |
332 | } else { | |
333 | /* kernel page size: */ | |
0a7de745 | 334 | if (PE_parse_boot_argn("-use_hwpagesize", &tmp_16k, sizeof(tmp_16k))) { |
5ba3f43e | 335 | PAGE_SHIFT_CONST = ARM_PGSHIFT; |
0a7de745 | 336 | } else { |
5ba3f43e | 337 | PAGE_SHIFT_CONST = PAGE_MAX_SHIFT; |
0a7de745 | 338 | } |
5ba3f43e A |
339 | /* old mode: 32-bit apps see same page size as kernel */ |
340 | page_shift_user32 = PAGE_SHIFT_CONST; | |
341 | } | |
342 | #endif | |
0a7de745 | 343 | #ifdef APPLETYPHOON |
5ba3f43e | 344 | if (PE_parse_boot_argn("cpus_defeatures", &cpus_defeatures, sizeof(cpus_defeatures))) { |
0a7de745 | 345 | if ((cpus_defeatures & 0xF) != 0) { |
5ba3f43e | 346 | cpu_defeatures_set(cpus_defeatures & 0xF); |
0a7de745 | 347 | } |
5ba3f43e A |
348 | } |
349 | #endif | |
0a7de745 | 350 | } |
5ba3f43e A |
351 | #endif |
352 | ||
353 | ml_parse_cpu_topology(); | |
354 | ||
355 | master_cpu = ml_get_boot_cpu_number(); | |
356 | assert(master_cpu >= 0 && master_cpu <= ml_get_max_cpu_number()); | |
357 | ||
358 | BootCpuData.cpu_number = (unsigned short)master_cpu; | |
0a7de745 | 359 | #if __arm__ |
5ba3f43e A |
360 | BootCpuData.cpu_exc_vectors = (vm_offset_t)&ExceptionVectorsTable; |
361 | #endif | |
0a7de745 | 362 | BootCpuData.intstack_top = (vm_offset_t) &intstack_top; |
5ba3f43e | 363 | BootCpuData.istackptr = BootCpuData.intstack_top; |
5ba3f43e | 364 | #if __arm64__ |
0a7de745 | 365 | BootCpuData.excepstack_top = (vm_offset_t) &excepstack_top; |
5ba3f43e | 366 | BootCpuData.excepstackptr = BootCpuData.excepstack_top; |
d9a64523 | 367 | #else |
0a7de745 | 368 | BootCpuData.fiqstack_top = (vm_offset_t) &fiqstack_top; |
d9a64523 | 369 | BootCpuData.fiqstackptr = BootCpuData.fiqstack_top; |
5ba3f43e A |
370 | #endif |
371 | BootCpuData.cpu_processor = cpu_processor_alloc(TRUE); | |
372 | BootCpuData.cpu_console_buf = (void *)NULL; | |
373 | CpuDataEntries[master_cpu].cpu_data_vaddr = &BootCpuData; | |
374 | CpuDataEntries[master_cpu].cpu_data_paddr = (void *)((uintptr_t)(args->physBase) | |
0a7de745 A |
375 | + ((uintptr_t)&BootCpuData |
376 | - (uintptr_t)(args->virtBase))); | |
5ba3f43e | 377 | |
ea3f0419 A |
378 | thread = thread_bootstrap(); |
379 | thread->machine.CpuDatap = &BootCpuData; | |
380 | machine_set_current_thread(thread); | |
381 | ||
5ba3f43e A |
382 | /* |
383 | * Preemption is enabled for this thread so that it can lock mutexes without | |
384 | * tripping the preemption check. In reality scheduling is not enabled until | |
0a7de745 | 385 | * this thread completes, and there are no other threads to switch to, so |
5ba3f43e A |
386 | * preemption level is not really meaningful for the bootstrap thread. |
387 | */ | |
388 | thread->machine.preemption_count = 0; | |
0a7de745 A |
389 | #if __arm__ && __ARM_USER_PROTECT__ |
390 | { | |
391 | unsigned int ttbr0_val, ttbr1_val, ttbcr_val; | |
392 | __asm__ volatile ("mrc p15,0,%0,c2,c0,0\n" : "=r"(ttbr0_val)); | |
393 | __asm__ volatile ("mrc p15,0,%0,c2,c0,1\n" : "=r"(ttbr1_val)); | |
394 | __asm__ volatile ("mrc p15,0,%0,c2,c0,2\n" : "=r"(ttbcr_val)); | |
5ba3f43e A |
395 | thread->machine.uptw_ttb = ttbr0_val; |
396 | thread->machine.kptw_ttb = ttbr1_val; | |
397 | thread->machine.uptw_ttc = ttbcr_val; | |
0a7de745 | 398 | } |
5ba3f43e A |
399 | #endif |
400 | BootCpuData.cpu_processor->processor_data.kernel_timer = &thread->system_timer; | |
401 | BootCpuData.cpu_processor->processor_data.thread_timer = &thread->system_timer; | |
402 | ||
403 | cpu_bootstrap(); | |
404 | ||
405 | rtclock_early_init(); | |
406 | ||
cb323159 A |
407 | lck_mod_init(); |
408 | ||
409 | /* | |
410 | * Initialize the timer callout world | |
411 | */ | |
412 | timer_call_init(); | |
413 | ||
5ba3f43e A |
414 | kernel_early_bootstrap(); |
415 | ||
416 | cpu_init(); | |
417 | ||
5ba3f43e A |
418 | processor_bootstrap(); |
419 | my_master_proc = master_processor; | |
420 | ||
0a7de745 | 421 | (void)PE_parse_boot_argn("diag", &arm_diag, sizeof(arm_diag)); |
5ba3f43e | 422 | |
0a7de745 A |
423 | if (PE_parse_boot_argn("maxmem", &maxmem, sizeof(maxmem))) { |
424 | xmaxmem = (uint64_t) maxmem * (1024 * 1024); | |
425 | } else if (PE_get_default("hw.memsize", &memsize, sizeof(memsize))) { | |
5ba3f43e | 426 | xmaxmem = (uint64_t) memsize; |
0a7de745 | 427 | } else { |
5ba3f43e | 428 | xmaxmem = 0; |
0a7de745 | 429 | } |
5ba3f43e A |
430 | |
431 | if (PE_parse_boot_argn("up_style_idle_exit", &up_style_idle_exit, sizeof(up_style_idle_exit))) { | |
432 | up_style_idle_exit = 1; | |
433 | } | |
434 | #if INTERRUPT_MASKED_DEBUG | |
435 | int wdt_boot_arg = 0; | |
436 | /* Disable if WDT is disabled or no_interrupt_mask_debug in boot-args */ | |
437 | if (PE_parse_boot_argn("no_interrupt_masked_debug", &interrupt_masked_debug, | |
0a7de745 | 438 | sizeof(interrupt_masked_debug)) || (PE_parse_boot_argn("wdt", &wdt_boot_arg, |
cb323159 | 439 | sizeof(wdt_boot_arg)) && (wdt_boot_arg == -1)) || kern_feature_override(KF_INTERRUPT_MASKED_DEBUG_OVRD)) { |
5ba3f43e A |
440 | interrupt_masked_debug = 0; |
441 | } | |
442 | ||
443 | PE_parse_boot_argn("interrupt_masked_debug_timeout", &interrupt_masked_timeout, sizeof(interrupt_masked_timeout)); | |
444 | #endif | |
445 | ||
c6bf4f31 A |
446 | #if HAS_NEX_PG |
447 | PE_parse_boot_argn("nexpg", &nex_pg, sizeof(nex_pg)); | |
448 | set_nex_pg(); // Apply NEX powergating settings to boot CPU | |
449 | #endif | |
5ba3f43e | 450 | |
c6bf4f31 A |
451 | #if HAS_BP_RET |
452 | PE_parse_boot_argn("bpret", &bp_ret, sizeof(bp_ret)); | |
453 | set_bp_ret(); // Apply branch predictor retention settings to boot CPU | |
454 | #endif | |
5ba3f43e A |
455 | |
456 | PE_parse_boot_argn("immediate_NMI", &force_immediate_debug_halt, sizeof(force_immediate_debug_halt)); | |
457 | ||
458 | #if __ARM_PAN_AVAILABLE__ | |
5ba3f43e | 459 | __builtin_arm_wsr("pan", 1); |
5ba3f43e A |
460 | #endif /* __ARM_PAN_AVAILABLE__ */ |
461 | ||
462 | arm_vm_init(xmaxmem, args); | |
463 | ||
464 | uint32_t debugmode; | |
465 | if (PE_parse_boot_argn("debug", &debugmode, sizeof(debugmode)) && | |
0a7de745 | 466 | debugmode) { |
5ba3f43e | 467 | patch_low_glo(); |
0a7de745 | 468 | } |
5ba3f43e A |
469 | |
470 | printf_init(); | |
471 | panic_init(); | |
d9a64523 A |
472 | #if __arm64__ |
473 | /* Enable asynchronous exceptions */ | |
474 | __builtin_arm_wsr("DAIFClr", DAIFSC_ASYNCF); | |
475 | #endif | |
5ba3f43e A |
476 | #if __arm64__ && WITH_CLASSIC_S2R |
477 | sleep_token_buffer_init(); | |
478 | #endif | |
479 | ||
480 | PE_consistent_debug_inherit(); | |
481 | ||
482 | /* setup debugging output if one has been chosen */ | |
483 | PE_init_kprintf(FALSE); | |
484 | ||
485 | kprintf("kprintf initialized\n"); | |
486 | ||
487 | serialmode = 0; /* Assume normal keyboard and console */ | |
488 | if (PE_parse_boot_argn("serial", &serialmode, sizeof(serialmode))) { /* Do we want a serial | |
0a7de745 A |
489 | * keyboard and/or |
490 | * console? */ | |
5ba3f43e A |
491 | kprintf("Serial mode specified: %08X\n", serialmode); |
492 | int force_sync = serialmode & SERIALMODE_SYNCDRAIN; | |
493 | if (force_sync || PE_parse_boot_argn("drain_uart_sync", &force_sync, sizeof(force_sync))) { | |
494 | if (force_sync) { | |
495 | serialmode |= SERIALMODE_SYNCDRAIN; | |
496 | kprintf( | |
0a7de745 A |
497 | "WARNING: Forcing uart driver to output synchronously." |
498 | "printf()s/IOLogs will impact kernel performance.\n" | |
499 | "You are advised to avoid using 'drain_uart_sync' boot-arg.\n"); | |
5ba3f43e A |
500 | } |
501 | } | |
502 | } | |
503 | if (kern_feature_override(KF_SERIAL_OVRD)) { | |
504 | serialmode = 0; | |
505 | } | |
506 | ||
507 | if (serialmode & SERIALMODE_OUTPUT) { /* Start serial if requested */ | |
508 | (void)switch_to_serial_console(); /* Switch into serial mode */ | |
509 | disableConsoleOutput = FALSE; /* Allow printfs to happen */ | |
510 | } | |
511 | PE_create_console(); | |
512 | ||
513 | /* setup console output */ | |
514 | PE_init_printf(FALSE); | |
515 | ||
516 | #if __arm64__ | |
517 | #if DEBUG | |
518 | dump_kva_space(); | |
519 | #endif | |
520 | #endif | |
521 | ||
522 | cpu_machine_idle_init(TRUE); | |
523 | ||
0a7de745 A |
524 | #if (__ARM_ARCH__ == 7) |
525 | if (arm_diag & 0x8000) { | |
5ba3f43e | 526 | set_mmu_control((get_mmu_control()) ^ SCTLR_PREDIC); |
0a7de745 | 527 | } |
5ba3f43e A |
528 | #endif |
529 | ||
530 | PE_init_platform(TRUE, &BootCpuData); | |
cb323159 A |
531 | |
532 | #if __arm64__ | |
533 | if (PE_parse_boot_argn("wfe_events_sec", &events_per_sec, sizeof(events_per_sec))) { | |
534 | if (events_per_sec <= 0) { | |
535 | events_per_sec = 1; | |
536 | } else if (events_per_sec > USEC_PER_SEC) { | |
537 | events_per_sec = USEC_PER_SEC; | |
538 | } | |
539 | } else { | |
540 | #if defined(ARM_BOARD_WFE_TIMEOUT_NS) | |
541 | events_per_sec = NSEC_PER_SEC / ARM_BOARD_WFE_TIMEOUT_NS; | |
542 | #else /* !defined(ARM_BOARD_WFE_TIMEOUT_NS) */ | |
543 | /* Default to 1usec (or as close as we can get) */ | |
544 | events_per_sec = USEC_PER_SEC; | |
545 | #endif /* !defined(ARM_BOARD_WFE_TIMEOUT_NS) */ | |
546 | } | |
547 | #endif | |
548 | ||
5ba3f43e | 549 | cpu_timebase_init(TRUE); |
cb323159 | 550 | PE_init_cpu(); |
d9a64523 | 551 | fiq_context_bootstrap(TRUE); |
5ba3f43e A |
552 | |
553 | ||
554 | /* | |
555 | * Initialize the stack protector for all future calls | |
556 | * to C code. Since kernel_bootstrap() eventually | |
557 | * switches stack context without returning through this | |
558 | * function, we do not risk failing the check even though | |
559 | * we mutate the guard word during execution. | |
560 | */ | |
561 | __stack_chk_guard = (unsigned long)early_random(); | |
562 | /* Zero a byte of the protector to guard | |
563 | * against string vulnerabilities | |
564 | */ | |
565 | __stack_chk_guard &= ~(0xFFULL << 8); | |
566 | machine_startup(args); | |
567 | } | |
568 | ||
569 | /* | |
570 | * Routine: arm_init_cpu | |
571 | * Function: | |
572 | * Re-initialize CPU when coming out of reset | |
573 | */ | |
574 | ||
575 | void | |
576 | arm_init_cpu( | |
0a7de745 | 577 | cpu_data_t *cpu_data_ptr) |
5ba3f43e A |
578 | { |
579 | #if __ARM_PAN_AVAILABLE__ | |
5ba3f43e | 580 | __builtin_arm_wsr("pan", 1); |
5ba3f43e A |
581 | #endif |
582 | ||
cb323159 | 583 | |
5ba3f43e A |
584 | cpu_data_ptr->cpu_flags &= ~SleepState; |
585 | #if __ARM_SMP__ && defined(ARMA7) | |
586 | cpu_data_ptr->cpu_CLW_active = 1; | |
587 | #endif | |
588 | ||
589 | machine_set_current_thread(cpu_data_ptr->cpu_active_thread); | |
590 | ||
591 | #if __arm64__ | |
d9a64523 A |
592 | pmap_clear_user_ttb(); |
593 | flush_mmu_tlb(); | |
5ba3f43e | 594 | /* Enable asynchronous exceptions */ |
d9a64523 | 595 | __builtin_arm_wsr("DAIFClr", DAIFSC_ASYNCF); |
5ba3f43e A |
596 | #endif |
597 | ||
598 | cpu_machine_idle_init(FALSE); | |
599 | ||
600 | cpu_init(); | |
601 | ||
0a7de745 A |
602 | #if (__ARM_ARCH__ == 7) |
603 | if (arm_diag & 0x8000) { | |
5ba3f43e | 604 | set_mmu_control((get_mmu_control()) ^ SCTLR_PREDIC); |
0a7de745 | 605 | } |
5ba3f43e | 606 | #endif |
0a7de745 A |
607 | #ifdef APPLETYPHOON |
608 | if ((cpus_defeatures & (0xF << 4 * cpu_data_ptr->cpu_number)) != 0) { | |
609 | cpu_defeatures_set((cpus_defeatures >> 4 * cpu_data_ptr->cpu_number) & 0xF); | |
610 | } | |
5ba3f43e A |
611 | #endif |
612 | /* Initialize the timebase before serial_init, as some serial | |
613 | * drivers use mach_absolute_time() to implement rate control | |
614 | */ | |
615 | cpu_timebase_init(FALSE); | |
616 | ||
617 | if (cpu_data_ptr == &BootCpuData) { | |
618 | #if __arm64__ && __ARM_GLOBAL_SLEEP_BIT__ | |
619 | /* | |
620 | * Prevent CPUs from going into deep sleep until all | |
621 | * CPUs are ready to do so. | |
622 | */ | |
623 | arm64_stall_sleep = TRUE; | |
624 | #endif | |
625 | serial_init(); | |
626 | PE_init_platform(TRUE, NULL); | |
627 | commpage_update_timebase(); | |
628 | } | |
cb323159 | 629 | PE_init_cpu(); |
5ba3f43e A |
630 | |
631 | fiq_context_init(TRUE); | |
632 | cpu_data_ptr->rtcPop = EndOfAllTime; | |
633 | timer_resync_deadlines(); | |
634 | ||
635 | #if DEVELOPMENT || DEBUG | |
636 | PE_arm_debug_enable_trace(); | |
637 | #endif | |
638 | ||
639 | kprintf("arm_cpu_init(): cpu %d online\n", cpu_data_ptr->cpu_processor->cpu_id); | |
640 | ||
641 | if (cpu_data_ptr == &BootCpuData) { | |
642 | #if CONFIG_TELEMETRY | |
643 | bootprofile_wake_from_sleep(); | |
644 | #endif /* CONFIG_TELEMETRY */ | |
d9a64523 | 645 | } |
5ba3f43e | 646 | #if MONOTONIC && defined(__arm64__) |
d9a64523 | 647 | mt_wake_per_core(); |
5ba3f43e | 648 | #endif /* MONOTONIC && defined(__arm64__) */ |
d9a64523 | 649 | |
c6bf4f31 A |
650 | #if defined(KERNEL_INTEGRITY_CTRR) |
651 | if (cpu_data_ptr->cluster_master) { | |
652 | lck_spin_lock(&ctrr_cpu_start_lck); | |
653 | ctrr_cluster_locked[cpu_data_ptr->cpu_cluster_id] = 1; | |
654 | thread_wakeup(&ctrr_cluster_locked[cpu_data_ptr->cpu_cluster_id]); | |
655 | lck_spin_unlock(&ctrr_cpu_start_lck); | |
656 | } | |
657 | #endif | |
5ba3f43e A |
658 | |
659 | slave_main(NULL); | |
660 | } | |
661 | ||
662 | /* | |
663 | * Routine: arm_init_idle_cpu | |
664 | * Function: | |
665 | */ | |
666 | void __attribute__((noreturn)) | |
667 | arm_init_idle_cpu( | |
0a7de745 | 668 | cpu_data_t *cpu_data_ptr) |
5ba3f43e A |
669 | { |
670 | #if __ARM_PAN_AVAILABLE__ | |
5ba3f43e | 671 | __builtin_arm_wsr("pan", 1); |
5ba3f43e A |
672 | #endif |
673 | #if __ARM_SMP__ && defined(ARMA7) | |
674 | cpu_data_ptr->cpu_CLW_active = 1; | |
675 | #endif | |
676 | ||
677 | machine_set_current_thread(cpu_data_ptr->cpu_active_thread); | |
678 | ||
679 | #if __arm64__ | |
d9a64523 A |
680 | pmap_clear_user_ttb(); |
681 | flush_mmu_tlb(); | |
5ba3f43e | 682 | /* Enable asynchronous exceptions */ |
d9a64523 | 683 | __builtin_arm_wsr("DAIFClr", DAIFSC_ASYNCF); |
5ba3f43e A |
684 | #endif |
685 | ||
0a7de745 A |
686 | #if (__ARM_ARCH__ == 7) |
687 | if (arm_diag & 0x8000) { | |
5ba3f43e | 688 | set_mmu_control((get_mmu_control()) ^ SCTLR_PREDIC); |
0a7de745 | 689 | } |
5ba3f43e | 690 | #endif |
0a7de745 A |
691 | #ifdef APPLETYPHOON |
692 | if ((cpus_defeatures & (0xF << 4 * cpu_data_ptr->cpu_number)) != 0) { | |
693 | cpu_defeatures_set((cpus_defeatures >> 4 * cpu_data_ptr->cpu_number) & 0xF); | |
694 | } | |
5ba3f43e A |
695 | #endif |
696 | ||
697 | fiq_context_init(FALSE); | |
698 | ||
d9a64523 | 699 | cpu_idle_exit(TRUE); |
5ba3f43e | 700 | } |