xref: /xnu-10063.121.3/tests/ldt.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /*
2*2c2f96dcSApple OSS Distributions  * Copyright (c) 2019 Apple Inc. All rights reserved.
3*2c2f96dcSApple OSS Distributions  *
4*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*2c2f96dcSApple OSS Distributions  *
6*2c2f96dcSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*2c2f96dcSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*2c2f96dcSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*2c2f96dcSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*2c2f96dcSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*2c2f96dcSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*2c2f96dcSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*2c2f96dcSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*2c2f96dcSApple OSS Distributions  *
15*2c2f96dcSApple OSS Distributions  * Please obtain a copy of the License at
16*2c2f96dcSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*2c2f96dcSApple OSS Distributions  *
18*2c2f96dcSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*2c2f96dcSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*2c2f96dcSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*2c2f96dcSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*2c2f96dcSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*2c2f96dcSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*2c2f96dcSApple OSS Distributions  * limitations under the License.
25*2c2f96dcSApple OSS Distributions  *
26*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*2c2f96dcSApple OSS Distributions  */
28*2c2f96dcSApple OSS Distributions 
29*2c2f96dcSApple OSS Distributions // #define STANDALONE
30*2c2f96dcSApple OSS Distributions 
31*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
32*2c2f96dcSApple OSS Distributions #include <darwintest.h>
33*2c2f96dcSApple OSS Distributions #endif
34*2c2f96dcSApple OSS Distributions #include <architecture/i386/table.h>
35*2c2f96dcSApple OSS Distributions #include <i386/user_ldt.h>
36*2c2f96dcSApple OSS Distributions #include <mach/i386/vm_param.h>
37*2c2f96dcSApple OSS Distributions #include <mach/i386/thread_status.h>
38*2c2f96dcSApple OSS Distributions #include <mach/mach.h>
39*2c2f96dcSApple OSS Distributions #include <signal.h>
40*2c2f96dcSApple OSS Distributions #include <stdio.h>
41*2c2f96dcSApple OSS Distributions #include <stdlib.h>
42*2c2f96dcSApple OSS Distributions #include <strings.h>
43*2c2f96dcSApple OSS Distributions #include <sys/mman.h>
44*2c2f96dcSApple OSS Distributions #include <sys/types.h>
45*2c2f96dcSApple OSS Distributions #include <sys/signal.h>
46*2c2f96dcSApple OSS Distributions #include <sys/sysctl.h>
47*2c2f96dcSApple OSS Distributions #include <assert.h>
48*2c2f96dcSApple OSS Distributions #include <errno.h>
49*2c2f96dcSApple OSS Distributions #include <fcntl.h>
50*2c2f96dcSApple OSS Distributions #include <pthread.h>
51*2c2f96dcSApple OSS Distributions #include <unistd.h>
52*2c2f96dcSApple OSS Distributions #include <ldt_mach_exc.h>
53*2c2f96dcSApple OSS Distributions 
54*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
55*2c2f96dcSApple OSS Distributions T_GLOBAL_META(
56*2c2f96dcSApple OSS Distributions 	T_META_NAMESPACE("xnu.intel"),
57*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
58*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("intel"),
59*2c2f96dcSApple OSS Distributions 	T_META_OWNER("seth_goldberg"),
60*2c2f96dcSApple OSS Distributions 	T_META_CHECK_LEAKS(false)
61*2c2f96dcSApple OSS Distributions 	);
62*2c2f96dcSApple OSS Distributions #endif
63*2c2f96dcSApple OSS Distributions 
64*2c2f96dcSApple OSS Distributions #define COMPAT_MODE_CS_SELECTOR 0x1f
65*2c2f96dcSApple OSS Distributions #define SYSENTER_SELECTOR 0xb
66*2c2f96dcSApple OSS Distributions /* #define DEBUG 1 */
67*2c2f96dcSApple OSS Distributions #define P2ROUNDUP(x, align)     (-(-((long)x) & -((long)align)))
68*2c2f96dcSApple OSS Distributions #define MSG 2048
69*2c2f96dcSApple OSS Distributions 
70*2c2f96dcSApple OSS Distributions #define NORMAL_RUN_TIME  (10)
71*2c2f96dcSApple OSS Distributions #define TIMEOUT_OVERHEAD (10)
72*2c2f96dcSApple OSS Distributions 
73*2c2f96dcSApple OSS Distributions /*
74*2c2f96dcSApple OSS Distributions  * General theory of operation:
75*2c2f96dcSApple OSS Distributions  * ----------------------------
76*2c2f96dcSApple OSS Distributions  * (1) Ensure that all code and data to be accessed from compatibility mode is
77*2c2f96dcSApple OSS Distributions  *     located in the low 4GiB of virtual address space.
78*2c2f96dcSApple OSS Distributions  * (2) Allocate required segments via the i386_set_ldt() system call, making
79*2c2f96dcSApple OSS Distributions  *     sure to set the descriptor type correctly (code vs. data).  Creating
80*2c2f96dcSApple OSS Distributions  *     64-bit code segments is not allowed (just use the existing 0x2b selector.)
81*2c2f96dcSApple OSS Distributions  * (3) Once you know which selector is associated with the desired code, use a
82*2c2f96dcSApple OSS Distributions  *     trampoline (or thunk) to (a) switch to a stack that's located below 4GiB
83*2c2f96dcSApple OSS Distributions  *     and (b) save ABI-mandated caller-saved state so that if it's trashed by
84*2c2f96dcSApple OSS Distributions  *     compatibility-mode code, it can be restored before returning to 64-bit
85*2c2f96dcSApple OSS Distributions  *     mode (if desired), and finally (c) long-jump or long-call (aka far call)
86*2c2f96dcSApple OSS Distributions  *     to the segment and desired offset (this example uses an offset of 0 for
87*2c2f96dcSApple OSS Distributions  *     simplicity.)
88*2c2f96dcSApple OSS Distributions  * (4) Once in compatibility mode, if a framework call or system call is required,
89*2c2f96dcSApple OSS Distributions  *     the code must trampoline back to 64-bit mode to do so.  System calls from
90*2c2f96dcSApple OSS Distributions  *     compatibility mode code are not supported and will result in invalid opcode
91*2c2f96dcSApple OSS Distributions  *     exceptions.  This example includes a simple 64-bit trampoline (which must
92*2c2f96dcSApple OSS Distributions  *     be located in the low 4GiB of virtual address space, since it's executed
93*2c2f96dcSApple OSS Distributions  *     by compatibility-mode code.)  Note that since the 64-bit ABI mandates that
94*2c2f96dcSApple OSS Distributions  *     the stack must be aligned to a 16-byte boundary, the sample trampoline
95*2c2f96dcSApple OSS Distributions  *     performs that rounding, to simplify compatibility-mode code.  Additionally,
96*2c2f96dcSApple OSS Distributions  *     since 64-bit native code makes use of thread-local storage, the user-mode
97*2c2f96dcSApple OSS Distributions  *     GSbase must be restored.  This sample includes two ways to do that-- (a) by
98*2c2f96dcSApple OSS Distributions  *     calling into a C implementation that associates the thread-local storage
99*2c2f96dcSApple OSS Distributions  *     pointer with a stack range (which will be unique for each thread.), and
100*2c2f96dcSApple OSS Distributions  *     (b) by storing the original GSbase in a block of memory installed into
101*2c2f96dcSApple OSS Distributions  *     GSbase before calling into compatibility-mode code.  A special machdep
102*2c2f96dcSApple OSS Distributions  *     system call restores GSbase as needed.  Note that the sample trampoline
103*2c2f96dcSApple OSS Distributions  *     does not save and restore %gs (or most other register state, so that is an
104*2c2f96dcSApple OSS Distributions  *     area that may be tailored to the application's requirements.)
105*2c2f96dcSApple OSS Distributions  * (5) Once running in compatibility mode, should synchronous or asynchronous
106*2c2f96dcSApple OSS Distributions  *     exceptions occur, this sample shows how a mach exception handler (running
107*2c2f96dcSApple OSS Distributions  *     in a detached thread, handling exceptions for the entire task) can catch
108*2c2f96dcSApple OSS Distributions  *     such exceptions and manipulate thread state to perform recovery (or not.)
109*2c2f96dcSApple OSS Distributions  *     Other ways to handle exceptions include installing per-thread exception
110*2c2f96dcSApple OSS Distributions  *     servers.  Alternatively, BSD signal handlers can be used.  Note that once a
111*2c2f96dcSApple OSS Distributions  *     process installs a custom LDT, *ALL* future signal deliveries will include
112*2c2f96dcSApple OSS Distributions  *     ucontext pointers to mcontext structures that include enhanced thread
113*2c2f96dcSApple OSS Distributions  *     state embedded (e.g. the %ds, %es, %ss, and GSBase registers) [This assumes
114*2c2f96dcSApple OSS Distributions  *     that the SA_SIGINFO is passed to sigaction(2) when registering handlers].
115*2c2f96dcSApple OSS Distributions  *     The mcontext size (part of the ucontext) can be used to differentiate between
116*2c2f96dcSApple OSS Distributions  *     different mcontext flavors (e.g. those with/without full thread state plus
117*2c2f96dcSApple OSS Distributions  *     x87 FP state, AVX state, or AVX2/3 state).
118*2c2f96dcSApple OSS Distributions  */
119*2c2f96dcSApple OSS Distributions 
120*2c2f96dcSApple OSS Distributions /*
121*2c2f96dcSApple OSS Distributions  * This test exercises the custom LDT functionality exposed via the i386_{get,set}_ldt
122*2c2f96dcSApple OSS Distributions  * system calls.
123*2c2f96dcSApple OSS Distributions  *
124*2c2f96dcSApple OSS Distributions  * Tests include:
125*2c2f96dcSApple OSS Distributions  * (1a) Exception handling (due to an exception or another thread sending a signal) while
126*2c2f96dcSApple OSS Distributions  *      running in compatibility mode;
127*2c2f96dcSApple OSS Distributions  * (1b) Signal handling while running in compatibility mode;
128*2c2f96dcSApple OSS Distributions  * (2)  Thunking back to 64-bit mode and executing a framework function (e.g. printf)
129*2c2f96dcSApple OSS Distributions  * (3)  Ensuring that transitions to compatibility mode and back to 64-bit mode
130*2c2f96dcSApple OSS Distributions  *      do not negatively impact system calls and framework calls in 64-bit mode
131*2c2f96dcSApple OSS Distributions  * (4)  Use of thread_get_state / thread_set_state to configure a thread to
132*2c2f96dcSApple OSS Distributions  *      execute in compatibility mode with the proper LDT code segment (this is
133*2c2f96dcSApple OSS Distributions  *      effectively what the exception handler does when the passed-in new_state
134*2c2f96dcSApple OSS Distributions  *      is changed (or what the BSD signal handler return handling does when the
135*2c2f96dcSApple OSS Distributions  *      mcontext is modified).)
136*2c2f96dcSApple OSS Distributions  * (5)  Ensure that compatibility mode code cannot make system calls via sysenter or
137*2c2f96dcSApple OSS Distributions  *      old-style int {0x80..0x82}.
138*2c2f96dcSApple OSS Distributions  * (6)  Negative testing to ensure errors are returned if the consumer tries
139*2c2f96dcSApple OSS Distributions  *      to set a disallowed segment type / Long flag. [TBD]
140*2c2f96dcSApple OSS Distributions  */
141*2c2f96dcSApple OSS Distributions 
142*2c2f96dcSApple OSS Distributions /*
143*2c2f96dcSApple OSS Distributions  * Note that these addresses are not necessarily available due to ASLR, so
144*2c2f96dcSApple OSS Distributions  * a robust implementation should determine the proper range to use via
145*2c2f96dcSApple OSS Distributions  * another means.
146*2c2f96dcSApple OSS Distributions  */
147*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
148*2c2f96dcSApple OSS Distributions /* libdarwintest needs LOTs of stack */
149*2c2f96dcSApple OSS Distributions #endif
150*2c2f96dcSApple OSS Distributions #define FIXED_STACK_SIZE (PAGE_SIZE * 16)
151*2c2f96dcSApple OSS Distributions #define FIXED_TRAMP_MAXLEN (PAGE_SIZE * 8)
152*2c2f96dcSApple OSS Distributions 
153*2c2f96dcSApple OSS Distributions #pragma pack(1)
154*2c2f96dcSApple OSS Distributions typedef struct {
155*2c2f96dcSApple OSS Distributions 	uint64_t off;
156*2c2f96dcSApple OSS Distributions 	uint16_t seg;
157*2c2f96dcSApple OSS Distributions } far_call_t;
158*2c2f96dcSApple OSS Distributions #pragma pack()
159*2c2f96dcSApple OSS Distributions 
160*2c2f96dcSApple OSS Distributions typedef struct {
161*2c2f96dcSApple OSS Distributions 	uint64_t stack_base;
162*2c2f96dcSApple OSS Distributions 	uint64_t stack_limit;
163*2c2f96dcSApple OSS Distributions 	uint64_t GSbase;
164*2c2f96dcSApple OSS Distributions } stackaddr_to_gsbase_t;
165*2c2f96dcSApple OSS Distributions 
166*2c2f96dcSApple OSS Distributions typedef struct thread_arg {
167*2c2f96dcSApple OSS Distributions 	pthread_mutex_t         mutex;
168*2c2f96dcSApple OSS Distributions 	pthread_cond_t          condvar;
169*2c2f96dcSApple OSS Distributions 	volatile boolean_t      done;
170*2c2f96dcSApple OSS Distributions 	uint32_t                compat_stackaddr;       /* Compatibility mode stack address */
171*2c2f96dcSApple OSS Distributions } thread_arg_t;
172*2c2f96dcSApple OSS Distributions 
173*2c2f96dcSApple OSS Distributions typedef struct custom_tsd {
174*2c2f96dcSApple OSS Distributions 	struct custom_tsd *     this_tsd_base;
175*2c2f96dcSApple OSS Distributions 	uint64_t                orig_tsd_base;
176*2c2f96dcSApple OSS Distributions } custom_tsd_t;
177*2c2f96dcSApple OSS Distributions 
178*2c2f96dcSApple OSS Distributions typedef uint64_t (*compat_tramp_t)(far_call_t *fcp, void *lowmemstk, uint64_t arg_for_32bit,
179*2c2f96dcSApple OSS Distributions     uint64_t callback, uint64_t absolute_addr_of_thunk64);
180*2c2f96dcSApple OSS Distributions 
181*2c2f96dcSApple OSS Distributions #define GS_RELATIVE volatile __attribute__((address_space(256)))
182*2c2f96dcSApple OSS Distributions static custom_tsd_t GS_RELATIVE *mytsd = (custom_tsd_t GS_RELATIVE *)0;
183*2c2f96dcSApple OSS Distributions 
184*2c2f96dcSApple OSS Distributions static far_call_t input_desc = { .seg = COMPAT_MODE_CS_SELECTOR, .off = 0 };
185*2c2f96dcSApple OSS Distributions static uint64_t stackAddr = 0;
186*2c2f96dcSApple OSS Distributions static compat_tramp_t thunkit = NULL;
187*2c2f96dcSApple OSS Distributions static uint64_t thunk64_addr;
188*2c2f96dcSApple OSS Distributions /* stack2gs[0] is initialized in map_lowmem_stack() */
189*2c2f96dcSApple OSS Distributions static stackaddr_to_gsbase_t stack2gs[] = { { 0 } };
190*2c2f96dcSApple OSS Distributions 
191*2c2f96dcSApple OSS Distributions extern int compat_mode_trampoline(far_call_t *, void *, uint64_t);
192*2c2f96dcSApple OSS Distributions extern void long_mode_trampoline(void);
193*2c2f96dcSApple OSS Distributions extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
194*2c2f96dcSApple OSS Distributions 
195*2c2f96dcSApple OSS Distributions extern void code_32(void);
196*2c2f96dcSApple OSS Distributions 
197*2c2f96dcSApple OSS Distributions kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port,
198*2c2f96dcSApple OSS Distributions     mach_port_t thread,
199*2c2f96dcSApple OSS Distributions     mach_port_t task,
200*2c2f96dcSApple OSS Distributions     exception_type_t exception,
201*2c2f96dcSApple OSS Distributions     mach_exception_data_t code,
202*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t code_count,
203*2c2f96dcSApple OSS Distributions     int * flavor,
204*2c2f96dcSApple OSS Distributions     thread_state_t old_state,
205*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_state_count,
206*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
207*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t * new_state_count);
208*2c2f96dcSApple OSS Distributions 
209*2c2f96dcSApple OSS Distributions kern_return_t
210*2c2f96dcSApple OSS Distributions catch_mach_exception_raise_state(mach_port_t exception_port,
211*2c2f96dcSApple OSS Distributions     exception_type_t exception,
212*2c2f96dcSApple OSS Distributions     const mach_exception_data_t code,
213*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t codeCnt,
214*2c2f96dcSApple OSS Distributions     int *flavor,
215*2c2f96dcSApple OSS Distributions     const thread_state_t old_state,
216*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_stateCnt,
217*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
218*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t *new_stateCnt);
219*2c2f96dcSApple OSS Distributions 
220*2c2f96dcSApple OSS Distributions kern_return_t
221*2c2f96dcSApple OSS Distributions catch_mach_exception_raise(mach_port_t exception_port,
222*2c2f96dcSApple OSS Distributions     mach_port_t thread,
223*2c2f96dcSApple OSS Distributions     mach_port_t task,
224*2c2f96dcSApple OSS Distributions     exception_type_t exception,
225*2c2f96dcSApple OSS Distributions     mach_exception_data_t code,
226*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t codeCnt,
227*2c2f96dcSApple OSS Distributions     int *flavor,
228*2c2f96dcSApple OSS Distributions     thread_state_t old_state,
229*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_stateCnt,
230*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
231*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t *new_stateCnt);
232*2c2f96dcSApple OSS Distributions 
233*2c2f96dcSApple OSS Distributions extern void _thread_set_tsd_base(uint64_t);
234*2c2f96dcSApple OSS Distributions static uint64_t stack_range_to_GSbase(uint64_t stackptr, uint64_t GSbase);
235*2c2f96dcSApple OSS Distributions void restore_gsbase(uint64_t stackptr);
236*2c2f96dcSApple OSS Distributions 
237*2c2f96dcSApple OSS Distributions static uint64_t
get_gsbase(void)238*2c2f96dcSApple OSS Distributions get_gsbase(void)
239*2c2f96dcSApple OSS Distributions {
240*2c2f96dcSApple OSS Distributions 	struct thread_identifier_info tiinfo;
241*2c2f96dcSApple OSS Distributions 	unsigned int info_count = THREAD_IDENTIFIER_INFO_COUNT;
242*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
243*2c2f96dcSApple OSS Distributions 
244*2c2f96dcSApple OSS Distributions 	if ((kr = thread_info(mach_thread_self(), THREAD_IDENTIFIER_INFO,
245*2c2f96dcSApple OSS Distributions 	    (thread_info_t) &tiinfo, &info_count)) != KERN_SUCCESS) {
246*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Could not get tsd base address.  This will not end well.\n");
247*2c2f96dcSApple OSS Distributions 		return 0;
248*2c2f96dcSApple OSS Distributions 	}
249*2c2f96dcSApple OSS Distributions 
250*2c2f96dcSApple OSS Distributions 	return (uint64_t)tiinfo.thread_handle;
251*2c2f96dcSApple OSS Distributions }
252*2c2f96dcSApple OSS Distributions 
253*2c2f96dcSApple OSS Distributions void
restore_gsbase(uint64_t stackptr)254*2c2f96dcSApple OSS Distributions restore_gsbase(uint64_t stackptr)
255*2c2f96dcSApple OSS Distributions {
256*2c2f96dcSApple OSS Distributions 	/* Restore GSbase so tsd is accessible in long mode */
257*2c2f96dcSApple OSS Distributions 	uint64_t orig_GSbase = stack_range_to_GSbase(stackptr, 0);
258*2c2f96dcSApple OSS Distributions 
259*2c2f96dcSApple OSS Distributions 	assert(orig_GSbase != 0);
260*2c2f96dcSApple OSS Distributions 	_thread_set_tsd_base(orig_GSbase);
261*2c2f96dcSApple OSS Distributions }
262*2c2f96dcSApple OSS Distributions 
263*2c2f96dcSApple OSS Distributions /*
264*2c2f96dcSApple OSS Distributions  * Though we've directed all exceptions through the catch_mach_exception_raise_state_identity
265*2c2f96dcSApple OSS Distributions  * entry point, we still must provide these two other entry points, otherwise a linker error
266*2c2f96dcSApple OSS Distributions  * will occur.
267*2c2f96dcSApple OSS Distributions  */
268*2c2f96dcSApple OSS Distributions kern_return_t
catch_mach_exception_raise(mach_port_t exception_port,mach_port_t thread,mach_port_t task,exception_type_t exception,mach_exception_data_t code,mach_msg_type_number_t codeCnt,int * flavor,thread_state_t old_state,mach_msg_type_number_t old_stateCnt,thread_state_t new_state,mach_msg_type_number_t * new_stateCnt)269*2c2f96dcSApple OSS Distributions catch_mach_exception_raise(mach_port_t exception_port,
270*2c2f96dcSApple OSS Distributions     mach_port_t thread,
271*2c2f96dcSApple OSS Distributions     mach_port_t task,
272*2c2f96dcSApple OSS Distributions     exception_type_t exception,
273*2c2f96dcSApple OSS Distributions     mach_exception_data_t code,
274*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t codeCnt,
275*2c2f96dcSApple OSS Distributions     int *flavor,
276*2c2f96dcSApple OSS Distributions     thread_state_t old_state,
277*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_stateCnt,
278*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
279*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t *new_stateCnt)
280*2c2f96dcSApple OSS Distributions {
281*2c2f96dcSApple OSS Distributions #pragma unused(exception_port, thread, task, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt)
282*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "Unexpected exception handler called: %s\n", __func__);
283*2c2f96dcSApple OSS Distributions 	return KERN_FAILURE;
284*2c2f96dcSApple OSS Distributions }
285*2c2f96dcSApple OSS Distributions 
286*2c2f96dcSApple OSS Distributions kern_return_t
catch_mach_exception_raise_state(mach_port_t exception_port,exception_type_t exception,const mach_exception_data_t code,mach_msg_type_number_t codeCnt,int * flavor,const thread_state_t old_state,mach_msg_type_number_t old_stateCnt,thread_state_t new_state,mach_msg_type_number_t * new_stateCnt)287*2c2f96dcSApple OSS Distributions catch_mach_exception_raise_state(mach_port_t exception_port,
288*2c2f96dcSApple OSS Distributions     exception_type_t exception,
289*2c2f96dcSApple OSS Distributions     const mach_exception_data_t code,
290*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t codeCnt,
291*2c2f96dcSApple OSS Distributions     int *flavor,
292*2c2f96dcSApple OSS Distributions     const thread_state_t old_state,
293*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_stateCnt,
294*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
295*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t *new_stateCnt)
296*2c2f96dcSApple OSS Distributions {
297*2c2f96dcSApple OSS Distributions #pragma unused(exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt)
298*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "Unexpected exception handler called: %s\n", __func__);
299*2c2f96dcSApple OSS Distributions 	return KERN_FAILURE;
300*2c2f96dcSApple OSS Distributions }
301*2c2f96dcSApple OSS Distributions 
302*2c2f96dcSApple OSS Distributions static void
handle_arithmetic_exception(_STRUCT_X86_THREAD_FULL_STATE64 * xtfs64,uint64_t * ip_skip_countp)303*2c2f96dcSApple OSS Distributions handle_arithmetic_exception(_STRUCT_X86_THREAD_FULL_STATE64 *xtfs64, uint64_t *ip_skip_countp)
304*2c2f96dcSApple OSS Distributions {
305*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "Caught divide-error exception\n");
306*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "cs=0x%x rip=0x%x gs=0x%x ss=0x%x rsp=0x%llx\n",
307*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss64.__cs,
308*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss64.__rip, (unsigned)xtfs64->__ss64.__gs,
309*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss, xtfs64->__ss64.__rsp);
310*2c2f96dcSApple OSS Distributions 	*ip_skip_countp = 2;
311*2c2f96dcSApple OSS Distributions }
312*2c2f96dcSApple OSS Distributions 
313*2c2f96dcSApple OSS Distributions static void
handle_badinsn_exception(_STRUCT_X86_THREAD_FULL_STATE64 * xtfs64,uint64_t __unused * ip_skip_countp)314*2c2f96dcSApple OSS Distributions handle_badinsn_exception(_STRUCT_X86_THREAD_FULL_STATE64 *xtfs64, uint64_t __unused *ip_skip_countp)
315*2c2f96dcSApple OSS Distributions {
316*2c2f96dcSApple OSS Distributions 	extern void first_invalid_opcode(void);
317*2c2f96dcSApple OSS Distributions 	extern void last_invalid_opcode(void);
318*2c2f96dcSApple OSS Distributions 
319*2c2f96dcSApple OSS Distributions 	uint64_t start_addr = ((uintptr_t)first_invalid_opcode - (uintptr_t)code_32);
320*2c2f96dcSApple OSS Distributions 	uint64_t end_addr = ((uintptr_t)last_invalid_opcode - (uintptr_t)code_32);
321*2c2f96dcSApple OSS Distributions 
322*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "Caught invalid opcode exception\n");
323*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "cs=%x rip=%x gs=%x ss=0x%x rsp=0x%llx | handling between 0x%llx and 0x%llx\n",
324*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss64.__cs,
325*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss64.__rip, (unsigned)xtfs64->__ss64.__gs,
326*2c2f96dcSApple OSS Distributions 	    (unsigned)xtfs64->__ss, xtfs64->__ss64.__rsp,
327*2c2f96dcSApple OSS Distributions 	    start_addr, end_addr);
328*2c2f96dcSApple OSS Distributions 
329*2c2f96dcSApple OSS Distributions 	/*
330*2c2f96dcSApple OSS Distributions 	 * We expect to handle 4 invalid opcode exceptions:
331*2c2f96dcSApple OSS Distributions 	 * (1) sysenter
332*2c2f96dcSApple OSS Distributions 	 * (2) int $0x80
333*2c2f96dcSApple OSS Distributions 	 * (3) int $0x81
334*2c2f96dcSApple OSS Distributions 	 * (4) int $0x82
335*2c2f96dcSApple OSS Distributions 	 * (Note that due to the way the invalid opcode indication was implemented,
336*2c2f96dcSApple OSS Distributions 	 * %rip is already set to the next instruction.)
337*2c2f96dcSApple OSS Distributions 	 */
338*2c2f96dcSApple OSS Distributions 	if (xtfs64->__ss64.__rip >= start_addr && xtfs64->__ss64.__rip <= end_addr) {
339*2c2f96dcSApple OSS Distributions 		/*
340*2c2f96dcSApple OSS Distributions 		 * On return from the failed sysenter, %cs is changed to the
341*2c2f96dcSApple OSS Distributions 		 * sysenter code selector and %ss is set to 0x23, so switch them
342*2c2f96dcSApple OSS Distributions 		 * back to sane values.
343*2c2f96dcSApple OSS Distributions 		 */
344*2c2f96dcSApple OSS Distributions 		if ((unsigned)xtfs64->__ss64.__cs == SYSENTER_SELECTOR) {
345*2c2f96dcSApple OSS Distributions 			xtfs64->__ss64.__cs = COMPAT_MODE_CS_SELECTOR;
346*2c2f96dcSApple OSS Distributions 			xtfs64->__ss = 0x23; /* XXX */
347*2c2f96dcSApple OSS Distributions 		}
348*2c2f96dcSApple OSS Distributions 	}
349*2c2f96dcSApple OSS Distributions }
350*2c2f96dcSApple OSS Distributions 
351*2c2f96dcSApple OSS Distributions kern_return_t
catch_mach_exception_raise_state_identity(mach_port_t exception_port,mach_port_t thread,mach_port_t task,exception_type_t exception,mach_exception_data_t code,mach_msg_type_number_t codeCnt,int * flavor,thread_state_t old_state,mach_msg_type_number_t old_stateCnt,thread_state_t new_state,mach_msg_type_number_t * new_stateCnt)352*2c2f96dcSApple OSS Distributions catch_mach_exception_raise_state_identity(mach_port_t exception_port,
353*2c2f96dcSApple OSS Distributions     mach_port_t thread,
354*2c2f96dcSApple OSS Distributions     mach_port_t task,
355*2c2f96dcSApple OSS Distributions     exception_type_t exception,
356*2c2f96dcSApple OSS Distributions     mach_exception_data_t code,
357*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t codeCnt,
358*2c2f96dcSApple OSS Distributions     int * flavor,
359*2c2f96dcSApple OSS Distributions     thread_state_t old_state,
360*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t old_stateCnt,
361*2c2f96dcSApple OSS Distributions     thread_state_t new_state,
362*2c2f96dcSApple OSS Distributions     mach_msg_type_number_t * new_stateCnt)
363*2c2f96dcSApple OSS Distributions {
364*2c2f96dcSApple OSS Distributions #pragma unused(exception_port, thread, task)
365*2c2f96dcSApple OSS Distributions 
366*2c2f96dcSApple OSS Distributions 	_STRUCT_X86_THREAD_FULL_STATE64 *xtfs64 = (_STRUCT_X86_THREAD_FULL_STATE64 *)(void *)old_state;
367*2c2f96dcSApple OSS Distributions 	_STRUCT_X86_THREAD_FULL_STATE64 *new_xtfs64 = (_STRUCT_X86_THREAD_FULL_STATE64 *)(void *)new_state;
368*2c2f96dcSApple OSS Distributions 	uint64_t rip_skip_count = 0;
369*2c2f96dcSApple OSS Distributions 
370*2c2f96dcSApple OSS Distributions 	/*
371*2c2f96dcSApple OSS Distributions 	 * Check the exception code and thread state.
372*2c2f96dcSApple OSS Distributions 	 * If we were executing 32-bit code (or 64-bit code on behalf of
373*2c2f96dcSApple OSS Distributions 	 * 32-bit code), we could update the thread state to effectively longjmp
374*2c2f96dcSApple OSS Distributions 	 * back to a safe location where the victim thread can recover.
375*2c2f96dcSApple OSS Distributions 	 * Then again, we could return KERN_NOT_SUPPORTED and allow the process
376*2c2f96dcSApple OSS Distributions 	 * to be nuked.
377*2c2f96dcSApple OSS Distributions 	 */
378*2c2f96dcSApple OSS Distributions 
379*2c2f96dcSApple OSS Distributions 	switch (exception) {
380*2c2f96dcSApple OSS Distributions 	case EXC_ARITHMETIC:
381*2c2f96dcSApple OSS Distributions 		if (codeCnt >= 1 && code[0] == EXC_I386_DIV) {
382*2c2f96dcSApple OSS Distributions 			handle_arithmetic_exception(xtfs64, &rip_skip_count);
383*2c2f96dcSApple OSS Distributions 		}
384*2c2f96dcSApple OSS Distributions 		break;
385*2c2f96dcSApple OSS Distributions 
386*2c2f96dcSApple OSS Distributions 	case EXC_BAD_INSTRUCTION:
387*2c2f96dcSApple OSS Distributions 	{
388*2c2f96dcSApple OSS Distributions 		if (codeCnt >= 1 && code[0] == EXC_I386_INVOP) {
389*2c2f96dcSApple OSS Distributions 			handle_badinsn_exception(xtfs64, &rip_skip_count);
390*2c2f96dcSApple OSS Distributions 		}
391*2c2f96dcSApple OSS Distributions 		break;
392*2c2f96dcSApple OSS Distributions 	}
393*2c2f96dcSApple OSS Distributions 
394*2c2f96dcSApple OSS Distributions 	default:
395*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Unsupported catch_mach_exception_raise_state_identity: code 0x%llx sub 0x%llx\n",
396*2c2f96dcSApple OSS Distributions 		    code[0], codeCnt > 1 ? code[1] : 0LL);
397*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "flavor=%d %%cs=0x%x %%rip=0x%llx\n", *flavor, (unsigned)xtfs64->__ss64.__cs,
398*2c2f96dcSApple OSS Distributions 		    xtfs64->__ss64.__rip);
399*2c2f96dcSApple OSS Distributions 	}
400*2c2f96dcSApple OSS Distributions 
401*2c2f96dcSApple OSS Distributions 	/*
402*2c2f96dcSApple OSS Distributions 	 * If this exception happened in compatibility mode,
403*2c2f96dcSApple OSS Distributions 	 * assume it was the intentional division-by-zero and set the
404*2c2f96dcSApple OSS Distributions 	 * new state's cs register to just after the div instruction
405*2c2f96dcSApple OSS Distributions 	 * to enable the thread to resume.
406*2c2f96dcSApple OSS Distributions 	 */
407*2c2f96dcSApple OSS Distributions 	if ((unsigned)xtfs64->__ss64.__cs == COMPAT_MODE_CS_SELECTOR) {
408*2c2f96dcSApple OSS Distributions 		*new_stateCnt = old_stateCnt;
409*2c2f96dcSApple OSS Distributions 		*new_xtfs64 = *xtfs64;
410*2c2f96dcSApple OSS Distributions 		new_xtfs64->__ss64.__rip += rip_skip_count;
411*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "new cs=0x%x rip=0x%llx\n", (unsigned)new_xtfs64->__ss64.__cs,
412*2c2f96dcSApple OSS Distributions 		    new_xtfs64->__ss64.__rip);
413*2c2f96dcSApple OSS Distributions 		return KERN_SUCCESS;
414*2c2f96dcSApple OSS Distributions 	} else {
415*2c2f96dcSApple OSS Distributions 		return KERN_NOT_SUPPORTED;
416*2c2f96dcSApple OSS Distributions 	}
417*2c2f96dcSApple OSS Distributions }
418*2c2f96dcSApple OSS Distributions 
419*2c2f96dcSApple OSS Distributions static void *
handle_exceptions(void * arg)420*2c2f96dcSApple OSS Distributions handle_exceptions(void *arg)
421*2c2f96dcSApple OSS Distributions {
422*2c2f96dcSApple OSS Distributions 	mach_port_t ePort = (mach_port_t)arg;
423*2c2f96dcSApple OSS Distributions 	kern_return_t kret;
424*2c2f96dcSApple OSS Distributions 
425*2c2f96dcSApple OSS Distributions 	kret = mach_msg_server(mach_exc_server, MACH_MSG_SIZE_RELIABLE, ePort, 0);
426*2c2f96dcSApple OSS Distributions 	if (kret != KERN_SUCCESS) {
427*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "mach_msg_server: %s (%d)", mach_error_string(kret), kret);
428*2c2f96dcSApple OSS Distributions 	}
429*2c2f96dcSApple OSS Distributions 
430*2c2f96dcSApple OSS Distributions 	return NULL;
431*2c2f96dcSApple OSS Distributions }
432*2c2f96dcSApple OSS Distributions 
433*2c2f96dcSApple OSS Distributions static void
init_task_exception_server(void)434*2c2f96dcSApple OSS Distributions init_task_exception_server(void)
435*2c2f96dcSApple OSS Distributions {
436*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
437*2c2f96dcSApple OSS Distributions 	task_t me = mach_task_self();
438*2c2f96dcSApple OSS Distributions 	pthread_t handler_thread;
439*2c2f96dcSApple OSS Distributions 	pthread_attr_t  attr;
440*2c2f96dcSApple OSS Distributions 	mach_port_t ePort;
441*2c2f96dcSApple OSS Distributions 
442*2c2f96dcSApple OSS Distributions 	kr = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &ePort);
443*2c2f96dcSApple OSS Distributions 	if (kr != KERN_SUCCESS) {
444*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "allocate receive right: %d\n", kr);
445*2c2f96dcSApple OSS Distributions 		return;
446*2c2f96dcSApple OSS Distributions 	}
447*2c2f96dcSApple OSS Distributions 
448*2c2f96dcSApple OSS Distributions 	kr = mach_port_insert_right(me, ePort, ePort, MACH_MSG_TYPE_MAKE_SEND);
449*2c2f96dcSApple OSS Distributions 	if (kr != KERN_SUCCESS) {
450*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "insert right into port=[%d]: %d\n", ePort, kr);
451*2c2f96dcSApple OSS Distributions 		return;
452*2c2f96dcSApple OSS Distributions 	}
453*2c2f96dcSApple OSS Distributions 
454*2c2f96dcSApple OSS Distributions 	kr = task_set_exception_ports(me, EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC, ePort,
455*2c2f96dcSApple OSS Distributions 	    (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES), x86_THREAD_FULL_STATE64);
456*2c2f96dcSApple OSS Distributions 	if (kr != KERN_SUCCESS) {
457*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "abort: error setting task exception ports on task=[%d], handler=[%d]: %d\n", me, ePort, kr);
458*2c2f96dcSApple OSS Distributions 		exit(1);
459*2c2f96dcSApple OSS Distributions 	}
460*2c2f96dcSApple OSS Distributions 
461*2c2f96dcSApple OSS Distributions 	pthread_attr_init(&attr);
462*2c2f96dcSApple OSS Distributions 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
463*2c2f96dcSApple OSS Distributions 
464*2c2f96dcSApple OSS Distributions 	if (pthread_create(&handler_thread, &attr, handle_exceptions, (void *)(uintptr_t)ePort) != 0) {
465*2c2f96dcSApple OSS Distributions 		perror("pthread create error");
466*2c2f96dcSApple OSS Distributions 		return;
467*2c2f96dcSApple OSS Distributions 	}
468*2c2f96dcSApple OSS Distributions 
469*2c2f96dcSApple OSS Distributions 	pthread_attr_destroy(&attr);
470*2c2f96dcSApple OSS Distributions }
471*2c2f96dcSApple OSS Distributions 
472*2c2f96dcSApple OSS Distributions static union ldt_entry *descs = 0;
473*2c2f96dcSApple OSS Distributions static uint64_t idx;
474*2c2f96dcSApple OSS Distributions static int saw_ud2 = 0;
475*2c2f96dcSApple OSS Distributions static boolean_t ENV_set_ldt_in_sighandler = FALSE;
476*2c2f96dcSApple OSS Distributions 
477*2c2f96dcSApple OSS Distributions static void
signal_handler(int signo,siginfo_t * sinfop,void * ucontext)478*2c2f96dcSApple OSS Distributions signal_handler(int signo, siginfo_t *sinfop, void *ucontext)
479*2c2f96dcSApple OSS Distributions {
480*2c2f96dcSApple OSS Distributions 	uint64_t rip_skip_count = 0;
481*2c2f96dcSApple OSS Distributions 	ucontext_t *uctxp = (ucontext_t *)ucontext;
482*2c2f96dcSApple OSS Distributions 	union {
483*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT_AVX512_64 *avx512_basep;
484*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT_AVX512_64_FULL *avx512_fullp;
485*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT_AVX64 *avx64_basep;
486*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT_AVX64_FULL *avx64_fullp;
487*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT64 *fp_basep;
488*2c2f96dcSApple OSS Distributions 		_STRUCT_MCONTEXT64_FULL *fp_fullp;
489*2c2f96dcSApple OSS Distributions 	} mctx;
490*2c2f96dcSApple OSS Distributions 
491*2c2f96dcSApple OSS Distributions 	mctx.fp_fullp = (_STRUCT_MCONTEXT64_FULL *)uctxp->uc_mcontext;
492*2c2f96dcSApple OSS Distributions 
493*2c2f96dcSApple OSS Distributions 	/*
494*2c2f96dcSApple OSS Distributions 	 * Note that GSbase must be restored before calling into any frameworks
495*2c2f96dcSApple OSS Distributions 	 * that might access anything %gs-relative (e.g. TSD) if the signal
496*2c2f96dcSApple OSS Distributions 	 * handler was triggered while the thread was running with a non-default
497*2c2f96dcSApple OSS Distributions 	 * (system-established) GSbase.
498*2c2f96dcSApple OSS Distributions 	 */
499*2c2f96dcSApple OSS Distributions 
500*2c2f96dcSApple OSS Distributions 	if ((signo != SIGFPE && signo != SIGILL) || sinfop->si_signo != signo) {
501*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
502*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Unexpected signal %d\n", signo);
503*2c2f96dcSApple OSS Distributions #else
504*2c2f96dcSApple OSS Distributions 		restore_gsbase(mctx.fp_fullp->__ss.__ss64.__rsp);
505*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Not handling signal %d\n", signo);
506*2c2f96dcSApple OSS Distributions 		abort();
507*2c2f96dcSApple OSS Distributions #endif
508*2c2f96dcSApple OSS Distributions 	}
509*2c2f96dcSApple OSS Distributions 
510*2c2f96dcSApple OSS Distributions 	if (uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT_AVX512_64) ||
511*2c2f96dcSApple OSS Distributions 	    uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT_AVX64) ||
512*2c2f96dcSApple OSS Distributions 	    uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT64)) {
513*2c2f96dcSApple OSS Distributions 		_STRUCT_X86_THREAD_STATE64 *ss64 = &mctx.fp_basep->__ss;
514*2c2f96dcSApple OSS Distributions 
515*2c2f96dcSApple OSS Distributions 		/*
516*2c2f96dcSApple OSS Distributions 		 * The following block is an illustration of what NOT to do.
517*2c2f96dcSApple OSS Distributions 		 * Configuring an LDT for the first time in a signal handler
518*2c2f96dcSApple OSS Distributions 		 * will likely cause the process to crash.
519*2c2f96dcSApple OSS Distributions 		 */
520*2c2f96dcSApple OSS Distributions 		if (ENV_set_ldt_in_sighandler == TRUE && !saw_ud2) {
521*2c2f96dcSApple OSS Distributions 			/* Set the LDT: */
522*2c2f96dcSApple OSS Distributions 			int cnt = i386_set_ldt((int)idx, &descs[idx], 1);
523*2c2f96dcSApple OSS Distributions 			if (cnt != (int)idx) {
524*2c2f96dcSApple OSS Distributions #ifdef DEBUG
525*2c2f96dcSApple OSS Distributions 				fprintf(stderr, "i386_set_ldt unexpectedly returned %d (errno = %s)\n", cnt, strerror(errno));
526*2c2f96dcSApple OSS Distributions #endif
527*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
528*2c2f96dcSApple OSS Distributions 				T_LOG("i386_set_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
529*2c2f96dcSApple OSS Distributions 				T_ASSERT_FAIL("i386_set_ldt failure");
530*2c2f96dcSApple OSS Distributions #else
531*2c2f96dcSApple OSS Distributions 				exit(1);
532*2c2f96dcSApple OSS Distributions #endif
533*2c2f96dcSApple OSS Distributions 			}
534*2c2f96dcSApple OSS Distributions #ifdef DEBUG
535*2c2f96dcSApple OSS Distributions 			printf("i386_set_ldt returned %d\n", cnt);
536*2c2f96dcSApple OSS Distributions #endif
537*2c2f96dcSApple OSS Distributions 			ss64->__rip += 2;       /* ud2 is 2 bytes */
538*2c2f96dcSApple OSS Distributions 
539*2c2f96dcSApple OSS Distributions 			saw_ud2 = 1;
540*2c2f96dcSApple OSS Distributions 
541*2c2f96dcSApple OSS Distributions 			/*
542*2c2f96dcSApple OSS Distributions 			 * When we return here, the sigreturn processing code will try to copy a FULL
543*2c2f96dcSApple OSS Distributions 			 * thread context from the signal stack, which will likely cause the resumed
544*2c2f96dcSApple OSS Distributions 			 * thread to fault and be terminated.
545*2c2f96dcSApple OSS Distributions 			 */
546*2c2f96dcSApple OSS Distributions 			return;
547*2c2f96dcSApple OSS Distributions 		}
548*2c2f96dcSApple OSS Distributions 
549*2c2f96dcSApple OSS Distributions 		restore_gsbase(ss64->__rsp);
550*2c2f96dcSApple OSS Distributions 
551*2c2f96dcSApple OSS Distributions 		/*
552*2c2f96dcSApple OSS Distributions 		 * If we're in this block, either we are dispatching a signal received
553*2c2f96dcSApple OSS Distributions 		 * before we installed a custom LDT or we are on a kernel without
554*2c2f96dcSApple OSS Distributions 		 * BSD-signalling-sending-full-thread-state support.  It's likely the latter case.
555*2c2f96dcSApple OSS Distributions 		 */
556*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
557*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("This system doesn't support BSD signals with full thread state.");
558*2c2f96dcSApple OSS Distributions #else
559*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "This system doesn't support BSD signals with full thread state.  Aborting.\n");
560*2c2f96dcSApple OSS Distributions 		abort();
561*2c2f96dcSApple OSS Distributions #endif
562*2c2f96dcSApple OSS Distributions 	} else if (uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT_AVX512_64_FULL) ||
563*2c2f96dcSApple OSS Distributions 	    uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT_AVX64_FULL) ||
564*2c2f96dcSApple OSS Distributions 	    uctxp->uc_mcsize == sizeof(_STRUCT_MCONTEXT64_FULL)) {
565*2c2f96dcSApple OSS Distributions 		_STRUCT_X86_THREAD_FULL_STATE64 *ss64 = &mctx.fp_fullp->__ss;
566*2c2f96dcSApple OSS Distributions 
567*2c2f96dcSApple OSS Distributions 		/*
568*2c2f96dcSApple OSS Distributions 		 * Since we're handing this signal on the same thread, we may need to
569*2c2f96dcSApple OSS Distributions 		 * restore GSbase.
570*2c2f96dcSApple OSS Distributions 		 */
571*2c2f96dcSApple OSS Distributions 		uint64_t orig_gsbase = stack_range_to_GSbase(ss64->__ss64.__rsp, 0);
572*2c2f96dcSApple OSS Distributions 		if (orig_gsbase != 0 && orig_gsbase != ss64->__gsbase) {
573*2c2f96dcSApple OSS Distributions 			restore_gsbase(ss64->__ss64.__rsp);
574*2c2f96dcSApple OSS Distributions 		}
575*2c2f96dcSApple OSS Distributions 
576*2c2f96dcSApple OSS Distributions 		if (signo == SIGFPE) {
577*2c2f96dcSApple OSS Distributions 			handle_arithmetic_exception(ss64, &rip_skip_count);
578*2c2f96dcSApple OSS Distributions 		} else if (signo == SIGILL) {
579*2c2f96dcSApple OSS Distributions 			handle_badinsn_exception(ss64, &rip_skip_count);
580*2c2f96dcSApple OSS Distributions 		}
581*2c2f96dcSApple OSS Distributions 
582*2c2f96dcSApple OSS Distributions 		/*
583*2c2f96dcSApple OSS Distributions 		 * If this exception happened in compatibility mode,
584*2c2f96dcSApple OSS Distributions 		 * assume it was the intentional division-by-zero and set the
585*2c2f96dcSApple OSS Distributions 		 * new state's cs register to just after the div instruction
586*2c2f96dcSApple OSS Distributions 		 * to enable the thread to resume.
587*2c2f96dcSApple OSS Distributions 		 */
588*2c2f96dcSApple OSS Distributions 		if ((unsigned)ss64->__ss64.__cs == COMPAT_MODE_CS_SELECTOR) {
589*2c2f96dcSApple OSS Distributions 			ss64->__ss64.__rip += rip_skip_count;
590*2c2f96dcSApple OSS Distributions 			fprintf(stderr, "new cs=0x%x rip=0x%llx\n", (unsigned)ss64->__ss64.__cs,
591*2c2f96dcSApple OSS Distributions 			    ss64->__ss64.__rip);
592*2c2f96dcSApple OSS Distributions 		}
593*2c2f96dcSApple OSS Distributions 	} else {
594*2c2f96dcSApple OSS Distributions 		_STRUCT_X86_THREAD_STATE64 *ss64 = &mctx.fp_basep->__ss;
595*2c2f96dcSApple OSS Distributions 
596*2c2f96dcSApple OSS Distributions 		restore_gsbase(ss64->__rsp);
597*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
598*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Unknown mcontext size %lu: Aborting.", uctxp->uc_mcsize);
599*2c2f96dcSApple OSS Distributions #else
600*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Unknown mcontext size %lu: Aborting.\n", uctxp->uc_mcsize);
601*2c2f96dcSApple OSS Distributions 		abort();
602*2c2f96dcSApple OSS Distributions #endif
603*2c2f96dcSApple OSS Distributions 	}
604*2c2f96dcSApple OSS Distributions }
605*2c2f96dcSApple OSS Distributions 
606*2c2f96dcSApple OSS Distributions static void
setup_signal_handling(void)607*2c2f96dcSApple OSS Distributions setup_signal_handling(void)
608*2c2f96dcSApple OSS Distributions {
609*2c2f96dcSApple OSS Distributions 	int rv;
610*2c2f96dcSApple OSS Distributions 
611*2c2f96dcSApple OSS Distributions 	struct sigaction sa = {
612*2c2f96dcSApple OSS Distributions 		.__sigaction_u = { .__sa_sigaction = signal_handler },
613*2c2f96dcSApple OSS Distributions 		.sa_flags = SA_SIGINFO
614*2c2f96dcSApple OSS Distributions 	};
615*2c2f96dcSApple OSS Distributions 
616*2c2f96dcSApple OSS Distributions 	sigfillset(&sa.sa_mask);
617*2c2f96dcSApple OSS Distributions 
618*2c2f96dcSApple OSS Distributions 	rv = sigaction(SIGFPE, &sa, NULL);
619*2c2f96dcSApple OSS Distributions 	if (rv != 0) {
620*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
621*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Failed to configure SIGFPE signal handler\n");
622*2c2f96dcSApple OSS Distributions #else
623*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Failed to configure SIGFPE signal handler\n");
624*2c2f96dcSApple OSS Distributions 		abort();
625*2c2f96dcSApple OSS Distributions #endif
626*2c2f96dcSApple OSS Distributions 	}
627*2c2f96dcSApple OSS Distributions 
628*2c2f96dcSApple OSS Distributions 	rv = sigaction(SIGILL, &sa, NULL);
629*2c2f96dcSApple OSS Distributions 	if (rv != 0) {
630*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
631*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Failed to configure SIGILL signal handler\n");
632*2c2f96dcSApple OSS Distributions #else
633*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Failed to configure SIGILL signal handler\n");
634*2c2f96dcSApple OSS Distributions 		abort();
635*2c2f96dcSApple OSS Distributions #endif
636*2c2f96dcSApple OSS Distributions 	}
637*2c2f96dcSApple OSS Distributions }
638*2c2f96dcSApple OSS Distributions 
639*2c2f96dcSApple OSS Distributions static void
teardown_signal_handling(void)640*2c2f96dcSApple OSS Distributions teardown_signal_handling(void)
641*2c2f96dcSApple OSS Distributions {
642*2c2f96dcSApple OSS Distributions 	if (signal(SIGFPE, SIG_DFL) == SIG_ERR) {
643*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
644*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Error resetting SIGFPE signal disposition\n");
645*2c2f96dcSApple OSS Distributions #else
646*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Error resetting SIGFPE signal disposition\n");
647*2c2f96dcSApple OSS Distributions 		abort();
648*2c2f96dcSApple OSS Distributions #endif
649*2c2f96dcSApple OSS Distributions 	}
650*2c2f96dcSApple OSS Distributions 
651*2c2f96dcSApple OSS Distributions 	if (signal(SIGILL, SIG_DFL) == SIG_ERR) {
652*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
653*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Error resetting SIGILL signal disposition\n");
654*2c2f96dcSApple OSS Distributions #else
655*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Error resetting SIGILL signal disposition\n");
656*2c2f96dcSApple OSS Distributions 		abort();
657*2c2f96dcSApple OSS Distributions #endif
658*2c2f96dcSApple OSS Distributions 	}
659*2c2f96dcSApple OSS Distributions }
660*2c2f96dcSApple OSS Distributions 
661*2c2f96dcSApple OSS Distributions #ifdef DEBUG
662*2c2f96dcSApple OSS Distributions static void
dump_desc(union ldt_entry * entp)663*2c2f96dcSApple OSS Distributions dump_desc(union ldt_entry *entp)
664*2c2f96dcSApple OSS Distributions {
665*2c2f96dcSApple OSS Distributions 	printf("base %p lim %p type 0x%x dpl %x present %x opsz %x granular %x\n",
666*2c2f96dcSApple OSS Distributions 	    (void *)(uintptr_t)(entp->code.base00 + (entp->code.base16 << 16) + (entp->code.base24 << 24)),
667*2c2f96dcSApple OSS Distributions 	    (void *)(uintptr_t)(entp->code.limit00 + (entp->code.limit16 << 16)),
668*2c2f96dcSApple OSS Distributions 	    entp->code.type,
669*2c2f96dcSApple OSS Distributions 	    entp->code.dpl,
670*2c2f96dcSApple OSS Distributions 	    entp->code.present,
671*2c2f96dcSApple OSS Distributions 	    entp->code.opsz,
672*2c2f96dcSApple OSS Distributions 	    entp->code.granular);
673*2c2f96dcSApple OSS Distributions }
674*2c2f96dcSApple OSS Distributions #endif
675*2c2f96dcSApple OSS Distributions 
676*2c2f96dcSApple OSS Distributions static int
map_lowmem_stack(void ** lowmemstk)677*2c2f96dcSApple OSS Distributions map_lowmem_stack(void **lowmemstk)
678*2c2f96dcSApple OSS Distributions {
679*2c2f96dcSApple OSS Distributions 	void *addr;
680*2c2f96dcSApple OSS Distributions 	int err;
681*2c2f96dcSApple OSS Distributions 
682*2c2f96dcSApple OSS Distributions 	if ((addr = mmap(0, FIXED_STACK_SIZE + PAGE_SIZE, PROT_READ | PROT_WRITE,
683*2c2f96dcSApple OSS Distributions 	    MAP_32BIT | MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) {
684*2c2f96dcSApple OSS Distributions 		return errno;
685*2c2f96dcSApple OSS Distributions 	}
686*2c2f96dcSApple OSS Distributions 
687*2c2f96dcSApple OSS Distributions 	if ((uintptr_t)addr > 0xFFFFF000ULL) {
688*2c2f96dcSApple OSS Distributions 		/* Error: This kernel does not support MAP_32BIT or there's a bug. */
689*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
690*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("%s: failed to map a 32-bit-accessible stack", __func__);
691*2c2f96dcSApple OSS Distributions #else
692*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "This kernel returned a virtual address > 4G (%p) despite MAP_32BIT.  Aborting.\n", addr);
693*2c2f96dcSApple OSS Distributions 		exit(1);
694*2c2f96dcSApple OSS Distributions #endif
695*2c2f96dcSApple OSS Distributions 	}
696*2c2f96dcSApple OSS Distributions 
697*2c2f96dcSApple OSS Distributions 	/* Enforce one page of redzone at the bottom of the stack */
698*2c2f96dcSApple OSS Distributions 	if (mprotect(addr, PAGE_SIZE, PROT_NONE) < 0) {
699*2c2f96dcSApple OSS Distributions 		err = errno;
700*2c2f96dcSApple OSS Distributions 		(void) munmap(addr, FIXED_STACK_SIZE + PAGE_SIZE);
701*2c2f96dcSApple OSS Distributions 		return err;
702*2c2f96dcSApple OSS Distributions 	}
703*2c2f96dcSApple OSS Distributions 
704*2c2f96dcSApple OSS Distributions 	if (lowmemstk) {
705*2c2f96dcSApple OSS Distributions 		stack2gs[0].stack_base = (uintptr_t)addr + PAGE_SIZE;
706*2c2f96dcSApple OSS Distributions 		stack2gs[0].stack_limit = stack2gs[0].stack_base + FIXED_STACK_SIZE;
707*2c2f96dcSApple OSS Distributions 		*lowmemstk = (void *)((uintptr_t)addr + PAGE_SIZE);
708*2c2f96dcSApple OSS Distributions 	}
709*2c2f96dcSApple OSS Distributions 
710*2c2f96dcSApple OSS Distributions 	return 0;
711*2c2f96dcSApple OSS Distributions }
712*2c2f96dcSApple OSS Distributions 
713*2c2f96dcSApple OSS Distributions static int
map_32bit_code_impl(uint8_t * code_src,size_t code_len,void ** codeptr,size_t szlimit)714*2c2f96dcSApple OSS Distributions map_32bit_code_impl(uint8_t *code_src, size_t code_len, void **codeptr,
715*2c2f96dcSApple OSS Distributions     size_t szlimit)
716*2c2f96dcSApple OSS Distributions {
717*2c2f96dcSApple OSS Distributions 	void *addr;
718*2c2f96dcSApple OSS Distributions 	size_t sz = (size_t)P2ROUNDUP(code_len, (unsigned)PAGE_SIZE);
719*2c2f96dcSApple OSS Distributions 
720*2c2f96dcSApple OSS Distributions 	if (code_len > szlimit) {
721*2c2f96dcSApple OSS Distributions 		return E2BIG;
722*2c2f96dcSApple OSS Distributions 	}
723*2c2f96dcSApple OSS Distributions 
724*2c2f96dcSApple OSS Distributions #ifdef DEBUG
725*2c2f96dcSApple OSS Distributions 	printf("size = %lu, szlimit = %u\n", sz, (unsigned)szlimit);
726*2c2f96dcSApple OSS Distributions #endif
727*2c2f96dcSApple OSS Distributions 
728*2c2f96dcSApple OSS Distributions 	if ((addr = mmap(0, sz, PROT_READ | PROT_WRITE | PROT_EXEC,
729*2c2f96dcSApple OSS Distributions 	    MAP_32BIT | MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) {
730*2c2f96dcSApple OSS Distributions 		return errno;
731*2c2f96dcSApple OSS Distributions 	}
732*2c2f96dcSApple OSS Distributions 
733*2c2f96dcSApple OSS Distributions 	if ((uintptr_t)addr > 0xFFFFF000ULL) {
734*2c2f96dcSApple OSS Distributions 		/* Error: This kernel does not support MAP_32BIT or there's a bug. */
735*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
736*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("%s: failed to map a 32-bit-accessible trampoline", __func__);
737*2c2f96dcSApple OSS Distributions #else
738*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "This kernel returned a virtual address > 4G (%p) despite MAP_32BIT.  Aborting.\n", addr);
739*2c2f96dcSApple OSS Distributions 		exit(1);
740*2c2f96dcSApple OSS Distributions #endif
741*2c2f96dcSApple OSS Distributions 	}
742*2c2f96dcSApple OSS Distributions 
743*2c2f96dcSApple OSS Distributions #ifdef DEBUG
744*2c2f96dcSApple OSS Distributions 	printf("Mapping code @%p..%p => %p..%p\n", (void *)code_src,
745*2c2f96dcSApple OSS Distributions 	    (void *)((uintptr_t)code_src + (unsigned)code_len),
746*2c2f96dcSApple OSS Distributions 	    addr, (void *)((uintptr_t)addr + (unsigned)code_len));
747*2c2f96dcSApple OSS Distributions #endif
748*2c2f96dcSApple OSS Distributions 
749*2c2f96dcSApple OSS Distributions 	bcopy(code_src, addr, code_len);
750*2c2f96dcSApple OSS Distributions 
751*2c2f96dcSApple OSS Distributions 	/* Fill the rest of the page with NOPs */
752*2c2f96dcSApple OSS Distributions 	if ((sz - code_len) > 0) {
753*2c2f96dcSApple OSS Distributions 		memset((void *)((uintptr_t)addr + code_len), 0x90, sz - code_len);
754*2c2f96dcSApple OSS Distributions 	}
755*2c2f96dcSApple OSS Distributions 
756*2c2f96dcSApple OSS Distributions 	if (codeptr) {
757*2c2f96dcSApple OSS Distributions 		*codeptr = addr;
758*2c2f96dcSApple OSS Distributions 	}
759*2c2f96dcSApple OSS Distributions 
760*2c2f96dcSApple OSS Distributions 	return 0;
761*2c2f96dcSApple OSS Distributions }
762*2c2f96dcSApple OSS Distributions 
763*2c2f96dcSApple OSS Distributions static int
map_32bit_trampoline(compat_tramp_t * lowmemtrampp)764*2c2f96dcSApple OSS Distributions map_32bit_trampoline(compat_tramp_t *lowmemtrampp)
765*2c2f96dcSApple OSS Distributions {
766*2c2f96dcSApple OSS Distributions 	extern int compat_mode_trampoline_len;
767*2c2f96dcSApple OSS Distributions 
768*2c2f96dcSApple OSS Distributions 	return map_32bit_code_impl((uint8_t *)&compat_mode_trampoline,
769*2c2f96dcSApple OSS Distributions 	           (size_t)compat_mode_trampoline_len, (void **)lowmemtrampp,
770*2c2f96dcSApple OSS Distributions 	           FIXED_TRAMP_MAXLEN);
771*2c2f96dcSApple OSS Distributions }
772*2c2f96dcSApple OSS Distributions 
773*2c2f96dcSApple OSS Distributions static uint64_t
stack_range_to_GSbase(uint64_t stackptr,uint64_t GSbase)774*2c2f96dcSApple OSS Distributions stack_range_to_GSbase(uint64_t stackptr, uint64_t GSbase)
775*2c2f96dcSApple OSS Distributions {
776*2c2f96dcSApple OSS Distributions 	unsigned long i;
777*2c2f96dcSApple OSS Distributions 
778*2c2f96dcSApple OSS Distributions 	for (i = 0; i < sizeof(stack2gs) / sizeof(stack2gs[0]); i++) {
779*2c2f96dcSApple OSS Distributions 		if (stackptr >= stack2gs[i].stack_base &&
780*2c2f96dcSApple OSS Distributions 		    stackptr < stack2gs[i].stack_limit) {
781*2c2f96dcSApple OSS Distributions 			if (GSbase != 0) {
782*2c2f96dcSApple OSS Distributions #ifdef DEBUG
783*2c2f96dcSApple OSS Distributions 				fprintf(stderr, "Updated gsbase for stack at 0x%llx..0x%llx to 0x%llx\n",
784*2c2f96dcSApple OSS Distributions 				    stack2gs[i].stack_base, stack2gs[i].stack_limit, GSbase);
785*2c2f96dcSApple OSS Distributions #endif
786*2c2f96dcSApple OSS Distributions 				stack2gs[i].GSbase = GSbase;
787*2c2f96dcSApple OSS Distributions 			}
788*2c2f96dcSApple OSS Distributions 			return stack2gs[i].GSbase;
789*2c2f96dcSApple OSS Distributions 		}
790*2c2f96dcSApple OSS Distributions 	}
791*2c2f96dcSApple OSS Distributions 	return 0;
792*2c2f96dcSApple OSS Distributions }
793*2c2f96dcSApple OSS Distributions 
794*2c2f96dcSApple OSS Distributions static uint64_t
call_compatmode(uint32_t stackaddr,uint64_t compat_arg,uint64_t callback)795*2c2f96dcSApple OSS Distributions call_compatmode(uint32_t stackaddr, uint64_t compat_arg, uint64_t callback)
796*2c2f96dcSApple OSS Distributions {
797*2c2f96dcSApple OSS Distributions 	uint64_t rv;
798*2c2f96dcSApple OSS Distributions 
799*2c2f96dcSApple OSS Distributions 	/*
800*2c2f96dcSApple OSS Distributions 	 * Depending on how this is used, this allocation may need to be
801*2c2f96dcSApple OSS Distributions 	 * made with an allocator that returns virtual addresses below 4G.
802*2c2f96dcSApple OSS Distributions 	 */
803*2c2f96dcSApple OSS Distributions 	custom_tsd_t *new_GSbase = malloc(PAGE_SIZE);
804*2c2f96dcSApple OSS Distributions 
805*2c2f96dcSApple OSS Distributions 	/*
806*2c2f96dcSApple OSS Distributions 	 * Change the GSbase (so things like printf will fail unless GSbase is
807*2c2f96dcSApple OSS Distributions 	 * restored)
808*2c2f96dcSApple OSS Distributions 	 */
809*2c2f96dcSApple OSS Distributions 	if (new_GSbase != NULL) {
810*2c2f96dcSApple OSS Distributions #ifdef DEBUG
811*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Setting new GS base: %p\n", (void *)new_GSbase);
812*2c2f96dcSApple OSS Distributions #endif
813*2c2f96dcSApple OSS Distributions 		new_GSbase->this_tsd_base = new_GSbase;
814*2c2f96dcSApple OSS Distributions 		new_GSbase->orig_tsd_base = get_gsbase();
815*2c2f96dcSApple OSS Distributions 		_thread_set_tsd_base((uintptr_t)new_GSbase);
816*2c2f96dcSApple OSS Distributions 	} else {
817*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
818*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Failed to allocate a page for new GSbase");
819*2c2f96dcSApple OSS Distributions #else
820*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Failed to allocate a page for new GSbase");
821*2c2f96dcSApple OSS Distributions 		abort();
822*2c2f96dcSApple OSS Distributions #endif
823*2c2f96dcSApple OSS Distributions 	}
824*2c2f96dcSApple OSS Distributions 
825*2c2f96dcSApple OSS Distributions 	rv = thunkit(&input_desc, (void *)(uintptr_t)stackaddr, compat_arg,
826*2c2f96dcSApple OSS Distributions 	    callback, thunk64_addr);
827*2c2f96dcSApple OSS Distributions 
828*2c2f96dcSApple OSS Distributions 	restore_gsbase(stackaddr);
829*2c2f96dcSApple OSS Distributions 
830*2c2f96dcSApple OSS Distributions 	free(new_GSbase);
831*2c2f96dcSApple OSS Distributions 
832*2c2f96dcSApple OSS Distributions 	return rv;
833*2c2f96dcSApple OSS Distributions }
834*2c2f96dcSApple OSS Distributions 
835*2c2f96dcSApple OSS Distributions static uint64_t
get_cursp(void)836*2c2f96dcSApple OSS Distributions get_cursp(void)
837*2c2f96dcSApple OSS Distributions {
838*2c2f96dcSApple OSS Distributions 	uint64_t curstk;
839*2c2f96dcSApple OSS Distributions 	__asm__ __volatile__ ("movq %%rsp, %0" : "=r" (curstk) :: "memory");
840*2c2f96dcSApple OSS Distributions 	return curstk;
841*2c2f96dcSApple OSS Distributions }
842*2c2f96dcSApple OSS Distributions 
843*2c2f96dcSApple OSS Distributions static void
hello_from_32bit(void)844*2c2f96dcSApple OSS Distributions hello_from_32bit(void)
845*2c2f96dcSApple OSS Distributions {
846*2c2f96dcSApple OSS Distributions 	uint64_t cur_tsd_base = (uint64_t)(uintptr_t)mytsd->this_tsd_base;
847*2c2f96dcSApple OSS Distributions 	restore_gsbase(get_cursp());
848*2c2f96dcSApple OSS Distributions 
849*2c2f96dcSApple OSS Distributions 	printf("Hello on behalf of 32-bit compatibility mode!\n");
850*2c2f96dcSApple OSS Distributions 
851*2c2f96dcSApple OSS Distributions 	_thread_set_tsd_base(cur_tsd_base);
852*2c2f96dcSApple OSS Distributions }
853*2c2f96dcSApple OSS Distributions 
854*2c2f96dcSApple OSS Distributions /*
855*2c2f96dcSApple OSS Distributions  * Thread for executing 32-bit code
856*2c2f96dcSApple OSS Distributions  */
857*2c2f96dcSApple OSS Distributions static void *
thread_32bit(void * arg)858*2c2f96dcSApple OSS Distributions thread_32bit(void *arg)
859*2c2f96dcSApple OSS Distributions {
860*2c2f96dcSApple OSS Distributions 	thread_arg_t *targp = (thread_arg_t *)arg;
861*2c2f96dcSApple OSS Distributions 	uint64_t cthread_self = 0;
862*2c2f96dcSApple OSS Distributions 
863*2c2f96dcSApple OSS Distributions 	/* Save the GSbase for context switch back to 64-bit mode */
864*2c2f96dcSApple OSS Distributions 	cthread_self = get_gsbase();
865*2c2f96dcSApple OSS Distributions 
866*2c2f96dcSApple OSS Distributions 	/*
867*2c2f96dcSApple OSS Distributions 	 * Associate GSbase with the compat-mode stack (which will be used for long mode
868*2c2f96dcSApple OSS Distributions 	 * thunk calls as well.)
869*2c2f96dcSApple OSS Distributions 	 */
870*2c2f96dcSApple OSS Distributions 	(void)stack_range_to_GSbase(targp->compat_stackaddr, cthread_self);
871*2c2f96dcSApple OSS Distributions 
872*2c2f96dcSApple OSS Distributions #ifdef DEBUG
873*2c2f96dcSApple OSS Distributions 	printf("[thread %p] tsd base => %p\n", (void *)pthread_self(), (void *)cthread_self);
874*2c2f96dcSApple OSS Distributions #endif
875*2c2f96dcSApple OSS Distributions 
876*2c2f96dcSApple OSS Distributions 	pthread_mutex_lock(&targp->mutex);
877*2c2f96dcSApple OSS Distributions 
878*2c2f96dcSApple OSS Distributions 	do {
879*2c2f96dcSApple OSS Distributions 		if (targp->done == FALSE) {
880*2c2f96dcSApple OSS Distributions 			pthread_cond_wait(&targp->condvar, &targp->mutex);
881*2c2f96dcSApple OSS Distributions 		}
882*2c2f96dcSApple OSS Distributions 
883*2c2f96dcSApple OSS Distributions 		/* Finally, execute the test */
884*2c2f96dcSApple OSS Distributions 		if (call_compatmode(targp->compat_stackaddr, 0,
885*2c2f96dcSApple OSS Distributions 		    (uint64_t)&hello_from_32bit) == 1) {
886*2c2f96dcSApple OSS Distributions 			printf("32-bit code test passed\n");
887*2c2f96dcSApple OSS Distributions 		} else {
888*2c2f96dcSApple OSS Distributions 			printf("32-bit code test failed\n");
889*2c2f96dcSApple OSS Distributions 		}
890*2c2f96dcSApple OSS Distributions 	} while (targp->done == FALSE);
891*2c2f96dcSApple OSS Distributions 
892*2c2f96dcSApple OSS Distributions 	pthread_mutex_unlock(&targp->mutex);
893*2c2f96dcSApple OSS Distributions 
894*2c2f96dcSApple OSS Distributions 	return 0;
895*2c2f96dcSApple OSS Distributions }
896*2c2f96dcSApple OSS Distributions 
897*2c2f96dcSApple OSS Distributions static void
join_32bit_thread(pthread_t * thridp,thread_arg_t * cmargp)898*2c2f96dcSApple OSS Distributions join_32bit_thread(pthread_t *thridp, thread_arg_t *cmargp)
899*2c2f96dcSApple OSS Distributions {
900*2c2f96dcSApple OSS Distributions 	(void)pthread_mutex_lock(&cmargp->mutex);
901*2c2f96dcSApple OSS Distributions 	cmargp->done = TRUE;
902*2c2f96dcSApple OSS Distributions 	(void)pthread_cond_signal(&cmargp->condvar);
903*2c2f96dcSApple OSS Distributions 	(void)pthread_mutex_unlock(&cmargp->mutex);
904*2c2f96dcSApple OSS Distributions 	(void)pthread_join(*thridp, NULL);
905*2c2f96dcSApple OSS Distributions 	*thridp = 0;
906*2c2f96dcSApple OSS Distributions }
907*2c2f96dcSApple OSS Distributions 
908*2c2f96dcSApple OSS Distributions static int
create_worker_thread(thread_arg_t * cmargp,uint32_t stackaddr,pthread_t * cmthreadp)909*2c2f96dcSApple OSS Distributions create_worker_thread(thread_arg_t *cmargp, uint32_t stackaddr, pthread_t *cmthreadp)
910*2c2f96dcSApple OSS Distributions {
911*2c2f96dcSApple OSS Distributions 	*cmargp = (thread_arg_t) { .mutex = PTHREAD_MUTEX_INITIALIZER,
912*2c2f96dcSApple OSS Distributions 		                   .condvar = PTHREAD_COND_INITIALIZER,
913*2c2f96dcSApple OSS Distributions 		                   .done = FALSE,
914*2c2f96dcSApple OSS Distributions 		                   .compat_stackaddr = stackaddr };
915*2c2f96dcSApple OSS Distributions 
916*2c2f96dcSApple OSS Distributions 	return pthread_create(cmthreadp, NULL, thread_32bit, cmargp);
917*2c2f96dcSApple OSS Distributions }
918*2c2f96dcSApple OSS Distributions 
919*2c2f96dcSApple OSS Distributions static void
ldt64_test_setup(pthread_t * cmthreadp,thread_arg_t * cmargp,boolean_t setldt_in_sighandler)920*2c2f96dcSApple OSS Distributions ldt64_test_setup(pthread_t *cmthreadp, thread_arg_t *cmargp, boolean_t setldt_in_sighandler)
921*2c2f96dcSApple OSS Distributions {
922*2c2f96dcSApple OSS Distributions 	extern void thunk64(void);
923*2c2f96dcSApple OSS Distributions 	extern void thunk64_movabs(void);
924*2c2f96dcSApple OSS Distributions 	int cnt = 0, err;
925*2c2f96dcSApple OSS Distributions 	void *addr;
926*2c2f96dcSApple OSS Distributions 	uintptr_t code_addr;
927*2c2f96dcSApple OSS Distributions 	uintptr_t thunk64_movabs_addr;
928*2c2f96dcSApple OSS Distributions 
929*2c2f96dcSApple OSS Distributions 	descs = malloc(sizeof(union ldt_entry) * 256);
930*2c2f96dcSApple OSS Distributions 	if (descs == 0) {
931*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
932*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Could not allocate descriptor storage");
933*2c2f96dcSApple OSS Distributions #else
934*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Could not allocate descriptor storage\n");
935*2c2f96dcSApple OSS Distributions 		abort();
936*2c2f96dcSApple OSS Distributions #endif
937*2c2f96dcSApple OSS Distributions 	}
938*2c2f96dcSApple OSS Distributions 
939*2c2f96dcSApple OSS Distributions #ifdef DEBUG
940*2c2f96dcSApple OSS Distributions 	printf("32-bit code is at %p\n", (void *)&code_32);
941*2c2f96dcSApple OSS Distributions #endif
942*2c2f96dcSApple OSS Distributions 
943*2c2f96dcSApple OSS Distributions 	if ((err = map_lowmem_stack(&addr)) != 0) {
944*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
945*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("failed to mmap lowmem stack: %s", strerror(err));
946*2c2f96dcSApple OSS Distributions #else
947*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Failed to mmap lowmem stack: %s\n", strerror(err));
948*2c2f96dcSApple OSS Distributions 		exit(1);
949*2c2f96dcSApple OSS Distributions #endif
950*2c2f96dcSApple OSS Distributions 	}
951*2c2f96dcSApple OSS Distributions 
952*2c2f96dcSApple OSS Distributions 	stackAddr = (uintptr_t)addr + FIXED_STACK_SIZE - 16;
953*2c2f96dcSApple OSS Distributions #ifdef DEBUG
954*2c2f96dcSApple OSS Distributions 	printf("lowstack addr = %p\n", (void *)stackAddr);
955*2c2f96dcSApple OSS Distributions #endif
956*2c2f96dcSApple OSS Distributions 
957*2c2f96dcSApple OSS Distributions 	if ((err = map_32bit_trampoline(&thunkit)) != 0) {
958*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
959*2c2f96dcSApple OSS Distributions 		T_LOG("Failed to map trampoline into lowmem: %s\n", strerror(err));
960*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Failed to map trampoline into lowmem");
961*2c2f96dcSApple OSS Distributions #else
962*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Failed to map trampoline into lowmem: %s\n", strerror(err));
963*2c2f96dcSApple OSS Distributions 		exit(1);
964*2c2f96dcSApple OSS Distributions #endif
965*2c2f96dcSApple OSS Distributions 	}
966*2c2f96dcSApple OSS Distributions 
967*2c2f96dcSApple OSS Distributions 	/*
968*2c2f96dcSApple OSS Distributions 	 * Store long_mode_trampoline's address into the constant part of the movabs
969*2c2f96dcSApple OSS Distributions 	 * instruction in thunk64
970*2c2f96dcSApple OSS Distributions 	 */
971*2c2f96dcSApple OSS Distributions 	thunk64_movabs_addr = (uintptr_t)thunkit + ((uintptr_t)thunk64_movabs - (uintptr_t)compat_mode_trampoline);
972*2c2f96dcSApple OSS Distributions 	*((uint64_t *)(thunk64_movabs_addr + 2)) = (uint64_t)&long_mode_trampoline;
973*2c2f96dcSApple OSS Distributions 
974*2c2f96dcSApple OSS Distributions 	bzero(descs, sizeof(union ldt_entry) * 256);
975*2c2f96dcSApple OSS Distributions 
976*2c2f96dcSApple OSS Distributions 	if ((cnt = i386_get_ldt(0, descs, 1)) <= 0) {
977*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
978*2c2f96dcSApple OSS Distributions 		T_LOG("i386_get_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
979*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("i386_get_ldt failure");
980*2c2f96dcSApple OSS Distributions #else
981*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "i386_get_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
982*2c2f96dcSApple OSS Distributions 		exit(1);
983*2c2f96dcSApple OSS Distributions #endif
984*2c2f96dcSApple OSS Distributions 	}
985*2c2f96dcSApple OSS Distributions 
986*2c2f96dcSApple OSS Distributions #ifdef DEBUG
987*2c2f96dcSApple OSS Distributions 	printf("i386_get_ldt returned %d\n", cnt);
988*2c2f96dcSApple OSS Distributions #endif
989*2c2f96dcSApple OSS Distributions 
990*2c2f96dcSApple OSS Distributions 	idx = (unsigned)cnt;      /* Put the desired descriptor in the first available slot */
991*2c2f96dcSApple OSS Distributions 
992*2c2f96dcSApple OSS Distributions 	/*
993*2c2f96dcSApple OSS Distributions 	 * code_32's address for the purposes of this descriptor is the base mapped address of
994*2c2f96dcSApple OSS Distributions 	 * the thunkit function + the offset of code_32 from compat_mode_trampoline.
995*2c2f96dcSApple OSS Distributions 	 */
996*2c2f96dcSApple OSS Distributions 	code_addr = (uintptr_t)thunkit + ((uintptr_t)code_32 - (uintptr_t)compat_mode_trampoline);
997*2c2f96dcSApple OSS Distributions 	thunk64_addr = (uintptr_t)thunkit + ((uintptr_t)thunk64 - (uintptr_t)compat_mode_trampoline);
998*2c2f96dcSApple OSS Distributions 
999*2c2f96dcSApple OSS Distributions 	/* Initialize desired descriptor */
1000*2c2f96dcSApple OSS Distributions 	descs[idx].code.limit00 = (unsigned short)(((code_addr >> 12) + 1) & 0xFFFF);
1001*2c2f96dcSApple OSS Distributions 	descs[idx].code.limit16 = (unsigned char)((((code_addr >> 12) + 1) >> 16) & 0xF);
1002*2c2f96dcSApple OSS Distributions 	descs[idx].code.base00 = (unsigned short)((code_addr) & 0xFFFF);
1003*2c2f96dcSApple OSS Distributions 	descs[idx].code.base16 = (unsigned char)((code_addr >> 16) & 0xFF);
1004*2c2f96dcSApple OSS Distributions 	descs[idx].code.base24 = (unsigned char)((code_addr >> 24) & 0xFF);
1005*2c2f96dcSApple OSS Distributions 	descs[idx].code.type = DESC_CODE_READ;
1006*2c2f96dcSApple OSS Distributions 	descs[idx].code.opsz = DESC_CODE_32B;
1007*2c2f96dcSApple OSS Distributions 	descs[idx].code.granular = DESC_GRAN_PAGE;
1008*2c2f96dcSApple OSS Distributions 	descs[idx].code.dpl = 3;
1009*2c2f96dcSApple OSS Distributions 	descs[idx].code.present = 1;
1010*2c2f96dcSApple OSS Distributions 
1011*2c2f96dcSApple OSS Distributions 	if (setldt_in_sighandler == FALSE) {
1012*2c2f96dcSApple OSS Distributions 		/* Set the LDT: */
1013*2c2f96dcSApple OSS Distributions 		cnt = i386_set_ldt((int)idx, &descs[idx], 1);
1014*2c2f96dcSApple OSS Distributions 		if (cnt != (int)idx) {
1015*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1016*2c2f96dcSApple OSS Distributions 			T_LOG("i386_set_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
1017*2c2f96dcSApple OSS Distributions 			T_ASSERT_FAIL("i386_set_ldt failure");
1018*2c2f96dcSApple OSS Distributions #else
1019*2c2f96dcSApple OSS Distributions 			fprintf(stderr, "i386_set_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
1020*2c2f96dcSApple OSS Distributions 			exit(1);
1021*2c2f96dcSApple OSS Distributions #endif
1022*2c2f96dcSApple OSS Distributions 		}
1023*2c2f96dcSApple OSS Distributions #ifdef DEBUG
1024*2c2f96dcSApple OSS Distributions 		printf("i386_set_ldt returned %d\n", cnt);
1025*2c2f96dcSApple OSS Distributions #endif
1026*2c2f96dcSApple OSS Distributions 	} else {
1027*2c2f96dcSApple OSS Distributions 		__asm__ __volatile__ ("ud2" ::: "memory");
1028*2c2f96dcSApple OSS Distributions 	}
1029*2c2f96dcSApple OSS Distributions 
1030*2c2f96dcSApple OSS Distributions 
1031*2c2f96dcSApple OSS Distributions 	/* Read back the LDT to ensure it was set properly */
1032*2c2f96dcSApple OSS Distributions 	if ((cnt = i386_get_ldt(0, descs, (int)idx)) > 0) {
1033*2c2f96dcSApple OSS Distributions #ifdef DEBUG
1034*2c2f96dcSApple OSS Distributions 		for (int i = 0; i < cnt; i++) {
1035*2c2f96dcSApple OSS Distributions 			dump_desc(&descs[i]);
1036*2c2f96dcSApple OSS Distributions 		}
1037*2c2f96dcSApple OSS Distributions #endif
1038*2c2f96dcSApple OSS Distributions 	} else {
1039*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1040*2c2f96dcSApple OSS Distributions 		T_LOG("i386_get_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
1041*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("i386_get_ldt failure");
1042*2c2f96dcSApple OSS Distributions #else
1043*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "i386_get_ldt unexpectedly returned %d (errno: %s)\n", cnt, strerror(errno));
1044*2c2f96dcSApple OSS Distributions 		exit(1);
1045*2c2f96dcSApple OSS Distributions #endif
1046*2c2f96dcSApple OSS Distributions 	}
1047*2c2f96dcSApple OSS Distributions 
1048*2c2f96dcSApple OSS Distributions 	free(descs);
1049*2c2f96dcSApple OSS Distributions 
1050*2c2f96dcSApple OSS Distributions 	if ((err = create_worker_thread(cmargp, (uint32_t)stackAddr, cmthreadp)) != 0) {
1051*2c2f96dcSApple OSS Distributions #ifdef DEBUG
1052*2c2f96dcSApple OSS Distributions 		fprintf(stderr, "Fatal: Could not create thread: %s\n", strerror(err));
1053*2c2f96dcSApple OSS Distributions #endif
1054*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1055*2c2f96dcSApple OSS Distributions 		T_LOG("Fatal: Could not create thread: %s\n", strerror(err));
1056*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("Thread creation failure");
1057*2c2f96dcSApple OSS Distributions #else
1058*2c2f96dcSApple OSS Distributions 		exit(1);
1059*2c2f96dcSApple OSS Distributions #endif
1060*2c2f96dcSApple OSS Distributions 	}
1061*2c2f96dcSApple OSS Distributions }
1062*2c2f96dcSApple OSS Distributions 
1063*2c2f96dcSApple OSS Distributions #ifdef STANDALONE
1064*2c2f96dcSApple OSS Distributions static void
test_ldt64_with_bsdsig(void)1065*2c2f96dcSApple OSS Distributions test_ldt64_with_bsdsig(void)
1066*2c2f96dcSApple OSS Distributions #else
1067*2c2f96dcSApple OSS Distributions /*
1068*2c2f96dcSApple OSS Distributions  * Main test declarations
1069*2c2f96dcSApple OSS Distributions  */
1070*2c2f96dcSApple OSS Distributions T_DECL(ldt64_with_bsd_sighandling,
1071*2c2f96dcSApple OSS Distributions     "Ensures that a 64-bit process can create LDT entries and can execute code in "
1072*2c2f96dcSApple OSS Distributions     "compatibility mode with BSD signal handling",
1073*2c2f96dcSApple OSS Distributions     T_META_TIMEOUT(NORMAL_RUN_TIME + TIMEOUT_OVERHEAD))
1074*2c2f96dcSApple OSS Distributions #endif
1075*2c2f96dcSApple OSS Distributions {
1076*2c2f96dcSApple OSS Distributions 	pthread_t cmthread;
1077*2c2f96dcSApple OSS Distributions 	thread_arg_t cmarg;
1078*2c2f96dcSApple OSS Distributions 
1079*2c2f96dcSApple OSS Distributions 	int translated = 0;
1080*2c2f96dcSApple OSS Distributions 	size_t translated_size = sizeof(int);
1081*2c2f96dcSApple OSS Distributions 
1082*2c2f96dcSApple OSS Distributions 	sysctlbyname("sysctl.proc_translated", &translated, &translated_size, NULL, 0);
1083*2c2f96dcSApple OSS Distributions 
1084*2c2f96dcSApple OSS Distributions 	if (translated) {
1085*2c2f96dcSApple OSS Distributions 		T_SKIP("Skipping this test because it is translated");
1086*2c2f96dcSApple OSS Distributions 	}
1087*2c2f96dcSApple OSS Distributions 
1088*2c2f96dcSApple OSS Distributions 	setup_signal_handling();
1089*2c2f96dcSApple OSS Distributions 
1090*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1091*2c2f96dcSApple OSS Distributions 	T_SETUPBEGIN;
1092*2c2f96dcSApple OSS Distributions #endif
1093*2c2f96dcSApple OSS Distributions 	ENV_set_ldt_in_sighandler = (getenv("LDT_SET_IN_SIGHANDLER") != NULL) ? TRUE : FALSE;
1094*2c2f96dcSApple OSS Distributions 	ldt64_test_setup(&cmthread, &cmarg, ENV_set_ldt_in_sighandler);
1095*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1096*2c2f96dcSApple OSS Distributions 	T_SETUPEND;
1097*2c2f96dcSApple OSS Distributions #endif
1098*2c2f96dcSApple OSS Distributions 
1099*2c2f96dcSApple OSS Distributions 	join_32bit_thread(&cmthread, &cmarg);
1100*2c2f96dcSApple OSS Distributions 
1101*2c2f96dcSApple OSS Distributions 	teardown_signal_handling();
1102*2c2f96dcSApple OSS Distributions 
1103*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1104*2c2f96dcSApple OSS Distributions 	T_PASS("Successfully completed ldt64 test with BSD signal handling");
1105*2c2f96dcSApple OSS Distributions #else
1106*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "PASSED: ldt64_with_bsd_signal_handling\n");
1107*2c2f96dcSApple OSS Distributions #endif
1108*2c2f96dcSApple OSS Distributions }
1109*2c2f96dcSApple OSS Distributions 
1110*2c2f96dcSApple OSS Distributions #ifdef STANDALONE
1111*2c2f96dcSApple OSS Distributions static void
test_ldt64_with_machexc(void)1112*2c2f96dcSApple OSS Distributions test_ldt64_with_machexc(void)
1113*2c2f96dcSApple OSS Distributions #else
1114*2c2f96dcSApple OSS Distributions T_DECL(ldt64_with_mach_exception_handling,
1115*2c2f96dcSApple OSS Distributions     "Ensures that a 64-bit process can create LDT entries and can execute code in "
1116*2c2f96dcSApple OSS Distributions     "compatibility mode with Mach exception handling",
1117*2c2f96dcSApple OSS Distributions     T_META_TIMEOUT(NORMAL_RUN_TIME + TIMEOUT_OVERHEAD))
1118*2c2f96dcSApple OSS Distributions #endif
1119*2c2f96dcSApple OSS Distributions {
1120*2c2f96dcSApple OSS Distributions 	pthread_t cmthread;
1121*2c2f96dcSApple OSS Distributions 	thread_arg_t cmarg;
1122*2c2f96dcSApple OSS Distributions 
1123*2c2f96dcSApple OSS Distributions 	int translated = 0;
1124*2c2f96dcSApple OSS Distributions 	size_t translated_size = sizeof(int);
1125*2c2f96dcSApple OSS Distributions 
1126*2c2f96dcSApple OSS Distributions 	sysctlbyname("sysctl.proc_translated", &translated, &translated_size, NULL, 0);
1127*2c2f96dcSApple OSS Distributions 
1128*2c2f96dcSApple OSS Distributions 	if (translated) {
1129*2c2f96dcSApple OSS Distributions 		T_SKIP("Skipping this test because it is translated");
1130*2c2f96dcSApple OSS Distributions 	}
1131*2c2f96dcSApple OSS Distributions 
1132*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1133*2c2f96dcSApple OSS Distributions 	T_SETUPBEGIN;
1134*2c2f96dcSApple OSS Distributions #endif
1135*2c2f96dcSApple OSS Distributions 	ldt64_test_setup(&cmthread, &cmarg, FALSE);
1136*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1137*2c2f96dcSApple OSS Distributions 	T_SETUPEND;
1138*2c2f96dcSApple OSS Distributions #endif
1139*2c2f96dcSApple OSS Distributions 
1140*2c2f96dcSApple OSS Distributions 	/* Now repeat with Mach exception handling */
1141*2c2f96dcSApple OSS Distributions 	init_task_exception_server();
1142*2c2f96dcSApple OSS Distributions 
1143*2c2f96dcSApple OSS Distributions 	join_32bit_thread(&cmthread, &cmarg);
1144*2c2f96dcSApple OSS Distributions 
1145*2c2f96dcSApple OSS Distributions #ifndef STANDALONE
1146*2c2f96dcSApple OSS Distributions 	T_PASS("Successfully completed ldt64 test with mach exception handling");
1147*2c2f96dcSApple OSS Distributions #else
1148*2c2f96dcSApple OSS Distributions 	fprintf(stderr, "PASSED: ldt64_with_mach_exception_handling\n");
1149*2c2f96dcSApple OSS Distributions #endif
1150*2c2f96dcSApple OSS Distributions }
1151*2c2f96dcSApple OSS Distributions 
1152*2c2f96dcSApple OSS Distributions #ifdef STANDALONE
1153*2c2f96dcSApple OSS Distributions int
main(int __unused argc,char ** __unused argv)1154*2c2f96dcSApple OSS Distributions main(int __unused argc, char ** __unused argv)
1155*2c2f96dcSApple OSS Distributions {
1156*2c2f96dcSApple OSS Distributions 	test_ldt64_with_bsdsig();
1157*2c2f96dcSApple OSS Distributions 	test_ldt64_with_machexc();
1158*2c2f96dcSApple OSS Distributions }
1159*2c2f96dcSApple OSS Distributions #endif
1160