xref: /xnu-11215.1.10/osfmk/arm/model_dep.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1 /*
2  * Copyright (c) 2007-2020 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 #include <debug.h>
30 #include <mach_kdp.h>
31 #include <kern/kern_stackshot.h>
32 
33 #include <kern/thread.h>
34 #include <machine/pmap.h>
35 #include <device/device_types.h>
36 
37 #include <mach/vm_param.h>
38 #include <mach/clock_types.h>
39 #include <mach/machine.h>
40 #include <mach/kmod.h>
41 #include <pexpert/boot.h>
42 #include <pexpert/pexpert.h>
43 
44 #include <ptrauth.h>
45 
46 #include <kern/misc_protos.h>
47 #include <kern/startup.h>
48 #include <kern/clock.h>
49 #include <kern/debug.h>
50 #include <kern/processor.h>
51 #include <kdp/kdp_core.h>
52 #if ALTERNATE_DEBUGGER
53 #include <arm64/alternate_debugger.h>
54 #endif
55 #include <machine/atomic.h>
56 #include <machine/trap.h>
57 #include <kern/spl.h>
58 #include <pexpert/pexpert.h>
59 #include <kdp/kdp_callout.h>
60 #include <kdp/kdp_dyld.h>
61 #include <kdp/kdp_internal.h>
62 #include <kdp/kdp_common.h>
63 #include <uuid/uuid.h>
64 #include <sys/codesign.h>
65 #include <sys/time.h>
66 
67 #if CONFIG_SPTM
68 #include <kern/percpu.h>
69 #include <arm64/sptm/pmap/pmap_data.h>
70 #endif
71 
72 #include <IOKit/IOPlatformExpert.h>
73 #include <IOKit/IOKitServer.h>
74 
75 #include <mach/vm_prot.h>
76 #include <vm/vm_map_xnu.h>
77 #include <vm/pmap.h>
78 #include <vm/vm_shared_region.h>
79 #include <mach/time_value.h>
80 #include <machine/machparam.h>  /* for btop */
81 
82 #include <console/video_console.h>
83 #include <console/serial_protos.h>
84 #include <arm/cpu_data.h>
85 #include <arm/cpu_data_internal.h>
86 #include <arm/cpu_internal.h>
87 #include <arm/misc_protos.h>
88 #include <libkern/OSKextLibPrivate.h>
89 #include <vm/vm_kern.h>
90 #include <kern/kern_cdata.h>
91 #include <kern/ledger.h>
92 
93 
94 #if DEVELOPMENT || DEBUG
95 #include <kern/ext_paniclog.h>
96 #endif
97 
98 #if CONFIG_EXCLAVES
99 #include <kern/exclaves_panic.h>
100 #include <kern/exclaves_inspection.h>
101 #endif
102 
103 #if     MACH_KDP
104 void    kdp_trap(unsigned int, struct arm_saved_state *);
105 #endif
106 
107 /*
108  * Increment the PANICLOG_VERSION if you change the format of the panic
109  * log in any way.
110  */
111 #define PANICLOG_VERSION 14
112 static struct kcdata_descriptor kc_panic_data;
113 
114 extern char iBoot_version[];
115 #if defined(TARGET_OS_OSX) && defined(__arm64__)
116 extern char iBoot_Stage_2_version[];
117 #endif /* defined(TARGET_OS_OSX) && defined(__arm64__) */
118 
119 extern volatile uint32_t        debug_enabled;
120 extern unsigned int         not_in_kdp;
121 
122 extern int                              copyinframe(vm_address_t fp, uint32_t * frame);
123 extern void                             kdp_callouts(kdp_event_t event);
124 
125 /* #include <sys/proc.h> */
126 #define MAXCOMLEN 16
127 struct proc;
128 extern int        proc_pid(struct proc *p);
129 extern void       proc_name_kdp(struct proc *, char *, int);
130 
131 /*
132  * Make sure there's enough space to include the relevant bits in the format required
133  * within the space allocated for the panic version string in the panic header.
134  * The format required by OSAnalytics/DumpPanic is 'Product Version (OS Version)'.
135  */
136 #define PANIC_HEADER_VERSION_FMT_STR "%.14s (%.14s)"
137 
138 extern const char version[];
139 extern char       osversion[];
140 extern char       osproductversion[];
141 extern char       osreleasetype[];
142 
143 #if defined(XNU_TARGET_OS_BRIDGE)
144 extern char     macosproductversion[];
145 extern char     macosversion[];
146 #endif
147 
148 extern uint8_t          gPlatformECID[8];
149 extern uint32_t         gPlatformMemoryID;
150 
151 extern uint64_t         last_hwaccess_thread;
152 extern uint8_t          last_hwaccess_type; /* 0 : read, 1 : write. */
153 extern uint8_t          last_hwaccess_size;
154 extern uint64_t         last_hwaccess_paddr;
155 
156 /*Choosing the size for gTargetTypeBuffer as 16 and size for gModelTypeBuffer as 32
157  *  since the target name and model name typically  doesn't exceed this size */
158 extern char  gTargetTypeBuffer[16];
159 extern char  gModelTypeBuffer[32];
160 
161 extern struct timeval    gIOLastSleepTime;
162 extern struct timeval    gIOLastWakeTime;
163 extern boolean_t                 is_clock_configured;
164 extern boolean_t kernelcache_uuid_valid;
165 extern uuid_t kernelcache_uuid;
166 extern uuid_string_t bootsessionuuid_string;
167 
168 extern uint64_t roots_installed;
169 
170 /* Definitions for frame pointers */
171 #define FP_ALIGNMENT_MASK      ((uint32_t)(0x3))
172 #define FP_LR_OFFSET           ((uint32_t)4)
173 #define FP_LR_OFFSET64         ((uint32_t)8)
174 #define FP_MAX_NUM_TO_EVALUATE (50)
175 
176 /* Timeout for all processors responding to debug crosscall */
177 MACHINE_TIMEOUT(debug_ack_timeout, "debug-ack", 240000, MACHINE_TIMEOUT_UNIT_TIMEBASE, NULL);
178 
179 /* Forward functions definitions */
180 void panic_display_times(void);
181 void panic_print_symbol_name(vm_address_t search);
182 
183 
184 /* Global variables */
185 static uint32_t       panic_bt_depth;
186 boolean_t             PanicInfoSaved = FALSE;
187 boolean_t             force_immediate_debug_halt = FALSE;
188 unsigned int          debug_ack_timeout_count = 0;
189 volatile unsigned int debugger_sync = 0;
190 volatile unsigned int mp_kdp_trap = 0; /* CPUs signalled by the debug CPU will spin on this */
191 volatile unsigned int debug_cpus_spinning = 0; /* Number of signalled CPUs still spinning on mp_kdp_trap (in DebuggerXCall). */
192 unsigned int          DebugContextCount = 0;
193 bool                  trap_is_stackshot = false; /* Whether the trap is for a stackshot */
194 
195 #if defined(__arm64__)
196 uint8_t PE_smc_stashed_x86_system_state = 0xFF;
197 uint8_t PE_smc_stashed_x86_power_state = 0xFF;
198 uint8_t PE_smc_stashed_x86_efi_boot_state = 0xFF;
199 uint8_t PE_smc_stashed_x86_shutdown_cause = 0xFF;
200 uint64_t PE_smc_stashed_x86_prev_power_transitions = UINT64_MAX;
201 uint32_t PE_pcie_stashed_link_state = UINT32_MAX;
202 uint64_t PE_nvram_stashed_x86_macos_slide = UINT64_MAX;
203 #endif
204 
205 
206 /*
207  * Backtrace a single frame.
208  */
209 static void
print_one_backtrace(pmap_t pmap,vm_offset_t topfp,const char * cur_marker,boolean_t is_64_bit,boolean_t print_kexts_in_backtrace)210 print_one_backtrace(pmap_t pmap, vm_offset_t topfp, const char *cur_marker,
211     boolean_t is_64_bit, boolean_t print_kexts_in_backtrace)
212 {
213 	unsigned int    i = 0;
214 	addr64_t        lr = 0;
215 	addr64_t        fp = topfp;
216 	addr64_t        fp_for_ppn = 0;
217 	ppnum_t         ppn = (ppnum_t)NULL;
218 	vm_offset_t     raddrs[FP_MAX_NUM_TO_EVALUATE] = { 0 };
219 	bool            dump_kernel_stack = (fp >= VM_MIN_KERNEL_ADDRESS);
220 
221 #if defined(HAS_APPLE_PAC)
222 	fp = (addr64_t)ptrauth_strip((void *)fp, ptrauth_key_frame_pointer);
223 #endif
224 	do {
225 		if ((fp == 0) || ((fp & FP_ALIGNMENT_MASK) != 0)) {
226 			break;
227 		}
228 		if (dump_kernel_stack && ((fp < VM_MIN_KERNEL_ADDRESS) || (fp > VM_MAX_KERNEL_ADDRESS))) {
229 			break;
230 		}
231 		if ((!dump_kernel_stack) && (fp >= VM_MIN_KERNEL_ADDRESS)) {
232 			break;
233 		}
234 
235 		/*
236 		 * Check to see if current address will result in a different
237 		 * ppn than previously computed (to avoid recomputation) via
238 		 * (addr) ^ fp_for_ppn) >> PAGE_SHIFT)
239 		 */
240 		if ((((fp + FP_LR_OFFSET) ^ fp_for_ppn) >> PAGE_SHIFT) != 0x0U) {
241 			ppn = pmap_find_phys(pmap, fp + FP_LR_OFFSET);
242 			fp_for_ppn = fp + (is_64_bit ? FP_LR_OFFSET64 : FP_LR_OFFSET);
243 		}
244 		if (ppn != (ppnum_t)NULL) {
245 			if (is_64_bit) {
246 				lr = ml_phys_read_double_64(((((vm_offset_t)ppn) << PAGE_SHIFT)) | ((fp + FP_LR_OFFSET64) & PAGE_MASK));
247 #if defined(HAS_APPLE_PAC)
248 				/* return addresses on stack will be signed by arm64e ABI */
249 				lr = (addr64_t) ptrauth_strip((void *)lr, ptrauth_key_return_address);
250 #endif
251 			} else {
252 				lr = ml_phys_read_word(((((vm_offset_t)ppn) << PAGE_SHIFT)) | ((fp + FP_LR_OFFSET) & PAGE_MASK));
253 			}
254 		} else {
255 			if (is_64_bit) {
256 				paniclog_append_noflush("%s\t  Could not read LR from frame at 0x%016llx\n", cur_marker, fp + FP_LR_OFFSET64);
257 			} else {
258 				paniclog_append_noflush("%s\t  Could not read LR from frame at 0x%08x\n", cur_marker, (uint32_t)(fp + FP_LR_OFFSET));
259 			}
260 			break;
261 		}
262 		if (((fp ^ fp_for_ppn) >> PAGE_SHIFT) != 0x0U) {
263 			ppn = pmap_find_phys(pmap, fp);
264 			fp_for_ppn = fp;
265 		}
266 		if (ppn != (ppnum_t)NULL) {
267 			if (is_64_bit) {
268 				fp = ml_phys_read_double_64(((((vm_offset_t)ppn) << PAGE_SHIFT)) | (fp & PAGE_MASK));
269 #if defined(HAS_APPLE_PAC)
270 				/* frame pointers on stack will be signed by arm64e ABI */
271 				fp = (addr64_t) ptrauth_strip((void *)fp, ptrauth_key_frame_pointer);
272 #endif
273 			} else {
274 				fp = ml_phys_read_word(((((vm_offset_t)ppn) << PAGE_SHIFT)) | (fp & PAGE_MASK));
275 			}
276 		} else {
277 			if (is_64_bit) {
278 				paniclog_append_noflush("%s\t  Could not read FP from frame at 0x%016llx\n", cur_marker, fp);
279 			} else {
280 				paniclog_append_noflush("%s\t  Could not read FP from frame at 0x%08x\n", cur_marker, (uint32_t)fp);
281 			}
282 			break;
283 		}
284 		/*
285 		 * Counter 'i' may == FP_MAX_NUM_TO_EVALUATE when running one
286 		 * extra round to check whether we have all frames in order to
287 		 * indicate (in)complete backtrace below. This happens in a case
288 		 * where total frame count and FP_MAX_NUM_TO_EVALUATE are equal.
289 		 * Do not capture anything.
290 		 */
291 		if (i < FP_MAX_NUM_TO_EVALUATE && lr) {
292 			if (is_64_bit) {
293 				paniclog_append_noflush("%s\t  lr: 0x%016llx  fp: 0x%016llx\n", cur_marker, lr, fp);
294 			} else {
295 				paniclog_append_noflush("%s\t  lr: 0x%08x  fp: 0x%08x\n", cur_marker, (uint32_t)lr, (uint32_t)fp);
296 			}
297 			raddrs[i] = lr;
298 		}
299 	} while ((++i <= FP_MAX_NUM_TO_EVALUATE) && (fp != topfp));
300 
301 	if (i > FP_MAX_NUM_TO_EVALUATE && fp != 0) {
302 		paniclog_append_noflush("Backtrace continues...\n");
303 	}
304 
305 	if (print_kexts_in_backtrace && i > 0) {
306 		kmod_panic_dump(&raddrs[0], i);
307 	}
308 }
309 
310 #define SANE_TASK_LIMIT 256
311 #define TOP_RUNNABLE_LIMIT 5
312 #define PANICLOG_UUID_BUF_SIZE 256
313 
314 extern void panic_print_vnodes(void);
315 
316 static void
panic_display_tpidrs(void)317 panic_display_tpidrs(void)
318 {
319 #if defined(__arm64__)
320 	paniclog_append_noflush("TPIDRx_ELy = {1: 0x%016llx  0: 0x%016llx  0ro: 0x%016llx }\n",
321 	    __builtin_arm_rsr64("TPIDR_EL1"), __builtin_arm_rsr64("TPIDR_EL0"),
322 	    __builtin_arm_rsr64("TPIDRRO_EL0"));
323 #endif //defined(__arm64__)
324 }
325 
326 static void
panic_display_hung_cpus_help(void)327 panic_display_hung_cpus_help(void)
328 {
329 #if defined(__arm64__)
330 	const uint32_t pcsr_offset = 0x90;
331 
332 	/*
333 	 * Print some info that might help in cases where nothing
334 	 * else does
335 	 */
336 	const ml_topology_info_t *info = ml_get_topology_info();
337 	if (info) {
338 		unsigned i, retry;
339 
340 		for (i = 0; i < info->num_cpus; i++) {
341 			if (!PE_cpu_power_check_kdp(i)) {
342 				paniclog_append_noflush("CORE %u is offline, skipping\n", i);
343 				continue;
344 			}
345 			if (info->cpus[i].cpu_UTTDBG_regs) {
346 				volatile uint64_t *pcsr = (volatile uint64_t*)(info->cpus[i].cpu_UTTDBG_regs + pcsr_offset);
347 				volatile uint32_t *pcsrTrigger = (volatile uint32_t*)pcsr;
348 				uint64_t pc = 0;
349 
350 				// a number of retries are needed till this works
351 				for (retry = 1024; retry && !pc; retry--) {
352 					//a 32-bit read is required to make a PC sample be produced, else we'll only get a zero
353 					(void)*pcsrTrigger;
354 					pc = *pcsr;
355 				}
356 
357 				//postprocessing (same as astris does)
358 				if (pc >> 48) {
359 					pc |= 0xffff000000000000ull;
360 				}
361 				paniclog_append_noflush("CORE %u recently retired instr at 0x%016llx\n", i, pc);
362 			}
363 		}
364 	}
365 #endif //defined(__arm64__)
366 }
367 
368 
369 
370 static void
panic_display_pvhs_locked(void)371 panic_display_pvhs_locked(void)
372 {
373 }
374 
375 static void
panic_display_pvh_to_lock(void)376 panic_display_pvh_to_lock(void)
377 {
378 }
379 
380 static void
panic_display_last_pc_lr(void)381 panic_display_last_pc_lr(void)
382 {
383 #if defined(__arm64__)
384 	const int max_cpu = ml_get_max_cpu_number();
385 
386 	for (int cpu = 0; cpu <= max_cpu; cpu++) {
387 		cpu_data_t *current_cpu_datap = cpu_datap(cpu);
388 
389 		if (current_cpu_datap == NULL) {
390 			continue;
391 		}
392 
393 		if (current_cpu_datap == getCpuDatap()) {
394 			/**
395 			 * Skip printing the PC/LR if this is the CPU
396 			 * that initiated the panic.
397 			 */
398 			paniclog_append_noflush("CORE %u is the one that panicked. Check the full backtrace for details.\n", cpu);
399 			continue;
400 		}
401 
402 		paniclog_append_noflush("CORE %u: PC=0x%016llx, LR=0x%016llx, FP=0x%016llx\n", cpu,
403 		    current_cpu_datap->ipi_pc, (uint64_t)VM_KERNEL_STRIP_PTR(current_cpu_datap->ipi_lr),
404 		    (uint64_t)VM_KERNEL_STRIP_PTR(current_cpu_datap->ipi_fp));
405 	}
406 #endif
407 }
408 
409 #if CONFIG_EXCLAVES
410 static void
panic_report_exclaves_stackshot(void)411 panic_report_exclaves_stackshot(void)
412 {
413 	if (exclaves_panic_ss_status == EXCLAVES_PANIC_STACKSHOT_FOUND) {
414 		paniclog_append_noflush("** Exclaves panic stackshot found\n");
415 	} else if (exclaves_panic_ss_status == EXCLAVES_PANIC_STACKSHOT_NOT_FOUND) {
416 		paniclog_append_noflush("** Exclaves panic stackshot not found\n");
417 	} else if (exclaves_panic_ss_status == EXCLAVES_PANIC_STACKSHOT_DECODE_FAILED) {
418 		paniclog_append_noflush("!! Exclaves panic stackshot decode failed !!\n");
419 	}
420 }
421 #endif /* CONFIG_EXCLAVES */
422 
423 static void
do_print_all_backtraces(const char * message,uint64_t panic_options,const char * panic_initiator)424 do_print_all_backtraces(const char *message, uint64_t panic_options, const char *panic_initiator)
425 {
426 	int             logversion = PANICLOG_VERSION;
427 	thread_t        cur_thread = current_thread();
428 	uintptr_t       cur_fp;
429 	task_t          task;
430 	struct proc    *proc;
431 	int             print_vnodes = 0;
432 	const char *nohilite_thread_marker = "\t";
433 
434 	/* end_marker_bytes set to 200 for printing END marker + stackshot summary info always */
435 	int bytes_traced = 0, bytes_remaining = 0, end_marker_bytes = 200;
436 	int bytes_uncompressed = 0;
437 	uint64_t bytes_used = 0ULL;
438 	int err = 0;
439 	char *stackshot_begin_loc = NULL;
440 	kc_format_t kc_format;
441 	bool filesetKC = false;
442 	uint32_t panic_initiator_len = 0;
443 #if CONFIG_EXT_PANICLOG
444 	uint32_t ext_paniclog_bytes = 0;
445 #endif
446 
447 #if defined(__arm64__)
448 	__asm__         volatile ("add %0, xzr, fp":"=r"(cur_fp));
449 #else
450 #error Unknown architecture.
451 #endif
452 	if (panic_bt_depth != 0) {
453 		return;
454 	}
455 	panic_bt_depth++;
456 
457 	__unused bool result = PE_get_primary_kc_format(&kc_format);
458 	assert(result == true);
459 	filesetKC = kc_format == KCFormatFileset;
460 
461 	/* Truncate panic string to 1200 bytes */
462 	paniclog_append_noflush("Debugger message: %.1200s\n", message);
463 	if (debug_enabled) {
464 		paniclog_append_noflush("Device: %s\n",
465 		    ('\0' != gTargetTypeBuffer[0]) ? gTargetTypeBuffer : "Not set yet");
466 		paniclog_append_noflush("Hardware Model: %s\n",
467 		    ('\0' != gModelTypeBuffer[0]) ? gModelTypeBuffer:"Not set yet");
468 		paniclog_append_noflush("ECID: %02X%02X%02X%02X%02X%02X%02X%02X\n", gPlatformECID[7],
469 		    gPlatformECID[6], gPlatformECID[5], gPlatformECID[4], gPlatformECID[3],
470 		    gPlatformECID[2], gPlatformECID[1], gPlatformECID[0]);
471 		if (last_hwaccess_thread) {
472 			paniclog_append_noflush("AppleHWAccess Thread: 0x%llx\n", last_hwaccess_thread);
473 			if (!last_hwaccess_size) {
474 				paniclog_append_noflush("AppleHWAccess last access: no access data, this is unexpected.\n");
475 			} else {
476 				const char *typ = last_hwaccess_type ? "write" : "read";
477 				paniclog_append_noflush("AppleHWAccess last access: %s of size %u at address 0x%llx\n", typ, last_hwaccess_size, last_hwaccess_paddr);
478 			}
479 		}
480 		paniclog_append_noflush("Boot args: %s\n", PE_boot_args());
481 	}
482 	paniclog_append_noflush("Memory ID: 0x%x\n", gPlatformMemoryID);
483 	paniclog_append_noflush("OS release type: %.256s\n",
484 	    ('\0' != osreleasetype[0]) ? osreleasetype : "Not set yet");
485 	paniclog_append_noflush("OS version: %.256s\n",
486 	    ('\0' != osversion[0]) ? osversion : "Not set yet");
487 #if defined(XNU_TARGET_OS_BRIDGE)
488 	paniclog_append_noflush("macOS version: %.256s\n",
489 	    ('\0' != macosversion[0]) ? macosversion : "Not set");
490 #endif
491 	paniclog_append_noflush("Kernel version: %.512s\n", version);
492 
493 #if CONFIG_EXCLAVES
494 	exclaves_panic_append_info();
495 #endif
496 
497 	if (kernelcache_uuid_valid) {
498 		if (filesetKC) {
499 			paniclog_append_noflush("Fileset Kernelcache UUID: ");
500 		} else {
501 			paniclog_append_noflush("KernelCache UUID: ");
502 		}
503 		for (size_t index = 0; index < sizeof(uuid_t); index++) {
504 			paniclog_append_noflush("%02X", kernelcache_uuid[index]);
505 		}
506 		paniclog_append_noflush("\n");
507 	}
508 	panic_display_kernel_uuid();
509 
510 	if (bootsessionuuid_string[0] != '\0') {
511 		paniclog_append_noflush("Boot session UUID: %s\n", bootsessionuuid_string);
512 	} else {
513 		paniclog_append_noflush("Boot session UUID not yet initialized\n");
514 	}
515 
516 	paniclog_append_noflush("iBoot version: %.128s\n", iBoot_version);
517 #if defined(TARGET_OS_OSX) && defined(__arm64__)
518 	paniclog_append_noflush("iBoot Stage 2 version: %.128s\n", iBoot_Stage_2_version);
519 #endif /* defined(TARGET_OS_OSX) && defined(__arm64__) */
520 
521 	paniclog_append_noflush("secure boot?: %s\n", debug_enabled ? "NO": "YES");
522 	paniclog_append_noflush("roots installed: %lld\n", roots_installed);
523 #if defined(XNU_TARGET_OS_BRIDGE)
524 	paniclog_append_noflush("x86 EFI Boot State: ");
525 	if (PE_smc_stashed_x86_efi_boot_state != 0xFF) {
526 		paniclog_append_noflush("0x%x\n", PE_smc_stashed_x86_efi_boot_state);
527 	} else {
528 		paniclog_append_noflush("not available\n");
529 	}
530 	paniclog_append_noflush("x86 System State: ");
531 	if (PE_smc_stashed_x86_system_state != 0xFF) {
532 		paniclog_append_noflush("0x%x\n", PE_smc_stashed_x86_system_state);
533 	} else {
534 		paniclog_append_noflush("not available\n");
535 	}
536 	paniclog_append_noflush("x86 Power State: ");
537 	if (PE_smc_stashed_x86_power_state != 0xFF) {
538 		paniclog_append_noflush("0x%x\n", PE_smc_stashed_x86_power_state);
539 	} else {
540 		paniclog_append_noflush("not available\n");
541 	}
542 	paniclog_append_noflush("x86 Shutdown Cause: ");
543 	if (PE_smc_stashed_x86_shutdown_cause != 0xFF) {
544 		paniclog_append_noflush("0x%x\n", PE_smc_stashed_x86_shutdown_cause);
545 	} else {
546 		paniclog_append_noflush("not available\n");
547 	}
548 	paniclog_append_noflush("x86 Previous Power Transitions: ");
549 	if (PE_smc_stashed_x86_prev_power_transitions != UINT64_MAX) {
550 		paniclog_append_noflush("0x%llx\n", PE_smc_stashed_x86_prev_power_transitions);
551 	} else {
552 		paniclog_append_noflush("not available\n");
553 	}
554 	paniclog_append_noflush("PCIeUp link state: ");
555 	if (PE_pcie_stashed_link_state != UINT32_MAX) {
556 		paniclog_append_noflush("0x%x\n", PE_pcie_stashed_link_state);
557 	} else {
558 		paniclog_append_noflush("not available\n");
559 	}
560 	paniclog_append_noflush("macOS kernel slide: ");
561 	if (PE_nvram_stashed_x86_macos_slide != UINT64_MAX) {
562 		paniclog_append_noflush("%#llx\n", PE_nvram_stashed_x86_macos_slide);
563 	} else {
564 		paniclog_append_noflush("not available\n");
565 	}
566 #endif
567 	if (panic_data_buffers != NULL) {
568 		paniclog_append_noflush("%s data: ", panic_data_buffers->producer_name);
569 		uint8_t *panic_buffer_data = (uint8_t *) panic_data_buffers->buf;
570 		for (int i = 0; i < panic_data_buffers->len; i++) {
571 			paniclog_append_noflush("%02X", panic_buffer_data[i]);
572 		}
573 		paniclog_append_noflush("\n");
574 	}
575 	paniclog_append_noflush("Paniclog version: %d\n", logversion);
576 
577 	panic_display_kernel_aslr();
578 	panic_display_times();
579 	panic_display_zalloc();
580 	panic_display_hung_cpus_help();
581 	panic_display_tpidrs();
582 	panic_display_pvhs_locked();
583 	panic_display_pvh_to_lock();
584 	panic_display_last_pc_lr();
585 #if CONFIG_ECC_LOGGING
586 	panic_display_ecc_errors();
587 #endif /* CONFIG_ECC_LOGGING */
588 	panic_display_compressor_stats();
589 
590 #if DEVELOPMENT || DEBUG
591 	if (cs_debug_unsigned_exec_failures != 0 || cs_debug_unsigned_mmap_failures != 0) {
592 		paniclog_append_noflush("Unsigned code exec failures: %u\n", cs_debug_unsigned_exec_failures);
593 		paniclog_append_noflush("Unsigned code mmap failures: %u\n", cs_debug_unsigned_mmap_failures);
594 	}
595 #endif
596 
597 	// Highlight threads that used high amounts of CPU in the panic log if requested (historically requested for watchdog panics)
598 	if (panic_options & DEBUGGER_OPTION_PRINT_CPU_USAGE_PANICLOG) {
599 		thread_t        top_runnable[5] = {0};
600 		thread_t        thread;
601 		int                     total_cpu_usage = 0;
602 
603 		print_vnodes = 1;
604 
605 
606 		for (thread = (thread_t)queue_first(&threads);
607 		    PANIC_VALIDATE_PTR(thread) && !queue_end(&threads, (queue_entry_t)thread);
608 		    thread = (thread_t)queue_next(&thread->threads)) {
609 			total_cpu_usage += thread->cpu_usage;
610 
611 			// Look for the 5 runnable threads with highest priority
612 			if (thread->state & TH_RUN) {
613 				int                     k;
614 				thread_t        comparison_thread = thread;
615 
616 				for (k = 0; k < TOP_RUNNABLE_LIMIT; k++) {
617 					if (top_runnable[k] == 0) {
618 						top_runnable[k] = comparison_thread;
619 						break;
620 					} else if (comparison_thread->sched_pri > top_runnable[k]->sched_pri) {
621 						thread_t temp = top_runnable[k];
622 						top_runnable[k] = comparison_thread;
623 						comparison_thread = temp;
624 					} // if comparison thread has higher priority than previously saved thread
625 				} // loop through highest priority runnable threads
626 			} // Check if thread is runnable
627 		} // Loop through all threads
628 
629 		// Print the relevant info for each thread identified
630 		paniclog_append_noflush("Total cpu_usage: %d\n", total_cpu_usage);
631 		paniclog_append_noflush("Thread task pri cpu_usage\n");
632 
633 		for (int i = 0; i < TOP_RUNNABLE_LIMIT; i++) {
634 			if (top_runnable[i] &&
635 			    panic_get_thread_proc_task(top_runnable[i], &task, &proc) && proc) {
636 				char name[MAXCOMLEN + 1];
637 				proc_name_kdp(proc, name, sizeof(name));
638 				paniclog_append_noflush("%p %s %d %d\n",
639 				    top_runnable[i], name, top_runnable[i]->sched_pri, top_runnable[i]->cpu_usage);
640 			}
641 		} // Loop through highest priority runnable threads
642 		paniclog_append_noflush("\n");
643 	}
644 
645 	// print current task info
646 	if (panic_get_thread_proc_task(cur_thread, &task, &proc)) {
647 		if (PANIC_VALIDATE_PTR(task->map) &&
648 		    PANIC_VALIDATE_PTR(task->map->pmap)) {
649 			ledger_amount_t resident = 0;
650 			if (task != kernel_task) {
651 				ledger_get_balance(task->ledger, task_ledgers.phys_mem, &resident);
652 				resident >>= VM_MAP_PAGE_SHIFT(task->map);
653 			}
654 			paniclog_append_noflush("Panicked task %p: %lld pages, %d threads: ",
655 			    task, resident, task->thread_count);
656 		} else {
657 			paniclog_append_noflush("Panicked task %p: %d threads: ",
658 			    task, task->thread_count);
659 		}
660 
661 		if (proc) {
662 			char            name[MAXCOMLEN + 1];
663 			proc_name_kdp(proc, name, sizeof(name));
664 			paniclog_append_noflush("pid %d: %s", proc_pid(proc), name);
665 		} else {
666 			paniclog_append_noflush("unknown task");
667 		}
668 
669 		paniclog_append_noflush("\n");
670 	}
671 
672 	if (cur_fp < VM_MAX_KERNEL_ADDRESS) {
673 		paniclog_append_noflush("Panicked thread: %p, backtrace: 0x%llx, tid: %llu\n",
674 		    cur_thread, (addr64_t)cur_fp, thread_tid(cur_thread));
675 #if __LP64__
676 		print_one_backtrace(kernel_pmap, cur_fp, nohilite_thread_marker, TRUE, filesetKC);
677 #else
678 		print_one_backtrace(kernel_pmap, cur_fp, nohilite_thread_marker, FALSE, filesetKC);
679 #endif
680 	} else {
681 		paniclog_append_noflush("Could not print panicked thread backtrace:"
682 		    "frame pointer outside kernel vm.\n");
683 	}
684 
685 	paniclog_append_noflush("\n");
686 	if (filesetKC) {
687 		kext_dump_panic_lists(&paniclog_append_noflush);
688 		paniclog_append_noflush("\n");
689 	}
690 	panic_info->eph_panic_log_len = PE_get_offset_into_panic_region(debug_buf_ptr) - panic_info->eph_panic_log_offset;
691 	/* set the os version data in the panic header in the format 'Product Version (OS Version)' (only if they have been set) */
692 	if ((osversion[0] != '\0') && (osproductversion[0] != '\0')) {
693 		snprintf((char *)&panic_info->eph_os_version, sizeof(panic_info->eph_os_version), PANIC_HEADER_VERSION_FMT_STR,
694 		    osproductversion, osversion);
695 	}
696 #if defined(XNU_TARGET_OS_BRIDGE)
697 	if ((macosversion[0] != '\0') && (macosproductversion[0] != '\0')) {
698 		snprintf((char *)&panic_info->eph_macos_version, sizeof(panic_info->eph_macos_version), PANIC_HEADER_VERSION_FMT_STR,
699 		    macosproductversion, macosversion);
700 	}
701 #endif
702 	if (bootsessionuuid_string[0] != '\0') {
703 		memcpy(panic_info->eph_bootsessionuuid_string, bootsessionuuid_string,
704 		    sizeof(panic_info->eph_bootsessionuuid_string));
705 	}
706 	panic_info->eph_roots_installed = roots_installed;
707 
708 	if (panic_initiator != NULL) {
709 		bytes_remaining = debug_buf_size - (unsigned int)((uintptr_t)debug_buf_ptr - (uintptr_t)debug_buf_base);
710 		// If panic_initiator isn't null, safely copy up to MAX_PANIC_INITIATOR_SIZE
711 		panic_initiator_len = strnlen(panic_initiator, MAX_PANIC_INITIATOR_SIZE);
712 		// Calculate the bytes to write, accounting for remaining buffer space, and ensuring the lowest size we can have is 0
713 		panic_initiator_len = MAX(0, MIN(panic_initiator_len, bytes_remaining));
714 		panic_info->eph_panic_initiator_offset = (panic_initiator_len != 0) ? PE_get_offset_into_panic_region(debug_buf_ptr) : 0;
715 		panic_info->eph_panic_initiator_len = panic_initiator_len;
716 		memcpy(debug_buf_ptr, panic_initiator, panic_initiator_len);
717 		debug_buf_ptr += panic_initiator_len;
718 	}
719 
720 	if (debug_ack_timeout_count) {
721 		panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_FAILED_DEBUGGERSYNC;
722 		panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
723 		paniclog_append_noflush("!! debugger synchronization failed, no stackshot !!\n");
724 	} else if (panic_stackshot_active()) {
725 		panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_FAILED_NESTED;
726 		panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
727 		paniclog_append_noflush("!! panicked during stackshot, skipping panic stackshot !!\n");
728 	} else {
729 		/* Align the stackshot buffer to an 8-byte address (especially important for armv7k devices) */
730 		debug_buf_ptr += (8 - ((uintptr_t)debug_buf_ptr % 8));
731 		stackshot_begin_loc = debug_buf_ptr;
732 
733 		bytes_remaining = debug_buf_size - (unsigned int)((uintptr_t)stackshot_begin_loc - (uintptr_t)debug_buf_base);
734 		err = kcdata_memory_static_init(&kc_panic_data, (mach_vm_address_t)debug_buf_ptr,
735 		    KCDATA_BUFFER_BEGIN_COMPRESSED, bytes_remaining - end_marker_bytes,
736 		    KCFLAG_USE_MEMCOPY);
737 		if (err == KERN_SUCCESS) {
738 			uint64_t stackshot_flags = (STACKSHOT_GET_GLOBAL_MEM_STATS | STACKSHOT_SAVE_LOADINFO | STACKSHOT_KCDATA_FORMAT |
739 			    STACKSHOT_ENABLE_BT_FAULTING | STACKSHOT_ENABLE_UUID_FAULTING | STACKSHOT_FROM_PANIC | STACKSHOT_DO_COMPRESS |
740 			    STACKSHOT_DISABLE_LATENCY_INFO | STACKSHOT_NO_IO_STATS | STACKSHOT_THREAD_WAITINFO | STACKSHOT_GET_DQ |
741 			    STACKSHOT_COLLECT_SHAREDCACHE_LAYOUT);
742 
743 			err = kcdata_init_compress(&kc_panic_data, KCDATA_BUFFER_BEGIN_STACKSHOT, kdp_memcpy, KCDCT_ZLIB);
744 			if (err != KERN_SUCCESS) {
745 				panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_COMPRESS_FAILED;
746 				stackshot_flags &= ~STACKSHOT_DO_COMPRESS;
747 			}
748 			if (filesetKC) {
749 				stackshot_flags |= STACKSHOT_SAVE_KEXT_LOADINFO;
750 			}
751 
752 			kdp_snapshot_preflight(-1, stackshot_begin_loc, bytes_remaining - end_marker_bytes,
753 			    stackshot_flags, &kc_panic_data, 0, 0);
754 			err = do_panic_stackshot(NULL);
755 			bytes_traced = kdp_stack_snapshot_bytes_traced();
756 			if (bytes_traced > 0 && !err) {
757 				debug_buf_ptr += bytes_traced;
758 				panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_SUCCEEDED;
759 				panic_info->eph_stackshot_offset = PE_get_offset_into_panic_region(stackshot_begin_loc);
760 				panic_info->eph_stackshot_len = bytes_traced;
761 
762 				panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
763 #if CONFIG_EXCLAVES
764 				panic_report_exclaves_stackshot();
765 #endif /* CONFIG_EXCLAVES */
766 				if (stackshot_flags & STACKSHOT_DO_COMPRESS) {
767 					panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_DATA_COMPRESSED;
768 					bytes_uncompressed = kdp_stack_snapshot_bytes_uncompressed();
769 					paniclog_append_noflush("\n** Stackshot Succeeded ** Bytes Traced %d (Uncompressed %d) **\n", bytes_traced, bytes_uncompressed);
770 				} else {
771 					paniclog_append_noflush("\n** Stackshot Succeeded ** Bytes Traced %d **\n", bytes_traced);
772 				}
773 			} else {
774 				bytes_used = kcdata_memory_get_used_bytes(&kc_panic_data);
775 #if CONFIG_EXCLAVES
776 				panic_report_exclaves_stackshot();
777 #endif /* CONFIG_EXCLAVES */
778 				if (bytes_used > 0) {
779 					/* Zero out the stackshot data */
780 					bzero(stackshot_begin_loc, bytes_used);
781 					panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_FAILED_INCOMPLETE;
782 
783 					panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
784 					paniclog_append_noflush("\n** Stackshot Incomplete ** Bytes Filled %llu, err %d **\n", bytes_used, err);
785 				} else {
786 					bzero(stackshot_begin_loc, bytes_used);
787 					panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_FAILED_ERROR;
788 
789 					panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
790 					paniclog_append_noflush("\n!! Stackshot Failed !! Bytes Traced %d, err %d\n", bytes_traced, err);
791 				}
792 			}
793 		} else {
794 			panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_STACKSHOT_FAILED_ERROR;
795 			panic_info->eph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr);
796 			paniclog_append_noflush("\n!! Stackshot Failed !!\nkcdata_memory_static_init returned %d", err);
797 		}
798 	}
799 
800 #if CONFIG_EXT_PANICLOG
801 	// Write ext paniclog at the end of the paniclog region.
802 	ext_paniclog_bytes = ext_paniclog_write_panicdata();
803 	panic_info->eph_ext_paniclog_offset = (ext_paniclog_bytes != 0) ?
804 	    PE_get_offset_into_panic_region((debug_buf_base + debug_buf_size) - ext_paniclog_bytes) :
805 	    0;
806 	panic_info->eph_ext_paniclog_len = ext_paniclog_bytes;
807 #endif
808 
809 	assert(panic_info->eph_other_log_offset != 0);
810 
811 	if (print_vnodes != 0) {
812 		panic_print_vnodes();
813 	}
814 
815 	panic_bt_depth--;
816 }
817 
818 /*
819  * Entry to print_all_backtraces is serialized by the debugger lock
820  */
821 static void
print_all_backtraces(const char * message,uint64_t panic_options,const char * panic_initiator)822 print_all_backtraces(const char *message, uint64_t panic_options, const char *panic_initiator)
823 {
824 	unsigned int initial_not_in_kdp = not_in_kdp;
825 
826 	cpu_data_t * cpu_data_ptr = getCpuDatap();
827 
828 	assert(cpu_data_ptr->PAB_active == FALSE);
829 	cpu_data_ptr->PAB_active = TRUE;
830 
831 	/*
832 	 * Because print all backtraces uses the pmap routines, it needs to
833 	 * avoid taking pmap locks.  Right now, this is conditionalized on
834 	 * not_in_kdp.
835 	 */
836 	not_in_kdp = 0;
837 	do_print_all_backtraces(message, panic_options, panic_initiator);
838 
839 	not_in_kdp = initial_not_in_kdp;
840 
841 	cpu_data_ptr->PAB_active = FALSE;
842 }
843 
844 void
panic_display_times()845 panic_display_times()
846 {
847 	if (kdp_clock_is_locked()) {
848 		paniclog_append_noflush("Warning: clock is locked.  Can't get time\n");
849 		return;
850 	}
851 
852 	extern lck_ticket_t clock_lock;
853 	extern lck_grp_t clock_lock_grp;
854 
855 	if ((is_clock_configured) && (lck_ticket_lock_try(&clock_lock, &clock_lock_grp))) {
856 		clock_sec_t     secs, boot_secs;
857 		clock_usec_t    usecs, boot_usecs;
858 
859 		lck_ticket_unlock(&clock_lock);
860 
861 		clock_get_calendar_microtime(&secs, &usecs);
862 		clock_get_boottime_microtime(&boot_secs, &boot_usecs);
863 
864 		paniclog_append_noflush("mach_absolute_time: 0x%llx\n", mach_absolute_time());
865 		paniclog_append_noflush("Epoch Time:        sec       usec\n");
866 		paniclog_append_noflush("  Boot    : 0x%08x 0x%08x\n", (unsigned int)boot_secs, (unsigned int)boot_usecs);
867 		paniclog_append_noflush("  Sleep   : 0x%08x 0x%08x\n", (unsigned int)gIOLastSleepTime.tv_sec, (unsigned int)gIOLastSleepTime.tv_usec);
868 		paniclog_append_noflush("  Wake    : 0x%08x 0x%08x\n", (unsigned int)gIOLastWakeTime.tv_sec, (unsigned int)gIOLastWakeTime.tv_usec);
869 		paniclog_append_noflush("  Calendar: 0x%08x 0x%08x\n\n", (unsigned int)secs, (unsigned int)usecs);
870 	}
871 }
872 
873 void
panic_print_symbol_name(vm_address_t search)874 panic_print_symbol_name(vm_address_t search)
875 {
876 #pragma unused(search)
877 	// empty stub. Really only used on x86_64.
878 	return;
879 }
880 
881 void
SavePanicInfo(const char * message,__unused void * panic_data,uint64_t panic_options,const char * panic_initiator)882 SavePanicInfo(
883 	const char *message, __unused void *panic_data, uint64_t panic_options, const char* panic_initiator)
884 {
885 	/*
886 	 * This should be initialized by the time we get here, but
887 	 * if it is not, asserting about it will be of no use (it will
888 	 * come right back to here), so just loop right here and now.
889 	 * This prevents early-boot panics from becoming recursive and
890 	 * thus makes them easier to debug. If you attached to a device
891 	 * and see your PC here, look down a few frames to see your
892 	 * early-boot panic there.
893 	 */
894 	while (!panic_info || panic_info->eph_panic_log_offset == 0) {
895 		// rdar://87170225 (PanicHardening: audit panic code for naked spinloops)
896 		// rdar://88094367 (Add test hooks for panic at different stages in XNU)
897 		;
898 	}
899 
900 	if (panic_options & DEBUGGER_OPTION_PANICLOGANDREBOOT) {
901 		panic_info->eph_panic_flags  |= EMBEDDED_PANIC_HEADER_FLAG_BUTTON_RESET_PANIC;
902 	}
903 
904 	if (panic_options & DEBUGGER_OPTION_COMPANION_PROC_INITIATED_PANIC) {
905 		panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_COMPANION_PROC_INITIATED_PANIC;
906 	}
907 
908 	if (panic_options & DEBUGGER_OPTION_INTEGRATED_COPROC_INITIATED_PANIC) {
909 		panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_INTEGRATED_COPROC_INITIATED_PANIC;
910 	}
911 
912 	if (panic_options & DEBUGGER_OPTION_USERSPACE_INITIATED_PANIC) {
913 		panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_USERSPACE_INITIATED_PANIC;
914 	}
915 
916 #if defined(XNU_TARGET_OS_BRIDGE)
917 	panic_info->eph_x86_power_state = PE_smc_stashed_x86_power_state;
918 	panic_info->eph_x86_efi_boot_state = PE_smc_stashed_x86_efi_boot_state;
919 	panic_info->eph_x86_system_state = PE_smc_stashed_x86_system_state;
920 #endif
921 
922 	/*
923 	 * On newer targets, panic data is stored directly into the iBoot panic region.
924 	 * If we re-enter SavePanicInfo (e.g. on a double panic) on such a target, update the
925 	 * panic CRC so that iBoot can hopefully find *something* useful in the panic region.
926 	 */
927 	if (PanicInfoSaved && (debug_buf_base >= (char*)gPanicBase) && (debug_buf_base < (char*)gPanicBase + gPanicSize)) {
928 		unsigned int pi_size = (unsigned int)(debug_buf_ptr - gPanicBase);
929 		PE_update_panic_crc((unsigned char*)gPanicBase, &pi_size);
930 		PE_sync_panic_buffers(); // extra precaution; panic path likely isn't reliable if we're here
931 	}
932 
933 	if (PanicInfoSaved || (debug_buf_size == 0)) {
934 		return;
935 	}
936 
937 	PanicInfoSaved = TRUE;
938 
939 
940 	print_all_backtraces(message, panic_options, panic_initiator);
941 
942 	assert(panic_info->eph_panic_log_len != 0);
943 	panic_info->eph_other_log_len = PE_get_offset_into_panic_region(debug_buf_ptr) - panic_info->eph_other_log_offset;
944 
945 	PEHaltRestart(kPEPanicSync);
946 
947 	/*
948 	 * Notifies registered IOPlatformPanicAction callbacks
949 	 * (which includes one to disable the memcache) and flushes
950 	 * the buffer contents from the cache
951 	 */
952 	paniclog_flush();
953 }
954 
955 void
paniclog_flush()956 paniclog_flush()
957 {
958 	unsigned int panicbuf_length = 0;
959 
960 	panicbuf_length = (unsigned int)(debug_buf_ptr - gPanicBase);
961 	if (!debug_buf_ptr || !panicbuf_length) {
962 		return;
963 	}
964 
965 	/*
966 	 * Updates the log length of the last part of the panic log.
967 	 */
968 	panic_info->eph_other_log_len = PE_get_offset_into_panic_region(debug_buf_ptr) - panic_info->eph_other_log_offset;
969 
970 	/*
971 	 * Updates the metadata at the beginning of the panic buffer,
972 	 * updates the CRC.
973 	 */
974 	PE_update_panic_crc((unsigned char *)gPanicBase, &panicbuf_length);
975 
976 	/*
977 	 * This is currently unused by platform KEXTs on embedded but is
978 	 * kept for compatibility with the published IOKit interfaces.
979 	 */
980 	PESavePanicInfo((unsigned char *)gPanicBase, panicbuf_length);
981 
982 	PE_sync_panic_buffers();
983 }
984 
985 #if CONFIG_SPTM
986 /*
987  * Patch thread state to appear as if a debugger stop IPI occurred, when a thread
988  * is parked in SPTM panic loop. This allows stackshot to proceed as usual.
989  */
990 static void
DebuggerPatchupThreadState(int cpu,xnu_saved_registers_t * regp)991 DebuggerPatchupThreadState(
992 	int cpu, xnu_saved_registers_t *regp)
993 {
994 	cpu_data_t         *target_cpu_datap;
995 	arm_saved_state_t  *statep;
996 	vm_offset_t        kstackptr;
997 
998 	target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
999 	statep = target_cpu_datap->cpu_active_thread->machine.kpcb;
1000 	kstackptr = (vm_offset_t)target_cpu_datap->cpu_active_thread->machine.kstackptr;
1001 
1002 	target_cpu_datap->ipi_pc = regp->pc;
1003 	target_cpu_datap->ipi_lr = regp->lr;
1004 	target_cpu_datap->ipi_fp = regp->fp;
1005 
1006 	if (statep != NULL) {
1007 		statep->ss_64.fp = regp->fp;
1008 		statep->ss_64.lr = regp->lr;
1009 		statep->ss_64.sp = regp->sp;
1010 		statep->ss_64.pc = regp->pc;
1011 	} else if ((void *)kstackptr != NULL) {
1012 		arm_kernel_saved_state_t *kstatep = (arm_kernel_saved_state_t *)kstackptr;
1013 		kstatep->fp = regp->fp;
1014 		kstatep->lr = regp->lr;
1015 		kstatep->sp = regp->sp;
1016 	}
1017 }
1018 #endif
1019 
1020 /*
1021  * @function DebuggerXCallEnter
1022  *
1023  * @abstract IPI other cores so this core can run in a single-threaded context.
1024  *
1025  * @discussion This function should be called with the debugger lock held.  It
1026  * signals the other cores to go into a busy loop so this core can run in a
1027  * single-threaded context and inspect kernel memory.
1028  *
1029  * @param proceed_on_sync_failure If true, then go ahead and try to debug even
1030  * if we can't synch with the other cores.  This is inherently unsafe and should
1031  * only be used if the kernel is going down in flames anyway.
1032  *
1033  * @param is_stackshot If true, this is a stackshot request.
1034  *
1035  * @result returns KERN_OPERATION_TIMED_OUT if synchronization times out and
1036  * proceed_on_sync_failure is false.
1037  */
1038 kern_return_t
DebuggerXCallEnter(boolean_t proceed_on_sync_failure,bool is_stackshot)1039 DebuggerXCallEnter(
1040 	boolean_t proceed_on_sync_failure, bool is_stackshot)
1041 {
1042 	uint64_t max_mabs_time, current_mabs_time;
1043 	int cpu;
1044 	int timeout_cpu = -1;
1045 	int max_cpu;
1046 	unsigned int sync_pending;
1047 	cpu_data_t      *target_cpu_datap;
1048 	cpu_data_t      *cpu_data_ptr = getCpuDatap();
1049 
1050 	/* Check for nested debugger entry. */
1051 	cpu_data_ptr->debugger_active++;
1052 	if (cpu_data_ptr->debugger_active != 1) {
1053 		return KERN_SUCCESS;
1054 	}
1055 
1056 	/*
1057 	 * If debugger_sync is not 0, someone responded excessively late to the last
1058 	 * debug request (we zero the sync variable in the return function).  Zero it
1059 	 * again here.  This should prevent us from getting out of sync (heh) and
1060 	 * timing out on every entry to the debugger if we timeout once.
1061 	 */
1062 
1063 	debugger_sync = 0;
1064 	mp_kdp_trap = 1;
1065 	debug_cpus_spinning = 0;
1066 	trap_is_stackshot = is_stackshot;
1067 
1068 
1069 	/*
1070 	 * Try to signal all CPUs (except ourselves, of course).  Use debugger_sync to
1071 	 * synchronize with every CPU that we appeared to signal successfully (cpu_signal
1072 	 * is not synchronous).
1073 	 */
1074 	max_cpu = ml_get_max_cpu_number();
1075 
1076 	boolean_t immediate_halt = FALSE;
1077 	if (proceed_on_sync_failure && force_immediate_debug_halt) {
1078 		immediate_halt = TRUE;
1079 	}
1080 
1081 	if (!immediate_halt) {
1082 		for (cpu = 0; cpu <= max_cpu; cpu++) {
1083 			target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
1084 
1085 			if ((target_cpu_datap == NULL) || (target_cpu_datap == cpu_data_ptr)) {
1086 				continue;
1087 			}
1088 
1089 			kern_return_t ret = cpu_signal(target_cpu_datap, SIGPdebug, (void *)NULL, NULL);
1090 			if (ret == KERN_SUCCESS) {
1091 				os_atomic_inc(&debugger_sync, relaxed);
1092 				os_atomic_inc(&debug_cpus_spinning, relaxed);
1093 			} else if (proceed_on_sync_failure) {
1094 				kprintf("cpu_signal failed in DebuggerXCallEnter\n");
1095 			}
1096 		}
1097 
1098 		max_mabs_time = os_atomic_load(&debug_ack_timeout, relaxed);
1099 
1100 		if (max_mabs_time > 0) {
1101 			current_mabs_time = mach_absolute_time();
1102 			max_mabs_time += current_mabs_time;
1103 			assert(max_mabs_time > current_mabs_time);
1104 		}
1105 
1106 		/*
1107 		 * Wait for DEBUG_ACK_TIMEOUT ns for a response from everyone we IPI'd.  If we
1108 		 * timeout, that is simply too bad; we don't have a true NMI, and one CPU may be
1109 		 * uninterruptibly spinning on someone else.  The best we can hope for is that
1110 		 * all other CPUs have either responded or are spinning in a context that is
1111 		 * debugger safe.
1112 		 */
1113 		do {
1114 			current_mabs_time = mach_absolute_time();
1115 			sync_pending = os_atomic_load(&debugger_sync, acquire);
1116 		} while ((sync_pending != 0) && (max_mabs_time == 0 || current_mabs_time < max_mabs_time));
1117 	}
1118 
1119 	if (!immediate_halt && max_mabs_time > 0 && current_mabs_time >= max_mabs_time) {
1120 		/*
1121 		 * We timed out trying to IPI the other CPUs. Skip counting any CPUs that
1122 		 * are offline; then we must account for the remainder, either counting
1123 		 * them as halted, or trying to dbgwrap them to get them to halt in the
1124 		 * case where the system is going down and we are running a dev fused
1125 		 * device.
1126 		 */
1127 		__builtin_arm_dmb(DMB_ISH);
1128 		for (cpu = 0; cpu <= max_cpu; cpu++) {
1129 			target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
1130 
1131 			if ((target_cpu_datap == NULL) || (target_cpu_datap == cpu_data_ptr)) {
1132 				continue;
1133 			}
1134 			if (!(target_cpu_datap->cpu_signal & SIGPdebug)) {
1135 				continue;
1136 			}
1137 			if (processor_array[cpu]->state <= PROCESSOR_PENDING_OFFLINE) {
1138 				/*
1139 				 * This is a processor that was successfully sent a SIGPdebug signal
1140 				 * but which hasn't acknowledged it because it went offline with
1141 				 * interrupts disabled before the IPI was delivered, so count it
1142 				 * as halted here.
1143 				 */
1144 				os_atomic_dec(&debugger_sync, relaxed);
1145 				kprintf("%s>found CPU %d offline, debugger_sync=%d\n", __FUNCTION__, cpu, debugger_sync);
1146 				continue;
1147 			}
1148 			timeout_cpu = cpu;
1149 #if CONFIG_SPTM
1150 			if (proceed_on_sync_failure) {
1151 				/*
1152 				 * If a core is spinning in the SPTM panic loop, consider it
1153 				 * as sync'd, and try to patch up the thread state from the
1154 				 * SPTM callee saved registers.
1155 				 */
1156 				bool sptm_panic_loop = false;
1157 				vm_offset_t base = other_percpu_base(cpu);
1158 				pmap_sptm_percpu_data_t *sptm_pcpu = PERCPU_GET_WITH_BASE(base, pmap_sptm_percpu);
1159 				uint64_t sptm_cpuid = sptm_pcpu->sptm_cpu_id;
1160 
1161 				if (sptm_get_cpu_state(sptm_cpuid, CPUSTATE_PANIC_SPIN, &sptm_panic_loop)
1162 				    == SPTM_SUCCESS) {
1163 					xnu_saved_registers_t regs;
1164 
1165 					if (sptm_copy_callee_saved_state(sptm_cpuid, &regs)
1166 					    == LIBSPTM_SUCCESS) {
1167 						DebuggerPatchupThreadState(cpu, &regs);
1168 					}
1169 
1170 					kprintf("%s>found CPU %d in SPTM\n", __FUNCTION__, cpu);
1171 					os_atomic_dec(&debugger_sync, relaxed);
1172 				}
1173 			}
1174 #endif
1175 		}
1176 
1177 		if (debugger_sync == 0) {
1178 			return KERN_SUCCESS;
1179 		} else if (!proceed_on_sync_failure) {
1180 			panic("%s>Debugger synch pending on cpu %d\n",
1181 			    __FUNCTION__, timeout_cpu);
1182 		}
1183 	}
1184 	if (immediate_halt || (max_mabs_time > 0 && current_mabs_time >= max_mabs_time)) {
1185 		if (immediate_halt) {
1186 			__builtin_arm_dmb(DMB_ISH);
1187 		}
1188 		for (cpu = 0; cpu <= max_cpu; cpu++) {
1189 			target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
1190 
1191 			if ((target_cpu_datap == NULL) || (target_cpu_datap == cpu_data_ptr)) {
1192 				continue;
1193 			}
1194 			paniclog_append_noflush("Attempting to forcibly halt cpu %d\n", cpu);
1195 			dbgwrap_status_t halt_status = ml_dbgwrap_halt_cpu(cpu, 0);
1196 			if (halt_status < 0) {
1197 				paniclog_append_noflush("cpu %d failed to halt with error %d: %s\n", cpu, halt_status, ml_dbgwrap_strerror(halt_status));
1198 			} else {
1199 				if (halt_status > 0) {
1200 					paniclog_append_noflush("cpu %d halted with warning %d: %s\n", cpu, halt_status, ml_dbgwrap_strerror(halt_status));
1201 				}
1202 				target_cpu_datap->halt_status = CPU_HALTED;
1203 			}
1204 		}
1205 		for (cpu = 0; cpu <= max_cpu; cpu++) {
1206 			target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
1207 
1208 			if ((target_cpu_datap == NULL) || (target_cpu_datap == cpu_data_ptr)) {
1209 				continue;
1210 			}
1211 			dbgwrap_status_t halt_status = ml_dbgwrap_halt_cpu_with_state(cpu,
1212 			    NSEC_PER_SEC, &target_cpu_datap->halt_state);
1213 			if ((halt_status < 0) || (halt_status == DBGWRAP_WARN_CPU_OFFLINE)) {
1214 				paniclog_append_noflush("Unable to obtain state for cpu %d with status %d: %s\n", cpu, halt_status, ml_dbgwrap_strerror(halt_status));
1215 				debug_ack_timeout_count++;
1216 			} else {
1217 				paniclog_append_noflush("cpu %d successfully halted\n", cpu);
1218 				target_cpu_datap->halt_status = CPU_HALTED_WITH_STATE;
1219 			}
1220 		}
1221 		if (immediate_halt) {
1222 			paniclog_append_noflush("Immediate halt requested on all cores\n");
1223 		} else {
1224 			paniclog_append_noflush("Debugger synchronization timed out; timeout %llu nanoseconds\n",
1225 			    os_atomic_load(&debug_ack_timeout, relaxed));
1226 		}
1227 	}
1228 	return KERN_SUCCESS;
1229 }
1230 
1231 /*
1232  * @function DebuggerXCallReturn
1233  *
1234  * @abstract Resume normal multicore operation after DebuggerXCallEnter()
1235  *
1236  * @discussion This function should be called with debugger lock held.
1237  */
1238 void
DebuggerXCallReturn(void)1239 DebuggerXCallReturn(
1240 	void)
1241 {
1242 	cpu_data_t      *cpu_data_ptr = getCpuDatap();
1243 	uint64_t max_mabs_time, current_mabs_time;
1244 
1245 	cpu_data_ptr->debugger_active--;
1246 	if (cpu_data_ptr->debugger_active != 0) {
1247 		return;
1248 	}
1249 
1250 	mp_kdp_trap = 0;
1251 	debugger_sync = 0;
1252 
1253 	max_mabs_time = os_atomic_load(&debug_ack_timeout, relaxed);
1254 
1255 	if (max_mabs_time > 0) {
1256 		current_mabs_time = mach_absolute_time();
1257 		max_mabs_time += current_mabs_time;
1258 		assert(max_mabs_time > current_mabs_time);
1259 	}
1260 
1261 	/*
1262 	 * Wait for other CPUs to stop spinning on mp_kdp_trap (see DebuggerXCall).
1263 	 * It's possible for one or more CPUs to not decrement debug_cpus_spinning,
1264 	 * since they may be stuck somewhere else with interrupts disabled.
1265 	 * Wait for DEBUG_ACK_TIMEOUT ns for a response and move on if we don't get it.
1266 	 *
1267 	 * Note that the same is done in DebuggerXCallEnter, when we wait for other
1268 	 * CPUS to update debugger_sync. If we time out, let's hope for all CPUs to be
1269 	 * spinning in a debugger-safe context
1270 	 */
1271 	while ((os_atomic_load_exclusive(&debug_cpus_spinning, acquire) != 0) &&
1272 	    (max_mabs_time == 0 || current_mabs_time < max_mabs_time)) {
1273 		__builtin_arm_wfe();
1274 		current_mabs_time = mach_absolute_time();
1275 	}
1276 	os_atomic_clear_exclusive();
1277 
1278 	// checking debug_ack_timeout != 0 is a workaround for rdar://124242354
1279 	if (current_mabs_time >= max_mabs_time && os_atomic_load(&debug_ack_timeout, relaxed) != 0) {
1280 		panic("Resuming from debugger synchronization failed: waited %llu nanoseconds\n", os_atomic_load(&debug_ack_timeout, relaxed));
1281 	}
1282 }
1283 
1284 extern void wait_while_mp_kdp_trap(bool check_SIGPdebug);
1285 /*
1286  * Spin while mp_kdp_trap is set.
1287  *
1288  * processor_offline() calls this with check_SIGPdebug=true
1289  * to break out of the spin loop if the cpu has SIGPdebug
1290  * pending.
1291  */
1292 void
wait_while_mp_kdp_trap(bool check_SIGPdebug)1293 wait_while_mp_kdp_trap(bool check_SIGPdebug)
1294 {
1295 	bool found_mp_kdp_trap = false;
1296 	bool found_SIGPdebug = false;
1297 
1298 	while (os_atomic_load_exclusive(&mp_kdp_trap, relaxed) != 0) {
1299 		found_mp_kdp_trap = true;
1300 		if (check_SIGPdebug && cpu_has_SIGPdebug_pending()) {
1301 			found_SIGPdebug = true;
1302 			break;
1303 		}
1304 		__builtin_arm_wfe();
1305 	}
1306 	os_atomic_clear_exclusive();
1307 
1308 	if (check_SIGPdebug && found_mp_kdp_trap) {
1309 		kprintf("%s>found_mp_kdp_trap=true found_SIGPdebug=%s\n", __FUNCTION__, found_SIGPdebug ? "true" : "false");
1310 	}
1311 }
1312 
1313 void
DebuggerXCall(void * ctx)1314 DebuggerXCall(
1315 	void            *ctx)
1316 {
1317 	boolean_t               save_context = FALSE;
1318 	vm_offset_t             kstackptr = 0;
1319 	arm_saved_state_t       *regs = (arm_saved_state_t *) ctx;
1320 
1321 	if (regs != NULL) {
1322 #if defined(__arm64__)
1323 		current_cpu_datap()->ipi_pc = (uint64_t)get_saved_state_pc(regs);
1324 		current_cpu_datap()->ipi_lr = (uint64_t)get_saved_state_lr(regs);
1325 		current_cpu_datap()->ipi_fp = (uint64_t)get_saved_state_fp(regs);
1326 		save_context = PSR64_IS_KERNEL(get_saved_state_cpsr(regs));
1327 #endif
1328 	}
1329 
1330 	kstackptr = (vm_offset_t)current_thread()->machine.kstackptr;
1331 
1332 #if defined(__arm64__)
1333 	arm_kernel_saved_state_t *state = (arm_kernel_saved_state_t *)kstackptr;
1334 
1335 	if (save_context) {
1336 		/* Save the interrupted context before acknowledging the signal */
1337 		current_thread()->machine.kpcb = regs;
1338 	} else if (regs) {
1339 		/* zero old state so machine_trace_thread knows not to backtrace it */
1340 		state->fp = 0;
1341 		state->pc_was_in_userspace = true;
1342 		state->lr = 0;
1343 		state->sp = 0;
1344 		state->ssbs = 0;
1345 		state->uao = 0;
1346 		state->dit = 0;
1347 	}
1348 #endif
1349 
1350 	/*
1351 	 * When running in serial mode, the core capturing the dump may hold interrupts disabled
1352 	 * for a time longer than the timeout. That path includes logic to reset the timestamp
1353 	 * so that we do not eventually trigger the interrupt timeout assert().
1354 	 *
1355 	 * Here we check whether other cores have already gone over the timeout at this point
1356 	 * before spinning, so we at least cover the IPI reception path. After spinning, however,
1357 	 * we reset the timestamp so as to avoid hitting the interrupt timeout assert().
1358 	 */
1359 	if ((serialmode & SERIALMODE_OUTPUT) || trap_is_stackshot) {
1360 		INTERRUPT_MASKED_DEBUG_END();
1361 	}
1362 
1363 	/*
1364 	 * Before we decrement debugger sync, do stackshot preflight work (if applicable).
1365 	 * Namely, we want to signal that we're available to do stackshot work, and we need to
1366 	 * signal so before the stackshot-calling CPU starts work.
1367 	 */
1368 
1369 	if (trap_is_stackshot) {
1370 		stackshot_cpu_preflight();
1371 	}
1372 
1373 	os_atomic_dec(&debugger_sync, release);
1374 
1375 	/* If we trapped because we're doing a stackshot, do our work first. */
1376 	if (trap_is_stackshot) {
1377 		stackshot_aux_cpu_entry();
1378 	}
1379 
1380 
1381 	wait_while_mp_kdp_trap(false);
1382 
1383 	/**
1384 	 * Alert the triggering CPU that this CPU is done spinning. The CPU that
1385 	 * signalled all of the other CPUs will wait (in DebuggerXCallReturn) for
1386 	 * all of the CPUs to exit the above loop before continuing.
1387 	 */
1388 	os_atomic_dec(&debug_cpus_spinning, release);
1389 
1390 #if SCHED_HYGIENE_DEBUG
1391 	/*
1392 	 * We also abandon the measurement for preemption disable
1393 	 * timeouts, if any. Normally, time in interrupt handlers would be
1394 	 * subtracted from preemption disable time, and this will happen
1395 	 * up to this point here, but since we here "end" the interrupt
1396 	 * handler prematurely (from the point of view of interrupt masked
1397 	 * debugging), the time spinning would otherwise still be
1398 	 * attributed to preemption disable time, and potentially trigger
1399 	 * an event, which could be a panic.
1400 	 */
1401 	abandon_preemption_disable_measurement();
1402 #endif /* SCHED_HYGIENE_DEBUG */
1403 
1404 	if ((serialmode & SERIALMODE_OUTPUT) || trap_is_stackshot) {
1405 		INTERRUPT_MASKED_DEBUG_START(current_thread()->machine.int_handler_addr, current_thread()->machine.int_type);
1406 	}
1407 
1408 #if defined(__arm64__)
1409 	current_thread()->machine.kpcb = NULL;
1410 #endif /* defined(__arm64__) */
1411 
1412 	/* Any cleanup for our pushed context should go here */
1413 }
1414 
1415 void
DebuggerCall(unsigned int reason,void * ctx)1416 DebuggerCall(
1417 	unsigned int    reason,
1418 	void            *ctx)
1419 {
1420 #if     !MACH_KDP
1421 #pragma unused(reason,ctx)
1422 #endif /* !MACH_KDP */
1423 
1424 #if ALTERNATE_DEBUGGER
1425 	alternate_debugger_enter();
1426 #endif
1427 
1428 #if     MACH_KDP
1429 	kdp_trap(reason, (struct arm_saved_state *)ctx);
1430 #else
1431 	/* TODO: decide what to do if no debugger config */
1432 #endif
1433 }
1434 
1435 boolean_t
bootloader_valid_page(ppnum_t ppn)1436 bootloader_valid_page(ppnum_t ppn)
1437 {
1438 	return pmap_bootloader_page(ppn);
1439 }
1440