xref: /xnu-8792.61.2/osfmk/kern/debug.c (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
1 /*
2  * Copyright (c) 2000-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  * @OSF_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 
57 #include <mach_assert.h>
58 #include <mach_kdp.h>
59 #include <kdp/kdp.h>
60 #include <kdp/kdp_core.h>
61 #include <kdp/kdp_internal.h>
62 #include <kdp/kdp_callout.h>
63 #include <kern/cpu_number.h>
64 #include <kern/kalloc.h>
65 #include <kern/percpu.h>
66 #include <kern/spl.h>
67 #include <kern/thread.h>
68 #include <kern/assert.h>
69 #include <kern/sched_prim.h>
70 #include <kern/socd_client.h>
71 #include <kern/misc_protos.h>
72 #include <kern/clock.h>
73 #include <kern/telemetry.h>
74 #include <kern/ecc.h>
75 #include <kern/kern_cdata.h>
76 #include <kern/zalloc_internal.h>
77 #include <kern/iotrace.h>
78 #include <pexpert/device_tree.h>
79 #include <vm/vm_kern.h>
80 #include <vm/vm_map.h>
81 #include <vm/pmap.h>
82 #include <vm/vm_compressor.h>
83 #include <stdarg.h>
84 #include <stdatomic.h>
85 #include <sys/pgo.h>
86 #include <console/serial_protos.h>
87 #include <IOKit/IOBSD.h>
88 
89 #if !(MACH_KDP && CONFIG_KDP_INTERACTIVE_DEBUGGING)
90 #include <kdp/kdp_udp.h>
91 #endif
92 #include <kern/processor.h>
93 
94 #if defined(__i386__) || defined(__x86_64__)
95 #include <IOKit/IOBSD.h>
96 
97 #include <i386/cpu_threads.h>
98 #include <i386/pmCPU.h>
99 #include <i386/lbr.h>
100 #endif
101 
102 #include <IOKit/IOPlatformExpert.h>
103 #include <machine/machine_cpu.h>
104 #include <machine/pal_routines.h>
105 
106 #include <sys/kdebug.h>
107 #include <libkern/OSKextLibPrivate.h>
108 #include <libkern/OSAtomic.h>
109 #include <libkern/kernel_mach_header.h>
110 #include <libkern/section_keywords.h>
111 #include <uuid/uuid.h>
112 #include <mach_debug/zone_info.h>
113 #include <mach/resource_monitors.h>
114 #include <machine/machine_routines.h>
115 
116 #include <os/log_private.h>
117 
118 #if defined(__arm64__)
119 #include <pexpert/pexpert.h> /* For gPanicBase */
120 #include <arm/caches_internal.h>
121 #include <arm/misc_protos.h>
122 extern volatile struct xnu_hw_shmem_dbg_command_info *hwsd_info;
123 #endif
124 
125 #include <san/kcov.h>
126 
127 #if CONFIG_XNUPOST
128 #include <tests/xnupost.h>
129 extern int vsnprintf(char *, size_t, const char *, va_list);
130 #endif
131 
132 #if CONFIG_CSR
133 #include <sys/csr.h>
134 #endif
135 
136 extern int IODTGetLoaderInfo( const char *key, void **infoAddr, int *infosize );
137 extern void IODTFreeLoaderInfo( const char *key, void *infoAddr, int infoSize );
138 
139 unsigned int    halt_in_debugger = 0;
140 unsigned int    current_debugger = 0;
141 unsigned int    active_debugger = 0;
142 unsigned int    panicDebugging = FALSE;
143 unsigned int    kernel_debugger_entry_count = 0;
144 
145 #if DEVELOPMENT || DEBUG
146 unsigned int    panic_test_failure_mode = PANIC_TEST_FAILURE_MODE_BADPTR;
147 unsigned int    panic_test_action_count = 1;
148 unsigned int    panic_test_case = PANIC_TEST_CASE_DISABLED;
149 #endif
150 
151 #if defined(__arm64__)
152 struct additional_panic_data_buffer *panic_data_buffers = NULL;
153 #endif
154 
155 #if defined(__arm64__)
156 /*
157  * Magic number; this should be identical to the armv7 encoding for trap.
158  */
159 #define TRAP_DEBUGGER __asm__ volatile(".long 0xe7ffdeff")
160 #elif defined (__x86_64__)
161 #define TRAP_DEBUGGER __asm__("int3")
162 #else
163 #error No TRAP_DEBUGGER for this architecture
164 #endif
165 
166 #if defined(__i386__) || defined(__x86_64__)
167 #define panic_stop()    pmCPUHalt(PM_HALT_PANIC)
168 #else
169 #define panic_stop()    panic_spin_forever()
170 #endif
171 
172 struct debugger_state {
173 	uint64_t        db_panic_options;
174 	debugger_op     db_current_op;
175 	boolean_t       db_proceed_on_sync_failure;
176 	const char     *db_message;
177 	const char     *db_panic_str;
178 	va_list        *db_panic_args;
179 	void           *db_panic_data_ptr;
180 	unsigned long   db_panic_caller;
181 	/* incremented whenever we panic or call Debugger (current CPU panic level) */
182 	uint32_t        db_entry_count;
183 	kern_return_t   db_op_return;
184 };
185 static struct debugger_state PERCPU_DATA(debugger_state);
186 
187 /* __pure2 is correct if this function is called with preemption disabled */
188 static inline __pure2 struct debugger_state *
current_debugger_state(void)189 current_debugger_state(void)
190 {
191 	return PERCPU_GET(debugger_state);
192 }
193 
194 #define CPUDEBUGGEROP    current_debugger_state()->db_current_op
195 #define CPUDEBUGGERMSG   current_debugger_state()->db_message
196 #define CPUPANICSTR      current_debugger_state()->db_panic_str
197 #define CPUPANICARGS     current_debugger_state()->db_panic_args
198 #define CPUPANICOPTS     current_debugger_state()->db_panic_options
199 #define CPUPANICDATAPTR  current_debugger_state()->db_panic_data_ptr
200 #define CPUDEBUGGERSYNC  current_debugger_state()->db_proceed_on_sync_failure
201 #define CPUDEBUGGERCOUNT current_debugger_state()->db_entry_count
202 #define CPUDEBUGGERRET   current_debugger_state()->db_op_return
203 #define CPUPANICCALLER   current_debugger_state()->db_panic_caller
204 
205 
206 /*
207  *  Usage:
208  *  panic_test_action_count is in the context of other flags, e.g. for IO errors it is "succeed this many times then fail" and for nesting it is "panic this many times then succeed"
209  *  panic_test_failure_mode is a bit map of things to do
210  *  panic_test_case is what sort of test we are injecting
211  *
212  *  For more details see definitions in debugger.h
213  *
214  *  Note that not all combinations are sensible, but some actions can be combined, e.g.
215  *  - BADPTR+SPIN with action count = 3 will cause panic->panic->spin
216  *  - BADPTR with action count = 2 will cause 2 nested panics (in addition to the initial panic)
217  *  - IO_ERR with action 15 will cause 14 successful IOs, then fail on the next one
218  */
219 #if DEVELOPMENT || DEBUG
220 #define INJECT_NESTED_PANIC_IF_REQUESTED(requested)                                                                                                                                                                                                         \
221 MACRO_BEGIN                                                                                                                                                                                                                                                                                                                     \
222 	if ((panic_test_case & requested) && panic_test_action_count) {                                                                                                                                                                                                                                                                                                \
223 	    panic_test_action_count--; \
224 	        volatile int *panic_test_badpointer = (int *)4;                                                                                                                                                                                                                         \
225 	        if ((panic_test_failure_mode & PANIC_TEST_FAILURE_MODE_SPIN) && (!panic_test_action_count)) { printf("inject spin...\n"); while(panic_test_badpointer); }                                                                       \
226 	        if ((panic_test_failure_mode & PANIC_TEST_FAILURE_MODE_BADPTR) && (panic_test_action_count+1)) { printf("inject badptr...\n"); *panic_test_badpointer = 0; }                                                                       \
227 	        if ((panic_test_failure_mode & PANIC_TEST_FAILURE_MODE_PANIC) && (panic_test_action_count+1)) { printf("inject panic...\n"); panic("nested panic level %d", panic_test_action_count); }                      \
228 	}                                                                                                                                                                                                                                                                                                                               \
229 MACRO_END
230 
231 #endif /* DEVELOPMENT || DEBUG */
232 
233 debugger_op debugger_current_op = DBOP_NONE;
234 const char *debugger_panic_str = NULL;
235 va_list *debugger_panic_args = NULL;
236 void *debugger_panic_data = NULL;
237 uint64_t debugger_panic_options = 0;
238 const char *debugger_message = NULL;
239 unsigned long debugger_panic_caller = 0;
240 
241 void panic_trap_to_debugger(const char *panic_format_str, va_list *panic_args,
242     unsigned int reason, void *ctx, uint64_t panic_options_mask, void *panic_data,
243     unsigned long panic_caller) __dead2 __printflike(1, 0);
244 static void kdp_machine_reboot_type(unsigned int type, uint64_t debugger_flags);
245 void panic_spin_forever(void) __dead2;
246 extern kern_return_t do_stackshot(void);
247 extern void PE_panic_hook(const char*);
248 
249 #define NESTEDDEBUGGERENTRYMAX 5
250 static unsigned int max_debugger_entry_count = NESTEDDEBUGGERENTRYMAX;
251 
252 SECURITY_READ_ONLY_LATE(bool) awl_scratch_reg_supported = false;
253 static bool PERCPU_DATA(hv_entry_detected); // = false
254 static void awl_set_scratch_reg_hv_bit(void);
255 void awl_mark_hv_entry(void);
256 static bool awl_pm_state_change_cbk(void *param, enum cpu_event event, unsigned int cpu_or_cluster);
257 
258 #if defined(__arm64__)
259 #define DEBUG_BUF_SIZE (4096)
260 
261 /* debug_buf is directly linked with iBoot panic region for arm targets */
262 char *debug_buf_base = NULL;
263 char *debug_buf_ptr = NULL;
264 unsigned int debug_buf_size = 0;
265 
266 SECURITY_READ_ONLY_LATE(boolean_t) kdp_explicitly_requested = FALSE;
267 #else /* defined(__arm64__) */
268 #define DEBUG_BUF_SIZE ((3 * PAGE_SIZE) + offsetof(struct macos_panic_header, mph_data))
269 /* EXTENDED_DEBUG_BUF_SIZE definition is now in debug.h */
270 static_assert(((EXTENDED_DEBUG_BUF_SIZE % PANIC_FLUSH_BOUNDARY) == 0), "Extended debug buf size must match SMC alignment requirements");
271 
272 char debug_buf[DEBUG_BUF_SIZE];
273 struct macos_panic_header *panic_info = (struct macos_panic_header *)debug_buf;
274 char *debug_buf_base = (debug_buf + offsetof(struct macos_panic_header, mph_data));
275 char *debug_buf_ptr = (debug_buf + offsetof(struct macos_panic_header, mph_data));
276 
277 /*
278  * We don't include the size of the panic header in the length of the data we actually write.
279  * On co-processor platforms, we lose sizeof(struct macos_panic_header) bytes from the end of
280  * the end of the log because we only support writing (3*PAGESIZE) bytes.
281  */
282 unsigned int debug_buf_size = (DEBUG_BUF_SIZE - offsetof(struct macos_panic_header, mph_data));
283 
284 boolean_t extended_debug_log_enabled = FALSE;
285 #endif /* defined(__arm64__) */
286 
287 #if defined(XNU_TARGET_OS_OSX)
288 #define KDBG_TRACE_PANIC_FILENAME "/var/tmp/panic.trace"
289 #else
290 #define KDBG_TRACE_PANIC_FILENAME "/var/log/panic.trace"
291 #endif
292 
293 /* Debugger state */
294 atomic_int     debugger_cpu = ATOMIC_VAR_INIT(DEBUGGER_NO_CPU);
295 boolean_t      debugger_allcpus_halted = FALSE;
296 boolean_t      debugger_safe_to_return = TRUE;
297 unsigned int   debugger_context = 0;
298 
299 static char model_name[64];
300 unsigned char *kernel_uuid;
301 
302 boolean_t kernelcache_uuid_valid = FALSE;
303 uuid_t kernelcache_uuid;
304 uuid_string_t kernelcache_uuid_string;
305 
306 boolean_t pageablekc_uuid_valid = FALSE;
307 uuid_t pageablekc_uuid;
308 uuid_string_t pageablekc_uuid_string;
309 
310 boolean_t auxkc_uuid_valid = FALSE;
311 uuid_t auxkc_uuid;
312 uuid_string_t auxkc_uuid_string;
313 
314 
315 /*
316  * By default we treat Debugger() the same as calls to panic(), unless
317  * we have debug boot-args present and the DB_KERN_DUMP_ON_NMI *NOT* set.
318  * If DB_KERN_DUMP_ON_NMI is *NOT* set, return from Debugger() is supported.
319  *
320  * Return from Debugger() is currently only implemented on x86
321  */
322 static boolean_t debugger_is_panic = TRUE;
323 
324 TUNABLE(unsigned int, debug_boot_arg, "debug", 0);
325 
326 TUNABLE(int, verbose_panic_flow_logging, "verbose_panic_flow_logging", 0);
327 
328 char kernel_uuid_string[37]; /* uuid_string_t */
329 char kernelcache_uuid_string[37]; /* uuid_string_t */
330 char   panic_disk_error_description[512];
331 size_t panic_disk_error_description_size = sizeof(panic_disk_error_description);
332 
333 extern unsigned int write_trace_on_panic;
334 int kext_assertions_enable =
335 #if DEBUG || DEVELOPMENT
336     TRUE;
337 #else
338     FALSE;
339 #endif
340 
341 #if (DEVELOPMENT || DEBUG)
342 uint64_t xnu_platform_stall_value = PLATFORM_STALL_XNU_DISABLE;
343 #endif
344 
345 /*
346  * Maintain the physically-contiguous carveouts for the carveout bootargs.
347  */
348 TUNABLE_WRITEABLE(boolean_t, phys_carveout_core, "phys_carveout_core", 1);
349 
350 TUNABLE(uint32_t, phys_carveout_mb, "phys_carveout_mb", 0);
351 SECURITY_READ_ONLY_LATE(vm_offset_t) phys_carveout = 0;
352 SECURITY_READ_ONLY_LATE(uintptr_t) phys_carveout_pa = 0;
353 SECURITY_READ_ONLY_LATE(size_t) phys_carveout_size = 0;
354 
355 
356 /*
357  * Returns whether kernel debugging is expected to be restricted
358  * on the device currently based on CSR or other platform restrictions.
359  */
360 boolean_t
kernel_debugging_restricted(void)361 kernel_debugging_restricted(void)
362 {
363 #if XNU_TARGET_OS_OSX
364 #if CONFIG_CSR
365 	if (csr_check(CSR_ALLOW_KERNEL_DEBUGGER) != 0) {
366 		return TRUE;
367 	}
368 #endif /* CONFIG_CSR */
369 	return FALSE;
370 #else /* XNU_TARGET_OS_OSX */
371 	return FALSE;
372 #endif /* XNU_TARGET_OS_OSX */
373 }
374 
375 __startup_func
376 static void
panic_init(void)377 panic_init(void)
378 {
379 	unsigned long uuidlen = 0;
380 	void *uuid;
381 
382 	uuid = getuuidfromheader(&_mh_execute_header, &uuidlen);
383 	if ((uuid != NULL) && (uuidlen == sizeof(uuid_t))) {
384 		kernel_uuid = uuid;
385 		uuid_unparse_upper(*(uuid_t *)uuid, kernel_uuid_string);
386 	}
387 
388 	/*
389 	 * Take the value of the debug boot-arg into account
390 	 */
391 #if MACH_KDP
392 	if (!kernel_debugging_restricted() && debug_boot_arg) {
393 		if (debug_boot_arg & DB_HALT) {
394 			halt_in_debugger = 1;
395 		}
396 
397 #if defined(__arm64__)
398 		if (debug_boot_arg & DB_NMI) {
399 			panicDebugging  = TRUE;
400 		}
401 #else
402 		panicDebugging = TRUE;
403 #endif /* defined(__arm64__) */
404 	}
405 
406 	if (!PE_parse_boot_argn("nested_panic_max", &max_debugger_entry_count, sizeof(max_debugger_entry_count))) {
407 		max_debugger_entry_count = NESTEDDEBUGGERENTRYMAX;
408 	}
409 
410 #if defined(__arm64__)
411 	char kdpname[80];
412 
413 	kdp_explicitly_requested = PE_parse_boot_argn("kdp_match_name", kdpname, sizeof(kdpname));
414 #endif /* defined(__arm64__) */
415 
416 #endif /* MACH_KDP */
417 
418 #if defined (__x86_64__)
419 	/*
420 	 * By default we treat Debugger() the same as calls to panic(), unless
421 	 * we have debug boot-args present and the DB_KERN_DUMP_ON_NMI *NOT* set.
422 	 * If DB_KERN_DUMP_ON_NMI is *NOT* set, return from Debugger() is supported.
423 	 * This is because writing an on-device corefile is a destructive operation.
424 	 *
425 	 * Return from Debugger() is currently only implemented on x86
426 	 */
427 	if (PE_i_can_has_debugger(NULL) && !(debug_boot_arg & DB_KERN_DUMP_ON_NMI)) {
428 		debugger_is_panic = FALSE;
429 	}
430 #endif
431 }
432 STARTUP(TUNABLES, STARTUP_RANK_MIDDLE, panic_init);
433 
434 #if defined (__x86_64__)
435 void
extended_debug_log_init(void)436 extended_debug_log_init(void)
437 {
438 	assert(coprocessor_paniclog_flush);
439 	/*
440 	 * Allocate an extended panic log buffer that has space for the panic
441 	 * stackshot at the end. Update the debug buf pointers appropriately
442 	 * to point at this new buffer.
443 	 *
444 	 * iBoot pre-initializes the panic region with the NULL character. We set this here
445 	 * so we can accurately calculate the CRC for the region without needing to flush the
446 	 * full region over SMC.
447 	 */
448 	char *new_debug_buf = kalloc_data(EXTENDED_DEBUG_BUF_SIZE, Z_WAITOK | Z_ZERO);
449 
450 	panic_info = (struct macos_panic_header *)new_debug_buf;
451 	debug_buf_ptr = debug_buf_base = (new_debug_buf + offsetof(struct macos_panic_header, mph_data));
452 	debug_buf_size = (EXTENDED_DEBUG_BUF_SIZE - offsetof(struct macos_panic_header, mph_data));
453 
454 	extended_debug_log_enabled = TRUE;
455 
456 	/*
457 	 * Insert a compiler barrier so we don't free the other panic stackshot buffer
458 	 * until after we've marked the new one as available
459 	 */
460 	__compiler_barrier();
461 	kmem_free(kernel_map, panic_stackshot_buf, panic_stackshot_buf_len);
462 	panic_stackshot_buf = 0;
463 	panic_stackshot_buf_len = 0;
464 }
465 #endif /* defined (__x86_64__) */
466 
467 void
debug_log_init(void)468 debug_log_init(void)
469 {
470 #if defined(__arm64__)
471 	if (!gPanicBase) {
472 		printf("debug_log_init: Error!! gPanicBase is still not initialized\n");
473 		return;
474 	}
475 	/* Shift debug buf start location and size by the length of the panic header */
476 	debug_buf_base = (char *)gPanicBase + sizeof(struct embedded_panic_header);
477 	debug_buf_ptr = debug_buf_base;
478 	debug_buf_size = gPanicSize - sizeof(struct embedded_panic_header);
479 #else
480 	kern_return_t kr = KERN_SUCCESS;
481 	bzero(panic_info, DEBUG_BUF_SIZE);
482 
483 	assert(debug_buf_base != NULL);
484 	assert(debug_buf_ptr != NULL);
485 	assert(debug_buf_size != 0);
486 
487 	/*
488 	 * We allocate a buffer to store a panic time stackshot. If we later discover that this is a
489 	 * system that supports flushing a stackshot via an extended debug log (see above), we'll free this memory
490 	 * as it's not necessary on this platform. This information won't be available until the IOPlatform has come
491 	 * up.
492 	 */
493 	kr = kmem_alloc(kernel_map, &panic_stackshot_buf, PANIC_STACKSHOT_BUFSIZE,
494 	    KMA_DATA | KMA_ZERO, VM_KERN_MEMORY_DIAG);
495 	assert(kr == KERN_SUCCESS);
496 	if (kr == KERN_SUCCESS) {
497 		panic_stackshot_buf_len = PANIC_STACKSHOT_BUFSIZE;
498 	}
499 #endif
500 }
501 
502 void
phys_carveout_init(void)503 phys_carveout_init(void)
504 {
505 	if (!PE_i_can_has_debugger(NULL)) {
506 		return;
507 	}
508 
509 	kern_return_t kr;
510 
511 	struct carveout {
512 		const char *name;
513 		vm_offset_t *va;
514 		uint32_t requested_size;
515 		uintptr_t *pa;
516 		size_t *allocated_size;
517 		uint64_t present;
518 	} carveouts[] =
519 	{{"phys_carveout",
520 	  &phys_carveout,
521 	  phys_carveout_mb,
522 	  &phys_carveout_pa,
523 	  &phys_carveout_size,
524 	  (phys_carveout_mb != 0)},
525 	};
526 
527 	for (int i = 0; i < (sizeof(carveouts) / sizeof(struct carveout)); i++) {
528 		if (carveouts[i].present) {
529 			size_t temp_carveout_size = 0;
530 			if (os_mul_overflow(carveouts[i].requested_size, 1024 * 1024, &temp_carveout_size)) {
531 				panic("%s_mb size overflowed (%uMB)",
532 				    carveouts[i].name, carveouts[i].requested_size);
533 				return;
534 			}
535 
536 			kr = kmem_alloc_contig(kernel_map, carveouts[i].va,
537 			    temp_carveout_size, PAGE_MASK, 0, 0,
538 			    KMA_PERMANENT | KMA_NOPAGEWAIT | KMA_DATA, VM_KERN_MEMORY_DIAG);
539 			if (kr != KERN_SUCCESS) {
540 				panic("failed to allocate %uMB for %s_mb: %u",
541 				    carveouts[i].requested_size, carveouts[i].name, (unsigned int)kr);
542 				return;
543 			}
544 
545 			*carveouts[i].pa = kvtophys(*carveouts[i].va);
546 			*carveouts[i].allocated_size = temp_carveout_size;
547 		}
548 	}
549 
550 #if __arm64__ && (DEVELOPMENT || DEBUG)
551 	/* likely panic_trace boot-arg is also set so check and enable tracing if necessary into new carveout */
552 	PE_arm_debug_enable_trace(true);
553 #endif /* __arm64__ && (DEVELOPMENT || DEBUG) */
554 }
555 
556 boolean_t
debug_is_in_phys_carveout(vm_map_offset_t va)557 debug_is_in_phys_carveout(vm_map_offset_t va)
558 {
559 	return phys_carveout_size && va >= phys_carveout &&
560 	       va < (phys_carveout + phys_carveout_size);
561 }
562 
563 boolean_t
debug_can_coredump_phys_carveout(void)564 debug_can_coredump_phys_carveout(void)
565 {
566 	return phys_carveout_core;
567 }
568 
569 static void
DebuggerLock(void)570 DebuggerLock(void)
571 {
572 	int my_cpu = cpu_number();
573 	int debugger_exp_cpu = DEBUGGER_NO_CPU;
574 	assert(ml_get_interrupts_enabled() == FALSE);
575 
576 	if (atomic_load(&debugger_cpu) == my_cpu) {
577 		return;
578 	}
579 
580 	while (!atomic_compare_exchange_strong(&debugger_cpu, &debugger_exp_cpu, my_cpu)) {
581 		debugger_exp_cpu = DEBUGGER_NO_CPU;
582 	}
583 
584 	return;
585 }
586 
587 static void
DebuggerUnlock(void)588 DebuggerUnlock(void)
589 {
590 	assert(atomic_load_explicit(&debugger_cpu, memory_order_relaxed) == cpu_number());
591 
592 	/*
593 	 * We don't do an atomic exchange here in case
594 	 * there's another CPU spinning to acquire the debugger_lock
595 	 * and we never get a chance to update it. We already have the
596 	 * lock so we can simply store DEBUGGER_NO_CPU and follow with
597 	 * a barrier.
598 	 */
599 	atomic_store(&debugger_cpu, DEBUGGER_NO_CPU);
600 	OSMemoryBarrier();
601 
602 	return;
603 }
604 
605 static kern_return_t
DebuggerHaltOtherCores(boolean_t proceed_on_failure,bool is_stackshot)606 DebuggerHaltOtherCores(boolean_t proceed_on_failure, bool is_stackshot)
607 {
608 #if defined(__arm64__)
609 	return DebuggerXCallEnter(proceed_on_failure, is_stackshot);
610 #else /* defined(__arm64__) */
611 #pragma unused(proceed_on_failure)
612 #pragma unused(is_stackshot)
613 	mp_kdp_enter(proceed_on_failure);
614 	return KERN_SUCCESS;
615 #endif
616 }
617 
618 static void
DebuggerResumeOtherCores(void)619 DebuggerResumeOtherCores(void)
620 {
621 #if defined(__arm64__)
622 	DebuggerXCallReturn();
623 #else /* defined(__arm64__) */
624 	mp_kdp_exit();
625 #endif
626 }
627 
628 __printflike(3, 0)
629 static void
DebuggerSaveState(debugger_op db_op,const char * db_message,const char * db_panic_str,va_list * db_panic_args,uint64_t db_panic_options,void * db_panic_data_ptr,boolean_t db_proceed_on_sync_failure,unsigned long db_panic_caller)630 DebuggerSaveState(debugger_op db_op, const char *db_message, const char *db_panic_str,
631     va_list *db_panic_args, uint64_t db_panic_options, void *db_panic_data_ptr,
632     boolean_t db_proceed_on_sync_failure, unsigned long db_panic_caller)
633 {
634 	CPUDEBUGGEROP = db_op;
635 
636 	/*
637 	 * Note:
638 	 * if CPUDEBUGGERCOUNT == 1 then we are in the normal case - record the panic data
639 	 * if CPUDEBUGGERCOUNT > 1 and CPUPANICSTR == NULL then we are in a nested panic that happened before DebuggerSaveState was called, so store the nested panic data
640 	 * if CPUDEBUGGERCOUNT > 1 and CPUPANICSTR != NULL then we are in a nested panic that happened after DebuggerSaveState was called, so leave the original panic data
641 	 *
642 	 * TODO: is it safe to flatten this to if (CPUPANICSTR == NULL)?
643 	 */
644 	if (CPUDEBUGGERCOUNT == 1 || CPUPANICSTR == NULL) {
645 		CPUDEBUGGERMSG = db_message;
646 		CPUPANICSTR = db_panic_str;
647 		CPUPANICARGS = db_panic_args;
648 		CPUPANICDATAPTR = db_panic_data_ptr;
649 		CPUPANICCALLER = db_panic_caller;
650 	}
651 
652 	CPUDEBUGGERSYNC = db_proceed_on_sync_failure;
653 	CPUDEBUGGERRET = KERN_SUCCESS;
654 
655 	/* Reset these on any nested panics */
656 	// follow up in rdar://88497308 (nested panics should not clobber panic flags)
657 	CPUPANICOPTS = db_panic_options;
658 
659 	return;
660 }
661 
662 /*
663  * Save the requested debugger state/action into the current processor's
664  * percu state and trap to the debugger.
665  */
666 kern_return_t
DebuggerTrapWithState(debugger_op db_op,const char * db_message,const char * db_panic_str,va_list * db_panic_args,uint64_t db_panic_options,void * db_panic_data_ptr,boolean_t db_proceed_on_sync_failure,unsigned long db_panic_caller)667 DebuggerTrapWithState(debugger_op db_op, const char *db_message, const char *db_panic_str,
668     va_list *db_panic_args, uint64_t db_panic_options, void *db_panic_data_ptr,
669     boolean_t db_proceed_on_sync_failure, unsigned long db_panic_caller)
670 {
671 	kern_return_t ret;
672 
673 	assert(ml_get_interrupts_enabled() == FALSE);
674 	DebuggerSaveState(db_op, db_message, db_panic_str, db_panic_args,
675 	    db_panic_options, db_panic_data_ptr,
676 	    db_proceed_on_sync_failure, db_panic_caller);
677 
678 	/*
679 	 * On ARM this generates an uncategorized exception -> sleh code ->
680 	 *   DebuggerCall -> kdp_trap -> handle_debugger_trap
681 	 * So that is how XNU ensures that only one core can panic.
682 	 * The rest of the cores are halted by IPI if possible; if that
683 	 * fails it will fall back to dbgwrap.
684 	 */
685 	TRAP_DEBUGGER;
686 
687 	ret = CPUDEBUGGERRET;
688 
689 	DebuggerSaveState(DBOP_NONE, NULL, NULL, NULL, 0, NULL, FALSE, 0);
690 
691 	return ret;
692 }
693 
694 void __attribute__((noinline))
Assert(const char * file,int line,const char * expression)695 Assert(
696 	const char      *file,
697 	int             line,
698 	const char      *expression
699 	)
700 {
701 #if CONFIG_NONFATAL_ASSERTS
702 	static TUNABLE(bool, mach_assert, "assertions", true);
703 
704 	if (!mach_assert) {
705 		kprintf("%s:%d non-fatal Assertion: %s", file, line, expression);
706 		return;
707 	}
708 #endif
709 
710 	panic_plain("%s:%d Assertion failed: %s", file, line, expression);
711 }
712 
713 boolean_t
debug_is_current_cpu_in_panic_state(void)714 debug_is_current_cpu_in_panic_state(void)
715 {
716 	return current_debugger_state()->db_entry_count > 0;
717 }
718 
719 /*
720  * check if we are in a nested panic, report findings, take evasive action where necessary
721  *
722  * see also PE_update_panicheader_nestedpanic
723  */
724 static void
check_and_handle_nested_panic(uint64_t panic_options_mask,unsigned long panic_caller,const char * db_panic_str,va_list * db_panic_args)725 check_and_handle_nested_panic(uint64_t panic_options_mask, unsigned long panic_caller, const char *db_panic_str, va_list *db_panic_args)
726 {
727 	if ((CPUDEBUGGERCOUNT > 1) && (CPUDEBUGGERCOUNT < max_debugger_entry_count)) {
728 		// Note: this is the first indication in the panic log or serial that we are off the rails...
729 		//
730 		// if we panic *before* the paniclog is finalized then this will end up in the ips report with a panic_caller addr that gives us a clue
731 		// if we panic *after* the log is finalized then we will only see it in the serial log
732 		//
733 		paniclog_append_noflush("Nested panic detected - entry count: %d panic_caller: 0x%016lx\n", CPUDEBUGGERCOUNT, panic_caller);
734 		paniclog_flush();
735 
736 		// print the *new* panic string to the console, we might not get it by other means...
737 		// TODO: I tried to write this stuff to the paniclog, but the serial output gets corrupted and the panicstring in the ips file is <mysterious>
738 		// rdar://87846117 (NestedPanic: output panic string to paniclog)
739 		if (db_panic_str) {
740 			printf("Nested panic string:\n");
741 #pragma clang diagnostic push
742 #pragma clang diagnostic ignored "-Wformat-nonliteral"
743 			_doprnt(db_panic_str, db_panic_args, PE_kputc, 0);
744 #pragma clang diagnostic pop
745 			printf("\n<end nested panic string>\n");
746 		}
747 	}
748 
749 	// Stage 1 bailout
750 	//
751 	// Try to complete the normal panic flow, i.e. try to make sure the callouts happen and we flush the paniclog.  If this fails with another nested
752 	// panic then we will land in Stage 2 below...
753 	//
754 	if (CPUDEBUGGERCOUNT == max_debugger_entry_count) {
755 		uint32_t panic_details = 0;
756 
757 		// if this is a force-reset panic then capture a log and reboot immediately.
758 		if (panic_options_mask & DEBUGGER_OPTION_PANICLOGANDREBOOT) {
759 			panic_details |= kPanicDetailsForcePowerOff;
760 		}
761 
762 		// normally the kPEPanicBegin is sent from debugger_collect_diagnostics(), but we might nested-panic before we get
763 		// there.  To be safe send another notification, the function called below will only send kPEPanicBegin if it has not yet been sent.
764 		//
765 		PEHaltRestartInternal(kPEPanicBegin, panic_details);
766 
767 		paniclog_append_noflush("Nested panic count exceeds limit %d, machine will reset or spin\n", max_debugger_entry_count);
768 		PE_update_panicheader_nestedpanic();
769 		paniclog_flush();
770 
771 		if (!panicDebugging) {
772 			// note that this will also send kPEPanicEnd
773 			kdp_machine_reboot_type(kPEPanicRestartCPU, panic_options_mask);
774 		}
775 
776 		// prints to console
777 		paniclog_append_noflush("\nNested panic stall. Stage 1 bailout. Please go to https://panic.apple.com to report this panic\n");
778 		panic_spin_forever();
779 	}
780 
781 	// Stage 2 bailout
782 	//
783 	// Things are severely hosed, we have nested to the point of bailout and then nested again during the bailout path.  Try to issue
784 	// a chipreset as quickly as possible, hopefully something in the panic log is salvageable, since we flushed it during Stage 1.
785 	//
786 	if (CPUDEBUGGERCOUNT == max_debugger_entry_count + 1) {
787 		if (!panicDebugging) {
788 			// note that:
789 			// - this code path should be audited for prints, as that is a common cause of nested panics
790 			// - this code path should take the fastest route to the actual reset, and not call any un-necessary code
791 			kdp_machine_reboot_type(kPEPanicRestartCPU, panic_options_mask & DEBUGGER_OPTION_SKIP_PANICEND_CALLOUTS);
792 		}
793 
794 		// prints to console, but another nested panic will land in Stage 3 where we simply spin, so that is sort of ok...
795 		paniclog_append_noflush("\nIn Nested panic stall. Stage 2 bailout. Please go to https://panic.apple.com to report this panic\n");
796 		panic_spin_forever();
797 	}
798 
799 	// Stage 3 bailout
800 	//
801 	// We are done here, we were unable to reset the platform without another nested panic.  Spin until the watchdog kicks in.
802 	//
803 	if (CPUDEBUGGERCOUNT > max_debugger_entry_count + 1) {
804 		kdp_machine_reboot_type(kPEHangCPU, 0);
805 	}
806 }
807 
808 void
Debugger(const char * message)809 Debugger(const char *message)
810 {
811 	DebuggerWithContext(0, NULL, message, DEBUGGER_OPTION_NONE, (unsigned long)(char *)__builtin_return_address(0));
812 }
813 
814 /*
815  *  Enter the Debugger
816  *
817  *  This is similar to, but not the same as a panic
818  *
819  *  Key differences:
820  *  - we get here from a debugger entry action (e.g. NMI)
821  *  - the system is resumable on x86 (in theory, however it is not clear if this is tested)
822  *  - rdar://57738811 (xnu: support resume from debugger via KDP on arm devices)
823  *
824  */
825 void
DebuggerWithContext(unsigned int reason,void * ctx,const char * message,uint64_t debugger_options_mask,unsigned long debugger_caller)826 DebuggerWithContext(unsigned int reason, void *ctx, const char *message,
827     uint64_t debugger_options_mask, unsigned long debugger_caller)
828 {
829 	spl_t previous_interrupts_state;
830 	boolean_t old_doprnt_hide_pointers = doprnt_hide_pointers;
831 
832 #if defined(__x86_64__) && (DEVELOPMENT || DEBUG)
833 	read_lbr();
834 #endif
835 	previous_interrupts_state = ml_set_interrupts_enabled(FALSE);
836 	disable_preemption();
837 
838 	/* track depth of debugger/panic entry */
839 	CPUDEBUGGERCOUNT++;
840 
841 	/* emit a tracepoint as early as possible in case of hang */
842 	SOCD_TRACE_XNU(PANIC, PACK_2X32(VALUE(cpu_number()), VALUE(CPUDEBUGGERCOUNT)), VALUE(debugger_options_mask), ADDR(message), ADDR(debugger_caller));
843 
844 	/* do max nested panic/debugger check, this will report nesting to the console and spin forever if we exceed a limit */
845 	check_and_handle_nested_panic(debugger_options_mask, debugger_caller, message, NULL);
846 
847 	/* Handle any necessary platform specific actions before we proceed */
848 	PEInitiatePanic();
849 
850 #if DEVELOPMENT || DEBUG
851 	INJECT_NESTED_PANIC_IF_REQUESTED(PANIC_TEST_CASE_RECURPANIC_ENTRY);
852 #endif
853 
854 	PE_panic_hook(message);
855 
856 	doprnt_hide_pointers = FALSE;
857 
858 	if (ctx != NULL) {
859 		DebuggerSaveState(DBOP_DEBUGGER, message,
860 		    NULL, NULL, debugger_options_mask, NULL, TRUE, 0);
861 		handle_debugger_trap(reason, 0, 0, ctx);
862 		DebuggerSaveState(DBOP_NONE, NULL, NULL,
863 		    NULL, 0, NULL, FALSE, 0);
864 	} else {
865 		DebuggerTrapWithState(DBOP_DEBUGGER, message,
866 		    NULL, NULL, debugger_options_mask, NULL, TRUE, 0);
867 	}
868 
869 	/* resume from the debugger */
870 
871 	CPUDEBUGGERCOUNT--;
872 	doprnt_hide_pointers = old_doprnt_hide_pointers;
873 	enable_preemption();
874 	ml_set_interrupts_enabled(previous_interrupts_state);
875 }
876 
877 static struct kdp_callout {
878 	struct kdp_callout * callout_next;
879 	kdp_callout_fn_t callout_fn;
880 	boolean_t callout_in_progress;
881 	void * callout_arg;
882 } * kdp_callout_list = NULL;
883 
884 /*
885  * Called from kernel context to register a kdp event callout.
886  */
887 void
kdp_register_callout(kdp_callout_fn_t fn,void * arg)888 kdp_register_callout(kdp_callout_fn_t fn, void * arg)
889 {
890 	struct kdp_callout * kcp;
891 	struct kdp_callout * list_head;
892 
893 	kcp = zalloc_permanent_type(struct kdp_callout);
894 
895 	kcp->callout_fn = fn;
896 	kcp->callout_arg = arg;
897 	kcp->callout_in_progress = FALSE;
898 
899 	/* Lock-less list insertion using compare and exchange. */
900 	do {
901 		list_head = kdp_callout_list;
902 		kcp->callout_next = list_head;
903 	} while (!OSCompareAndSwapPtr(list_head, kcp, &kdp_callout_list));
904 }
905 
906 static void
kdp_callouts(kdp_event_t event)907 kdp_callouts(kdp_event_t event)
908 {
909 	struct kdp_callout      *kcp = kdp_callout_list;
910 
911 	while (kcp) {
912 		if (!kcp->callout_in_progress) {
913 			kcp->callout_in_progress = TRUE;
914 			kcp->callout_fn(kcp->callout_arg, event);
915 			kcp->callout_in_progress = FALSE;
916 		}
917 		kcp = kcp->callout_next;
918 	}
919 }
920 
921 #if defined(__arm64__)
922 /*
923  * Register an additional buffer with data to include in the panic log
924  *
925  * <rdar://problem/50137705> tracks supporting more than one buffer
926  *
927  * Note that producer_name and buf should never be de-allocated as we reference these during panic.
928  */
929 void
register_additional_panic_data_buffer(const char * producer_name,void * buf,int len)930 register_additional_panic_data_buffer(const char *producer_name, void *buf, int len)
931 {
932 	if (panic_data_buffers != NULL) {
933 		panic("register_additional_panic_data_buffer called with buffer already registered");
934 	}
935 
936 	if (producer_name == NULL || (strlen(producer_name) == 0)) {
937 		panic("register_additional_panic_data_buffer called with invalid producer_name");
938 	}
939 
940 	if (buf == NULL) {
941 		panic("register_additional_panic_data_buffer called with invalid buffer pointer");
942 	}
943 
944 	if ((len <= 0) || (len > ADDITIONAL_PANIC_DATA_BUFFER_MAX_LEN)) {
945 		panic("register_additional_panic_data_buffer called with invalid length");
946 	}
947 
948 	struct additional_panic_data_buffer *new_panic_data_buffer = zalloc_permanent_type(struct additional_panic_data_buffer);
949 	new_panic_data_buffer->producer_name = producer_name;
950 	new_panic_data_buffer->buf = buf;
951 	new_panic_data_buffer->len = len;
952 
953 	if (!OSCompareAndSwapPtr(NULL, new_panic_data_buffer, &panic_data_buffers)) {
954 		panic("register_additional_panic_data_buffer called with buffer already registered");
955 	}
956 
957 	return;
958 }
959 #endif /* defined(__arm64__) */
960 
961 /*
962  * An overview of the xnu panic path:
963  *
964  * Several panic wrappers (panic(), panic_with_options(), etc.) all funnel into panic_trap_to_debugger().
965  * panic_trap_to_debugger() sets the panic state in the current processor's debugger_state prior
966  * to trapping into the debugger. Once we trap to the debugger, we end up in handle_debugger_trap()
967  * which tries to acquire the panic lock by atomically swapping the current CPU number into debugger_cpu.
968  * debugger_cpu acts as a synchronization point, from which the winning CPU can halt the other cores and
969  * continue to debugger_collect_diagnostics() where we write the paniclog, corefile (if appropriate) and proceed
970  * according to the device's boot-args.
971  */
972 #undef panic
973 void
panic(const char * str,...)974 panic(const char *str, ...)
975 {
976 	va_list panic_str_args;
977 
978 	va_start(panic_str_args, str);
979 	panic_trap_to_debugger(str, &panic_str_args, 0, NULL, 0, NULL, (unsigned long)(char *)__builtin_return_address(0));
980 	va_end(panic_str_args);
981 }
982 
983 void
panic_with_options(unsigned int reason,void * ctx,uint64_t debugger_options_mask,const char * str,...)984 panic_with_options(unsigned int reason, void *ctx, uint64_t debugger_options_mask, const char *str, ...)
985 {
986 	va_list panic_str_args;
987 
988 	va_start(panic_str_args, str);
989 	panic_trap_to_debugger(str, &panic_str_args, reason, ctx, (debugger_options_mask & ~DEBUGGER_INTERNAL_OPTIONS_MASK),
990 	    NULL, (unsigned long)(char *)__builtin_return_address(0));
991 	va_end(panic_str_args);
992 }
993 
994 boolean_t
panic_validate_ptr(void * ptr,vm_size_t size,const char * what)995 panic_validate_ptr(void *ptr, vm_size_t size, const char *what)
996 {
997 	if (ptr == NULL) {
998 		paniclog_append_noflush("NULL %s pointer\n", what);
999 		return false;
1000 	}
1001 
1002 	if (!ml_validate_nofault((vm_offset_t)ptr, size)) {
1003 		paniclog_append_noflush("Invalid %s pointer: %p (size %d)\n",
1004 		    what, ptr, (uint32_t)size);
1005 		return false;
1006 	}
1007 
1008 	return true;
1009 }
1010 
1011 boolean_t
panic_get_thread_proc_task(struct thread * thread,struct task ** task,struct proc ** proc)1012 panic_get_thread_proc_task(struct thread *thread, struct task **task, struct proc **proc)
1013 {
1014 	if (!PANIC_VALIDATE_PTR(thread)) {
1015 		return false;
1016 	}
1017 
1018 	if (!PANIC_VALIDATE_PTR(thread->t_tro)) {
1019 		return false;
1020 	}
1021 
1022 	if (!PANIC_VALIDATE_PTR(thread->t_tro->tro_task)) {
1023 		return false;
1024 	}
1025 
1026 	if (task) {
1027 		*task = thread->t_tro->tro_task;
1028 	}
1029 
1030 	if (!panic_validate_ptr(thread->t_tro->tro_proc,
1031 	    sizeof(struct proc *), "bsd_info")) {
1032 		*proc = NULL;
1033 	} else {
1034 		*proc = thread->t_tro->tro_proc;
1035 	}
1036 
1037 	return true;
1038 }
1039 
1040 #if defined (__x86_64__)
1041 /*
1042  * panic_with_thread_context() is used on x86 platforms to specify a different thread that should be backtraced in the paniclog.
1043  * We don't generally need this functionality on embedded platforms because embedded platforms include a panic time stackshot
1044  * from customer devices. We plumb the thread pointer via the debugger trap mechanism and backtrace the kernel stack from the
1045  * thread when writing the panic log.
1046  *
1047  * NOTE: panic_with_thread_context() should be called with an explicit thread reference held on the passed thread.
1048  */
1049 void
panic_with_thread_context(unsigned int reason,void * ctx,uint64_t debugger_options_mask,thread_t thread,const char * str,...)1050 panic_with_thread_context(unsigned int reason, void *ctx, uint64_t debugger_options_mask, thread_t thread, const char *str, ...)
1051 {
1052 	va_list panic_str_args;
1053 	__assert_only os_ref_count_t th_ref_count;
1054 
1055 	assert_thread_magic(thread);
1056 	th_ref_count = os_ref_get_count_raw(&thread->ref_count);
1057 	assertf(th_ref_count > 0, "panic_with_thread_context called with invalid thread %p with refcount %u", thread, th_ref_count);
1058 
1059 	/* Take a reference on the thread so it doesn't disappear by the time we try to backtrace it */
1060 	thread_reference(thread);
1061 
1062 	va_start(panic_str_args, str);
1063 	panic_trap_to_debugger(str, &panic_str_args, reason, ctx, ((debugger_options_mask & ~DEBUGGER_INTERNAL_OPTIONS_MASK) | DEBUGGER_INTERNAL_OPTION_THREAD_BACKTRACE),
1064 	    thread, (unsigned long)(char *)__builtin_return_address(0));
1065 
1066 	va_end(panic_str_args);
1067 }
1068 #endif /* defined (__x86_64__) */
1069 
1070 #pragma clang diagnostic push
1071 #pragma clang diagnostic ignored "-Wmissing-noreturn"
1072 void
panic_trap_to_debugger(const char * panic_format_str,va_list * panic_args,unsigned int reason,void * ctx,uint64_t panic_options_mask,void * panic_data_ptr,unsigned long panic_caller)1073 panic_trap_to_debugger(const char *panic_format_str, va_list *panic_args, unsigned int reason, void *ctx,
1074     uint64_t panic_options_mask, void *panic_data_ptr, unsigned long panic_caller)
1075 {
1076 #pragma clang diagnostic pop
1077 
1078 #if defined(__x86_64__) && (DEVELOPMENT || DEBUG)
1079 	read_lbr();
1080 #endif
1081 
1082 	/* Turn off I/O tracing once we've panicked */
1083 	iotrace_disable();
1084 
1085 	/* call machine-layer panic handler */
1086 	ml_panic_trap_to_debugger(panic_format_str, panic_args, reason, ctx, panic_options_mask, panic_caller);
1087 
1088 	/* track depth of debugger/panic entry */
1089 	CPUDEBUGGERCOUNT++;
1090 
1091 	/* emit a tracepoint as early as possible in case of hang */
1092 	SOCD_TRACE_XNU(PANIC, PACK_2X32(VALUE(cpu_number()), VALUE(CPUDEBUGGERCOUNT)), VALUE(panic_options_mask), ADDR(panic_format_str), ADDR(panic_caller));
1093 
1094 	/* do max nested panic/debugger check, this will report nesting to the console and spin forever if we exceed a limit */
1095 	check_and_handle_nested_panic(panic_options_mask, panic_caller, panic_format_str, panic_args);
1096 
1097 	/* Handle any necessary platform specific actions before we proceed */
1098 	PEInitiatePanic();
1099 
1100 #if DEVELOPMENT || DEBUG
1101 	INJECT_NESTED_PANIC_IF_REQUESTED(PANIC_TEST_CASE_RECURPANIC_ENTRY);
1102 #endif
1103 
1104 	PE_panic_hook(panic_format_str);
1105 
1106 #if defined (__x86_64__)
1107 	plctrace_disable();
1108 #endif
1109 
1110 	if (write_trace_on_panic && kdebug_enable) {
1111 		if (get_preemption_level() == 0 && !ml_at_interrupt_context()) {
1112 			ml_set_interrupts_enabled(TRUE);
1113 			KDBG_RELEASE(TRACE_PANIC);
1114 			kdbg_dump_trace_to_file(KDBG_TRACE_PANIC_FILENAME, false);
1115 		}
1116 	}
1117 
1118 	ml_set_interrupts_enabled(FALSE);
1119 	disable_preemption();
1120 
1121 #if defined (__x86_64__)
1122 	pmSafeMode(x86_lcpu(), PM_SAFE_FL_SAFE);
1123 #endif /* defined (__x86_64__) */
1124 
1125 	/* Never hide pointers from panic logs. */
1126 	doprnt_hide_pointers = FALSE;
1127 
1128 	if (ctx != NULL) {
1129 		/*
1130 		 * We called into panic from a trap, no need to trap again. Set the
1131 		 * state on the current CPU and then jump to handle_debugger_trap.
1132 		 */
1133 		DebuggerSaveState(DBOP_PANIC, "panic",
1134 		    panic_format_str, panic_args,
1135 		    panic_options_mask, panic_data_ptr, TRUE, panic_caller);
1136 		handle_debugger_trap(reason, 0, 0, ctx);
1137 	}
1138 
1139 #if defined(__arm64__)
1140 	/*
1141 	 *  Signal to fastsim that it should open debug ports (nop on hardware)
1142 	 */
1143 	__asm__         volatile ("HINT 0x45");
1144 #endif /* defined(__arm64__) */
1145 
1146 	DebuggerTrapWithState(DBOP_PANIC, "panic", panic_format_str,
1147 	    panic_args, panic_options_mask, panic_data_ptr, TRUE, panic_caller);
1148 
1149 	/*
1150 	 * Not reached.
1151 	 */
1152 	panic_stop();
1153 	__builtin_unreachable();
1154 }
1155 
1156 void
panic_spin_forever(void)1157 panic_spin_forever(void)
1158 {
1159 	for (;;) {
1160 #if defined(__arm__) || defined(__arm64__)
1161 		/* On arm32, which doesn't have a WFE timeout, this may not return.  But that should be OK on this path. */
1162 		__builtin_arm_wfe();
1163 #else
1164 		cpu_pause();
1165 #endif
1166 	}
1167 }
1168 
1169 static void
kdp_machine_reboot_type(unsigned int type,uint64_t debugger_flags)1170 kdp_machine_reboot_type(unsigned int type, uint64_t debugger_flags)
1171 {
1172 	if ((type == kPEPanicRestartCPU) && (debugger_flags & DEBUGGER_OPTION_SKIP_PANICEND_CALLOUTS)) {
1173 		PEHaltRestart(kPEPanicRestartCPUNoCallouts);
1174 	} else {
1175 		PEHaltRestart(type);
1176 	}
1177 	halt_all_cpus(TRUE);
1178 }
1179 
1180 void
kdp_machine_reboot(void)1181 kdp_machine_reboot(void)
1182 {
1183 	kdp_machine_reboot_type(kPEPanicRestartCPU, 0);
1184 }
1185 
1186 static __attribute__((unused)) void
panic_debugger_log(const char * string,...)1187 panic_debugger_log(const char *string, ...)
1188 {
1189 	va_list panic_debugger_log_args;
1190 
1191 	va_start(panic_debugger_log_args, string);
1192 #pragma clang diagnostic push
1193 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1194 	_doprnt(string, &panic_debugger_log_args, consdebug_putc, 16);
1195 #pragma clang diagnostic pop
1196 	va_end(panic_debugger_log_args);
1197 
1198 #if defined(__arm64__)
1199 	paniclog_flush();
1200 #endif
1201 }
1202 
1203 /*
1204  * Gather and save diagnostic information about a panic (or Debugger call).
1205  *
1206  * On embedded, Debugger and Panic are treated very similarly -- WDT uses Debugger so we can
1207  * theoretically return from it. On desktop, Debugger is treated as a conventional debugger -- i.e no
1208  * paniclog is written and no core is written unless we request a core on NMI.
1209  *
1210  * This routine handles kicking off local coredumps, paniclogs, calling into the Debugger/KDP (if it's configured),
1211  * and calling out to any other functions we have for collecting diagnostic info.
1212  */
1213 static void
debugger_collect_diagnostics(unsigned int exception,unsigned int code,unsigned int subcode,void * state)1214 debugger_collect_diagnostics(unsigned int exception, unsigned int code, unsigned int subcode, void *state)
1215 {
1216 #if DEVELOPMENT || DEBUG
1217 	INJECT_NESTED_PANIC_IF_REQUESTED(PANIC_TEST_CASE_RECURPANIC_PRELOG);
1218 #endif
1219 
1220 #if defined(__x86_64__)
1221 	kprintf("Debugger called: <%s>\n", debugger_message ? debugger_message : "");
1222 #endif
1223 	/*
1224 	 * DB_HALT (halt_in_debugger) can be requested on startup, we shouldn't generate
1225 	 * a coredump/paniclog for this type of debugger entry. If KDP isn't configured,
1226 	 * we'll just spin in kdp_raise_exception.
1227 	 */
1228 	if (debugger_current_op == DBOP_DEBUGGER && halt_in_debugger) {
1229 		kdp_raise_exception(exception, code, subcode, state);
1230 		if (debugger_safe_to_return && !debugger_is_panic) {
1231 			return;
1232 		}
1233 	}
1234 
1235 #ifdef CONFIG_KCOV
1236 	/* Try not to break core dump path by sanitizer. */
1237 	kcov_panic_disable();
1238 #endif
1239 
1240 	if ((debugger_current_op == DBOP_PANIC) ||
1241 	    ((debugger_current_op == DBOP_DEBUGGER) && debugger_is_panic)) {
1242 		/*
1243 		 * Attempt to notify listeners once and only once that we've started
1244 		 * panicking. Only do this for Debugger() calls if we're treating
1245 		 * Debugger() calls like panic().
1246 		 */
1247 		uint32_t panic_details = 0;
1248 		/* if this is a force-reset panic then capture a log and reboot immediately. */
1249 		if (debugger_panic_options & DEBUGGER_OPTION_PANICLOGANDREBOOT) {
1250 			panic_details |= kPanicDetailsForcePowerOff;
1251 		}
1252 		PEHaltRestartInternal(kPEPanicBegin, panic_details);
1253 
1254 		/*
1255 		 * Set the begin pointer in the panic log structure. We key off of this
1256 		 * static variable rather than contents from the panic header itself in case someone
1257 		 * has stomped over the panic_info structure. Also initializes the header magic.
1258 		 */
1259 		static boolean_t began_writing_paniclog = FALSE;
1260 		if (!began_writing_paniclog) {
1261 			PE_init_panicheader();
1262 			began_writing_paniclog = TRUE;
1263 		}
1264 
1265 		if (CPUDEBUGGERCOUNT > 1) {
1266 			/*
1267 			 * we are in a nested panic.  Record the nested bit in panic flags and do some housekeeping
1268 			 */
1269 			PE_update_panicheader_nestedpanic();
1270 			paniclog_flush();
1271 		}
1272 	}
1273 
1274 	/*
1275 	 * Write panic string if this was a panic.
1276 	 *
1277 	 * TODO: Consider moving to SavePanicInfo as this is part of the panic log.
1278 	 */
1279 	if (debugger_current_op == DBOP_PANIC) {
1280 		paniclog_append_noflush("panic(cpu %u caller 0x%lx): ", (unsigned) cpu_number(), debugger_panic_caller);
1281 		if (debugger_panic_str) {
1282 #pragma clang diagnostic push
1283 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1284 			_doprnt(debugger_panic_str, debugger_panic_args, consdebug_putc, 0);
1285 #pragma clang diagnostic pop
1286 		}
1287 		paniclog_append_noflush("\n");
1288 	}
1289 #if defined(__x86_64__)
1290 	else if (((debugger_current_op == DBOP_DEBUGGER) && debugger_is_panic)) {
1291 		paniclog_append_noflush("Debugger called: <%s>\n", debugger_message ? debugger_message : "");
1292 	}
1293 
1294 	/*
1295 	 * Debugger() is treated like panic() on embedded -- for example we use it for WDT
1296 	 * panics (so we need to write a paniclog). On desktop Debugger() is used in the
1297 	 * conventional sense.
1298 	 */
1299 	if (debugger_current_op == DBOP_PANIC || ((debugger_current_op == DBOP_DEBUGGER) && debugger_is_panic))
1300 #endif /* __x86_64__ */
1301 	{
1302 		kdp_callouts(KDP_EVENT_PANICLOG);
1303 
1304 		/*
1305 		 * Write paniclog and panic stackshot (if supported)
1306 		 * TODO: Need to clear panic log when return from debugger
1307 		 * hooked up for embedded
1308 		 */
1309 		SavePanicInfo(debugger_message, debugger_panic_data, debugger_panic_options);
1310 
1311 #if DEVELOPMENT || DEBUG
1312 		INJECT_NESTED_PANIC_IF_REQUESTED(PANIC_TEST_CASE_RECURPANIC_POSTLOG);
1313 #endif
1314 
1315 		/* DEBUGGER_OPTION_PANICLOGANDREBOOT is used for two finger resets on embedded so we get a paniclog */
1316 		if (debugger_panic_options & DEBUGGER_OPTION_PANICLOGANDREBOOT) {
1317 			PEHaltRestart(kPEPanicDiagnosticsDone);
1318 			PEHaltRestart(kPEPanicRestartCPUNoCallouts);
1319 		}
1320 	}
1321 
1322 #if CONFIG_KDP_INTERACTIVE_DEBUGGING
1323 	/*
1324 	 * If reboot on panic is enabled and the caller of panic indicated that we should skip
1325 	 * local coredumps, don't try to write these and instead go straight to reboot. This
1326 	 * allows us to persist any data that's stored in the panic log.
1327 	 */
1328 	if ((debugger_panic_options & DEBUGGER_OPTION_SKIP_LOCAL_COREDUMP) &&
1329 	    (debug_boot_arg & DB_REBOOT_POST_CORE)) {
1330 		PEHaltRestart(kPEPanicDiagnosticsDone);
1331 		kdp_machine_reboot_type(kPEPanicRestartCPU, debugger_panic_options);
1332 	}
1333 
1334 	/*
1335 	 * Consider generating a local corefile if the infrastructure is configured
1336 	 * and we haven't disabled on-device coredumps.
1337 	 */
1338 	if (on_device_corefile_enabled()) {
1339 		if (!kdp_has_polled_corefile()) {
1340 			if (debug_boot_arg & (DB_KERN_DUMP_ON_PANIC | DB_KERN_DUMP_ON_NMI)) {
1341 				paniclog_append_noflush("skipping local kernel core because core file could not be opened prior to panic (mode : 0x%x, error : 0x%x)\n",
1342 				    kdp_polled_corefile_mode(), kdp_polled_corefile_error());
1343 #if defined(__arm64__)
1344 				if (kdp_polled_corefile_mode() == kIOPolledCoreFileModeUnlinked) {
1345 					panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_COREFILE_UNLINKED;
1346 				}
1347 				panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_COREDUMP_FAILED;
1348 				paniclog_flush();
1349 #else /* defined(__arm64__) */
1350 				if (panic_info->mph_panic_log_offset != 0) {
1351 					if (kdp_polled_corefile_mode() == kIOPolledCoreFileModeUnlinked) {
1352 						panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_COREFILE_UNLINKED;
1353 					}
1354 					panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_COREDUMP_FAILED;
1355 					paniclog_flush();
1356 				}
1357 #endif /* defined(__arm64__) */
1358 			}
1359 		}
1360 #if XNU_MONITOR
1361 		else if ((pmap_get_cpu_data()->ppl_state == PPL_STATE_PANIC) && (debug_boot_arg & (DB_KERN_DUMP_ON_PANIC | DB_KERN_DUMP_ON_NMI))) {
1362 			paniclog_append_noflush("skipping local kernel core because the PPL is in PANIC state\n");
1363 			panic_info->eph_panic_flags |= EMBEDDED_PANIC_HEADER_FLAG_COREDUMP_FAILED;
1364 			paniclog_flush();
1365 		}
1366 #endif /* XNU_MONITOR */
1367 		else {
1368 			int ret = -1;
1369 
1370 #if defined (__x86_64__)
1371 			/* On x86 we don't do a coredump on Debugger unless the DB_KERN_DUMP_ON_NMI boot-arg is specified. */
1372 			if (debugger_current_op != DBOP_DEBUGGER || (debug_boot_arg & DB_KERN_DUMP_ON_NMI))
1373 #endif
1374 			{
1375 				/*
1376 				 * Doing an on-device coredump leaves the disk driver in a state
1377 				 * that can not be resumed.
1378 				 */
1379 				debugger_safe_to_return = FALSE;
1380 				begin_panic_transfer();
1381 				ret = kern_dump(KERN_DUMP_DISK);
1382 				abort_panic_transfer();
1383 
1384 #if DEVELOPMENT || DEBUG
1385 				INJECT_NESTED_PANIC_IF_REQUESTED(PANIC_TEST_CASE_RECURPANIC_POSTCORE);
1386 #endif
1387 			}
1388 
1389 			/*
1390 			 * If DB_REBOOT_POST_CORE is set, then reboot if coredump is sucessfully saved
1391 			 * or if option to ignore failures is set.
1392 			 */
1393 			if ((debug_boot_arg & DB_REBOOT_POST_CORE) &&
1394 			    ((ret == 0) || (debugger_panic_options & DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT))) {
1395 				PEHaltRestart(kPEPanicDiagnosticsDone);
1396 				kdp_machine_reboot_type(kPEPanicRestartCPU, debugger_panic_options);
1397 			}
1398 		}
1399 	}
1400 
1401 	if (debugger_current_op == DBOP_PANIC ||
1402 	    ((debugger_current_op == DBOP_DEBUGGER) && debugger_is_panic)) {
1403 		PEHaltRestart(kPEPanicDiagnosticsDone);
1404 	}
1405 
1406 	if (debug_boot_arg & DB_REBOOT_ALWAYS) {
1407 		kdp_machine_reboot_type(kPEPanicRestartCPU, debugger_panic_options);
1408 	}
1409 
1410 	/* If KDP is configured, try to trap to the debugger */
1411 #if defined(__arm64__)
1412 	if (kdp_explicitly_requested && (current_debugger != NO_CUR_DB)) {
1413 #else
1414 	if (current_debugger != NO_CUR_DB) {
1415 #endif
1416 		kdp_raise_exception(exception, code, subcode, state);
1417 		/*
1418 		 * Only return if we entered via Debugger and it's safe to return
1419 		 * (we halted the other cores successfully, this isn't a nested panic, etc)
1420 		 */
1421 		if (debugger_current_op == DBOP_DEBUGGER &&
1422 		    debugger_safe_to_return &&
1423 		    kernel_debugger_entry_count == 1 &&
1424 		    !debugger_is_panic) {
1425 			return;
1426 		}
1427 	}
1428 
1429 #if defined(__arm64__)
1430 	if (PE_i_can_has_debugger(NULL) && panicDebugging) {
1431 		/*
1432 		 * Print panic string at the end of serial output
1433 		 * to make panic more obvious when someone connects a debugger
1434 		 */
1435 		if (debugger_panic_str) {
1436 			panic_debugger_log("Original panic string:\n");
1437 			panic_debugger_log("panic(cpu %u caller 0x%lx): ", (unsigned) cpu_number(), debugger_panic_caller);
1438 #pragma clang diagnostic push
1439 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1440 			_doprnt(debugger_panic_str, debugger_panic_args, consdebug_putc, 0);
1441 #pragma clang diagnostic pop
1442 			panic_debugger_log("\n");
1443 		}
1444 
1445 		/* If panic debugging is configured and we're on a dev fused device, spin for astris to connect */
1446 		panic_spin_shmcon();
1447 	}
1448 #endif /* defined(__arm64__) */
1449 
1450 #else /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
1451 
1452 	PEHaltRestart(kPEPanicDiagnosticsDone);
1453 
1454 #endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
1455 
1456 	if (!panicDebugging) {
1457 		kdp_machine_reboot_type(kPEPanicRestartCPU, debugger_panic_options);
1458 	}
1459 
1460 	paniclog_append_noflush("\nPlease go to https://panic.apple.com to report this panic\n");
1461 	panic_spin_forever();
1462 }
1463 
1464 #if SCHED_HYGIENE_DEBUG
1465 uint64_t debugger_trap_timestamps[9];
1466 # define DEBUGGER_TRAP_TIMESTAMP(i) debugger_trap_timestamps[i] = mach_absolute_time();
1467 #else
1468 # define DEBUGGER_TRAP_TIMESTAMP(i)
1469 #endif /* SCHED_HYGIENE_DEBUG */
1470 
1471 void
1472 handle_debugger_trap(unsigned int exception, unsigned int code, unsigned int subcode, void *state)
1473 {
1474 	unsigned int initial_not_in_kdp = not_in_kdp;
1475 	kern_return_t ret;
1476 	debugger_op db_prev_op = debugger_current_op;
1477 
1478 	DEBUGGER_TRAP_TIMESTAMP(0);
1479 
1480 	DebuggerLock();
1481 	ret = DebuggerHaltOtherCores(CPUDEBUGGERSYNC, (CPUDEBUGGEROP == DBOP_STACKSHOT));
1482 
1483 	DEBUGGER_TRAP_TIMESTAMP(1);
1484 
1485 #if SCHED_HYGIENE_DEBUG
1486 	if (serialmode & SERIALMODE_OUTPUT) {
1487 		ml_spin_debug_reset(current_thread());
1488 	}
1489 #endif /* SCHED_HYGIENE_DEBUG */
1490 	if (ret != KERN_SUCCESS) {
1491 		CPUDEBUGGERRET = ret;
1492 		DebuggerUnlock();
1493 		return;
1494 	}
1495 
1496 	/* Update the global panic/debugger nested entry level */
1497 	kernel_debugger_entry_count = CPUDEBUGGERCOUNT;
1498 	if (kernel_debugger_entry_count > 0) {
1499 		console_suspend();
1500 	}
1501 
1502 	/*
1503 	 * TODO: Should we do anything special for nested panics here? i.e. if we've trapped more than twice
1504 	 * should we call into the debugger if it's configured and then reboot if the panic log has been written?
1505 	 */
1506 
1507 	if (CPUDEBUGGEROP == DBOP_NONE) {
1508 		/* If there was no debugger context setup, we trapped due to a software breakpoint */
1509 		debugger_current_op = DBOP_BREAKPOINT;
1510 	} else {
1511 		/* Not safe to return from a nested panic/debugger call */
1512 		if (debugger_current_op == DBOP_PANIC ||
1513 		    debugger_current_op == DBOP_DEBUGGER) {
1514 			debugger_safe_to_return = FALSE;
1515 		}
1516 
1517 		debugger_current_op = CPUDEBUGGEROP;
1518 
1519 		/* Only overwrite the panic message if there is none already - save the data from the first call */
1520 		if (debugger_panic_str == NULL) {
1521 			debugger_panic_str = CPUPANICSTR;
1522 			debugger_panic_args = CPUPANICARGS;
1523 			debugger_panic_data = CPUPANICDATAPTR;
1524 			debugger_message = CPUDEBUGGERMSG;
1525 			debugger_panic_caller = CPUPANICCALLER;
1526 		}
1527 
1528 		debugger_panic_options = CPUPANICOPTS;
1529 	}
1530 
1531 	/*
1532 	 * Clear the op from the processor debugger context so we can handle
1533 	 * breakpoints in the debugger
1534 	 */
1535 	CPUDEBUGGEROP = DBOP_NONE;
1536 
1537 	DEBUGGER_TRAP_TIMESTAMP(2);
1538 
1539 	kdp_callouts(KDP_EVENT_ENTER);
1540 	not_in_kdp = 0;
1541 
1542 	DEBUGGER_TRAP_TIMESTAMP(3);
1543 
1544 #if defined(__arm64__) && CONFIG_KDP_INTERACTIVE_DEBUGGING
1545 	shmem_mark_as_busy();
1546 #endif
1547 
1548 	if (debugger_current_op == DBOP_BREAKPOINT) {
1549 		kdp_raise_exception(exception, code, subcode, state);
1550 	} else if (debugger_current_op == DBOP_STACKSHOT) {
1551 		CPUDEBUGGERRET = do_stackshot();
1552 #if PGO
1553 	} else if (debugger_current_op == DBOP_RESET_PGO_COUNTERS) {
1554 		CPUDEBUGGERRET = do_pgo_reset_counters();
1555 #endif
1556 	} else {
1557 		/* note: this is the panic path...  */
1558 		debugger_collect_diagnostics(exception, code, subcode, state);
1559 	}
1560 
1561 #if defined(__arm64__) && CONFIG_KDP_INTERACTIVE_DEBUGGING
1562 	shmem_unmark_as_busy();
1563 #endif
1564 
1565 	DEBUGGER_TRAP_TIMESTAMP(4);
1566 
1567 	not_in_kdp = initial_not_in_kdp;
1568 	kdp_callouts(KDP_EVENT_EXIT);
1569 
1570 	DEBUGGER_TRAP_TIMESTAMP(5);
1571 
1572 	if (debugger_current_op != DBOP_BREAKPOINT) {
1573 		debugger_panic_str = NULL;
1574 		debugger_panic_args = NULL;
1575 		debugger_panic_data = NULL;
1576 		debugger_panic_options = 0;
1577 		debugger_message = NULL;
1578 	}
1579 
1580 	/* Restore the previous debugger state */
1581 	debugger_current_op = db_prev_op;
1582 
1583 	DEBUGGER_TRAP_TIMESTAMP(6);
1584 
1585 	DebuggerResumeOtherCores();
1586 
1587 	DEBUGGER_TRAP_TIMESTAMP(7);
1588 
1589 	DebuggerUnlock();
1590 
1591 	DEBUGGER_TRAP_TIMESTAMP(8);
1592 
1593 	return;
1594 }
1595 
1596 __attribute__((noinline, not_tail_called))
1597 void
1598 log(__unused int level, char *fmt, ...)
1599 {
1600 	void *caller = __builtin_return_address(0);
1601 	va_list listp;
1602 	va_list listp2;
1603 
1604 
1605 #ifdef lint
1606 	level++;
1607 #endif /* lint */
1608 #ifdef  MACH_BSD
1609 	va_start(listp, fmt);
1610 	va_copy(listp2, listp);
1611 
1612 	disable_preemption();
1613 	_doprnt(fmt, &listp, cons_putc_locked, 0);
1614 	enable_preemption();
1615 
1616 	va_end(listp);
1617 
1618 #pragma clang diagnostic push
1619 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1620 	os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, listp2, caller);
1621 #pragma clang diagnostic pop
1622 	va_end(listp2);
1623 #endif
1624 }
1625 
1626 /*
1627  * Per <rdar://problem/24974766>, skip appending log messages to
1628  * the new logging infrastructure in contexts where safety is
1629  * uncertain. These contexts include:
1630  *   - When we're in the debugger
1631  *   - We're in a panic
1632  *   - Interrupts are disabled
1633  *   - Or Pre-emption is disabled
1634  * In all the above cases, it is potentially unsafe to log messages.
1635  */
1636 
1637 boolean_t
1638 oslog_is_safe(void)
1639 {
1640 	return kernel_debugger_entry_count == 0 &&
1641 	       not_in_kdp == 1 &&
1642 	       get_preemption_level() == 0 &&
1643 	       ml_get_interrupts_enabled() == TRUE;
1644 }
1645 
1646 boolean_t
1647 debug_mode_active(void)
1648 {
1649 	return (0 != kernel_debugger_entry_count != 0) || (0 == not_in_kdp);
1650 }
1651 
1652 void
1653 debug_putc(char c)
1654 {
1655 	if ((debug_buf_size != 0) &&
1656 	    ((debug_buf_ptr - debug_buf_base) < (int)debug_buf_size)) {
1657 		*debug_buf_ptr = c;
1658 		debug_buf_ptr++;
1659 	}
1660 }
1661 
1662 #if defined (__x86_64__)
1663 struct pasc {
1664 	unsigned a: 7;
1665 	unsigned b: 7;
1666 	unsigned c: 7;
1667 	unsigned d: 7;
1668 	unsigned e: 7;
1669 	unsigned f: 7;
1670 	unsigned g: 7;
1671 	unsigned h: 7;
1672 }  __attribute__((packed));
1673 
1674 typedef struct pasc pasc_t;
1675 
1676 /*
1677  * In-place packing routines -- inefficient, but they're called at most once.
1678  * Assumes "buflen" is a multiple of 8. Used for compressing paniclogs on x86.
1679  */
1680 int
1681 packA(char *inbuf, uint32_t length, uint32_t buflen)
1682 {
1683 	unsigned int i, j = 0;
1684 	pasc_t pack;
1685 
1686 	length = MIN(((length + 7) & ~7), buflen);
1687 
1688 	for (i = 0; i < length; i += 8) {
1689 		pack.a = inbuf[i];
1690 		pack.b = inbuf[i + 1];
1691 		pack.c = inbuf[i + 2];
1692 		pack.d = inbuf[i + 3];
1693 		pack.e = inbuf[i + 4];
1694 		pack.f = inbuf[i + 5];
1695 		pack.g = inbuf[i + 6];
1696 		pack.h = inbuf[i + 7];
1697 		bcopy((char *) &pack, inbuf + j, 7);
1698 		j += 7;
1699 	}
1700 	return j;
1701 }
1702 
1703 void
1704 unpackA(char *inbuf, uint32_t length)
1705 {
1706 	pasc_t packs;
1707 	unsigned i = 0;
1708 	length = (length * 8) / 7;
1709 
1710 	while (i < length) {
1711 		packs = *(pasc_t *)&inbuf[i];
1712 		bcopy(&inbuf[i + 7], &inbuf[i + 8], MAX(0, (int) (length - i - 8)));
1713 		inbuf[i++] = packs.a;
1714 		inbuf[i++] = packs.b;
1715 		inbuf[i++] = packs.c;
1716 		inbuf[i++] = packs.d;
1717 		inbuf[i++] = packs.e;
1718 		inbuf[i++] = packs.f;
1719 		inbuf[i++] = packs.g;
1720 		inbuf[i++] = packs.h;
1721 	}
1722 }
1723 #endif /* defined (__x86_64__) */
1724 
1725 extern char *proc_name_address(void *);
1726 extern char *proc_longname_address(void *);
1727 
1728 __private_extern__ void
1729 panic_display_process_name(void)
1730 {
1731 	proc_name_t proc_name = {};
1732 	struct proc *cbsd_info = NULL;
1733 	task_t ctask = NULL;
1734 	vm_size_t size;
1735 
1736 	if (!panic_get_thread_proc_task(current_thread(), &ctask, &cbsd_info)) {
1737 		goto out;
1738 	}
1739 
1740 	if (cbsd_info == NULL) {
1741 		goto out;
1742 	}
1743 
1744 	size = ml_nofault_copy((vm_offset_t)proc_longname_address(cbsd_info),
1745 	    (vm_offset_t)&proc_name, sizeof(proc_name));
1746 
1747 	if (size == 0 || proc_name[0] == '\0') {
1748 		size = ml_nofault_copy((vm_offset_t)proc_name_address(cbsd_info),
1749 		    (vm_offset_t)&proc_name,
1750 		    MIN(sizeof(command_t), sizeof(proc_name)));
1751 		if (size > 0) {
1752 			proc_name[size - 1] = '\0';
1753 		}
1754 	}
1755 
1756 out:
1757 	proc_name[sizeof(proc_name) - 1] = '\0';
1758 	paniclog_append_noflush("\nProcess name corresponding to current thread (%p): %s\n",
1759 	    current_thread(), proc_name[0] != '\0' ? proc_name : "Unknown");
1760 }
1761 
1762 unsigned
1763 panic_active(void)
1764 {
1765 	return debugger_current_op == DBOP_PANIC ||
1766 	       (debugger_current_op == DBOP_DEBUGGER && debugger_is_panic);
1767 }
1768 
1769 void
1770 populate_model_name(char *model_string)
1771 {
1772 	strlcpy(model_name, model_string, sizeof(model_name));
1773 }
1774 
1775 void
1776 panic_display_model_name(void)
1777 {
1778 	char tmp_model_name[sizeof(model_name)];
1779 
1780 	if (ml_nofault_copy((vm_offset_t) &model_name, (vm_offset_t) &tmp_model_name, sizeof(model_name)) != sizeof(model_name)) {
1781 		return;
1782 	}
1783 
1784 	tmp_model_name[sizeof(tmp_model_name) - 1] = '\0';
1785 
1786 	if (tmp_model_name[0] != 0) {
1787 		paniclog_append_noflush("System model name: %s\n", tmp_model_name);
1788 	}
1789 }
1790 
1791 void
1792 panic_display_kernel_uuid(void)
1793 {
1794 	char tmp_kernel_uuid[sizeof(kernel_uuid_string)];
1795 
1796 	if (ml_nofault_copy((vm_offset_t) &kernel_uuid_string, (vm_offset_t) &tmp_kernel_uuid, sizeof(kernel_uuid_string)) != sizeof(kernel_uuid_string)) {
1797 		return;
1798 	}
1799 
1800 	if (tmp_kernel_uuid[0] != '\0') {
1801 		paniclog_append_noflush("Kernel UUID: %s\n", tmp_kernel_uuid);
1802 	}
1803 }
1804 
1805 void
1806 panic_display_kernel_aslr(void)
1807 {
1808 	kc_format_t kc_format;
1809 
1810 	PE_get_primary_kc_format(&kc_format);
1811 
1812 	if (kc_format == KCFormatFileset) {
1813 		void *kch = PE_get_kc_header(KCKindPrimary);
1814 		paniclog_append_noflush("KernelCache slide: 0x%016lx\n", (unsigned long) vm_kernel_slide);
1815 		paniclog_append_noflush("KernelCache base:  %p\n", (void*) kch);
1816 		paniclog_append_noflush("Kernel slide:      0x%016lx\n", vm_kernel_stext - (unsigned long)kch + vm_kernel_slide);
1817 		paniclog_append_noflush("Kernel text base:  %p\n", (void *) vm_kernel_stext);
1818 #if defined(__arm64__)
1819 		extern vm_offset_t segTEXTEXECB;
1820 		paniclog_append_noflush("Kernel text exec slide: 0x%016lx\n", (unsigned long)segTEXTEXECB - (unsigned long)kch + vm_kernel_slide);
1821 		paniclog_append_noflush("Kernel text exec base:  0x%016lx\n", (unsigned long)segTEXTEXECB);
1822 #endif /* defined(__arm64__) */
1823 	} else if (vm_kernel_slide) {
1824 		paniclog_append_noflush("Kernel slide:      0x%016lx\n", (unsigned long) vm_kernel_slide);
1825 		paniclog_append_noflush("Kernel text base:  %p\n", (void *)vm_kernel_stext);
1826 	} else {
1827 		paniclog_append_noflush("Kernel text base:  %p\n", (void *)vm_kernel_stext);
1828 	}
1829 }
1830 
1831 void
1832 panic_display_hibb(void)
1833 {
1834 #if defined(__i386__) || defined (__x86_64__)
1835 	paniclog_append_noflush("__HIB  text base: %p\n", (void *) vm_hib_base);
1836 #endif
1837 }
1838 
1839 #if CONFIG_ECC_LOGGING
1840 __private_extern__ void
1841 panic_display_ecc_errors(void)
1842 {
1843 	uint32_t count = ecc_log_get_correction_count();
1844 
1845 	if (count > 0) {
1846 		paniclog_append_noflush("ECC Corrections:%u\n", count);
1847 	}
1848 }
1849 #endif /* CONFIG_ECC_LOGGING */
1850 
1851 #if CONFIG_FREEZE
1852 extern bool freezer_incore_cseg_acct;
1853 extern int32_t c_segment_pages_compressed_incore;
1854 #endif
1855 
1856 extern uint32_t c_segment_pages_compressed;
1857 extern uint32_t c_segment_count;
1858 extern uint32_t c_segments_limit;
1859 extern uint32_t c_segment_pages_compressed_limit;
1860 extern uint32_t c_segment_pages_compressed_nearing_limit;
1861 extern uint32_t c_segments_nearing_limit;
1862 extern int vm_num_swap_files;
1863 
1864 void
1865 panic_display_compressor_stats(void)
1866 {
1867 	int isswaplow = vm_swap_low_on_space();
1868 #if CONFIG_FREEZE
1869 	uint32_t incore_seg_count;
1870 	uint32_t incore_compressed_pages;
1871 	if (freezer_incore_cseg_acct) {
1872 		incore_seg_count = c_segment_count - c_swappedout_count - c_swappedout_sparse_count;
1873 		incore_compressed_pages = c_segment_pages_compressed_incore;
1874 	} else {
1875 		incore_seg_count = c_segment_count;
1876 		incore_compressed_pages = c_segment_pages_compressed;
1877 	}
1878 
1879 	paniclog_append_noflush("Compressor Info: %u%% of compressed pages limit (%s) and %u%% of segments limit (%s) with %d swapfiles and %s swap space\n",
1880 	    (incore_compressed_pages * 100) / c_segment_pages_compressed_limit,
1881 	    (incore_compressed_pages > c_segment_pages_compressed_nearing_limit) ? "BAD":"OK",
1882 	    (incore_seg_count * 100) / c_segments_limit,
1883 	    (incore_seg_count > c_segments_nearing_limit) ? "BAD":"OK",
1884 	    vm_num_swap_files,
1885 	    isswaplow ? "LOW":"OK");
1886 #else /* CONFIG_FREEZE */
1887 	paniclog_append_noflush("Compressor Info: %u%% of compressed pages limit (%s) and %u%% of segments limit (%s) with %d swapfiles and %s swap space\n",
1888 	    (c_segment_pages_compressed * 100) / c_segment_pages_compressed_limit,
1889 	    (c_segment_pages_compressed > c_segment_pages_compressed_nearing_limit) ? "BAD":"OK",
1890 	    (c_segment_count * 100) / c_segments_limit,
1891 	    (c_segment_count > c_segments_nearing_limit) ? "BAD":"OK",
1892 	    vm_num_swap_files,
1893 	    isswaplow ? "LOW":"OK");
1894 #endif /* CONFIG_FREEZE */
1895 }
1896 
1897 #if !CONFIG_TELEMETRY
1898 int
1899 telemetry_gather(user_addr_t buffer __unused, uint32_t *length __unused, bool mark __unused)
1900 {
1901 	return KERN_NOT_SUPPORTED;
1902 }
1903 #endif
1904 
1905 #include <machine/machine_cpu.h>
1906 
1907 TUNABLE(uint32_t, kern_feature_overrides, "validation_disables", 0);
1908 
1909 boolean_t
1910 kern_feature_override(uint32_t fmask)
1911 {
1912 	return (kern_feature_overrides & fmask) == fmask;
1913 }
1914 
1915 boolean_t
1916 on_device_corefile_enabled(void)
1917 {
1918 	assert(startup_phase >= STARTUP_SUB_TUNABLES);
1919 #if CONFIG_KDP_INTERACTIVE_DEBUGGING
1920 	if (debug_boot_arg == 0) {
1921 		return FALSE;
1922 	}
1923 	if (debug_boot_arg & DB_DISABLE_LOCAL_CORE) {
1924 		return FALSE;
1925 	}
1926 #if !XNU_TARGET_OS_OSX
1927 	/*
1928 	 * outside of macOS, if there's a debug boot-arg set and local
1929 	 * cores aren't explicitly disabled, we always write a corefile.
1930 	 */
1931 	return TRUE;
1932 #else /* !XNU_TARGET_OS_OSX */
1933 	/*
1934 	 * on macOS, if corefiles on panic are requested and local cores
1935 	 * aren't disabled we write a local core.
1936 	 */
1937 	if (debug_boot_arg & (DB_KERN_DUMP_ON_NMI | DB_KERN_DUMP_ON_PANIC)) {
1938 		return TRUE;
1939 	}
1940 #endif /* !XNU_TARGET_OS_OSX */
1941 #endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
1942 	return FALSE;
1943 }
1944 
1945 boolean_t
1946 panic_stackshot_to_disk_enabled(void)
1947 {
1948 	assert(startup_phase >= STARTUP_SUB_TUNABLES);
1949 #if defined(__x86_64__)
1950 	if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
1951 		/* Only enabled on pre-Gibraltar machines where it hasn't been disabled explicitly */
1952 		if ((debug_boot_arg != 0) && (debug_boot_arg & DB_DISABLE_STACKSHOT_TO_DISK)) {
1953 			return FALSE;
1954 		}
1955 
1956 		return TRUE;
1957 	}
1958 #endif
1959 	return FALSE;
1960 }
1961 
1962 const char *
1963 sysctl_debug_get_preoslog(size_t *size)
1964 {
1965 	int result = 0;
1966 	void *preoslog_pa = NULL;
1967 	int preoslog_size = 0;
1968 
1969 	result = IODTGetLoaderInfo("preoslog", &preoslog_pa, &preoslog_size);
1970 	if (result || preoslog_pa == NULL || preoslog_size == 0) {
1971 		kprintf("Couldn't obtain preoslog region: result = %d, preoslog_pa = %p, preoslog_size = %d\n", result, preoslog_pa, preoslog_size);
1972 		*size = 0;
1973 		return NULL;
1974 	}
1975 
1976 	/*
1977 	 *  Beware:
1978 	 *  On release builds, we would need to call IODTFreeLoaderInfo("preoslog", preoslog_pa, preoslog_size) to free the preoslog buffer.
1979 	 *  On Development & Debug builds, we retain the buffer so it can be extracted from coredumps.
1980 	 */
1981 	*size = preoslog_size;
1982 	return (char *)(ml_static_ptovirt((vm_offset_t)(preoslog_pa)));
1983 }
1984 
1985 void
1986 sysctl_debug_free_preoslog(void)
1987 {
1988 #if RELEASE
1989 	int result = 0;
1990 	void *preoslog_pa = NULL;
1991 	int preoslog_size = 0;
1992 
1993 	result = IODTGetLoaderInfo("preoslog", &preoslog_pa, &preoslog_size);
1994 	if (result || preoslog_pa == NULL || preoslog_size == 0) {
1995 		kprintf("Couldn't obtain preoslog region: result = %d, preoslog_pa = %p, preoslog_size = %d\n", result, preoslog_pa, preoslog_size);
1996 		return;
1997 	}
1998 
1999 	IODTFreeLoaderInfo("preoslog", preoslog_pa, preoslog_size);
2000 #else
2001 	/*  On Development & Debug builds, we retain the buffer so it can be extracted from coredumps. */
2002 #endif // RELEASE
2003 }
2004 
2005 #if (DEVELOPMENT || DEBUG)
2006 
2007 void
2008 platform_stall_panic_or_spin(uint32_t req)
2009 {
2010 	if (xnu_platform_stall_value & req) {
2011 		if (xnu_platform_stall_value & PLATFORM_STALL_XNU_ACTION_PANIC) {
2012 			panic("Platform stall: User requested panic");
2013 		} else {
2014 			paniclog_append_noflush("\nUser requested platform stall. Stall Code: 0x%x", req);
2015 			panic_spin_forever();
2016 		}
2017 	}
2018 }
2019 #endif
2020 
2021 #define AWL_HV_ENTRY_FLAG (0x1)
2022 
2023 static inline void
2024 awl_set_scratch_reg_hv_bit(void)
2025 {
2026 #if defined(__arm64__)
2027 #define WATCHDOG_DIAG0     "S3_5_c15_c2_6"
2028 	uint64_t awl_diag0 = __builtin_arm_rsr64(WATCHDOG_DIAG0);
2029 	awl_diag0 |= AWL_HV_ENTRY_FLAG;
2030 	__builtin_arm_wsr64(WATCHDOG_DIAG0, awl_diag0);
2031 #endif // defined(__arm64__)
2032 }
2033 
2034 void
2035 awl_mark_hv_entry(void)
2036 {
2037 	if (__probable(*PERCPU_GET(hv_entry_detected) || !awl_scratch_reg_supported)) {
2038 		return;
2039 	}
2040 	*PERCPU_GET(hv_entry_detected) = true;
2041 
2042 	awl_set_scratch_reg_hv_bit();
2043 }
2044 
2045 /*
2046  * Awl WatchdogDiag0 is not restored by hardware when coming out of reset,
2047  * so restore it manually.
2048  */
2049 static bool
2050 awl_pm_state_change_cbk(void *param __unused, enum cpu_event event, unsigned int cpu_or_cluster __unused)
2051 {
2052 	if (event == CPU_BOOTED) {
2053 		if (*PERCPU_GET(hv_entry_detected)) {
2054 			awl_set_scratch_reg_hv_bit();
2055 		}
2056 	}
2057 
2058 	return true;
2059 }
2060 
2061 /*
2062  * Identifies and sets a flag if AWL Scratch0/1 exists in the system, subscribes
2063  * for a callback to restore register after hibernation
2064  */
2065 __startup_func
2066 static void
2067 set_awl_scratch_exists_flag_and_subscribe_for_pm(void)
2068 {
2069 	DTEntry base = NULL;
2070 
2071 	if (SecureDTLookupEntry(NULL, "/arm-io/wdt", &base) != kSuccess) {
2072 		return;
2073 	}
2074 	const uint8_t *data = NULL;
2075 	unsigned int data_size = sizeof(uint8_t);
2076 
2077 	if (base != NULL && SecureDTGetProperty(base, "awl-scratch-supported", (const void **)&data, &data_size) == kSuccess) {
2078 		for (unsigned int i = 0; i < data_size; i++) {
2079 			if (data[i] != 0) {
2080 				awl_scratch_reg_supported = true;
2081 				cpu_event_register_callback(awl_pm_state_change_cbk, NULL);
2082 				break;
2083 			}
2084 		}
2085 	}
2086 }
2087 STARTUP(EARLY_BOOT, STARTUP_RANK_MIDDLE, set_awl_scratch_exists_flag_and_subscribe_for_pm);
2088