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