xref: /xnu-8796.121.2/pexpert/arm/pe_identify_machine.c (revision c54f35ca767986246321eb901baf8f5ff7923f6a)
1 /*
2  * Copyright (c) 2007-2021 Apple Inc. All rights reserved.
3  * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4  */
5 #include <pexpert/pexpert.h>
6 #include <pexpert/boot.h>
7 #include <pexpert/protos.h>
8 #include <pexpert/device_tree.h>
9 
10 #include <pexpert/arm64/board_config.h>
11 
12 #include <kern/clock.h>
13 #include <machine/machine_routines.h>
14 #if DEVELOPMENT || DEBUG
15 #include <kern/simple_lock.h>
16 #include <kern/cpu_number.h>
17 #endif
18 
19 #define PANIC_TRACE_LOG 1
20 #define panic_trace_error(msg, args...) { if (panic_trace_debug == 1) kprintf("panic_trace: " msg "\n", ##args); else if (panic_trace_debug == 2) printf("panic_trace: " msg "\n", ##args); }
21 #if PANIC_TRACE_LOG
22 #define panic_trace_log(msg, args...) { if (panic_trace_debug) panic_trace_error(msg, ##args); }
23 #else
24 #define panic_trace_log(msg, args...)
25 #endif /* PANIC_TRACE_LOG */
26 
27 
28 /* Local declarations */
29 void pe_identify_machine(boot_args * bootArgs);
30 
31 /* External declarations */
32 extern void clean_mmu_dcache(void);
33 extern void flush_dcache64(addr64_t addr, unsigned count, int phys);
34 
35 static char    *gPESoCDeviceType;
36 static char     gPESoCDeviceTypeBuffer[SOC_DEVICE_TYPE_BUFFER_SIZE];
37 static vm_offset_t gPESoCBasePhys;
38 
39 static uint32_t pe_arm_init_timer(void *args);
40 
41 #if DEVELOPMENT || DEBUG
42 decl_simple_lock_data(, panic_hook_lock);
43 #endif
44 /*
45  * pe_identify_machine:
46  *
47  * Sets up platform parameters. Returns:    nothing
48  */
49 void
pe_identify_machine(boot_args * bootArgs)50 pe_identify_machine(boot_args * bootArgs)
51 {
52 	OpaqueDTEntryIterator iter;
53 	DTEntry         cpus, cpu;
54 	void const     *value;
55 	unsigned int    size;
56 	int             err;
57 
58 	(void)bootArgs;
59 
60 	if (pe_arm_get_soc_base_phys() == 0) {
61 		return;
62 	}
63 
64 	/* Clear the gPEClockFrequencyInfo struct */
65 	bzero((void *)&gPEClockFrequencyInfo, sizeof(clock_frequency_info_t));
66 
67 	/* Start with default values. */
68 	gPEClockFrequencyInfo.timebase_frequency_hz = 24000000;
69 	gPEClockFrequencyInfo.bus_clock_rate_hz = 100000000;
70 	gPEClockFrequencyInfo.cpu_clock_rate_hz = 400000000;
71 
72 	err = SecureDTLookupEntry(NULL, "/cpus", &cpus);
73 	assert(err == kSuccess);
74 
75 	err = SecureDTInitEntryIterator(cpus, &iter);
76 	assert(err == kSuccess);
77 
78 	while (kSuccess == SecureDTIterateEntries(&iter, &cpu)) {
79 		if ((kSuccess != SecureDTGetProperty(cpu, "state", &value, &size)) ||
80 		    (strncmp((char const *)value, "running", size) != 0)) {
81 			continue;
82 		}
83 
84 		/* Find the time base frequency first. */
85 		if (SecureDTGetProperty(cpu, "timebase-frequency", &value, &size) == kSuccess) {
86 			/*
87 			 * timebase_frequency_hz is only 32 bits, and
88 			 * the device tree should never provide 64
89 			 * bits so this if should never be taken.
90 			 */
91 			if (size == 8) {
92 				gPEClockFrequencyInfo.timebase_frequency_hz = *(uint64_t const *)value;
93 			} else {
94 				gPEClockFrequencyInfo.timebase_frequency_hz = *(uint32_t const *)value;
95 			}
96 		}
97 		gPEClockFrequencyInfo.dec_clock_rate_hz = gPEClockFrequencyInfo.timebase_frequency_hz;
98 
99 		/* Find the bus frequency next. */
100 		if (SecureDTGetProperty(cpu, "bus-frequency", &value, &size) == kSuccess) {
101 			if (size == 8) {
102 				gPEClockFrequencyInfo.bus_frequency_hz = *(uint64_t const *)value;
103 			} else {
104 				gPEClockFrequencyInfo.bus_frequency_hz = *(uint32_t const *)value;
105 			}
106 		}
107 		gPEClockFrequencyInfo.bus_frequency_min_hz = gPEClockFrequencyInfo.bus_frequency_hz;
108 		gPEClockFrequencyInfo.bus_frequency_max_hz = gPEClockFrequencyInfo.bus_frequency_hz;
109 
110 		if (gPEClockFrequencyInfo.bus_frequency_hz < 0x100000000ULL) {
111 			gPEClockFrequencyInfo.bus_clock_rate_hz = gPEClockFrequencyInfo.bus_frequency_hz;
112 		} else {
113 			gPEClockFrequencyInfo.bus_clock_rate_hz = 0xFFFFFFFF;
114 		}
115 
116 		/* Find the memory frequency next. */
117 		if (SecureDTGetProperty(cpu, "memory-frequency", &value, &size) == kSuccess) {
118 			if (size == 8) {
119 				gPEClockFrequencyInfo.mem_frequency_hz = *(uint64_t const *)value;
120 			} else {
121 				gPEClockFrequencyInfo.mem_frequency_hz = *(uint32_t const *)value;
122 			}
123 		}
124 		gPEClockFrequencyInfo.mem_frequency_min_hz = gPEClockFrequencyInfo.mem_frequency_hz;
125 		gPEClockFrequencyInfo.mem_frequency_max_hz = gPEClockFrequencyInfo.mem_frequency_hz;
126 
127 		/* Find the peripheral frequency next. */
128 		if (SecureDTGetProperty(cpu, "peripheral-frequency", &value, &size) == kSuccess) {
129 			if (size == 8) {
130 				gPEClockFrequencyInfo.prf_frequency_hz = *(uint64_t const *)value;
131 			} else {
132 				gPEClockFrequencyInfo.prf_frequency_hz = *(uint32_t const *)value;
133 			}
134 		}
135 		gPEClockFrequencyInfo.prf_frequency_min_hz = gPEClockFrequencyInfo.prf_frequency_hz;
136 		gPEClockFrequencyInfo.prf_frequency_max_hz = gPEClockFrequencyInfo.prf_frequency_hz;
137 
138 		/* Find the fixed frequency next. */
139 		if (SecureDTGetProperty(cpu, "fixed-frequency", &value, &size) == kSuccess) {
140 			if (size == 8) {
141 				gPEClockFrequencyInfo.fix_frequency_hz = *(uint64_t const *)value;
142 			} else {
143 				gPEClockFrequencyInfo.fix_frequency_hz = *(uint32_t const *)value;
144 			}
145 		}
146 		/* Find the cpu frequency last. */
147 		if (SecureDTGetProperty(cpu, "clock-frequency", &value, &size) == kSuccess) {
148 			if (size == 8) {
149 				gPEClockFrequencyInfo.cpu_frequency_hz = *(uint64_t const *)value;
150 			} else {
151 				gPEClockFrequencyInfo.cpu_frequency_hz = *(uint32_t const *)value;
152 			}
153 		}
154 		gPEClockFrequencyInfo.cpu_frequency_min_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
155 		gPEClockFrequencyInfo.cpu_frequency_max_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
156 
157 		if (gPEClockFrequencyInfo.cpu_frequency_hz < 0x100000000ULL) {
158 			gPEClockFrequencyInfo.cpu_clock_rate_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
159 		} else {
160 			gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFF;
161 		}
162 	}
163 
164 	/* Set the num / den pairs form the hz values. */
165 	gPEClockFrequencyInfo.bus_clock_rate_num = gPEClockFrequencyInfo.bus_clock_rate_hz;
166 	gPEClockFrequencyInfo.bus_clock_rate_den = 1;
167 
168 	gPEClockFrequencyInfo.bus_to_cpu_rate_num =
169 	    (2 * gPEClockFrequencyInfo.cpu_clock_rate_hz) / gPEClockFrequencyInfo.bus_clock_rate_hz;
170 	gPEClockFrequencyInfo.bus_to_cpu_rate_den = 2;
171 
172 	gPEClockFrequencyInfo.bus_to_dec_rate_num = 1;
173 	gPEClockFrequencyInfo.bus_to_dec_rate_den =
174 	    gPEClockFrequencyInfo.bus_clock_rate_hz / gPEClockFrequencyInfo.dec_clock_rate_hz;
175 }
176 
177 vm_offset_t
pe_arm_get_soc_base_phys(void)178 pe_arm_get_soc_base_phys(void)
179 {
180 	DTEntry         entryP;
181 	uintptr_t const *ranges_prop;
182 	uint32_t        prop_size;
183 	char const      *tmpStr;
184 
185 	if (SecureDTFindEntry("name", "arm-io", &entryP) == kSuccess) {
186 		if (gPESoCDeviceType == 0) {
187 			SecureDTGetProperty(entryP, "device_type", (void const **)&tmpStr, &prop_size);
188 			strlcpy(gPESoCDeviceTypeBuffer, tmpStr, SOC_DEVICE_TYPE_BUFFER_SIZE);
189 			gPESoCDeviceType = gPESoCDeviceTypeBuffer;
190 
191 			SecureDTGetProperty(entryP, "ranges", (void const **)&ranges_prop, &prop_size);
192 			gPESoCBasePhys = *(ranges_prop + 1);
193 		}
194 		return gPESoCBasePhys;
195 	}
196 	return 0;
197 }
198 
199 extern void     fleh_fiq_generic(void);
200 
201 vm_offset_t     gPicBase;
202 vm_offset_t     gTimerBase;
203 vm_offset_t     gSocPhys;
204 
205 #if DEVELOPMENT || DEBUG
206 // This block contains the panic trace implementation
207 TUNABLE_DT_WRITEABLE(panic_trace_t, panic_trace, "/arm-io/cpu-debug-interface", "panic-trace-mode", "panic_trace", panic_trace_disabled, TUNABLE_DT_NONE);
208 TUNABLE_WRITEABLE(boolean_t, panic_trace_debug, "panic_trace_debug", 1);
209 TUNABLE_WRITEABLE(uint64_t, panic_trace_core_cfg, "panic_trace_core_cfg", 0);
210 TUNABLE_WRITEABLE(uint64_t, panic_trace_ctl, "panic_trace_ctl", 0);
211 TUNABLE_WRITEABLE(uint64_t, panic_trace_pwr_state_ignore, "panic_trace_pwr_state_ignore", 0);
212 TUNABLE_WRITEABLE(boolean_t, panic_trace_experimental_hid, "panic_trace_experimental_hid", 0);
213 TUNABLE(unsigned int, bootarg_stop_clocks, "stop_clocks", 0);
214 extern unsigned int wfi;
215 
216 // The command buffer contains the converted commands from the device tree for commanding cpu_halt, enable_trace, etc.
217 #define DEBUG_COMMAND_BUFFER_SIZE 256
218 typedef struct command_buffer_element {
219 	uintptr_t address;
220 	uintptr_t address_pa;
221 	uintptr_t value;
222 	union cpu_selector {
223 		uint16_t mask;
224 		struct cpu_range {
225 			uint8_t min_cpu;
226 			uint8_t max_cpu;
227 		} range;
228 	} destination_cpu_selector;
229 	uint16_t delay_us;
230 	bool cpu_selector_is_range;
231 	bool is_32bit;
232 } command_buffer_element_t;
233 
234 #define CPU_SELECTOR_SHIFT              (16)
235 #define CPU_SELECTOR_MASK               (0xFFFF << CPU_SELECTOR_SHIFT)
236 #define REGISTER_OFFSET_MASK            ((1 << CPU_SELECTOR_SHIFT) - 1)
237 #define REGISTER_OFFSET(register_prop)  (register_prop & REGISTER_OFFSET_MASK)
238 #define CPU_SELECTOR(register_offset)   ((register_offset & CPU_SELECTOR_MASK) >> CPU_SELECTOR_SHIFT) // Upper 16bits holds the cpu selector
239 #define MAX_WINDOW_SIZE                 0xFFFF
240 #define DELAY_SHIFT                     (32)
241 #define DELAY_MASK                      (0xFFFFULL << DELAY_SHIFT)
242 #define DELAY_US(register_offset)       ((register_offset & DELAY_MASK) >> DELAY_SHIFT)
243 #define CPU_SELECTOR_ISRANGE_MASK       (1ULL << 62)
244 #define REGISTER_32BIT_MASK             (1ULL << 63)
245 #define ALL_CPUS                        0x0000
246 #define RESET_VIRTUAL_ADDRESS_WINDOW    0xFFFFFFFF
247 
248 #define REGISTER_IS_32BIT(register_offset)      ((register_offset & REGISTER_32BIT_MASK) != 0)
249 #define REGISTER_SIZE(register_offset)          (REGISTER_IS_32BIT(register_offset) ? sizeof(uint32_t) : sizeof(uintptr_t))
250 #define CPU_SELECTOR_IS_RANGE(register_offset)  ((register_offset & CPU_SELECTOR_ISRANGE_MASK) != 0)
251 #define CPU_SELECTOR_MIN_CPU(register_offset)   ((CPU_SELECTOR(register_offset) & 0xff00) >> 8)
252 #define CPU_SELECTOR_MAX_CPU(register_offset)   (CPU_SELECTOR(register_offset) & 0x00ff)
253 
254 // Record which CPU is currently running one of our debug commands, so we can trap panic reentrancy to PE_arm_debug_panic_hook.
255 static int running_debug_command_on_cpu_number = -1;
256 
257 // Determine whether the current debug command is intended for this CPU.
258 static inline bool
is_running_cpu_selected(command_buffer_element_t * command)259 is_running_cpu_selected(command_buffer_element_t *command)
260 {
261 	assert(running_debug_command_on_cpu_number >= 0);
262 	if (command->cpu_selector_is_range) {
263 		return running_debug_command_on_cpu_number >= command->destination_cpu_selector.range.min_cpu
264 		       && running_debug_command_on_cpu_number <= command->destination_cpu_selector.range.max_cpu;
265 	} else if (command->destination_cpu_selector.mask == ALL_CPUS) {
266 		return true;
267 	} else {
268 		return !!(command->destination_cpu_selector.mask & (1 << running_debug_command_on_cpu_number));
269 	}
270 }
271 
272 
273 // Pointers into debug_command_buffer for each operation. Assumes runtime will init them to zero.
274 static command_buffer_element_t *cpu_halt;
275 static command_buffer_element_t *enable_trace;
276 static command_buffer_element_t *enable_alt_trace;
277 static command_buffer_element_t *trace_halt;
278 static command_buffer_element_t *enable_stop_clocks;
279 static command_buffer_element_t *stop_clocks;
280 
281 
282 
283 /**************
284 * Public API *
285 **************/
286 
287 static void
pe_init_debug_command(DTEntry entryP,command_buffer_element_t ** command_buffer,const char * entry_name)288 pe_init_debug_command(DTEntry entryP, command_buffer_element_t **command_buffer, const char* entry_name)
289 {
290 	// statically allocate to prevent needing alloc at runtime
291 	static command_buffer_element_t debug_command_buffer[DEBUG_COMMAND_BUFFER_SIZE];
292 	static command_buffer_element_t *next_command_buffer_entry = debug_command_buffer;
293 
294 	// record this pointer but don't assign it to *command_buffer yet, in case we panic while half-initialized
295 	command_buffer_element_t *command_starting_index = next_command_buffer_entry;
296 
297 	uintptr_t const *reg_prop;
298 	uint32_t        prop_size, reg_window_size = 0;
299 	uintptr_t       base_address_pa = 0, debug_reg_window = 0;
300 
301 	if (command_buffer == 0) {
302 		panic_trace_log("%s: %s: no hook to assign this command to\n", __func__, entry_name);
303 		return;
304 	}
305 
306 	if (SecureDTGetProperty(entryP, entry_name, (void const **)&reg_prop, &prop_size) != kSuccess) {
307 		panic("%s: %s: failed to read property from device tree", __func__, entry_name);
308 	}
309 
310 	if (prop_size % (2 * sizeof(*reg_prop))) {
311 		panic("%s: %s: property size %u bytes is not a multiple of %lu",
312 		    __func__, entry_name, prop_size, 2 * sizeof(*reg_prop));
313 	}
314 
315 	// convert to real virt addresses and stuff commands into debug_command_buffer
316 	for (; prop_size; reg_prop += 2, prop_size -= 2 * sizeof(*reg_prop)) {
317 		if (*reg_prop == RESET_VIRTUAL_ADDRESS_WINDOW) {
318 			debug_reg_window = 0; // Create a new window
319 		} else if (debug_reg_window == 0) {
320 			// create a window from virtual address to the specified physical address
321 			base_address_pa = gSocPhys + *reg_prop;
322 			reg_window_size = ((uint32_t)*(reg_prop + 1));
323 			if (reg_window_size > MAX_WINDOW_SIZE) {
324 				panic("%s: %s: %#x-byte window at #%lx exceeds maximum size of %#x",
325 				    __func__, entry_name, reg_window_size, base_address_pa, MAX_WINDOW_SIZE );
326 			}
327 			debug_reg_window = ml_io_map(base_address_pa, reg_window_size);
328 			assert(debug_reg_window);
329 			panic_trace_log("%s: %s: %#x bytes at %#lx mapped to %#lx\n",
330 			    __func__, entry_name, reg_window_size, base_address_pa, debug_reg_window );
331 		} else {
332 			if ((REGISTER_OFFSET(*reg_prop) + REGISTER_SIZE(*reg_prop)) > reg_window_size) {
333 				panic("%s: %s[%ld]: %#lx(+%lu)-byte offset from %#lx exceeds allocated size of %#x",
334 				    __func__, entry_name, next_command_buffer_entry - command_starting_index,
335 				    REGISTER_OFFSET(*reg_prop), REGISTER_SIZE(*reg_prop), base_address_pa, reg_window_size );
336 			}
337 
338 			if (next_command_buffer_entry - debug_command_buffer >= DEBUG_COMMAND_BUFFER_SIZE - 1) {
339 				// can't use the very last entry, since we need it to terminate the command
340 				panic("%s: %s[%ld]: out of space in command buffer",
341 				    __func__, entry_name, next_command_buffer_entry - command_starting_index );
342 			}
343 
344 			next_command_buffer_entry->address    = debug_reg_window + REGISTER_OFFSET(*reg_prop);
345 			next_command_buffer_entry->address_pa = base_address_pa  + REGISTER_OFFSET(*reg_prop);
346 			next_command_buffer_entry->value      = *(reg_prop + 1);
347 #if defined(__arm64__)
348 			next_command_buffer_entry->delay_us   = DELAY_US(*reg_prop);
349 			next_command_buffer_entry->is_32bit   = REGISTER_IS_32BIT(*reg_prop);
350 #else
351 			next_command_buffer_entry->delay_us   = 0;
352 			next_command_buffer_entry->is_32bit   = false;
353 #endif
354 			if ((next_command_buffer_entry->cpu_selector_is_range = CPU_SELECTOR_IS_RANGE(*reg_prop))) {
355 				next_command_buffer_entry->destination_cpu_selector.range.min_cpu = (uint8_t)CPU_SELECTOR_MIN_CPU(*reg_prop);
356 				next_command_buffer_entry->destination_cpu_selector.range.max_cpu = (uint8_t)CPU_SELECTOR_MAX_CPU(*reg_prop);
357 			} else {
358 				next_command_buffer_entry->destination_cpu_selector.mask = (uint16_t)CPU_SELECTOR(*reg_prop);
359 			}
360 			next_command_buffer_entry++;
361 		}
362 	}
363 
364 	// null terminate the address field of the command to end it
365 	(next_command_buffer_entry++)->address = 0;
366 
367 	// save pointer into table for this command
368 	*command_buffer = command_starting_index;
369 }
370 
371 static void
pe_run_debug_command(command_buffer_element_t * command_buffer)372 pe_run_debug_command(command_buffer_element_t *command_buffer)
373 {
374 	// When both the CPUs panic, one will get stuck on the lock and the other CPU will be halted when the first executes the debug command
375 	simple_lock(&panic_hook_lock, LCK_GRP_NULL);
376 
377 	running_debug_command_on_cpu_number = cpu_number();
378 
379 	while (command_buffer && command_buffer->address) {
380 		if (is_running_cpu_selected(command_buffer)) {
381 			panic_trace_log("%s: cpu %d: reg write 0x%lx (VA 0x%lx):= 0x%lx",
382 			    __func__, running_debug_command_on_cpu_number, command_buffer->address_pa,
383 			    command_buffer->address, command_buffer->value);
384 			if (command_buffer->is_32bit) {
385 				*((volatile uint32_t*)(command_buffer->address)) = (uint32_t)(command_buffer->value);
386 			} else {
387 				*((volatile uintptr_t*)(command_buffer->address)) = command_buffer->value;      // register = value;
388 			}
389 			if (command_buffer->delay_us != 0) {
390 				uint64_t deadline;
391 				nanoseconds_to_absolutetime(command_buffer->delay_us * NSEC_PER_USEC, &deadline);
392 				deadline += ml_get_timebase();
393 				while (ml_get_timebase() < deadline) {
394 					os_compiler_barrier();
395 				}
396 			}
397 		}
398 		command_buffer++;
399 	}
400 
401 	running_debug_command_on_cpu_number = -1;
402 	simple_unlock(&panic_hook_lock);
403 }
404 
405 void
PE_arm_debug_enable_trace(bool should_log)406 PE_arm_debug_enable_trace(bool should_log)
407 {
408 	if (should_log) {
409 		panic_trace_log("%s enter", __FUNCTION__);
410 	}
411 	if (panic_trace & panic_trace_enabled) {
412 		pe_run_debug_command(enable_trace);
413 	} else if (panic_trace & panic_trace_alt_enabled) {
414 		pe_run_debug_command(enable_alt_trace);
415 	}
416 	if (should_log) {
417 		panic_trace_log("%s exit", __FUNCTION__);
418 	}
419 }
420 
421 static void
PE_arm_panic_hook(const char * str __unused)422 PE_arm_panic_hook(const char *str __unused)
423 {
424 	(void)str; // not used
425 	if (bootarg_stop_clocks) {
426 		pe_run_debug_command(stop_clocks);
427 	}
428 	// if panic trace is enabled
429 	if (panic_trace) {
430 		if (running_debug_command_on_cpu_number == cpu_number()) {
431 			// This is going to end badly if we don't trap, since we'd be panic-ing during our own code
432 			kprintf("## Panic Trace code caused the panic ##\n");
433 			return;  // allow the normal panic operation to occur.
434 		}
435 
436 		// Stop tracing to freeze the buffer and return to normal panic processing.
437 		pe_run_debug_command(trace_halt);
438 	}
439 }
440 
441 void (*PE_arm_debug_panic_hook)(const char *str) = PE_arm_panic_hook;
442 
443 void
PE_init_cpu(void)444 PE_init_cpu(void)
445 {
446 	if (bootarg_stop_clocks) {
447 		pe_run_debug_command(enable_stop_clocks);
448 	}
449 
450 	pe_init_fiq();
451 }
452 
453 #else
454 
455 void(*const PE_arm_debug_panic_hook)(const char *str) = NULL;
456 
457 void
PE_init_cpu(void)458 PE_init_cpu(void)
459 {
460 	pe_init_fiq();
461 }
462 
463 #endif  // DEVELOPMENT || DEBUG
464 
465 void
PE_panic_hook(const char * str __unused)466 PE_panic_hook(const char *str __unused)
467 {
468 	if (PE_arm_debug_panic_hook != NULL) {
469 		PE_arm_debug_panic_hook(str);
470 	}
471 }
472 
473 void
pe_arm_init_debug(void * args)474 pe_arm_init_debug(void *args)
475 {
476 	DTEntry         entryP;
477 	uintptr_t const *reg_prop;
478 	uint32_t        prop_size;
479 
480 	if (gSocPhys == 0) {
481 		kprintf("pe_arm_init_debug: failed to initialize gSocPhys == 0\n");
482 		return;
483 	}
484 
485 	if (SecureDTFindEntry("device_type", "cpu-debug-interface", &entryP) == kSuccess) {
486 		if (args != NULL) {
487 			if (SecureDTGetProperty(entryP, "reg", (void const **)&reg_prop, &prop_size) == kSuccess) {
488 				ml_init_arm_debug_interface(args, ml_io_map(gSocPhys + *reg_prop, *(reg_prop + 1)));
489 			}
490 #if DEVELOPMENT || DEBUG
491 			// When args != NULL, this means we're being called from arm_init on the boot CPU.
492 			// This controls one-time initialization of the Panic Trace infrastructure
493 
494 			simple_lock_init(&panic_hook_lock, 0); //assuming single threaded mode
495 
496 			if (panic_trace) {
497 				kprintf("pe_arm_init_debug: panic_trace=%d\n", panic_trace);
498 
499 				// Prepare debug command buffers.
500 				pe_init_debug_command(entryP, &cpu_halt, "cpu_halt");
501 				pe_init_debug_command(entryP, &enable_trace, "enable_trace");
502 				pe_init_debug_command(entryP, &enable_alt_trace, "enable_alt_trace");
503 				pe_init_debug_command(entryP, &trace_halt, "trace_halt");
504 
505 				// start tracing now
506 				PE_arm_debug_enable_trace(true);
507 			}
508 			if (bootarg_stop_clocks) {
509 				pe_init_debug_command(entryP, &enable_stop_clocks, "enable_stop_clocks");
510 				pe_init_debug_command(entryP, &stop_clocks, "stop_clocks");
511 			}
512 #endif
513 		}
514 	} else {
515 		kprintf("pe_arm_init_debug: failed to find cpu-debug-interface\n");
516 	}
517 
518 }
519 
520 static uint32_t
pe_arm_map_interrupt_controller(void)521 pe_arm_map_interrupt_controller(void)
522 {
523 	DTEntry         entryP;
524 	uintptr_t const *reg_prop;
525 	uint32_t        prop_size;
526 	vm_offset_t     soc_phys = 0;
527 
528 	gSocPhys = pe_arm_get_soc_base_phys();
529 
530 	soc_phys = gSocPhys;
531 	kprintf("pe_arm_map_interrupt_controller: soc_phys:  0x%lx\n", (unsigned long)soc_phys);
532 	if (soc_phys == 0) {
533 		return 0;
534 	}
535 
536 	if (SecureDTFindEntry("interrupt-controller", "master", &entryP) == kSuccess) {
537 		kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
538 		SecureDTGetProperty(entryP, "reg", (void const **)&reg_prop, &prop_size);
539 		gPicBase = ml_io_map(soc_phys + *reg_prop, *(reg_prop + 1));
540 		kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase);
541 	}
542 	if (gPicBase == 0) {
543 		kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
544 		return 0;
545 	}
546 
547 	if (SecureDTFindEntry("device_type", "timer", &entryP) == kSuccess) {
548 		kprintf("pe_arm_map_interrupt_controller: found timer\n");
549 		SecureDTGetProperty(entryP, "reg", (void const **)&reg_prop, &prop_size);
550 		gTimerBase = ml_io_map(soc_phys + *reg_prop, *(reg_prop + 1));
551 		kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase);
552 	}
553 	if (gTimerBase == 0) {
554 		kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
555 		return 0;
556 	}
557 
558 	return 1;
559 }
560 
561 uint32_t
pe_arm_init_interrupts(void * args)562 pe_arm_init_interrupts(void *args)
563 {
564 	kprintf("pe_arm_init_interrupts: args: %p\n", args);
565 
566 	/* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
567 	if (args != NULL) {
568 		if (!pe_arm_map_interrupt_controller()) {
569 			return 0;
570 		}
571 	}
572 
573 	return pe_arm_init_timer(args);
574 }
575 
576 static uint32_t
pe_arm_init_timer(void * args)577 pe_arm_init_timer(void *args)
578 {
579 	vm_offset_t     pic_base = 0;
580 	vm_offset_t     timer_base = 0;
581 	vm_offset_t     soc_phys;
582 	vm_offset_t     eoi_addr = 0;
583 	uint32_t        eoi_value = 0;
584 	struct tbd_ops  generic_funcs = {&fleh_fiq_generic, NULL, NULL};
585 	struct tbd_ops  empty_funcs __unused = {NULL, NULL, NULL};
586 	tbd_ops_t       tbd_funcs = &generic_funcs;
587 
588 	/* The SoC headers expect to use pic_base, timer_base, etc... */
589 	pic_base = gPicBase;
590 	timer_base = gTimerBase;
591 	soc_phys = gSocPhys;
592 
593 #if defined(__arm64__)
594 	tbd_funcs = &empty_funcs;
595 #else
596 	return 0;
597 #endif
598 
599 	if (args != NULL) {
600 		ml_init_timebase(args, tbd_funcs, eoi_addr, eoi_value);
601 	}
602 
603 	return 1;
604 }
605