]> git.saurik.com Git - apple/xnu.git/blame - osfmk/arm64/pcb.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / osfmk / arm64 / pcb.c
CommitLineData
5ba3f43e 1/*
0a7de745 2 * Copyright (c) 2007-2019 Apple Inc. All rights reserved.
5ba3f43e
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <debug.h>
30
31#include <types.h>
32
33#include <mach/mach_types.h>
34#include <mach/thread_status.h>
35#include <mach/vm_types.h>
36
37#include <kern/kern_types.h>
38#include <kern/task.h>
39#include <kern/thread.h>
40#include <kern/misc_protos.h>
41#include <kern/mach_param.h>
42#include <kern/spl.h>
43#include <kern/machine.h>
44#include <kern/kalloc.h>
45#include <kern/kpc.h>
46
47#if MONOTONIC
48#include <kern/monotonic.h>
49#endif /* MONOTONIC */
50
51#include <machine/atomic.h>
52#include <arm64/proc_reg.h>
53#include <arm64/machine_machdep.h>
54#include <arm/cpu_data_internal.h>
55#include <arm/machdep_call.h>
56#include <arm/misc_protos.h>
57#include <arm/cpuid.h>
58
59#include <vm/vm_map.h>
60#include <vm/vm_protos.h>
61
62#include <sys/kdebug.h>
63
64#define USER_SS_ZONE_ALLOC_SIZE (0x4000)
65
66extern int debug_task;
67
68zone_t ads_zone; /* zone for debug_state area */
69zone_t user_ss_zone; /* zone for user arm_context_t allocations */
70
71/*
cb323159 72 * Routine: consider_machine_collect
5ba3f43e
A
73 *
74 */
75void
76consider_machine_collect(void)
77{
78 pmap_gc();
79}
80
81/*
cb323159 82 * Routine: consider_machine_adjust
5ba3f43e
A
83 *
84 */
85void
86consider_machine_adjust(void)
87{
88}
89
cb323159 90
5ba3f43e 91/*
cb323159 92 * Routine: machine_switch_context
5ba3f43e
A
93 *
94 */
95thread_t
cb323159
A
96machine_switch_context(thread_t old,
97 thread_continue_t continuation,
98 thread_t new)
5ba3f43e
A
99{
100 thread_t retval;
cb323159
A
101 pmap_t new_pmap;
102 cpu_data_t * cpu_data_ptr;
5ba3f43e 103
cb323159
A
104#define machine_switch_context_kprintf(x...) \
105 /* kprintf("machine_switch_context: " x) */
5ba3f43e
A
106
107 cpu_data_ptr = getCpuDatap();
108 if (old == new)
109 panic("machine_switch_context");
110
111 kpc_off_cpu(old);
112
113
cb323159 114
5ba3f43e
A
115 new_pmap = new->map->pmap;
116 if (old->map->pmap != new_pmap)
117 pmap_switch(new_pmap);
118
cb323159 119
5ba3f43e
A
120 new->machine.CpuDatap = cpu_data_ptr;
121
0a7de745
A
122 /* TODO: Should this be ordered? */
123 old->machine.machine_thread_flags &= ~MACHINE_THREAD_FLAGS_ON_CPU;
124 new->machine.machine_thread_flags |= MACHINE_THREAD_FLAGS_ON_CPU;
125
5ba3f43e
A
126 machine_switch_context_kprintf("old= %x contination = %x new = %x\n", old, continuation, new);
127
128 retval = Switch_context(old, continuation, new);
129 assert(retval != NULL);
130
131 return retval;
132}
133
cb323159
A
134boolean_t
135machine_thread_on_core(thread_t thread)
136{
137 return thread->machine.machine_thread_flags & MACHINE_THREAD_FLAGS_ON_CPU;
138}
139
5ba3f43e 140/*
cb323159 141 * Routine: machine_thread_create
5ba3f43e
A
142 *
143 */
144kern_return_t
cb323159
A
145machine_thread_create(thread_t thread,
146 task_t task)
5ba3f43e
A
147{
148 arm_context_t *thread_user_ss = NULL;
149 kern_return_t result = KERN_SUCCESS;
150
cb323159
A
151#define machine_thread_create_kprintf(x...) \
152 /* kprintf("machine_thread_create: " x) */
5ba3f43e
A
153
154 machine_thread_create_kprintf("thread = %x\n", thread);
155
156 if (current_thread() != thread) {
157 thread->machine.CpuDatap = (cpu_data_t *)0;
158 }
159 thread->machine.preemption_count = 0;
160 thread->machine.cthread_self = 0;
161 thread->machine.cthread_data = 0;
cb323159
A
162#if defined(HAS_APPLE_PAC)
163 thread->machine.rop_pid = task->rop_pid;
164 thread->machine.disable_user_jop = task->disable_user_jop;
165#endif
5ba3f43e
A
166
167
168 if (task != kernel_task) {
169 /* If this isn't a kernel thread, we'll have userspace state. */
170 thread->machine.contextData = (arm_context_t *)zalloc(user_ss_zone);
171
172 if (!thread->machine.contextData) {
cb323159
A
173 result = KERN_FAILURE;
174 goto done;
5ba3f43e
A
175 }
176
177 thread->machine.upcb = &thread->machine.contextData->ss;
178 thread->machine.uNeon = &thread->machine.contextData->ns;
179
d9a64523 180 if (task_has_64Bit_data(task)) {
5ba3f43e
A
181 thread->machine.upcb->ash.flavor = ARM_SAVED_STATE64;
182 thread->machine.upcb->ash.count = ARM_SAVED_STATE64_COUNT;
183 thread->machine.uNeon->nsh.flavor = ARM_NEON_SAVED_STATE64;
184 thread->machine.uNeon->nsh.count = ARM_NEON_SAVED_STATE64_COUNT;
185 } else {
186 thread->machine.upcb->ash.flavor = ARM_SAVED_STATE32;
187 thread->machine.upcb->ash.count = ARM_SAVED_STATE32_COUNT;
188 thread->machine.uNeon->nsh.flavor = ARM_NEON_SAVED_STATE32;
189 thread->machine.uNeon->nsh.count = ARM_NEON_SAVED_STATE32_COUNT;
190 }
cb323159 191
5ba3f43e
A
192 } else {
193 thread->machine.upcb = NULL;
194 thread->machine.uNeon = NULL;
195 thread->machine.contextData = NULL;
196 }
197
5ba3f43e 198
cb323159 199 bzero(&thread->machine.perfctrl_state, sizeof(thread->machine.perfctrl_state));
5ba3f43e
A
200 result = machine_thread_state_initialize(thread);
201
cb323159 202done:
5ba3f43e
A
203 if (result != KERN_SUCCESS) {
204 thread_user_ss = thread->machine.contextData;
cb323159
A
205
206 if (thread_user_ss) {
207 thread->machine.upcb = NULL;
208 thread->machine.uNeon = NULL;
209 thread->machine.contextData = NULL;
210 zfree(user_ss_zone, thread_user_ss);
211 }
5ba3f43e
A
212 }
213
214 return result;
215}
216
217/*
cb323159 218 * Routine: machine_thread_destroy
5ba3f43e
A
219 *
220 */
221void
cb323159 222machine_thread_destroy(thread_t thread)
5ba3f43e
A
223{
224 arm_context_t *thread_user_ss;
225
226 if (thread->machine.contextData) {
227 /* Disassociate the user save state from the thread before we free it. */
228 thread_user_ss = thread->machine.contextData;
229 thread->machine.upcb = NULL;
230 thread->machine.uNeon = NULL;
231 thread->machine.contextData = NULL;
cb323159
A
232
233
5ba3f43e
A
234 zfree(user_ss_zone, thread_user_ss);
235 }
236
237 if (thread->machine.DebugData != NULL) {
238 if (thread->machine.DebugData == getCpuDatap()->cpu_user_debug) {
239 arm_debug_set(NULL);
240 }
241
242 zfree(ads_zone, thread->machine.DebugData);
243 }
244}
245
246
247/*
cb323159 248 * Routine: machine_thread_init
5ba3f43e
A
249 *
250 */
251void
252machine_thread_init(void)
253{
254 ads_zone = zinit(sizeof(arm_debug_state_t),
255 THREAD_CHUNK * (sizeof(arm_debug_state_t)),
256 THREAD_CHUNK * (sizeof(arm_debug_state_t)),
257 "arm debug state");
258
259 /*
260 * Create a zone for the user save state. At the time this zone was created,
261 * the user save state was 848 bytes, and the matching kalloc zone was 1024
262 * bytes, which would result in significant amounts of wasted space if we
263 * simply used kalloc to allocate the user saved state.
264 *
265 * 0x4000 has been chosen as the allocation size, as it results in 272 bytes
266 * of wasted space per chunk, which should correspond to 19 allocations.
267 */
268 user_ss_zone = zinit(sizeof(arm_context_t),
269 CONFIG_THREAD_MAX * (sizeof(arm_context_t)),
270 USER_SS_ZONE_ALLOC_SIZE,
271 "user save state");
cb323159 272
5ba3f43e
A
273}
274
275
276/*
cb323159 277 * Routine: get_useraddr
5ba3f43e
A
278 *
279 */
280user_addr_t
281get_useraddr()
282{
283 return (get_saved_state_pc(current_thread()->machine.upcb));
284}
285
286/*
cb323159 287 * Routine: machine_stack_detach
5ba3f43e
A
288 *
289 */
290vm_offset_t
cb323159 291machine_stack_detach(thread_t thread)
5ba3f43e 292{
cb323159 293 vm_offset_t stack;
5ba3f43e
A
294
295 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_DETACH),
cb323159 296 (uintptr_t)thread_tid(thread), thread->priority, thread->sched_pri, 0, 0);
5ba3f43e
A
297
298 stack = thread->kernel_stack;
299 thread->kernel_stack = 0;
300 thread->machine.kstackptr = 0;
301
302 return (stack);
303}
304
305
306/*
cb323159 307 * Routine: machine_stack_attach
5ba3f43e
A
308 *
309 */
310void
cb323159
A
311machine_stack_attach(thread_t thread,
312 vm_offset_t stack)
5ba3f43e
A
313{
314 struct arm_context *context;
315 struct arm_saved_state64 *savestate;
cb323159 316 uint32_t current_el;
5ba3f43e 317
cb323159
A
318#define machine_stack_attach_kprintf(x...) \
319 /* kprintf("machine_stack_attach: " x) */
5ba3f43e
A
320
321 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_ATTACH),
cb323159 322 (uintptr_t)thread_tid(thread), thread->priority, thread->sched_pri, 0, 0);
5ba3f43e
A
323
324 thread->kernel_stack = stack;
325 thread->machine.kstackptr = stack + kernel_stack_size - sizeof(struct thread_kernel_state);
326 thread_initialize_kernel_state(thread);
327
328 machine_stack_attach_kprintf("kstackptr: %lx\n", (vm_address_t)thread->machine.kstackptr);
329
cb323159 330 current_el = (uint32_t) __builtin_arm_rsr64("CurrentEL");
5ba3f43e
A
331 context = &((thread_kernel_state_t) thread->machine.kstackptr)->machine;
332 savestate = saved_state64(&context->ss);
333 savestate->fp = 0;
5ba3f43e 334 savestate->sp = thread->machine.kstackptr;
cb323159
A
335#if defined(HAS_APPLE_PAC)
336 /* Sign the initial kernel stack saved state */
337 const uint32_t default_cpsr = PSR64_KERNEL_DEFAULT & ~PSR64_MODE_EL_MASK;
338 asm volatile (
339 "mov x0, %[ss]" "\n"
340
341 "mov x1, xzr" "\n"
342 "str x1, [x0, %[SS64_PC]]" "\n"
343
344 "mov x2, %[default_cpsr_lo]" "\n"
345 "movk x2, %[default_cpsr_hi], lsl #16" "\n"
346 "mrs x3, CurrentEL" "\n"
347 "orr w2, w2, w3" "\n"
348 "str w2, [x0, %[SS64_CPSR]]" "\n"
349
350 "adrp x3, _thread_continue@page" "\n"
351 "add x3, x3, _thread_continue@pageoff" "\n"
352 "str x3, [x0, %[SS64_LR]]" "\n"
353
354 "mov x4, xzr" "\n"
355 "mov x5, xzr" "\n"
356 "stp x4, x5, [x0, %[SS64_X16]]" "\n"
357
358 "mov x6, lr" "\n"
359 "bl _ml_sign_thread_state" "\n"
360 "mov lr, x6" "\n"
361 :
362 : [ss] "r"(&context->ss),
363 [default_cpsr_lo] "M"(default_cpsr & 0xFFFF),
364 [default_cpsr_hi] "M"(default_cpsr >> 16),
365 [SS64_X16] "i"(offsetof(struct arm_saved_state, ss_64.x[16])),
366 [SS64_PC] "i"(offsetof(struct arm_saved_state, ss_64.pc)),
367 [SS64_CPSR] "i"(offsetof(struct arm_saved_state, ss_64.cpsr)),
368 [SS64_LR] "i"(offsetof(struct arm_saved_state, ss_64.lr))
369 : "x0", "x1", "x2", "x3", "x4", "x5", "x6"
370 );
371#else
372 savestate->lr = (uintptr_t)thread_continue;
373 savestate->cpsr = (PSR64_KERNEL_DEFAULT & ~PSR64_MODE_EL_MASK) | current_el;
374#endif /* defined(HAS_APPLE_PAC) */
d9a64523 375 machine_stack_attach_kprintf("thread = %p pc = %llx, sp = %llx\n", thread, savestate->lr, savestate->sp);
5ba3f43e
A
376}
377
378
379/*
cb323159 380 * Routine: machine_stack_handoff
5ba3f43e
A
381 *
382 */
383void
cb323159
A
384machine_stack_handoff(thread_t old,
385 thread_t new)
5ba3f43e 386{
cb323159
A
387 vm_offset_t stack;
388 pmap_t new_pmap;
389 cpu_data_t * cpu_data_ptr;
5ba3f43e
A
390
391 kpc_off_cpu(old);
392
393 stack = machine_stack_detach(old);
394 cpu_data_ptr = getCpuDatap();
395 new->kernel_stack = stack;
396 new->machine.kstackptr = stack + kernel_stack_size - sizeof(struct thread_kernel_state);
397 if (stack == old->reserved_stack) {
398 assert(new->reserved_stack);
399 old->reserved_stack = new->reserved_stack;
400 new->reserved_stack = stack;
401 }
402
403
cb323159 404
5ba3f43e
A
405 new_pmap = new->map->pmap;
406 if (old->map->pmap != new_pmap)
407 pmap_switch(new_pmap);
408
cb323159 409
5ba3f43e 410 new->machine.CpuDatap = cpu_data_ptr;
0a7de745
A
411
412 /* TODO: Should this be ordered? */
413 old->machine.machine_thread_flags &= ~MACHINE_THREAD_FLAGS_ON_CPU;
414 new->machine.machine_thread_flags |= MACHINE_THREAD_FLAGS_ON_CPU;
415
5ba3f43e
A
416 machine_set_current_thread(new);
417 thread_initialize_kernel_state(new);
418
419 return;
420}
421
422
423/*
cb323159 424 * Routine: call_continuation
5ba3f43e
A
425 *
426 */
427void
cb323159
A
428call_continuation(thread_continue_t continuation,
429 void *parameter,
430 wait_result_t wresult,
431 boolean_t enable_interrupts)
5ba3f43e 432{
cb323159
A
433#define call_continuation_kprintf(x...) \
434 /* kprintf("call_continuation_kprintf:" x) */
5ba3f43e
A
435
436 call_continuation_kprintf("thread = %p continuation = %p, stack = %p\n", current_thread(), continuation, current_thread()->machine.kstackptr);
d9a64523 437 Call_continuation(continuation, parameter, wresult, enable_interrupts);
a39ff7e2
A
438}
439
440#define SET_DBGBCRn(n, value, accum) \
441 __asm__ volatile( \
442 "msr DBGBCR" #n "_EL1, %[val]\n" \
443 "orr %[result], %[result], %[val]\n" \
444 : [result] "+r"(accum) : [val] "r"((value)))
445
446#define SET_DBGBVRn(n, value) \
447 __asm__ volatile("msr DBGBVR" #n "_EL1, %0" : : "r"(value))
448
449#define SET_DBGWCRn(n, value, accum) \
450 __asm__ volatile( \
451 "msr DBGWCR" #n "_EL1, %[val]\n" \
452 "orr %[result], %[result], %[val]\n" \
453 : [result] "+r"(accum) : [val] "r"((value)))
454
455#define SET_DBGWVRn(n, value) \
456 __asm__ volatile("msr DBGWVR" #n "_EL1, %0" : : "r"(value))
457
5ba3f43e
A
458void arm_debug_set32(arm_debug_state_t *debug_state)
459{
cb323159
A
460 struct cpu_data * cpu_data_ptr;
461 arm_debug_info_t * debug_info = arm_debug_info();
462 boolean_t intr, set_mde = 0;
463 arm_debug_state_t off_state;
464 uint32_t i;
465 uint64_t all_ctrls = 0;
5ba3f43e
A
466
467 intr = ml_set_interrupts_enabled(FALSE);
468 cpu_data_ptr = getCpuDatap();
469
470 // Set current user debug
471 cpu_data_ptr->cpu_user_debug = debug_state;
472
473 if (NULL == debug_state) {
474 bzero(&off_state, sizeof(off_state));
475 debug_state = &off_state;
476 }
477
478 switch (debug_info->num_breakpoint_pairs) {
479 case 16:
a39ff7e2
A
480 SET_DBGBVRn(15, (uint64_t)debug_state->uds.ds32.bvr[15]);
481 SET_DBGBCRn(15, (uint64_t)debug_state->uds.ds32.bcr[15], all_ctrls);
5ba3f43e 482 case 15:
a39ff7e2
A
483 SET_DBGBVRn(14, (uint64_t)debug_state->uds.ds32.bvr[14]);
484 SET_DBGBCRn(14, (uint64_t)debug_state->uds.ds32.bcr[14], all_ctrls);
5ba3f43e 485 case 14:
a39ff7e2
A
486 SET_DBGBVRn(13, (uint64_t)debug_state->uds.ds32.bvr[13]);
487 SET_DBGBCRn(13, (uint64_t)debug_state->uds.ds32.bcr[13], all_ctrls);
5ba3f43e 488 case 13:
a39ff7e2
A
489 SET_DBGBVRn(12, (uint64_t)debug_state->uds.ds32.bvr[12]);
490 SET_DBGBCRn(12, (uint64_t)debug_state->uds.ds32.bcr[12], all_ctrls);
5ba3f43e 491 case 12:
a39ff7e2
A
492 SET_DBGBVRn(11, (uint64_t)debug_state->uds.ds32.bvr[11]);
493 SET_DBGBCRn(11, (uint64_t)debug_state->uds.ds32.bcr[11], all_ctrls);
5ba3f43e 494 case 11:
a39ff7e2
A
495 SET_DBGBVRn(10, (uint64_t)debug_state->uds.ds32.bvr[10]);
496 SET_DBGBCRn(10, (uint64_t)debug_state->uds.ds32.bcr[10], all_ctrls);
5ba3f43e 497 case 10:
a39ff7e2
A
498 SET_DBGBVRn(9, (uint64_t)debug_state->uds.ds32.bvr[9]);
499 SET_DBGBCRn(9, (uint64_t)debug_state->uds.ds32.bcr[9], all_ctrls);
5ba3f43e 500 case 9:
a39ff7e2
A
501 SET_DBGBVRn(8, (uint64_t)debug_state->uds.ds32.bvr[8]);
502 SET_DBGBCRn(8, (uint64_t)debug_state->uds.ds32.bcr[8], all_ctrls);
5ba3f43e 503 case 8:
a39ff7e2
A
504 SET_DBGBVRn(7, (uint64_t)debug_state->uds.ds32.bvr[7]);
505 SET_DBGBCRn(7, (uint64_t)debug_state->uds.ds32.bcr[7], all_ctrls);
5ba3f43e 506 case 7:
a39ff7e2
A
507 SET_DBGBVRn(6, (uint64_t)debug_state->uds.ds32.bvr[6]);
508 SET_DBGBCRn(6, (uint64_t)debug_state->uds.ds32.bcr[6], all_ctrls);
5ba3f43e 509 case 6:
a39ff7e2
A
510 SET_DBGBVRn(5, (uint64_t)debug_state->uds.ds32.bvr[5]);
511 SET_DBGBCRn(5, (uint64_t)debug_state->uds.ds32.bcr[5], all_ctrls);
5ba3f43e 512 case 5:
a39ff7e2
A
513 SET_DBGBVRn(4, (uint64_t)debug_state->uds.ds32.bvr[4]);
514 SET_DBGBCRn(4, (uint64_t)debug_state->uds.ds32.bcr[4], all_ctrls);
5ba3f43e 515 case 4:
a39ff7e2
A
516 SET_DBGBVRn(3, (uint64_t)debug_state->uds.ds32.bvr[3]);
517 SET_DBGBCRn(3, (uint64_t)debug_state->uds.ds32.bcr[3], all_ctrls);
5ba3f43e 518 case 3:
a39ff7e2
A
519 SET_DBGBVRn(2, (uint64_t)debug_state->uds.ds32.bvr[2]);
520 SET_DBGBCRn(2, (uint64_t)debug_state->uds.ds32.bcr[2], all_ctrls);
5ba3f43e 521 case 2:
a39ff7e2
A
522 SET_DBGBVRn(1, (uint64_t)debug_state->uds.ds32.bvr[1]);
523 SET_DBGBCRn(1, (uint64_t)debug_state->uds.ds32.bcr[1], all_ctrls);
5ba3f43e 524 case 1:
a39ff7e2
A
525 SET_DBGBVRn(0, (uint64_t)debug_state->uds.ds32.bvr[0]);
526 SET_DBGBCRn(0, (uint64_t)debug_state->uds.ds32.bcr[0], all_ctrls);
5ba3f43e
A
527 default:
528 break;
529 }
530
531 switch (debug_info->num_watchpoint_pairs) {
532 case 16:
a39ff7e2
A
533 SET_DBGWVRn(15, (uint64_t)debug_state->uds.ds32.wvr[15]);
534 SET_DBGWCRn(15, (uint64_t)debug_state->uds.ds32.wcr[15], all_ctrls);
5ba3f43e 535 case 15:
a39ff7e2
A
536 SET_DBGWVRn(14, (uint64_t)debug_state->uds.ds32.wvr[14]);
537 SET_DBGWCRn(14, (uint64_t)debug_state->uds.ds32.wcr[14], all_ctrls);
5ba3f43e 538 case 14:
a39ff7e2
A
539 SET_DBGWVRn(13, (uint64_t)debug_state->uds.ds32.wvr[13]);
540 SET_DBGWCRn(13, (uint64_t)debug_state->uds.ds32.wcr[13], all_ctrls);
5ba3f43e 541 case 13:
a39ff7e2
A
542 SET_DBGWVRn(12, (uint64_t)debug_state->uds.ds32.wvr[12]);
543 SET_DBGWCRn(12, (uint64_t)debug_state->uds.ds32.wcr[12], all_ctrls);
5ba3f43e 544 case 12:
a39ff7e2
A
545 SET_DBGWVRn(11, (uint64_t)debug_state->uds.ds32.wvr[11]);
546 SET_DBGWCRn(11, (uint64_t)debug_state->uds.ds32.wcr[11], all_ctrls);
5ba3f43e 547 case 11:
a39ff7e2
A
548 SET_DBGWVRn(10, (uint64_t)debug_state->uds.ds32.wvr[10]);
549 SET_DBGWCRn(10, (uint64_t)debug_state->uds.ds32.wcr[10], all_ctrls);
5ba3f43e 550 case 10:
a39ff7e2
A
551 SET_DBGWVRn(9, (uint64_t)debug_state->uds.ds32.wvr[9]);
552 SET_DBGWCRn(9, (uint64_t)debug_state->uds.ds32.wcr[9], all_ctrls);
5ba3f43e 553 case 9:
a39ff7e2
A
554 SET_DBGWVRn(8, (uint64_t)debug_state->uds.ds32.wvr[8]);
555 SET_DBGWCRn(8, (uint64_t)debug_state->uds.ds32.wcr[8], all_ctrls);
5ba3f43e 556 case 8:
a39ff7e2
A
557 SET_DBGWVRn(7, (uint64_t)debug_state->uds.ds32.wvr[7]);
558 SET_DBGWCRn(7, (uint64_t)debug_state->uds.ds32.wcr[7], all_ctrls);
5ba3f43e 559 case 7:
a39ff7e2
A
560 SET_DBGWVRn(6, (uint64_t)debug_state->uds.ds32.wvr[6]);
561 SET_DBGWCRn(6, (uint64_t)debug_state->uds.ds32.wcr[6], all_ctrls);
5ba3f43e 562 case 6:
a39ff7e2
A
563 SET_DBGWVRn(5, (uint64_t)debug_state->uds.ds32.wvr[5]);
564 SET_DBGWCRn(5, (uint64_t)debug_state->uds.ds32.wcr[5], all_ctrls);
5ba3f43e 565 case 5:
a39ff7e2
A
566 SET_DBGWVRn(4, (uint64_t)debug_state->uds.ds32.wvr[4]);
567 SET_DBGWCRn(4, (uint64_t)debug_state->uds.ds32.wcr[4], all_ctrls);
5ba3f43e 568 case 4:
a39ff7e2
A
569 SET_DBGWVRn(3, (uint64_t)debug_state->uds.ds32.wvr[3]);
570 SET_DBGWCRn(3, (uint64_t)debug_state->uds.ds32.wcr[3], all_ctrls);
5ba3f43e 571 case 3:
a39ff7e2
A
572 SET_DBGWVRn(2, (uint64_t)debug_state->uds.ds32.wvr[2]);
573 SET_DBGWCRn(2, (uint64_t)debug_state->uds.ds32.wcr[2], all_ctrls);
5ba3f43e 574 case 2:
a39ff7e2
A
575 SET_DBGWVRn(1, (uint64_t)debug_state->uds.ds32.wvr[1]);
576 SET_DBGWCRn(1, (uint64_t)debug_state->uds.ds32.wcr[1], all_ctrls);
5ba3f43e 577 case 1:
a39ff7e2
A
578 SET_DBGWVRn(0, (uint64_t)debug_state->uds.ds32.wvr[0]);
579 SET_DBGWCRn(0, (uint64_t)debug_state->uds.ds32.wcr[0], all_ctrls);
5ba3f43e
A
580 default:
581 break;
582 }
583
a39ff7e2
A
584#if defined(CONFIG_KERNEL_INTEGRITY)
585 if ((all_ctrls & (ARM_DBG_CR_MODE_CONTROL_PRIVILEGED | ARM_DBG_CR_HIGHER_MODE_ENABLE)) != 0) {
586 panic("sorry, self-hosted debug is not supported: 0x%llx", all_ctrls);
587 }
588#endif
589
5ba3f43e
A
590 for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
591 if (0 != debug_state->uds.ds32.bcr[i]) {
592 set_mde = 1;
593 break;
594 }
595 }
596
597 for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
598 if (0 != debug_state->uds.ds32.wcr[i]) {
599 set_mde = 1;
600 break;
601 }
602 }
603
604 /*
605 * Breakpoint/Watchpoint Enable
606 */
607 if (set_mde) {
a39ff7e2 608 update_mdscr(0, 0x8000); // MDSCR_EL1[MDE]
5ba3f43e 609 } else {
a39ff7e2 610 update_mdscr(0x8000, 0);
5ba3f43e 611 }
cb323159 612
5ba3f43e
A
613 /*
614 * Software debug single step enable
615 */
616 if (debug_state->uds.ds32.mdscr_el1 & 0x1) {
a39ff7e2 617 update_mdscr(0x8000, 1); // ~MDE | SS : no brk/watch while single stepping (which we've set)
5ba3f43e 618
cb323159 619 mask_saved_state_cpsr(current_thread()->machine.upcb, PSR64_SS, 0);
5ba3f43e
A
620 } else {
621
a39ff7e2 622 update_mdscr(0x1, 0);
5ba3f43e
A
623
624#if SINGLE_STEP_RETIRE_ERRATA
625 // Workaround for radar 20619637
626 __builtin_arm_isb(ISB_SY);
627#endif
628 }
629
630 (void) ml_set_interrupts_enabled(intr);
631
632 return;
633}
634
635void arm_debug_set64(arm_debug_state_t *debug_state)
636{
cb323159
A
637 struct cpu_data * cpu_data_ptr;
638 arm_debug_info_t * debug_info = arm_debug_info();
639 boolean_t intr, set_mde = 0;
640 arm_debug_state_t off_state;
641 uint32_t i;
642 uint64_t all_ctrls = 0;
5ba3f43e
A
643
644 intr = ml_set_interrupts_enabled(FALSE);
645 cpu_data_ptr = getCpuDatap();
646
647 // Set current user debug
648 cpu_data_ptr->cpu_user_debug = debug_state;
649
650 if (NULL == debug_state) {
651 bzero(&off_state, sizeof(off_state));
652 debug_state = &off_state;
653 }
654
655 switch (debug_info->num_breakpoint_pairs) {
656 case 16:
a39ff7e2
A
657 SET_DBGBVRn(15, debug_state->uds.ds64.bvr[15]);
658 SET_DBGBCRn(15, (uint64_t)debug_state->uds.ds64.bcr[15], all_ctrls);
5ba3f43e 659 case 15:
a39ff7e2
A
660 SET_DBGBVRn(14, debug_state->uds.ds64.bvr[14]);
661 SET_DBGBCRn(14, (uint64_t)debug_state->uds.ds64.bcr[14], all_ctrls);
5ba3f43e 662 case 14:
a39ff7e2
A
663 SET_DBGBVRn(13, debug_state->uds.ds64.bvr[13]);
664 SET_DBGBCRn(13, (uint64_t)debug_state->uds.ds64.bcr[13], all_ctrls);
5ba3f43e 665 case 13:
a39ff7e2
A
666 SET_DBGBVRn(12, debug_state->uds.ds64.bvr[12]);
667 SET_DBGBCRn(12, (uint64_t)debug_state->uds.ds64.bcr[12], all_ctrls);
5ba3f43e 668 case 12:
a39ff7e2
A
669 SET_DBGBVRn(11, debug_state->uds.ds64.bvr[11]);
670 SET_DBGBCRn(11, (uint64_t)debug_state->uds.ds64.bcr[11], all_ctrls);
5ba3f43e 671 case 11:
a39ff7e2
A
672 SET_DBGBVRn(10, debug_state->uds.ds64.bvr[10]);
673 SET_DBGBCRn(10, (uint64_t)debug_state->uds.ds64.bcr[10], all_ctrls);
5ba3f43e 674 case 10:
a39ff7e2
A
675 SET_DBGBVRn(9, debug_state->uds.ds64.bvr[9]);
676 SET_DBGBCRn(9, (uint64_t)debug_state->uds.ds64.bcr[9], all_ctrls);
5ba3f43e 677 case 9:
a39ff7e2
A
678 SET_DBGBVRn(8, debug_state->uds.ds64.bvr[8]);
679 SET_DBGBCRn(8, (uint64_t)debug_state->uds.ds64.bcr[8], all_ctrls);
5ba3f43e 680 case 8:
a39ff7e2
A
681 SET_DBGBVRn(7, debug_state->uds.ds64.bvr[7]);
682 SET_DBGBCRn(7, (uint64_t)debug_state->uds.ds64.bcr[7], all_ctrls);
5ba3f43e 683 case 7:
a39ff7e2
A
684 SET_DBGBVRn(6, debug_state->uds.ds64.bvr[6]);
685 SET_DBGBCRn(6, (uint64_t)debug_state->uds.ds64.bcr[6], all_ctrls);
5ba3f43e 686 case 6:
a39ff7e2
A
687 SET_DBGBVRn(5, debug_state->uds.ds64.bvr[5]);
688 SET_DBGBCRn(5, (uint64_t)debug_state->uds.ds64.bcr[5], all_ctrls);
5ba3f43e 689 case 5:
a39ff7e2
A
690 SET_DBGBVRn(4, debug_state->uds.ds64.bvr[4]);
691 SET_DBGBCRn(4, (uint64_t)debug_state->uds.ds64.bcr[4], all_ctrls);
5ba3f43e 692 case 4:
a39ff7e2
A
693 SET_DBGBVRn(3, debug_state->uds.ds64.bvr[3]);
694 SET_DBGBCRn(3, (uint64_t)debug_state->uds.ds64.bcr[3], all_ctrls);
5ba3f43e 695 case 3:
a39ff7e2
A
696 SET_DBGBVRn(2, debug_state->uds.ds64.bvr[2]);
697 SET_DBGBCRn(2, (uint64_t)debug_state->uds.ds64.bcr[2], all_ctrls);
5ba3f43e 698 case 2:
a39ff7e2
A
699 SET_DBGBVRn(1, debug_state->uds.ds64.bvr[1]);
700 SET_DBGBCRn(1, (uint64_t)debug_state->uds.ds64.bcr[1], all_ctrls);
5ba3f43e 701 case 1:
a39ff7e2
A
702 SET_DBGBVRn(0, debug_state->uds.ds64.bvr[0]);
703 SET_DBGBCRn(0, (uint64_t)debug_state->uds.ds64.bcr[0], all_ctrls);
5ba3f43e
A
704 default:
705 break;
706 }
707
708 switch (debug_info->num_watchpoint_pairs) {
709 case 16:
a39ff7e2
A
710 SET_DBGWVRn(15, debug_state->uds.ds64.wvr[15]);
711 SET_DBGWCRn(15, (uint64_t)debug_state->uds.ds64.wcr[15], all_ctrls);
5ba3f43e 712 case 15:
a39ff7e2
A
713 SET_DBGWVRn(14, debug_state->uds.ds64.wvr[14]);
714 SET_DBGWCRn(14, (uint64_t)debug_state->uds.ds64.wcr[14], all_ctrls);
5ba3f43e 715 case 14:
a39ff7e2
A
716 SET_DBGWVRn(13, debug_state->uds.ds64.wvr[13]);
717 SET_DBGWCRn(13, (uint64_t)debug_state->uds.ds64.wcr[13], all_ctrls);
5ba3f43e 718 case 13:
a39ff7e2
A
719 SET_DBGWVRn(12, debug_state->uds.ds64.wvr[12]);
720 SET_DBGWCRn(12, (uint64_t)debug_state->uds.ds64.wcr[12], all_ctrls);
5ba3f43e 721 case 12:
a39ff7e2
A
722 SET_DBGWVRn(11, debug_state->uds.ds64.wvr[11]);
723 SET_DBGWCRn(11, (uint64_t)debug_state->uds.ds64.wcr[11], all_ctrls);
5ba3f43e 724 case 11:
a39ff7e2
A
725 SET_DBGWVRn(10, debug_state->uds.ds64.wvr[10]);
726 SET_DBGWCRn(10, (uint64_t)debug_state->uds.ds64.wcr[10], all_ctrls);
5ba3f43e 727 case 10:
a39ff7e2
A
728 SET_DBGWVRn(9, debug_state->uds.ds64.wvr[9]);
729 SET_DBGWCRn(9, (uint64_t)debug_state->uds.ds64.wcr[9], all_ctrls);
5ba3f43e 730 case 9:
a39ff7e2
A
731 SET_DBGWVRn(8, debug_state->uds.ds64.wvr[8]);
732 SET_DBGWCRn(8, (uint64_t)debug_state->uds.ds64.wcr[8], all_ctrls);
5ba3f43e 733 case 8:
a39ff7e2
A
734 SET_DBGWVRn(7, debug_state->uds.ds64.wvr[7]);
735 SET_DBGWCRn(7, (uint64_t)debug_state->uds.ds64.wcr[7], all_ctrls);
5ba3f43e 736 case 7:
a39ff7e2
A
737 SET_DBGWVRn(6, debug_state->uds.ds64.wvr[6]);
738 SET_DBGWCRn(6, (uint64_t)debug_state->uds.ds64.wcr[6], all_ctrls);
5ba3f43e 739 case 6:
a39ff7e2
A
740 SET_DBGWVRn(5, debug_state->uds.ds64.wvr[5]);
741 SET_DBGWCRn(5, (uint64_t)debug_state->uds.ds64.wcr[5], all_ctrls);
5ba3f43e 742 case 5:
a39ff7e2
A
743 SET_DBGWVRn(4, debug_state->uds.ds64.wvr[4]);
744 SET_DBGWCRn(4, (uint64_t)debug_state->uds.ds64.wcr[4], all_ctrls);
5ba3f43e 745 case 4:
a39ff7e2
A
746 SET_DBGWVRn(3, debug_state->uds.ds64.wvr[3]);
747 SET_DBGWCRn(3, (uint64_t)debug_state->uds.ds64.wcr[3], all_ctrls);
5ba3f43e 748 case 3:
a39ff7e2
A
749 SET_DBGWVRn(2, debug_state->uds.ds64.wvr[2]);
750 SET_DBGWCRn(2, (uint64_t)debug_state->uds.ds64.wcr[2], all_ctrls);
5ba3f43e 751 case 2:
a39ff7e2
A
752 SET_DBGWVRn(1, debug_state->uds.ds64.wvr[1]);
753 SET_DBGWCRn(1, (uint64_t)debug_state->uds.ds64.wcr[1], all_ctrls);
5ba3f43e 754 case 1:
a39ff7e2
A
755 SET_DBGWVRn(0, debug_state->uds.ds64.wvr[0]);
756 SET_DBGWCRn(0, (uint64_t)debug_state->uds.ds64.wcr[0], all_ctrls);
5ba3f43e
A
757 default:
758 break;
759 }
760
a39ff7e2
A
761#if defined(CONFIG_KERNEL_INTEGRITY)
762 if ((all_ctrls & (ARM_DBG_CR_MODE_CONTROL_PRIVILEGED | ARM_DBG_CR_HIGHER_MODE_ENABLE)) != 0) {
763 panic("sorry, self-hosted debug is not supported: 0x%llx", all_ctrls);
764 }
765#endif
766
5ba3f43e
A
767 for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
768 if (0 != debug_state->uds.ds64.bcr[i]) {
769 set_mde = 1;
770 break;
771 }
772 }
773
774 for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
775 if (0 != debug_state->uds.ds64.wcr[i]) {
776 set_mde = 1;
777 break;
778 }
779 }
780
781 /*
782 * Breakpoint/Watchpoint Enable
783 */
784 if (set_mde) {
a39ff7e2 785 update_mdscr(0, 0x8000); // MDSCR_EL1[MDE]
5ba3f43e 786 }
cb323159 787
5ba3f43e
A
788 /*
789 * Software debug single step enable
790 */
791 if (debug_state->uds.ds64.mdscr_el1 & 0x1) {
792
a39ff7e2 793 update_mdscr(0x8000, 1); // ~MDE | SS : no brk/watch while single stepping (which we've set)
5ba3f43e 794
cb323159 795 mask_saved_state_cpsr(current_thread()->machine.upcb, PSR64_SS, 0);
5ba3f43e
A
796 } else {
797
a39ff7e2 798 update_mdscr(0x1, 0);
5ba3f43e
A
799
800#if SINGLE_STEP_RETIRE_ERRATA
801 // Workaround for radar 20619637
802 __builtin_arm_isb(ISB_SY);
803#endif
804 }
805
806 (void) ml_set_interrupts_enabled(intr);
807
808 return;
809}
810
811void arm_debug_set(arm_debug_state_t *debug_state)
812{
813 if (debug_state) {
814 switch (debug_state->dsh.flavor) {
815 case ARM_DEBUG_STATE32:
816 arm_debug_set32(debug_state);
817 break;
818 case ARM_DEBUG_STATE64:
819 arm_debug_set64(debug_state);
820 break;
821 default:
822 panic("arm_debug_set");
823 break;
824 }
825 } else {
d9a64523 826 if (thread_is_64bit_data(current_thread()))
5ba3f43e
A
827 arm_debug_set64(debug_state);
828 else
829 arm_debug_set32(debug_state);
830 }
831}
832
833#define VM_MAX_ADDRESS32 ((vm_address_t) 0x80000000)
834boolean_t
835debug_legacy_state_is_valid(arm_legacy_debug_state_t *debug_state)
836{
cb323159 837 arm_debug_info_t *debug_info = arm_debug_info();
5ba3f43e
A
838 uint32_t i;
839 for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
840 if (0 != debug_state->bcr[i] && VM_MAX_ADDRESS32 <= debug_state->bvr[i])
841 return FALSE;
842 }
843
844 for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
845 if (0 != debug_state->wcr[i] && VM_MAX_ADDRESS32 <= debug_state->wvr[i])
846 return FALSE;
847 }
848 return TRUE;
849}
850
851boolean_t
852debug_state_is_valid32(arm_debug_state32_t *debug_state)
853{
cb323159 854 arm_debug_info_t *debug_info = arm_debug_info();
5ba3f43e
A
855 uint32_t i;
856 for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
857 if (0 != debug_state->bcr[i] && VM_MAX_ADDRESS32 <= debug_state->bvr[i])
858 return FALSE;
859 }
860
861 for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
862 if (0 != debug_state->wcr[i] && VM_MAX_ADDRESS32 <= debug_state->wvr[i])
863 return FALSE;
864 }
865 return TRUE;
866}
867
868boolean_t
869debug_state_is_valid64(arm_debug_state64_t *debug_state)
870{
cb323159 871 arm_debug_info_t *debug_info = arm_debug_info();
5ba3f43e
A
872 uint32_t i;
873 for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
874 if (0 != debug_state->bcr[i] && MACH_VM_MAX_ADDRESS <= debug_state->bvr[i])
875 return FALSE;
876 }
877
878 for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
879 if (0 != debug_state->wcr[i] && MACH_VM_MAX_ADDRESS <= debug_state->wvr[i])
880 return FALSE;
881 }
882 return TRUE;
883}
884
885/*
886 * Duplicate one arm_debug_state_t to another. "all" parameter
887 * is ignored in the case of ARM -- Is this the right assumption?
888 */
889void
cb323159
A
890copy_legacy_debug_state(arm_legacy_debug_state_t * src,
891 arm_legacy_debug_state_t * target,
892 __unused boolean_t all)
5ba3f43e
A
893{
894 bcopy(src, target, sizeof(arm_legacy_debug_state_t));
895}
896
897void
cb323159
A
898copy_debug_state32(arm_debug_state32_t * src,
899 arm_debug_state32_t * target,
900 __unused boolean_t all)
5ba3f43e
A
901{
902 bcopy(src, target, sizeof(arm_debug_state32_t));
903}
904
905void
cb323159
A
906copy_debug_state64(arm_debug_state64_t * src,
907 arm_debug_state64_t * target,
908 __unused boolean_t all)
5ba3f43e
A
909{
910 bcopy(src, target, sizeof(arm_debug_state64_t));
911}
912
913kern_return_t
cb323159
A
914machine_thread_set_tsd_base(thread_t thread,
915 mach_vm_offset_t tsd_base)
5ba3f43e 916{
5ba3f43e
A
917 if (thread->task == kernel_task) {
918 return KERN_INVALID_ARGUMENT;
919 }
920
921 if (tsd_base & MACHDEP_CPUNUM_MASK) {
922 return KERN_INVALID_ARGUMENT;
923 }
924
d9a64523 925 if (thread_is_64bit_addr(thread)) {
5ba3f43e
A
926 if (tsd_base > vm_map_max(thread->map))
927 tsd_base = 0ULL;
928 } else {
929 if (tsd_base > UINT32_MAX)
930 tsd_base = 0ULL;
931 }
932
933 thread->machine.cthread_self = tsd_base;
934
935 /* For current thread, make the TSD base active immediately */
936 if (thread == current_thread()) {
937 uint64_t cpunum, tpidrro_el0;
938
939 mp_disable_preemption();
940 tpidrro_el0 = get_tpidrro();
941 cpunum = tpidrro_el0 & (MACHDEP_CPUNUM_MASK);
942 set_tpidrro(tsd_base | cpunum);
943 mp_enable_preemption();
944
945 }
946
947 return KERN_SUCCESS;
948}
0a7de745
A
949
950void
951machine_tecs(__unused thread_t thr)
952{
953}
954
955int
956machine_csv(__unused cpuvn_e cve)
957{
958 return 0;
959}