]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/ml/arm/kdp_machdep.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / arm / kdp_machdep.c
CommitLineData
5ba3f43e
A
1/*
2 * Copyright (c) 2000-2016 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 <mach/mach_types.h>
30#include <mach/exception_types.h>
31#include <arm/exception.h>
32#include <arm/pmap.h>
33#include <arm/proc_reg.h>
34#include <arm/thread.h>
35#include <arm/trap.h>
36#include <arm/cpu_data_internal.h>
37#include <kdp/kdp_internal.h>
38#include <kern/debug.h>
39#include <IOKit/IOPlatformExpert.h>
5ba3f43e
A
40#include <libkern/OSAtomic.h>
41#include <vm/vm_map.h>
42
cb323159
A
43#if defined(HAS_APPLE_PAC)
44#include <ptrauth.h>
45#endif
5ba3f43e
A
46
47#define KDP_TEST_HARNESS 0
48#if KDP_TEST_HARNESS
49#define dprintf(x) kprintf x
50#else
51#define dprintf(x) do {} while (0)
52#endif
53
54void halt_all_cpus(boolean_t);
55void kdp_call(void);
56int kdp_getc(void);
57int machine_trace_thread(thread_t thread,
0a7de745
A
58 char * tracepos,
59 char * tracebound,
60 int nframes,
61 boolean_t user_p,
0a7de745 62 uint32_t * thread_trace_flags);
5ba3f43e 63int machine_trace_thread64(thread_t thread,
0a7de745
A
64 char * tracepos,
65 char * tracebound,
66 int nframes,
67 boolean_t user_p,
0a7de745 68 uint32_t * thread_trace_flags,
f427ee49
A
69 uint64_t *sp,
70 vm_offset_t fp);
5ba3f43e
A
71
72void kdp_trap(unsigned int, struct arm_saved_state * saved_state);
73
74extern vm_offset_t machine_trace_thread_get_kva(vm_offset_t cur_target_addr, vm_map_t map, uint32_t *thread_trace_flags);
75extern void machine_trace_thread_clear_validation_cache(void);
0a7de745 76extern vm_map_t kernel_map;
5ba3f43e
A
77
78#if CONFIG_KDP_INTERACTIVE_DEBUGGING
79void
80kdp_exception(
0a7de745 81 unsigned char * pkt, int * len, unsigned short * remote_port, unsigned int exception, unsigned int code, unsigned int subcode)
5ba3f43e
A
82{
83 struct {
84 kdp_exception_t pkt;
85 kdp_exc_info_t exc;
86 } aligned_pkt;
87
88 kdp_exception_t * rq = (kdp_exception_t *)&aligned_pkt;
89
90 bcopy((char *)pkt, (char *)rq, sizeof(*rq));
91 rq->hdr.request = KDP_EXCEPTION;
92 rq->hdr.is_reply = 0;
93 rq->hdr.seq = kdp.exception_seq;
94 rq->hdr.key = 0;
95 rq->hdr.len = sizeof(*rq) + sizeof(kdp_exc_info_t);
96
97 rq->n_exc_info = 1;
98 rq->exc_info[0].cpu = 0;
99 rq->exc_info[0].exception = exception;
100 rq->exc_info[0].code = code;
101 rq->exc_info[0].subcode = subcode;
102
103 rq->hdr.len += rq->n_exc_info * sizeof(kdp_exc_info_t);
104
105 bcopy((char *)rq, (char *)pkt, rq->hdr.len);
106
107 kdp.exception_ack_needed = TRUE;
108
109 *remote_port = kdp.exception_port;
110 *len = rq->hdr.len;
111}
112
113boolean_t
114kdp_exception_ack(unsigned char * pkt, int len)
115{
116 kdp_exception_ack_t aligned_pkt;
117 kdp_exception_ack_t * rq = (kdp_exception_ack_t *)&aligned_pkt;
118
0a7de745
A
119 if ((unsigned)len < sizeof(*rq)) {
120 return FALSE;
121 }
5ba3f43e
A
122
123 bcopy((char *)pkt, (char *)rq, sizeof(*rq));
124
0a7de745
A
125 if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION) {
126 return FALSE;
127 }
5ba3f43e
A
128
129 dprintf(("kdp_exception_ack seq %x %x\n", rq->hdr.seq, kdp.exception_seq));
130
131 if (rq->hdr.seq == kdp.exception_seq) {
132 kdp.exception_ack_needed = FALSE;
133 kdp.exception_seq++;
134 }
0a7de745 135 return TRUE;
5ba3f43e
A
136}
137
138static void
139kdp_getintegerstate(char * out_state)
140{
141#if defined(__arm__)
142 struct arm_thread_state thread_state;
143 struct arm_saved_state *saved_state;
144
145 saved_state = kdp.saved_state;
146
147 bzero((char *) &thread_state, sizeof(struct arm_thread_state));
148
149 saved_state_to_thread_state32(saved_state, &thread_state);
150
151 bcopy((char *) &thread_state, (char *) out_state, sizeof(struct arm_thread_state));
152#elif defined(__arm64__)
153 struct arm_thread_state64 thread_state64;
154 arm_saved_state_t *saved_state;
155
156 saved_state = kdp.saved_state;
157 assert(is_saved_state64(saved_state));
158
159 bzero((char *) &thread_state64, sizeof(struct arm_thread_state64));
160
161 saved_state_to_thread_state64(saved_state, &thread_state64);
162
163 bcopy((char *) &thread_state64, (char *) out_state, sizeof(struct arm_thread_state64));
164#else
165#error Unknown architecture.
166#endif
167}
168
169kdp_error_t
170kdp_machine_read_regs(__unused unsigned int cpu, unsigned int flavor, char * data, int * size)
171{
172 switch (flavor) {
173#if defined(__arm__)
174 case ARM_THREAD_STATE:
175 dprintf(("kdp_readregs THREAD_STATE\n"));
176 kdp_getintegerstate(data);
177 *size = ARM_THREAD_STATE_COUNT * sizeof(int);
178 return KDPERR_NO_ERROR;
179#elif defined(__arm64__)
180 case ARM_THREAD_STATE64:
181 dprintf(("kdp_readregs THREAD_STATE64\n"));
182 kdp_getintegerstate(data);
183 *size = ARM_THREAD_STATE64_COUNT * sizeof(int);
184 return KDPERR_NO_ERROR;
185#endif
186
187 case ARM_VFP_STATE:
188 dprintf(("kdp_readregs THREAD_FPSTATE\n"));
189 bzero((char *) data, sizeof(struct arm_vfp_state));
190 *size = ARM_VFP_STATE_COUNT * sizeof(int);
191 return KDPERR_NO_ERROR;
192
193 default:
194 dprintf(("kdp_readregs bad flavor %d\n"));
195 return KDPERR_BADFLAVOR;
196 }
197}
198
199static void
200kdp_setintegerstate(char * state_in)
201{
202#if defined(__arm__)
203 struct arm_thread_state thread_state;
204 struct arm_saved_state *saved_state;
205
206 bcopy((char *) state_in, (char *) &thread_state, sizeof(struct arm_thread_state));
207 saved_state = kdp.saved_state;
208
209 thread_state32_to_saved_state(&thread_state, saved_state);
210#elif defined(__arm64__)
211 struct arm_thread_state64 thread_state64;
212 struct arm_saved_state *saved_state;
213
214 bcopy((char *) state_in, (char *) &thread_state64, sizeof(struct arm_thread_state64));
215 saved_state = kdp.saved_state;
216 assert(is_saved_state64(saved_state));
217
218 thread_state64_to_saved_state(&thread_state64, saved_state);
219#else
220#error Unknown architecture.
221#endif
222}
223
224kdp_error_t
225kdp_machine_write_regs(__unused unsigned int cpu, unsigned int flavor, char * data, __unused int * size)
226{
227 switch (flavor) {
228#if defined(__arm__)
229 case ARM_THREAD_STATE:
230 dprintf(("kdp_writeregs THREAD_STATE\n"));
231 kdp_setintegerstate(data);
232 return KDPERR_NO_ERROR;
233#elif defined(__arm64__)
234 case ARM_THREAD_STATE64:
235 dprintf(("kdp_writeregs THREAD_STATE64\n"));
236 kdp_setintegerstate(data);
237 return KDPERR_NO_ERROR;
238#endif
239
240 case ARM_VFP_STATE:
241 dprintf(("kdp_writeregs THREAD_FPSTATE\n"));
242 return KDPERR_NO_ERROR;
243
244 default:
245 dprintf(("kdp_writeregs bad flavor %d\n"));
246 return KDPERR_BADFLAVOR;
247 }
248}
249
250void
251kdp_machine_hostinfo(kdp_hostinfo_t * hostinfo)
252{
253 hostinfo->cpus_mask = 1;
254 hostinfo->cpu_type = slot_type(0);
255 hostinfo->cpu_subtype = slot_subtype(0);
256}
257
258__attribute__((noreturn))
259void
f427ee49 260kdp_panic(const char * fmt, ...)
5ba3f43e 261{
f427ee49
A
262 char kdp_fmt[256];
263 va_list args;
264
265 va_start(args, fmt);
266 (void) snprintf(kdp_fmt, sizeof(kdp_fmt), "kdp panic: %s", fmt);
267 vprintf(kdp_fmt, args);
268 va_end(args);
269
5ba3f43e 270 while (1) {
0a7de745
A
271 }
272 ;
5ba3f43e
A
273}
274
275int
276kdp_intr_disbl(void)
277{
0a7de745 278 return splhigh();
5ba3f43e
A
279}
280
281void
282kdp_intr_enbl(int s)
283{
284 splx(s);
285}
286
287void
288kdp_us_spin(int usec)
289{
290 delay(usec / 100);
291}
292
293void
294kdp_call(void)
295{
296 Debugger("inline call to debugger(machine_startup)");
297}
298
299int
300kdp_getc(void)
301{
0a7de745 302 return cnmaygetc();
5ba3f43e
A
303}
304
305void
306kdp_machine_get_breakinsn(uint8_t * bytes, uint32_t * size)
307{
308 *(uint32_t *)bytes = GDB_TRAP_INSTR1;
309 *size = sizeof(uint32_t);
310}
311
312void
313kdp_sync_cache(void)
314{
315}
316
317int
318kdp_machine_ioport_read(kdp_readioport_req_t * rq, caddr_t data, uint16_t lcpu)
319{
320#pragma unused(rq, data, lcpu)
321 return 0;
322}
323
324int
325kdp_machine_ioport_write(kdp_writeioport_req_t * rq, caddr_t data, uint16_t lcpu)
326{
327#pragma unused(rq, data, lcpu)
328 return 0;
329}
330
331int
332kdp_machine_msr64_read(kdp_readmsr64_req_t *rq, caddr_t data, uint16_t lcpu)
333{
334#pragma unused(rq, data, lcpu)
0a7de745 335 return 0;
5ba3f43e
A
336}
337
338int
339kdp_machine_msr64_write(kdp_writemsr64_req_t *rq, caddr_t data, uint16_t lcpu)
340{
341#pragma unused(rq, data, lcpu)
0a7de745 342 return 0;
5ba3f43e
A
343}
344#endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
345
346void
347kdp_trap(unsigned int exception, struct arm_saved_state * saved_state)
348{
349 handle_debugger_trap(exception, 0, 0, saved_state);
350
351#if defined(__arm__)
352 if (saved_state->cpsr & PSR_TF) {
353 unsigned short instr = *((unsigned short *)(saved_state->pc));
0a7de745 354 if ((instr == (GDB_TRAP_INSTR1 & 0xFFFF)) || (instr == (GDB_TRAP_INSTR2 & 0xFFFF))) {
5ba3f43e 355 saved_state->pc += 2;
0a7de745 356 }
5ba3f43e
A
357 } else {
358 unsigned int instr = *((unsigned int *)(saved_state->pc));
0a7de745 359 if ((instr == GDB_TRAP_INSTR1) || (instr == GDB_TRAP_INSTR2)) {
5ba3f43e 360 saved_state->pc += 4;
0a7de745 361 }
5ba3f43e
A
362 }
363
364#elif defined(__arm64__)
365 assert(is_saved_state64(saved_state));
366
367 uint32_t instr = *((uint32_t *)get_saved_state_pc(saved_state));
368
369 /*
370 * As long as we are using the arm32 trap encoding to handling
371 * traps to the debugger, we should identify both variants and
372 * increment for both of them.
373 */
0a7de745 374 if ((instr == GDB_TRAP_INSTR1) || (instr == GDB_TRAP_INSTR2)) {
cb323159 375 add_saved_state_pc(saved_state, 4);
0a7de745 376 }
5ba3f43e
A
377#else
378#error Unknown architecture.
379#endif
380}
381
382#define ARM32_LR_OFFSET 4
383#define ARM64_LR_OFFSET 8
384
385/*
386 * Since sizeof (struct thread_snapshot) % 4 == 2
387 * make sure the compiler does not try to use word-aligned
388 * access to this data, which can result in alignment faults
389 * that can't be emulated in KDP context.
390 */
391typedef uint32_t uint32_align2_t __attribute__((aligned(2)));
392
393int
394machine_trace_thread(thread_t thread,
0a7de745
A
395 char * tracepos,
396 char * tracebound,
397 int nframes,
398 boolean_t user_p,
0a7de745 399 uint32_t * thread_trace_flags)
5ba3f43e
A
400{
401 uint32_align2_t * tracebuf = (uint32_align2_t *)tracepos;
402
f427ee49 403 vm_size_t framesize = sizeof(uint32_t);
5ba3f43e
A
404
405 vm_offset_t stacklimit = 0;
406 vm_offset_t stacklimit_bottom = 0;
407 int framecount = 0;
408 uint32_t short_fp = 0;
409 vm_offset_t fp = 0;
410 vm_offset_t pc, sp;
411 vm_offset_t prevfp = 0;
412 uint32_t prevlr = 0;
413 struct arm_saved_state * state;
414 vm_offset_t kern_virt_addr = 0;
415 vm_map_t bt_vm_map = VM_MAP_NULL;
416
417 nframes = (tracebound > tracepos) ? MIN(nframes, (int)((tracebound - tracepos) / framesize)) : 0;
418 if (!nframes) {
0a7de745 419 return 0;
5ba3f43e
A
420 }
421 framecount = 0;
422
423 if (user_p) {
424 /* Examine the user savearea */
425 state = get_user_regs(thread);
426 stacklimit = VM_MAX_ADDRESS;
427 stacklimit_bottom = VM_MIN_ADDRESS;
428
429 /* Fake up a stack frame for the PC */
430 *tracebuf++ = (uint32_t)get_saved_state_pc(state);
5ba3f43e
A
431 framecount++;
432 bt_vm_map = thread->task->map;
433 } else {
434#if defined(__arm64__)
435 panic("Attempted to trace kernel thread_t %p as a 32-bit context", thread);
436 return 0;
437#elif defined(__arm__)
438 /* kstackptr may not always be there, so recompute it */
439 state = &thread_get_kernel_state(thread)->machine;
440
441 stacklimit = VM_MAX_KERNEL_ADDRESS;
442 stacklimit_bottom = VM_MIN_KERNEL_ADDRESS;
443 bt_vm_map = kernel_map;
444#else
445#error Unknown architecture.
446#endif
447 }
448
449 /* Get the frame pointer */
450 fp = get_saved_state_fp(state);
451
452 /* Fill in the current link register */
453 prevlr = (uint32_t)get_saved_state_lr(state);
454 pc = get_saved_state_pc(state);
455 sp = get_saved_state_sp(state);
456
457 if (!user_p && !prevlr && !fp && !sp && !pc) {
458 return 0;
459 }
460
461 if (!user_p) {
462 /* This is safe since we will panic above on __arm64__ if !user_p */
463 prevlr = (uint32_t)VM_KERNEL_UNSLIDE(prevlr);
464 }
465
466 for (; framecount < nframes; framecount++) {
5ba3f43e 467 *tracebuf++ = prevlr;
5ba3f43e
A
468
469 /* Invalid frame */
470 if (!fp) {
471 break;
472 }
473 /* Unaligned frame */
474 if (fp & 0x0000003) {
475 break;
476 }
477 /* Frame is out of range, maybe a user FP while doing kernel BT */
478 if (fp > stacklimit) {
479 break;
480 }
481 if (fp < stacklimit_bottom) {
482 break;
483 }
0a7de745 484 /* Stack grows downward */
5ba3f43e 485 if (fp < prevfp) {
5ba3f43e
A
486 boolean_t prev_in_interrupt_stack = FALSE;
487
488 if (!user_p) {
489 /*
490 * As a special case, sometimes we are backtracing out of an interrupt
491 * handler, and the stack jumps downward because of the memory allocation
492 * pattern during early boot due to KASLR.
493 */
494 int cpu;
495 int max_cpu = ml_get_max_cpu_number();
0a7de745
A
496
497 for (cpu = 0; cpu <= max_cpu; cpu++) {
5ba3f43e 498 cpu_data_t *target_cpu_datap;
0a7de745 499
5ba3f43e 500 target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
0a7de745 501 if (target_cpu_datap == (cpu_data_t *)NULL) {
5ba3f43e 502 continue;
0a7de745
A
503 }
504
505 if (prevfp >= (target_cpu_datap->intstack_top - INTSTACK_SIZE) && prevfp < target_cpu_datap->intstack_top) {
5ba3f43e
A
506 prev_in_interrupt_stack = TRUE;
507 break;
508 }
d9a64523
A
509
510#if defined(__arm__)
0a7de745 511 if (prevfp >= (target_cpu_datap->fiqstack_top - FIQSTACK_SIZE) && prevfp < target_cpu_datap->fiqstack_top) {
d9a64523
A
512 prev_in_interrupt_stack = TRUE;
513 break;
514 }
515#elif defined(__arm64__)
0a7de745 516 if (prevfp >= (target_cpu_datap->excepstack_top - EXCEPSTACK_SIZE) && prevfp < target_cpu_datap->excepstack_top) {
d9a64523
A
517 prev_in_interrupt_stack = TRUE;
518 break;
519 }
520#endif
5ba3f43e
A
521 }
522 }
523
524 if (!prev_in_interrupt_stack) {
525 /* Corrupt frame pointer? */
526 break;
527 }
528 }
529 /* Assume there's a saved link register, and read it */
530 kern_virt_addr = machine_trace_thread_get_kva(fp + ARM32_LR_OFFSET, bt_vm_map, thread_trace_flags);
531
532 if (!kern_virt_addr) {
533 if (thread_trace_flags) {
534 *thread_trace_flags |= kThreadTruncatedBT;
535 }
536 break;
537 }
538
539 prevlr = *(uint32_t *)kern_virt_addr;
540 if (!user_p) {
541 /* This is safe since we will panic above on __arm64__ if !user_p */
542 prevlr = (uint32_t)VM_KERNEL_UNSLIDE(prevlr);
543 }
544
545 prevfp = fp;
546
547 /*
548 * Next frame; read the fp value into short_fp first
549 * as it is 32-bit.
550 */
551 kern_virt_addr = machine_trace_thread_get_kva(fp, bt_vm_map, thread_trace_flags);
552
553 if (kern_virt_addr) {
554 short_fp = *(uint32_t *)kern_virt_addr;
555 fp = (vm_offset_t) short_fp;
556 } else {
557 fp = 0;
558 if (thread_trace_flags) {
559 *thread_trace_flags |= kThreadTruncatedBT;
560 }
561 }
5ba3f43e
A
562 }
563 /* Reset the target pmap */
564 machine_trace_thread_clear_validation_cache();
0a7de745 565 return (int)(((char *)tracebuf) - tracepos);
5ba3f43e
A
566}
567
568int
569machine_trace_thread64(thread_t thread,
0a7de745
A
570 char * tracepos,
571 char * tracebound,
572 int nframes,
573 boolean_t user_p,
0a7de745 574 uint32_t * thread_trace_flags,
f427ee49
A
575 uint64_t *sp_out,
576 vm_offset_t fp)
5ba3f43e 577{
d9a64523 578#pragma unused(sp_out)
5ba3f43e 579#if defined(__arm__)
f427ee49 580#pragma unused(thread, tracepos, tracebound, nframes, user_p, thread_trace_flags, fp)
5ba3f43e
A
581 return 0;
582#elif defined(__arm64__)
583
584 uint64_t * tracebuf = (uint64_t *)tracepos;
f427ee49 585 vm_size_t framesize = sizeof(uint64_t);
5ba3f43e
A
586
587 vm_offset_t stacklimit = 0;
588 vm_offset_t stacklimit_bottom = 0;
589 int framecount = 0;
5ba3f43e
A
590 vm_offset_t pc = 0;
591 vm_offset_t sp = 0;
592 vm_offset_t prevfp = 0;
593 uint64_t prevlr = 0;
5ba3f43e
A
594 vm_offset_t kern_virt_addr = 0;
595 vm_map_t bt_vm_map = VM_MAP_NULL;
596
d9a64523
A
597 const boolean_t is_64bit_addr = thread_is_64bit_addr(thread);
598
5ba3f43e
A
599 nframes = (tracebound > tracepos) ? MIN(nframes, (int)((tracebound - tracepos) / framesize)) : 0;
600 if (!nframes) {
0a7de745 601 return 0;
5ba3f43e
A
602 }
603 framecount = 0;
604
605 if (user_p) {
606 /* Examine the user savearea */
f427ee49 607 struct arm_saved_state * state = thread->machine.upcb;
d9a64523
A
608 stacklimit = (is_64bit_addr) ? MACH_VM_MAX_ADDRESS : VM_MAX_ADDRESS;
609 stacklimit_bottom = (is_64bit_addr) ? MACH_VM_MIN_ADDRESS : VM_MIN_ADDRESS;
5ba3f43e
A
610
611 /* Fake up a stack frame for the PC */
612 *tracebuf++ = get_saved_state_pc(state);
5ba3f43e
A
613 framecount++;
614 bt_vm_map = thread->task->map;
f427ee49
A
615
616 /* Get the frame pointer */
617 if (fp == 0) {
618 fp = get_saved_state_fp(state);
619 }
620
621 /* Fill in the current link register */
622 prevlr = get_saved_state_lr(state);
623 pc = get_saved_state_pc(state);
624 sp = get_saved_state_sp(state);
5ba3f43e 625 } else {
c3c9b80d
A
626 struct arm_saved_state *state = thread->machine.kpcb;
627 if (state != NULL) {
628 if (fp == 0) {
629 fp = state->ss_64.fp;
630 }
5ba3f43e 631
c3c9b80d
A
632 prevlr = state->ss_64.lr;
633 pc = state->ss_64.pc;
634 sp = state->ss_64.sp;
635 } else {
636 /* kstackptr may not always be there, so recompute it */
637 arm_kernel_saved_state_t *kstate = &thread_get_kernel_state(thread)->machine.ss;
638
639 if (fp == 0) {
640 fp = kstate->fp;
641 }
642 prevlr = kstate->lr;
643 pc = kstate->pc;
644 sp = kstate->sp;
f427ee49 645 }
5ba3f43e 646
c3c9b80d
A
647 stacklimit = VM_MAX_KERNEL_ADDRESS;
648 stacklimit_bottom = VM_MIN_KERNEL_ADDRESS;
649 bt_vm_map = kernel_map;
f427ee49 650 }
5ba3f43e
A
651
652 if (!user_p && !prevlr && !fp && !sp && !pc) {
653 return 0;
654 }
655
656 if (!user_p) {
657 prevlr = VM_KERNEL_UNSLIDE(prevlr);
658 }
659
660 for (; framecount < nframes; framecount++) {
5ba3f43e 661 *tracebuf++ = prevlr;
5ba3f43e
A
662
663 /* Invalid frame */
664 if (!fp) {
665 break;
666 }
667 /*
668 * Unaligned frame; given that the stack register must always be
669 * 16-byte aligned, we are assured 8-byte alignment of the saved
670 * frame pointer and link register.
671 */
672 if (fp & 0x0000007) {
673 break;
674 }
675 /* Frame is out of range, maybe a user FP while doing kernel BT */
676 if (fp > stacklimit) {
677 break;
678 }
679 if (fp < stacklimit_bottom) {
680 break;
681 }
682 /* Stack grows downward */
683 if (fp < prevfp) {
684 boolean_t switched_stacks = FALSE;
685
686 if (!user_p) {
687 /*
688 * As a special case, sometimes we are backtracing out of an interrupt
689 * handler, and the stack jumps downward because of the memory allocation
690 * pattern during early boot due to KASLR.
691 */
692 int cpu;
693 int max_cpu = ml_get_max_cpu_number();
694
0a7de745 695 for (cpu = 0; cpu <= max_cpu; cpu++) {
5ba3f43e
A
696 cpu_data_t *target_cpu_datap;
697
698 target_cpu_datap = (cpu_data_t *)CpuDataEntries[cpu].cpu_data_vaddr;
0a7de745 699 if (target_cpu_datap == (cpu_data_t *)NULL) {
5ba3f43e 700 continue;
0a7de745 701 }
5ba3f43e 702
0a7de745 703 if (prevfp >= (target_cpu_datap->intstack_top - INTSTACK_SIZE) && prevfp < target_cpu_datap->intstack_top) {
5ba3f43e
A
704 switched_stacks = TRUE;
705 break;
706 }
d9a64523 707#if defined(__arm__)
0a7de745 708 if (prevfp >= (target_cpu_datap->fiqstack_top - FIQSTACK_SIZE) && prevfp < target_cpu_datap->fiqstack_top) {
d9a64523
A
709 switched_stacks = TRUE;
710 break;
711 }
712#elif defined(__arm64__)
0a7de745 713 if (prevfp >= (target_cpu_datap->excepstack_top - EXCEPSTACK_SIZE) && prevfp < target_cpu_datap->excepstack_top) {
d9a64523
A
714 switched_stacks = TRUE;
715 break;
716 }
717#endif
5ba3f43e
A
718 }
719
c6bf4f31
A
720#if XNU_MONITOR
721 vm_offset_t cpu_base = (vm_offset_t)pmap_stacks_start;
722 vm_offset_t cpu_top = (vm_offset_t)pmap_stacks_end;
723
724 if (((prevfp >= cpu_base) && (prevfp < cpu_top)) !=
725 ((fp >= cpu_base) && (fp < cpu_top))) {
726 switched_stacks = TRUE;
727 break;
728 }
729#endif
5ba3f43e
A
730 }
731
732 if (!switched_stacks) {
733 /* Corrupt frame pointer? */
734 break;
735 }
736 }
737
738 /* Assume there's a saved link register, and read it */
739 kern_virt_addr = machine_trace_thread_get_kva(fp + ARM64_LR_OFFSET, bt_vm_map, thread_trace_flags);
740
741 if (!kern_virt_addr) {
742 if (thread_trace_flags) {
743 *thread_trace_flags |= kThreadTruncatedBT;
744 }
745 break;
746 }
747
748 prevlr = *(uint64_t *)kern_virt_addr;
cb323159
A
749#if defined(HAS_APPLE_PAC)
750 /* return addresses on stack signed by arm64e ABI */
751 prevlr = (uint64_t) ptrauth_strip((void *)prevlr, ptrauth_key_return_address);
752#endif
5ba3f43e
A
753 if (!user_p) {
754 prevlr = VM_KERNEL_UNSLIDE(prevlr);
755 }
756
757 prevfp = fp;
758 /* Next frame */
759 kern_virt_addr = machine_trace_thread_get_kva(fp, bt_vm_map, thread_trace_flags);
760
761 if (kern_virt_addr) {
762 fp = *(uint64_t *)kern_virt_addr;
763 } else {
764 fp = 0;
765 if (thread_trace_flags) {
766 *thread_trace_flags |= kThreadTruncatedBT;
767 }
768 }
5ba3f43e
A
769 }
770 /* Reset the target pmap */
771 machine_trace_thread_clear_validation_cache();
0a7de745 772 return (int)(((char *)tracebuf) - tracepos);
5ba3f43e
A
773#else
774#error Unknown architecture.
775#endif
776}
777
778void
779kdp_ml_enter_debugger(void)
780{
0a7de745 781 __asm__ volatile (".long 0xe7ffdefe");
5ba3f43e 782}