]>
Commit | Line | Data |
---|---|---|
442fbc9d A |
1 | /* |
2 | * Copyright (c) 2020 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_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. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | #include "asm_help.h" | |
25 | #include <os/tsd.h> | |
26 | #include <TargetConditionals.h> | |
27 | ||
28 | /* | |
29 | * int getcontext(ucontext_t *ucp); | |
30 | * | |
31 | * _STRUCT_UCONTEXT { | |
32 | * int uc_onstack; | |
33 | * __darwin_sigset_t uc_sigmask; // signal mask used by this context | |
34 | * _STRUCT_SIGALTSTACK uc_stack; // stack used by this context | |
35 | * _STRUCT_UCONTEXT *uc_link; // pointer to resuming context | |
36 | * __darwin_size_t uc_mcsize; // size of the machine context passed in | |
37 | * _STRUCT_MCONTEXT *uc_mcontext; // pointer to machine specific context | |
38 | * #ifdef _XOPEN_SOURCE | |
39 | * _STRUCT_MCONTEXT __mcontext_data; | |
40 | * #endif | |
41 | * }; | |
42 | * | |
43 | * _STRUCT_MCONTEXT64 | |
44 | * { | |
45 | * _STRUCT_ARM_EXCEPTION_STATE64 __es; | |
46 | * _STRUCT_ARM_THREAD_STATE64 __ss; | |
47 | * _STRUCT_ARM_NEON_STATE64 __ns; | |
48 | * }; | |
49 | * | |
50 | * From the standard: | |
51 | * The getcontext(3) function shall initialize the structure pointed to by | |
52 | * ucp to the current user context of the calling thread. The ucontext_t | |
53 | * type that ucp points to defines the user context and includes the | |
54 | * contents of the calling thread's machine registers, the signal mask, and | |
55 | * the current execution stack. | |
56 | * | |
57 | * getcontext populates the following fields (with the help of a helper function): | |
58 | * uc_sigmask | |
59 | * uc_mcontext | |
60 | * uc_mcsize | |
61 | * __mcontext_data | |
62 | * uc_stack | |
63 | * | |
64 | * The ASM below mainly handles populating the machine context. Per the | |
65 | * standard, getcontext should populate the machine context such that if | |
66 | * setcontext is called with "ucp argument which was created with getcontext(), | |
67 | * program execution continues as if the corresponding call of getcontext() had | |
68 | * just returned". | |
69 | * | |
70 | * As such, the mcontext is saved such that: | |
71 | * - sp and fp are saved to be that of the caller. | |
72 | * - pc is not saved, lr is saved. We'll return from setcontext to the | |
73 | * caller (the current lr) via a ret. | |
74 | * - only callee save registers are saved in the machine context, caller | |
75 | * will restore the caller save registers. | |
76 | * - For neon registers, we save d8-d15. Per the standard: | |
77 | * Registers v8-v15 must be preserved by a callee across subroutine | |
78 | * calls; the remaining registers (v0-v7, v16-v31) do not need to be | |
79 | * preserved (or should be preserved by the caller). Additionally, | |
80 | * only the bottom 64 bits of each value stored in v8-v15 need to be | |
81 | * preserved; it is the responsibility of the caller to preserve larger | |
82 | * values. | |
83 | * - we don't need to save the arm exception state | |
84 | */ | |
85 | ||
86 | .text | |
87 | ||
88 | #if TARGET_OS_OSX || TARGET_OS_DRIVERKIT | |
89 | ||
90 | /* Pointer auths fp, sp and lr and puts them in the final locations specified by | |
91 | * input arguments | |
92 | * | |
93 | * Modifies: lr | |
94 | * Uses: x9 | |
95 | */ | |
96 | .macro PTR_SIGN_FP_SP_LR fp, sp, lr, flags | |
97 | #if defined(__arm64e__) | |
98 | // Sign fp with fp constant discriminator | |
99 | mov \fp, fp | |
100 | mov x9, #17687 // x9 = ptrauth_string_discriminator("fp") | |
101 | pacda \fp, x9 | |
102 | ||
103 | // Sign sp with sp constant discriminator | |
104 | mov \sp, sp | |
105 | mov x9, #52205 // x9 = ptrauth_string_discriminator("sp") | |
106 | pacda \sp, x9 | |
107 | ||
108 | // lr is signed with sp and b key, just set a flag marking so and don't | |
109 | // change the signature | |
110 | mov \lr, lr | |
111 | mov \flags, LR_SIGNED_WITH_IB | |
112 | #else | |
113 | mov \fp, fp | |
114 | mov \sp, sp | |
115 | mov \lr, lr | |
116 | #endif | |
117 | .endmacro | |
118 | ||
119 | .align 2 | |
120 | .globl _getcontext | |
121 | _getcontext: | |
122 | ARM64_STACK_PROLOG | |
123 | ||
124 | // Note that we're pushing and popping a frame around the subroutine call so | |
125 | // that we have the lr, fp, and sp saved | |
126 | PUSH_FRAME | |
127 | // We don't need to caller save x9 - x15 since we're not going to | |
128 | // save them in the mcontext later anyways and since they are caller save | |
129 | // registers, the caller of getcontext will restore them if needed. | |
130 | ||
131 | // x0 = ucp pointer | |
132 | // x1 = sp | |
133 | mov x1, sp | |
134 | bl _populate_signal_stack_context | |
135 | POP_FRAME // Restore lr, fp and sp | |
136 | ||
137 | // x0 = mcontext pointer | |
138 | ||
139 | // Pointer sign fp, sp, lr and mark flags as needed | |
140 | PTR_SIGN_FP_SP_LR x10, x11, x12, x13 | |
141 | ||
142 | // x10 = signed fp | |
143 | // x11 = signed sp | |
144 | // x12 = signed lr | |
145 | // x13 = mcontext flags | |
146 | ||
147 | // Save frame pointer and lr | |
148 | stp x10, x12, [x0, MCONTEXT_OFFSET_FP_LR] | |
149 | ||
150 | // Save stack pointer | |
151 | str x11, [x0, MCONTEXT_OFFSET_SP] | |
152 | ||
153 | #if defined(__arm64e__) | |
154 | // Save the flags | |
155 | str w13, [x0, MCONTEXT_OFFSET_FLAGS] | |
156 | #endif | |
157 | ||
158 | // Save x19 - x28 | |
159 | stp x19, x20, [x0, MCONTEXT_OFFSET_X19_X20] | |
160 | stp x21, x22, [x0, MCONTEXT_OFFSET_X21_X22] | |
161 | stp x23, x24, [x0, MCONTEXT_OFFSET_X23_X24] | |
162 | stp x25, x26, [x0, MCONTEXT_OFFSET_X25_X26] | |
163 | stp x27, x28, [x0, MCONTEXT_OFFSET_X27_X28] | |
164 | ||
165 | // Save return value | |
166 | str xzr, [x0, MCONTEXT_OFFSET_X0] | |
167 | ||
168 | // Save NEON registers | |
169 | str d8, [x0, MCONTEXT_OFFSET_D8] | |
170 | str d9, [x0, MCONTEXT_OFFSET_D9] | |
171 | str d10, [x0, MCONTEXT_OFFSET_D10] | |
172 | str d11, [x0, MCONTEXT_OFFSET_D11] | |
173 | str d12, [x0, MCONTEXT_OFFSET_D12] | |
174 | str d13, [x0, MCONTEXT_OFFSET_D13] | |
175 | str d14, [x0, MCONTEXT_OFFSET_D14] | |
176 | str d15, [x0, MCONTEXT_OFFSET_D15] | |
177 | ||
178 | mov x0, xzr /* Return value from getcontext */ | |
179 | ||
180 | ARM64_STACK_EPILOG | |
181 | ||
182 | #endif |