2 * Copyright (c) 2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * FILE_ID: thread_status.h
33 #ifndef _ARM_THREAD_STATUS_H_
34 #define _ARM_THREAD_STATUS_H_
36 #include <mach/machine/_structs.h>
37 #include <mach/message.h>
38 #include <mach/vm_types.h>
39 #include <mach/arm/thread_state.h>
42 * Support for determining the state of a thread
50 #define ARM_THREAD_STATE 1
51 #define ARM_UNIFIED_THREAD_STATE ARM_THREAD_STATE
52 #define ARM_VFP_STATE 2
53 #define ARM_EXCEPTION_STATE 3
54 #define ARM_DEBUG_STATE 4 /* pre-armv8 */
55 #define THREAD_STATE_NONE 5
56 #define ARM_THREAD_STATE64 6
57 #define ARM_EXCEPTION_STATE64 7
58 // ARM_THREAD_STATE_LAST 8 /* legacy */
59 #define ARM_THREAD_STATE32 9
61 #ifdef XNU_KERNEL_PRIVATE
62 #define X86_THREAD_STATE_NONE 13 /* i386/thread_status.h THREAD_STATE_NONE */
63 #endif /* XNU_KERNEL_PRIVATE */
66 #define ARM_DEBUG_STATE32 14
67 #define ARM_DEBUG_STATE64 15
68 #define ARM_NEON_STATE 16
69 #define ARM_NEON_STATE64 17
70 #define ARM_CPMU_STATE64 18
72 #ifdef XNU_KERNEL_PRIVATE
74 #define ARM_SAVED_STATE32 20
75 #define ARM_SAVED_STATE64 21
76 #define ARM_NEON_SAVED_STATE32 22
77 #define ARM_NEON_SAVED_STATE64 23
78 #endif /* XNU_KERNEL_PRIVATE */
81 #define ARM_STATE_FLAVOR_IS_OTHER_VALID(_flavor_) 0
83 #define ARM_PAGEIN_STATE 27
85 #define VALID_THREAD_STATE_FLAVOR(x) \
86 ((x == ARM_THREAD_STATE) || \
87 (x == ARM_VFP_STATE) || \
88 (x == ARM_EXCEPTION_STATE) || \
89 (x == ARM_DEBUG_STATE) || \
90 (x == THREAD_STATE_NONE) || \
91 (x == ARM_THREAD_STATE32) || \
92 (x == ARM_THREAD_STATE64) || \
93 (x == ARM_EXCEPTION_STATE64) || \
94 (x == ARM_NEON_STATE) || \
95 (x == ARM_NEON_STATE64) || \
96 (x == ARM_DEBUG_STATE32) || \
97 (x == ARM_DEBUG_STATE64) || \
98 (x == ARM_PAGEIN_STATE) || \
99 (ARM_STATE_FLAVOR_IS_OTHER_VALID(x)))
101 struct arm_state_hdr
{
105 typedef struct arm_state_hdr arm_state_hdr_t
;
107 typedef _STRUCT_ARM_THREAD_STATE arm_thread_state_t
;
108 typedef _STRUCT_ARM_THREAD_STATE arm_thread_state32_t
;
109 typedef _STRUCT_ARM_THREAD_STATE64 arm_thread_state64_t
;
112 #if __DARWIN_C_LEVEL >= __DARWIN_C_FULL && defined(__arm64__)
114 /* Accessor macros for arm_thread_state64_t pointer fields */
116 /* Return pc field of arm_thread_state64_t as a data pointer value */
117 #define arm_thread_state64_get_pc(ts) \
118 __darwin_arm_thread_state64_get_pc(ts)
119 /* Return pc field of arm_thread_state64_t as a function pointer. May return
120 * NULL if a valid function pointer cannot be constructed, the caller should
121 * fall back to the arm_thread_state64_get_pc() macro in that case. */
122 #define arm_thread_state64_get_pc_fptr(ts) \
123 __darwin_arm_thread_state64_get_pc_fptr(ts)
124 /* Set pc field of arm_thread_state64_t to a function pointer */
125 #define arm_thread_state64_set_pc_fptr(ts, fptr) \
126 __darwin_arm_thread_state64_set_pc_fptr(ts, fptr)
127 /* Return lr field of arm_thread_state64_t as a data pointer value */
128 #define arm_thread_state64_get_lr(ts) \
129 __darwin_arm_thread_state64_get_lr(ts)
130 /* Return lr field of arm_thread_state64_t as a function pointer. May return
131 * NULL if a valid function pointer cannot be constructed, the caller should
132 * fall back to the arm_thread_state64_get_lr() macro in that case. */
133 #define arm_thread_state64_get_lr_fptr(ts) \
134 __darwin_arm_thread_state64_get_lr_fptr(ts)
135 /* Set lr field of arm_thread_state64_t to a function pointer */
136 #define arm_thread_state64_set_lr_fptr(ts, fptr) \
137 __darwin_arm_thread_state64_set_lr_fptr(ts, fptr)
138 /* Return sp field of arm_thread_state64_t as a data pointer value */
139 #define arm_thread_state64_get_sp(ts) \
140 __darwin_arm_thread_state64_get_sp(ts)
141 /* Set sp field of arm_thread_state64_t to a data pointer value */
142 #define arm_thread_state64_set_sp(ts, ptr) \
143 __darwin_arm_thread_state64_set_sp(ts, ptr)
144 /* Return fp field of arm_thread_state64_t as a data pointer value */
145 #define arm_thread_state64_get_fp(ts) \
146 __darwin_arm_thread_state64_get_fp(ts)
147 /* Set fp field of arm_thread_state64_t to a data pointer value */
148 #define arm_thread_state64_set_fp(ts, ptr) \
149 __darwin_arm_thread_state64_set_fp(ts, ptr)
150 /* Strip ptr auth bits from pc, lr, sp and fp field of arm_thread_state64_t */
151 #define arm_thread_state64_ptrauth_strip(ts) \
152 __darwin_arm_thread_state64_ptrauth_strip(ts)
154 #endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL && defined(__arm64__) */
155 #endif /* !defined(KERNEL) */
157 struct arm_unified_thread_state
{
160 arm_thread_state32_t ts_32
;
161 arm_thread_state64_t ts_64
;
164 #define ts_32 uts.ts_32
165 #define ts_64 uts.ts_64
166 typedef struct arm_unified_thread_state arm_unified_thread_state_t
;
168 #define ARM_THREAD_STATE_COUNT ((mach_msg_type_number_t) \
169 (sizeof (arm_thread_state_t)/sizeof(uint32_t)))
170 #define ARM_THREAD_STATE32_COUNT ((mach_msg_type_number_t) \
171 (sizeof (arm_thread_state32_t)/sizeof(uint32_t)))
172 #define ARM_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
173 (sizeof (arm_thread_state64_t)/sizeof(uint32_t)))
174 #define ARM_UNIFIED_THREAD_STATE_COUNT ((mach_msg_type_number_t) \
175 (sizeof (arm_unified_thread_state_t)/sizeof(uint32_t)))
178 typedef _STRUCT_ARM_VFP_STATE arm_vfp_state_t
;
179 typedef _STRUCT_ARM_NEON_STATE arm_neon_state_t
;
180 typedef _STRUCT_ARM_NEON_STATE arm_neon_state32_t
;
181 typedef _STRUCT_ARM_NEON_STATE64 arm_neon_state64_t
;
184 typedef _STRUCT_ARM_EXCEPTION_STATE arm_exception_state_t
;
185 typedef _STRUCT_ARM_EXCEPTION_STATE arm_exception_state32_t
;
186 typedef _STRUCT_ARM_EXCEPTION_STATE64 arm_exception_state64_t
;
188 typedef _STRUCT_ARM_DEBUG_STATE32 arm_debug_state32_t
;
189 typedef _STRUCT_ARM_DEBUG_STATE64 arm_debug_state64_t
;
191 typedef _STRUCT_ARM_PAGEIN_STATE arm_pagein_state_t
;
193 #if defined(XNU_KERNEL_PRIVATE) && defined(__arm64__)
194 /* See below for ARM64 kernel structure definition for arm_debug_state. */
195 #else /* defined(XNU_KERNEL_PRIVATE) && defined(__arm64__) */
197 * Otherwise not ARM64 kernel and we must preserve legacy ARM definitions of
198 * arm_debug_state for binary compatability of userland consumers of this file.
201 typedef _STRUCT_ARM_DEBUG_STATE arm_debug_state_t
;
202 #elif defined(__arm64__)
203 typedef _STRUCT_ARM_LEGACY_DEBUG_STATE arm_debug_state_t
;
204 #else /* defined(__arm__) */
205 #error Undefined architecture
206 #endif /* defined(__arm__) */
207 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(__arm64__) */
209 #define ARM_VFP_STATE_COUNT ((mach_msg_type_number_t) \
210 (sizeof (arm_vfp_state_t)/sizeof(uint32_t)))
212 #define ARM_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \
213 (sizeof (arm_exception_state_t)/sizeof(uint32_t)))
215 #define ARM_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \
216 (sizeof (arm_exception_state64_t)/sizeof(uint32_t)))
218 #define ARM_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \
219 (sizeof (arm_debug_state_t)/sizeof(uint32_t)))
221 #define ARM_DEBUG_STATE32_COUNT ((mach_msg_type_number_t) \
222 (sizeof (arm_debug_state32_t)/sizeof(uint32_t)))
224 #define ARM_PAGEIN_STATE_COUNT ((mach_msg_type_number_t) \
225 (sizeof (arm_pagein_state_t)/sizeof(uint32_t)))
227 #define ARM_DEBUG_STATE64_COUNT ((mach_msg_type_number_t) \
228 (sizeof (arm_debug_state64_t)/sizeof(uint32_t)))
230 #define ARM_NEON_STATE_COUNT ((mach_msg_type_number_t) \
231 (sizeof (arm_neon_state_t)/sizeof(uint32_t)))
233 #define ARM_NEON_STATE64_COUNT ((mach_msg_type_number_t) \
234 (sizeof (arm_neon_state64_t)/sizeof(uint32_t)))
236 #define MACHINE_THREAD_STATE ARM_THREAD_STATE
237 #define MACHINE_THREAD_STATE_COUNT ARM_UNIFIED_THREAD_STATE_COUNT
241 * Largest state on this machine:
243 #define THREAD_MACHINE_STATE_MAX THREAD_STATE_MAX
245 #ifdef XNU_KERNEL_PRIVATE
247 static inline boolean_t
248 is_thread_state32(const arm_unified_thread_state_t
*its
)
250 return its
->ash
.flavor
== ARM_THREAD_STATE32
;
253 static inline boolean_t
254 is_thread_state64(const arm_unified_thread_state_t
*its
)
256 return its
->ash
.flavor
== ARM_THREAD_STATE64
;
259 static inline arm_thread_state32_t
*
260 thread_state32(arm_unified_thread_state_t
*its
)
265 static inline arm_thread_state64_t
*
266 thread_state64(arm_unified_thread_state_t
*its
)
271 static inline const arm_thread_state32_t
*
272 const_thread_state32(const arm_unified_thread_state_t
*its
)
277 static inline const arm_thread_state64_t
*
278 const_thread_state64(const arm_unified_thread_state_t
*its
)
284 #include <arm/proc_reg.h>
286 #define ARM_SAVED_STATE (THREAD_STATE_NONE + 1)
289 #define VFPSAVE_ALIGN 16
290 #define VFPSAVE_ATTRIB __attribute__((aligned (VFPSAVE_ALIGN)))
291 #define THREAD_ALIGN VFPSAVE_ALIGN
294 * vector floating point saved state
296 struct arm_vfpsaved_state
{
303 struct arm_saved_state
{
304 uint32_t r
[13]; /* General purpose register r0-r12 */
305 uint32_t sp
; /* Stack pointer r13 */
306 uint32_t lr
; /* Link register r14 */
307 uint32_t pc
; /* Program counter r15 */
308 uint32_t cpsr
; /* Current program status register */
309 uint32_t fsr
; /* Fault status */
310 uint32_t far
; /* Virtual Fault Address */
311 uint32_t exception
; /* exception number */
315 struct arm_vfpsaved_state VFPdata VFPSAVE_ATTRIB
;
316 // for packing reasons chtread_self and DebugData
317 // are inside the the PcbData when __ARM_VFP__ is set
318 arm_debug_state_t
*VFPpadding_DebugData
;
319 vm_address_t VFPpadding_cthread_self
;
322 typedef struct arm_saved_state arm_saved_state_t
;
325 * Just for coexistence with AArch64 code.
327 typedef struct arm_saved_state arm_saved_state32_t
;
330 copy_signed_thread_state(arm_saved_state_t
*dst
, const arm_saved_state_t
*src
)
335 static inline arm_saved_state32_t
*
336 saved_state32(arm_saved_state_t
*iss
)
341 static inline boolean_t
342 is_saved_state32(const arm_saved_state_t
*iss __unused
)
348 struct arm_saved_state_tagged
{
350 struct arm_saved_state state
;
352 typedef struct arm_saved_state_tagged arm_saved_state_tagged_t
;
354 #define ARM_SAVED_STATE32_COUNT ((mach_msg_type_number_t) \
355 (sizeof (arm_saved_state_t)/sizeof(unsigned int)))
358 static inline register_t
359 get_saved_state_pc(const arm_saved_state_t
*iss
)
365 add_saved_state_pc(arm_saved_state_t
*iss
, int diff
)
367 iss
->pc
+= (unsigned int)diff
;
371 set_saved_state_pc(arm_saved_state_t
*iss
, register_t pc
)
373 iss
->pc
= (typeof(iss
->pc
))pc
;
376 static inline register_t
377 get_saved_state_sp(const arm_saved_state_t
*iss
)
383 set_saved_state_sp(arm_saved_state_t
*iss
, register_t sp
)
388 static inline register_t
389 get_saved_state_fp(const arm_saved_state_t
*iss
)
395 set_saved_state_fp(arm_saved_state_t
*iss
, register_t fp
)
400 static inline register_t
401 get_saved_state_lr(const arm_saved_state_t
*iss
)
403 return (register_t
)iss
->lr
;
407 set_saved_state_lr(arm_saved_state_t
*iss
, register_t lr
)
412 static inline register_t
413 get_saved_state_cpsr(const arm_saved_state_t
*iss
)
419 mask_saved_state_cpsr(arm_saved_state_t
*iss
, uint32_t set_bits
, uint32_t clear_bits
)
421 iss
->cpsr
|= set_bits
;
422 iss
->cpsr
&= ~clear_bits
;
426 set_saved_state_cpsr(arm_saved_state_t
*iss
, register_t cpsr
)
431 static inline register_t
432 get_saved_state_reg(const arm_saved_state_t
*iss
, unsigned regno
)
434 return iss
->r
[regno
];
438 set_saved_state_reg(arm_saved_state_t
*iss
, unsigned regno
, register_t val
)
443 #elif defined(__arm64__)
445 #include <kern/assert.h>
446 #include <arm64/proc_reg.h>
447 #define CAST_ASSERT_SAFE(type, val) (assert((val) == ((type)(val))), (type)(val))
453 struct arm_saved_state32
{
454 uint32_t r
[13]; /* General purpose register r0-r12 */
455 uint32_t sp
; /* Stack pointer r13 */
456 uint32_t lr
; /* Link register r14 */
457 uint32_t pc
; /* Program counter r15 */
458 uint32_t cpsr
; /* Current program status register */
459 uint32_t far
; /* Virtual fault address */
460 uint32_t esr
; /* Exception syndrome register */
461 uint32_t exception
; /* Exception number */
463 typedef struct arm_saved_state32 arm_saved_state32_t
;
465 struct arm_saved_state32_tagged
{
467 struct arm_saved_state32 state
;
469 typedef struct arm_saved_state32_tagged arm_saved_state32_tagged_t
;
471 #define ARM_SAVED_STATE32_COUNT ((mach_msg_type_number_t) \
472 (sizeof(arm_saved_state32_t)/sizeof(unsigned int)))
474 struct arm_saved_state64
{
475 uint64_t x
[29]; /* General purpose registers x0-x28 */
476 uint64_t fp
; /* Frame pointer x29 */
477 uint64_t lr
; /* Link register x30 */
478 uint64_t sp
; /* Stack pointer x31 */
479 uint64_t pc
; /* Program counter */
480 uint32_t cpsr
; /* Current program status register */
481 uint32_t reserved
; /* Reserved padding */
482 uint64_t far
; /* Virtual fault address */
483 uint32_t esr
; /* Exception syndrome register */
484 uint32_t exception
; /* Exception number */
485 #if defined(HAS_APPLE_PAC)
487 #endif /* defined(HAS_APPLE_PAC) */
489 typedef struct arm_saved_state64 arm_saved_state64_t
;
491 #define ARM_SAVED_STATE64_COUNT ((mach_msg_type_number_t) \
492 (sizeof(arm_saved_state64_t)/sizeof(unsigned int)))
494 struct arm_saved_state64_tagged
{
496 struct arm_saved_state64 state
;
498 typedef struct arm_saved_state64_tagged arm_saved_state64_tagged_t
;
500 struct arm_saved_state
{
503 struct arm_saved_state32 ss_32
;
504 struct arm_saved_state64 ss_64
;
506 } __attribute__((aligned(16)));
507 #define ss_32 uss.ss_32
508 #define ss_64 uss.ss_64
510 typedef struct arm_saved_state arm_saved_state_t
;
512 struct arm_kernel_saved_state
{
513 uint64_t x
[12]; /* General purpose registers x16-x28 */
514 uint64_t fp
; /* Frame pointer x29 */
515 uint64_t lr
; /* Link register x30 */
516 uint64_t sp
; /* Stack pointer x31 */
517 uint64_t pc
; /* Program counter */
518 uint32_t cpsr
; /* Current program status register */
519 uint32_t reserved
; /* Reserved padding */
520 #if defined(HAS_APPLE_PAC)
522 #endif /* defined(HAS_APPLE_PAC) */
523 } __attribute__((aligned(16)));
525 typedef struct arm_kernel_saved_state arm_kernel_saved_state_t
;
527 #if defined(XNU_KERNEL_PRIVATE)
528 #if defined(HAS_APPLE_PAC)
530 #include <sys/cdefs.h>
533 * Used by MANIPULATE_SIGNED_THREAD_STATE(), potentially from C++ (IOKit) code.
534 * Open-coded to prevent a circular dependency between mach/arm/thread_status.h
535 * and osfmk/arm/machine_routines.h.
538 extern boolean_t
ml_set_interrupts_enabled(boolean_t
);
542 * Methods used to sign and check thread state to detect corruptions of saved
543 * thread state across exceptions and context switches.
545 extern void ml_sign_thread_state(arm_saved_state_t
*, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t);
547 extern void ml_check_signed_state(const arm_saved_state_t
*, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t);
549 /* XXX: including stddef.f here breaks ctfmerge on some builds, so use __builtin_offsetof() instead of offsetof() */
550 #define ss64_offsetof(x) __builtin_offsetof(struct arm_saved_state, ss_64.x)
553 * Verify the signed thread state in _iss, execute the assembly instructions
554 * _instr, and re-sign the modified thread state. Varargs specify additional
557 * _instr may read or modify the thread state in the following registers:
560 * x1: authed _iss->ss_64.pc
561 * w2: authed _iss->ss_64.cpsr
562 * x3: authed _iss->ss_64.lr
563 * x4: authed _iss->ss_64.x16
564 * x5: authed _iss->ss_64.x17
565 * x6: scratch register
566 * x7: scratch register
568 #define MANIPULATE_SIGNED_THREAD_STATE(_iss, _instr, ...) \
570 boolean_t _intr = ml_set_interrupts_enabled(FALSE); \
573 "mov x0, %[iss]" "\n" \
574 "ldp x4, x5, [x0, %[SS64_X16]]" "\n" \
575 "ldr x6, [x0, %[SS64_PC]]" "\n" \
576 "ldr w7, [x0, %[SS64_CPSR]]" "\n" \
577 "ldr x3, [x0, %[SS64_LR]]" "\n" \
580 "bl _ml_check_signed_state" "\n" \
584 "bl _ml_sign_thread_state" "\n" \
588 [SS64_X16] "i"(ss64_offsetof(x[16])), \
589 [SS64_PC] "i"(ss64_offsetof(pc)), \
590 [SS64_CPSR] "i"(ss64_offsetof(cpsr)), \
591 [SS64_LR] "i"(ss64_offsetof(lr)),##__VA_ARGS__ \
592 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8" \
594 ml_set_interrupts_enabled(_intr); \
598 check_and_sign_copied_thread_state(arm_saved_state_t
*dst
, const arm_saved_state_t
*src
)
600 MANIPULATE_SIGNED_THREAD_STATE(src
,
605 #endif /* defined(HAS_APPLE_PAC) */
608 copy_signed_thread_state(arm_saved_state_t
*dst
, const arm_saved_state_t
*src
)
611 #if defined(HAS_APPLE_PAC)
612 check_and_sign_copied_thread_state(dst
, src
);
616 #endif /* defined(XNU_KERNEL_PRIVATE) */
618 static inline boolean_t
619 is_saved_state32(const arm_saved_state_t
*iss
)
621 return iss
->ash
.flavor
== ARM_SAVED_STATE32
;
624 static inline boolean_t
625 is_saved_state64(const arm_saved_state_t
*iss
)
627 return iss
->ash
.flavor
== ARM_SAVED_STATE64
;
630 static inline arm_saved_state32_t
*
631 saved_state32(arm_saved_state_t
*iss
)
636 static inline const arm_saved_state32_t
*
637 const_saved_state32(const arm_saved_state_t
*iss
)
642 static inline arm_saved_state64_t
*
643 saved_state64(arm_saved_state_t
*iss
)
648 static inline const arm_saved_state64_t
*
649 const_saved_state64(const arm_saved_state_t
*iss
)
654 static inline register_t
655 get_saved_state_pc(const arm_saved_state_t
*iss
)
657 return (register_t
)(is_saved_state32(iss
) ? const_saved_state32(iss
)->pc
: const_saved_state64(iss
)->pc
);
661 add_saved_state_pc(arm_saved_state_t
*iss
, int diff
)
663 if (is_saved_state32(iss
)) {
664 uint64_t pc
= saved_state32(iss
)->pc
+ (uint32_t)diff
;
665 saved_state32(iss
)->pc
= CAST_ASSERT_SAFE(uint32_t, pc
);
667 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
668 MANIPULATE_SIGNED_THREAD_STATE(iss
,
669 "mov w6, %w[diff] \n"
670 "add x1, x1, w6, sxtw \n"
671 "str x1, [x0, %[SS64_PC]] \n",
675 saved_state64(iss
)->pc
+= (unsigned long)diff
;
676 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC) */
681 set_saved_state_pc(arm_saved_state_t
*iss
, register_t pc
)
683 if (is_saved_state32(iss
)) {
684 saved_state32(iss
)->pc
= CAST_ASSERT_SAFE(uint32_t, pc
);
686 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
687 MANIPULATE_SIGNED_THREAD_STATE(iss
,
689 "str x1, [x0, %[SS64_PC]] \n",
693 saved_state64(iss
)->pc
= (unsigned long)pc
;
694 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC) */
698 static inline register_t
699 get_saved_state_sp(const arm_saved_state_t
*iss
)
701 return (register_t
)(is_saved_state32(iss
) ? const_saved_state32(iss
)->sp
: const_saved_state64(iss
)->sp
);
705 set_saved_state_sp(arm_saved_state_t
*iss
, register_t sp
)
707 if (is_saved_state32(iss
)) {
708 saved_state32(iss
)->sp
= CAST_ASSERT_SAFE(uint32_t, sp
);
710 saved_state64(iss
)->sp
= (uint64_t)sp
;
714 static inline register_t
715 get_saved_state_lr(const arm_saved_state_t
*iss
)
717 return (register_t
)(is_saved_state32(iss
) ? const_saved_state32(iss
)->lr
: const_saved_state64(iss
)->lr
);
721 set_saved_state_lr(arm_saved_state_t
*iss
, register_t lr
)
723 if (is_saved_state32(iss
)) {
724 saved_state32(iss
)->lr
= CAST_ASSERT_SAFE(uint32_t, lr
);
726 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
727 MANIPULATE_SIGNED_THREAD_STATE(iss
,
729 "str x3, [x0, %[SS64_LR]] \n",
733 saved_state64(iss
)->lr
= (unsigned long)lr
;
734 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC) */
738 static inline register_t
739 get_saved_state_fp(const arm_saved_state_t
*iss
)
741 return (register_t
)(is_saved_state32(iss
) ? const_saved_state32(iss
)->r
[7] : const_saved_state64(iss
)->fp
);
745 set_saved_state_fp(arm_saved_state_t
*iss
, register_t fp
)
747 if (is_saved_state32(iss
)) {
748 saved_state32(iss
)->r
[7] = CAST_ASSERT_SAFE(uint32_t, fp
);
750 saved_state64(iss
)->fp
= (uint64_t)fp
;
755 check_saved_state_reglimit(const arm_saved_state_t
*iss
, unsigned reg
)
757 return is_saved_state32(iss
) ? (reg
< ARM_SAVED_STATE32_COUNT
) : (reg
< ARM_SAVED_STATE64_COUNT
);
760 static inline register_t
761 get_saved_state_reg(const arm_saved_state_t
*iss
, unsigned reg
)
763 if (!check_saved_state_reglimit(iss
, reg
)) {
767 return (register_t
)(is_saved_state32(iss
) ? (const_saved_state32(iss
)->r
[reg
]) : (const_saved_state64(iss
)->x
[reg
]));
771 set_saved_state_reg(arm_saved_state_t
*iss
, unsigned reg
, register_t value
)
773 if (!check_saved_state_reglimit(iss
, reg
)) {
777 if (is_saved_state32(iss
)) {
778 saved_state32(iss
)->r
[reg
] = CAST_ASSERT_SAFE(uint32_t, value
);
780 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
781 /* x16 and x17 are part of the jophash */
783 MANIPULATE_SIGNED_THREAD_STATE(iss
,
784 "mov x4, %[value] \n"
785 "str x4, [x0, %[SS64_X16]] \n",
789 } else if (reg
== 17) {
790 MANIPULATE_SIGNED_THREAD_STATE(iss
,
791 "mov x5, %[value] \n"
792 "str x5, [x0, %[SS64_X17]] \n",
794 [SS64_X17
] "i"(ss64_offsetof(x
[17]))
799 saved_state64(iss
)->x
[reg
] = (uint64_t)value
;
804 static inline uint32_t
805 get_saved_state_cpsr(const arm_saved_state_t
*iss
)
807 return is_saved_state32(iss
) ? const_saved_state32(iss
)->cpsr
: const_saved_state64(iss
)->cpsr
;
811 mask_saved_state_cpsr(arm_saved_state_t
*iss
, uint32_t set_bits
, uint32_t clear_bits
)
813 if (is_saved_state32(iss
)) {
814 saved_state32(iss
)->cpsr
|= set_bits
;
815 saved_state32(iss
)->cpsr
&= ~clear_bits
;
817 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
818 MANIPULATE_SIGNED_THREAD_STATE(iss
,
819 "mov w6, %w[set_bits] \n"
820 "orr w2, w2, w6, lsl #0 \n"
821 "mov w6, %w[clear_bits] \n"
822 "bic w2, w2, w6, lsl #0 \n"
823 "str w2, [x0, %[SS64_CPSR]] \n",
824 [set_bits
] "r"(set_bits
),
825 [clear_bits
] "r"(clear_bits
)
828 saved_state64(iss
)->cpsr
|= set_bits
;
829 saved_state64(iss
)->cpsr
&= ~clear_bits
;
830 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC) */
835 set_saved_state_cpsr(arm_saved_state_t
*iss
, uint32_t cpsr
)
837 if (is_saved_state32(iss
)) {
838 saved_state32(iss
)->cpsr
= cpsr
;
840 #if defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC)
841 MANIPULATE_SIGNED_THREAD_STATE(iss
,
842 "mov w2, %w[cpsr] \n"
843 "str w2, [x0, %[SS64_CPSR]] \n",
847 saved_state64(iss
)->cpsr
= cpsr
;
848 #endif /* defined(XNU_KERNEL_PRIVATE) && defined(HAS_APPLE_PAC) */
852 static inline register_t
853 get_saved_state_far(const arm_saved_state_t
*iss
)
855 return (register_t
)(is_saved_state32(iss
) ? const_saved_state32(iss
)->far
: const_saved_state64(iss
)->far
);
859 set_saved_state_far(arm_saved_state_t
*iss
, register_t far
)
861 if (is_saved_state32(iss
)) {
862 saved_state32(iss
)->far
= CAST_ASSERT_SAFE(uint32_t, far
);
864 saved_state64(iss
)->far
= (uint64_t)far
;
868 static inline uint32_t
869 get_saved_state_esr(const arm_saved_state_t
*iss
)
871 return is_saved_state32(iss
) ? const_saved_state32(iss
)->esr
: const_saved_state64(iss
)->esr
;
875 set_saved_state_esr(arm_saved_state_t
*iss
, uint32_t esr
)
877 if (is_saved_state32(iss
)) {
878 saved_state32(iss
)->esr
= esr
;
880 saved_state64(iss
)->esr
= esr
;
884 static inline uint32_t
885 get_saved_state_exc(const arm_saved_state_t
*iss
)
887 return is_saved_state32(iss
) ? const_saved_state32(iss
)->exception
: const_saved_state64(iss
)->exception
;
891 set_saved_state_exc(arm_saved_state_t
*iss
, uint32_t exc
)
893 if (is_saved_state32(iss
)) {
894 saved_state32(iss
)->exception
= exc
;
896 saved_state64(iss
)->exception
= exc
;
900 extern void panic_unimplemented(void);
903 get_saved_state_svc_number(const arm_saved_state_t
*iss
)
905 return is_saved_state32(iss
) ? (int)const_saved_state32(iss
)->r
[12] : (int)const_saved_state64(iss
)->x
[ARM64_SYSCALL_CODE_REG_NUM
]; /* Only first word counts here */
908 typedef _STRUCT_ARM_LEGACY_DEBUG_STATE arm_legacy_debug_state_t
;
910 struct arm_debug_aggregate_state
{
913 arm_debug_state32_t ds32
;
914 arm_debug_state64_t ds64
;
916 } __attribute__((aligned(16)));
918 typedef struct arm_debug_aggregate_state arm_debug_state_t
;
920 #define ARM_LEGACY_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \
921 (sizeof (arm_legacy_debug_state_t)/sizeof(uint32_t)))
926 typedef __uint128_t uint128_t
;
927 typedef uint64_t uint64x2_t
__attribute__((ext_vector_type(2)));
928 typedef uint32_t uint32x4_t
__attribute__((ext_vector_type(4)));
930 struct arm_neon_saved_state32
{
939 typedef struct arm_neon_saved_state32 arm_neon_saved_state32_t
;
941 #define ARM_NEON_SAVED_STATE32_COUNT ((mach_msg_type_number_t) \
942 (sizeof (arm_neon_saved_state32_t)/sizeof(unsigned int)))
944 struct arm_neon_saved_state64
{
953 typedef struct arm_neon_saved_state64 arm_neon_saved_state64_t
;
955 #define ARM_NEON_SAVED_STATE64_COUNT ((mach_msg_type_number_t) \
956 (sizeof (arm_neon_saved_state64_t)/sizeof(unsigned int)))
958 struct arm_neon_saved_state
{
961 struct arm_neon_saved_state32 ns_32
;
962 struct arm_neon_saved_state64 ns_64
;
965 typedef struct arm_neon_saved_state arm_neon_saved_state_t
;
966 #define ns_32 uns.ns_32
967 #define ns_64 uns.ns_64
969 struct arm_kernel_neon_saved_state
{
973 typedef struct arm_kernel_neon_saved_state arm_kernel_neon_saved_state_t
;
975 static inline boolean_t
976 is_neon_saved_state32(const arm_neon_saved_state_t
*state
)
978 return state
->nsh
.flavor
== ARM_NEON_SAVED_STATE32
;
981 static inline boolean_t
982 is_neon_saved_state64(const arm_neon_saved_state_t
*state
)
984 return state
->nsh
.flavor
== ARM_NEON_SAVED_STATE64
;
987 static inline arm_neon_saved_state32_t
*
988 neon_state32(arm_neon_saved_state_t
*state
)
990 return &state
->ns_32
;
993 static inline arm_neon_saved_state64_t
*
994 neon_state64(arm_neon_saved_state_t
*state
)
996 return &state
->ns_64
;
1001 * Aggregated context
1004 struct arm_context
{
1005 struct arm_saved_state ss
;
1006 struct arm_neon_saved_state ns
;
1008 typedef struct arm_context arm_context_t
;
1010 struct arm_kernel_context
{
1011 struct arm_kernel_saved_state ss
;
1012 struct arm_kernel_neon_saved_state ns
;
1014 typedef struct arm_kernel_context arm_kernel_context_t
;
1016 extern void saved_state_to_thread_state64(const arm_saved_state_t
*, arm_thread_state64_t
*);
1017 extern void thread_state64_to_saved_state(const arm_thread_state64_t
*, arm_saved_state_t
*);
1019 #else /* defined(__arm__) */
1021 #endif /* defined(__arm__) */
1023 extern void saved_state_to_thread_state32(const arm_saved_state_t
*, arm_thread_state32_t
*);
1024 extern void thread_state32_to_saved_state(const arm_thread_state32_t
*, arm_saved_state_t
*);
1026 #endif /* XNU_KERNEL_PRIVATE */
1028 #endif /* _ARM_THREAD_STATUS_H_ */