xref: /xnu-11215.1.10/osfmk/kern/exclaves_upcalls.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1 /*
2  * Copyright (c) 2023 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <mach/exclaves.h>
30 #include "exclaves_upcalls.h"
31 
32 #if CONFIG_EXCLAVES
33 
34 #if __has_include(<Tightbeam/tightbeam.h>)
35 
36 #include <mach/exclaves_l4.h>
37 
38 #include <stdint.h>
39 
40 #include <Tightbeam/tightbeam.h>
41 #include <Tightbeam/tightbeam_private.h>
42 
43 #include <kern/kalloc.h>
44 #include <kern/locks.h>
45 #include <kern/task.h>
46 
47 #include <xnuproxy/exclaves.h>
48 #include <xnuproxy/messages.h>
49 
50 #include "kern/exclaves.tightbeam.h"
51 
52 #include "exclaves_boot.h"
53 #include "exclaves_conclave.h"
54 #include "exclaves_debug.h"
55 #include "exclaves_driverkit.h"
56 #include "exclaves_memory.h"
57 #include "exclaves_stackshot.h"
58 #include "exclaves_storage.h"
59 #include "exclaves_test_stackshot.h"
60 #include "exclaves_xnuproxy.h"
61 
62 #include <sys/errno.h>
63 
64 #define EXCLAVES_ID_HELLO_EXCLAVE_EP                 \
65     (exclaves_service_lookup(EXCLAVES_DOMAIN_KERNEL, \
66     "com.apple.service.ExclavesCHelloServer"))
67 
68 #define EXCLAVES_ID_TIGHTBEAM_UPCALL \
69     ((exclaves_id_t)XNUPROXY_UPCALL_TIGHTBEAM)
70 
71 extern lck_mtx_t exclaves_boot_lock;
72 
73 typedef struct exclaves_upcall_handler_registration {
74 	exclaves_upcall_handler_t handler;
75 	void *context;
76 } exclaves_upcall_handler_registration_t;
77 
78 static exclaves_upcall_handler_registration_t
79     exclaves_upcall_handlers[NUM_XNUPROXY_UPCALLS];
80 
81 #define EXCLAVES_OBSOLETE_UPCALL_TESTING 1 // TODO: delete (rdar://123929546)
82 #ifdef EXCLAVES_OBSOLETE_UPCALL_TESTING
83 #if DEVELOPMENT || DEBUG
84 static kern_return_t
85 exclaves_test_hello_upcall_handler(void *, exclaves_tag_t *, exclaves_badge_t);
86 #endif /* DEVELOPMENT || DEBUG */
87 #endif // EXCLAVES_OBSOLETE_UPCALL_TESTING
88 
89 
90 /* -------------------------------------------------------------------------- */
91 #pragma mark Upcall Callouts
92 
93 static tb_error_t
94 exclaves_helloupcall(const uint64_t arg, tb_error_t (^completion)(uint64_t));
95 
96 /*
97  * Tightbeam upcall callout table.
98  * Don't add inline functionality here, instead call directly into your
99  * sub-system.
100  */
101 
102 static const xnuupcalls_xnuupcalls__server_s exclaves_tightbeam_upcalls = {
103 	/* BEGIN IGNORE CODESTYLE */
104 	/* Uncrustify doesn't deal well with Blocks. */
105 	.helloupcall = ^(const uint64_t arg, tb_error_t (^completion)(uint64_t)) {
106 		return exclaves_helloupcall(arg, completion);
107 	},
108 
109 	.alloc = ^(const uint32_t npages, xnuupcalls_pagekind_s kind,
110 	    tb_error_t (^completion)(xnuupcalls_pagelist_s)) {
111 		return exclaves_memory_upcall_alloc(npages, kind, completion);
112 	},
113 
114 	.free = ^(const uint32_t pages[_Nonnull EXCLAVES_MEMORY_MAX_REQUEST],
115 	    const uint32_t npages, const xnuupcalls_pagekind_s kind,
116 	    tb_error_t (^completion)(void)) {
117 		return exclaves_memory_upcall_free(pages, npages, kind, completion);
118 	},
119 
120 	.root = ^(const uint8_t exclaveid[_Nonnull 32],
121 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_root__result_s)) {
122 		return exclaves_storage_upcall_root(exclaveid, completion);
123 	},
124 
125 	.open = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid,
126 	    const uint8_t name[_Nonnull 256],
127 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_open__result_s)) {
128 		return exclaves_storage_upcall_open(fstag, rootid, name, completion);
129 	},
130 
131 	.close = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid,
132 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_close__result_s)) {
133 		return exclaves_storage_upcall_close(fstag, fileid, completion);
134 	},
135 
136 	.create = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid,
137 	    const uint8_t name[_Nonnull 256],
138 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_create__result_s)) {
139 		return exclaves_storage_upcall_create(fstag, rootid, name, completion);
140 	},
141 
142 	.read = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid,
143 	    const struct xnuupcalls_iodesc_s *descriptor,
144 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_read__result_s)) {
145 		return exclaves_storage_upcall_read(fstag, fileid, descriptor, completion);
146 	},
147 
148 	.write = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid,
149 	    const struct xnuupcalls_iodesc_s *descriptor,
150 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_write__result_s)) {
151 		return exclaves_storage_upcall_write(fstag, fileid, descriptor, completion);
152 	},
153 
154 	.remove = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid,
155 	    const uint8_t name[_Nonnull 256],
156 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_remove__result_s)) {
157 		return exclaves_storage_upcall_remove(fstag, rootid, name, completion);
158 	},
159 
160 	.sync = ^(const enum xnuupcalls_fstag_s fstag,
161 	    const enum xnuupcalls_syncop_s op,
162 	    const uint64_t fileid,
163 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_sync__result_s)) {
164 		return exclaves_storage_upcall_sync(fstag, op, fileid, completion);
165 	},
166 
167 	.readdir = ^(const enum xnuupcalls_fstag_s fstag,
168 	    const uint64_t fileid, const uint64_t buf,
169 	    const uint32_t length,
170 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_readdir__result_s)) {
171 		return exclaves_storage_upcall_readdir(fstag, fileid, buf, length, completion);
172 	},
173 
174 	.getsize = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid,
175 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_getsize__result_s)) {
176 		return exclaves_storage_upcall_getsize(fstag, fileid, completion);
177 	},
178 
179 	.sealstate = ^(const enum xnuupcalls_fstag_s fstag,
180 		tb_error_t (^completion)(xnuupcalls_xnuupcalls_sealstate__result_s)) {
181 		return exclaves_storage_upcall_sealstate(fstag, completion);
182 	},
183 
184 	.irq_register = ^(const uint64_t id, const int32_t index,
185 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_register__result_s)) {
186 		return exclaves_driverkit_upcall_irq_register(id, index, completion);
187 	},
188 
189 	.irq_remove = ^(const uint64_t id, const int32_t index,
190 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_remove__result_s)) {
191 		return exclaves_driverkit_upcall_irq_remove(id, index, completion);
192 	},
193 
194 	.irq_enable = ^(const uint64_t id, const int32_t index,
195 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_enable__result_s)) {
196 		return exclaves_driverkit_upcall_irq_enable(id, index, completion);
197 	},
198 
199 	.irq_disable = ^(const uint64_t id, const int32_t index,
200 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_disable__result_s)) {
201 		return exclaves_driverkit_upcall_irq_disable(id, index, completion);
202 	},
203 
204 	.timer_register = ^(const uint64_t id,
205 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_register__result_s)) {
206 		return exclaves_driverkit_upcall_timer_register(id, completion);
207 	},
208 
209 	.timer_remove = ^(const uint64_t id, const uint32_t timer_id,
210 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_remove__result_s)) {
211 		return exclaves_driverkit_upcall_timer_remove(id, timer_id, completion);
212 	},
213 
214 	.timer_enable = ^(const uint64_t id, const uint32_t timer_id,
215 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_enable__result_s)) {
216 		return exclaves_driverkit_upcall_timer_enable(id, timer_id, completion);
217 	},
218 
219 	.timer_disable = ^(const uint64_t id, const uint32_t timer_id,
220 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_disable__result_s)) {
221 		return exclaves_driverkit_upcall_timer_disable(id, timer_id, completion);
222 	},
223 
224 	.timer_set_timeout = ^(const uint64_t id, const uint32_t timer_id,
225 	    const struct xnuupcalls_drivertimerspecification_s *duration,
226 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_set_timeout__result_s)) {
227 		return exclaves_driverkit_upcall_timer_set_timeout(id, timer_id, duration, completion);
228 	},
229 
230 	.timer_cancel_timeout = ^(const uint64_t id, const uint32_t timer_id,
231 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_cancel_timeout__result_s)) {
232 		return exclaves_driverkit_upcall_timer_cancel_timeout(id, timer_id, completion);
233 	},
234 
235 	.lock_wl = ^(const uint64_t id,
236 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_lock_wl__result_s)) {
237 		return exclaves_driverkit_upcall_lock_wl(id, completion);
238 	},
239 
240 	.unlock_wl = ^(const uint64_t id,
241 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_unlock_wl__result_s)) {
242 		return exclaves_driverkit_upcall_unlock_wl(id, completion);
243 	},
244 
245 	.async_notification_signal = ^(const uint64_t id,
246 	    const uint32_t notificationID,
247 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_async_notification_signal__result_s)) {
248 		return exclaves_driverkit_upcall_async_notification_signal(id,
249 		    notificationID, completion);
250 	},
251 
252 	.mapper_activate = ^(const uint64_t id, const uint32_t mapperIndex,
253 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_mapper_activate__result_s)) {
254 		return exclaves_driverkit_upcall_mapper_activate(id,
255 		    mapperIndex, completion);
256 	},
257 
258 	.mapper_deactivate = ^(const uint64_t id, const uint32_t mapperIndex,
259 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_mapper_deactivate__result_s)) {
260 		return exclaves_driverkit_upcall_mapper_deactivate(id,
261 		    mapperIndex, completion);
262 	},
263 
264 	.notification_signal = ^(const uint64_t id, const uint32_t mask,
265 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_notification_signal__result_s)) {
266 		return exclaves_driverkit_upcall_notification_signal(id, mask,
267 		    completion);
268 	},
269 
270 	.ane_setpowerstate = ^(const uint64_t id, const uint32_t desiredState,
271 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_setpowerstate__result_s)) {
272 		return exclaves_driverkit_upcall_ane_setpowerstate(id, desiredState,
273 			completion);
274 	},
275 
276 	.ane_worksubmit = ^(const uint64_t id, const uint64_t requestID,
277 	    const uint32_t taskDescriptorCount, const uint64_t submitTimestamp,
278 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_worksubmit__result_s)) {
279 		return exclaves_driverkit_upcall_ane_worksubmit(id, requestID,
280 			taskDescriptorCount, submitTimestamp, completion);
281 	},
282 
283 	.ane_workbegin = ^(const uint64_t id, const uint64_t requestID,
284 	    const uint64_t beginTimestamp,
285 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_workbegin__result_s)) {
286 		return exclaves_driverkit_upcall_ane_workbegin(id, requestID,
287 			beginTimestamp, completion);
288 	},
289 
290 	.ane_workend = ^(const uint64_t id, const uint64_t requestID,
291 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_workend__result_s)) {
292 		return exclaves_driverkit_upcall_ane_workend(id, requestID, completion);
293 	},
294 
295 	.conclave_suspend = ^(const uint32_t flags,
296 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_suspend__result_s)) {
297 		return exclaves_conclave_upcall_suspend(flags, completion);
298 	},
299 
300 	.conclave_stop = ^(const uint32_t flags,
301 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_stop__result_s)) {
302 		return exclaves_conclave_upcall_stop(flags, completion);
303 	},
304 	.conclave_crash_info = ^(const xnuupcalls_conclavesharedbuffer_s *shared_buf,
305 	    const uint32_t length,
306 	    tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_crash_info__result_s)) {
307 		return exclaves_conclave_upcall_crash_info(shared_buf, length, completion);
308 	},
309 	/* END IGNORE CODESTYLE */
310 };
311 
312 kern_return_t
exclaves_register_upcall_handler(exclaves_id_t upcall_id,void * upcall_context,exclaves_upcall_handler_t upcall_handler)313 exclaves_register_upcall_handler(exclaves_id_t upcall_id, void *upcall_context,
314     exclaves_upcall_handler_t upcall_handler)
315 {
316 	assert3u(upcall_id, <, NUM_XNUPROXY_UPCALLS);
317 	assert(upcall_handler != NULL);
318 
319 	lck_mtx_assert(&exclaves_boot_lock, LCK_MTX_ASSERT_OWNED);
320 	assert(exclaves_upcall_handlers[upcall_id].handler == NULL);
321 
322 	exclaves_upcall_handlers[upcall_id] =
323 	    (exclaves_upcall_handler_registration_t){
324 		.handler = upcall_handler,
325 		.context = upcall_context,
326 	};
327 
328 	return KERN_SUCCESS;
329 }
330 
331 kern_return_t
exclaves_upcall_init(void)332 exclaves_upcall_init(void)
333 {
334 	lck_mtx_assert(&exclaves_boot_lock, LCK_MTX_ASSERT_OWNED);
335 
336 #ifdef EXCLAVES_OBSOLETE_UPCALL_TESTING
337 #if DEVELOPMENT || DEBUG
338 	kern_return_t kr;
339 	kr = exclaves_register_upcall_handler(
340 		XNUPROXY_UPCALL_HELLOUPCALL, NULL,
341 		exclaves_test_hello_upcall_handler);
342 	assert3u(kr, ==, KERN_SUCCESS);
343 #endif /* DEVELOPMENT || DEBUG */
344 #endif // EXCLAVES_OBSOLETE_UPCALL_TESTING
345 
346 	tb_endpoint_t tb_upcall_ep = tb_endpoint_create_with_value(
347 		TB_TRANSPORT_TYPE_XNU, EXCLAVES_ID_TIGHTBEAM_UPCALL,
348 		TB_ENDPOINT_OPTIONS_NONE);
349 #pragma clang diagnostic push
350 #pragma clang diagnostic ignored "-Wcast-qual" /* FIXME: rdar://103647654 */
351 	tb_error_t error = xnuupcalls_xnuupcalls__server_start(tb_upcall_ep,
352 	    (xnuupcalls_xnuupcalls__server_s *)&exclaves_tightbeam_upcalls);
353 #pragma clang diagnostic pop
354 
355 	return error == TB_ERROR_SUCCESS ? KERN_SUCCESS : KERN_FAILURE;
356 }
357 
358 /* Unslid pointers defining the range of code which triggers upcall handlers */
359 uintptr_t exclaves_upcall_range_start;
360 uintptr_t exclaves_upcall_range_end;
361 
362 __startup_func
363 static void
initialize_exclaves_upcall_range(void)364 initialize_exclaves_upcall_range(void)
365 {
366 	exclaves_upcall_range_start = VM_KERNEL_UNSLIDE(&exclaves_upcall_start_label);
367 	assert3u(exclaves_upcall_range_start, !=, 0);
368 	exclaves_upcall_range_end = VM_KERNEL_UNSLIDE(&exclaves_upcall_end_label);
369 	assert3u(exclaves_upcall_range_end, !=, 0);
370 }
371 STARTUP(EARLY_BOOT, STARTUP_RANK_MIDDLE, initialize_exclaves_upcall_range);
372 
373 bool
exclaves_upcall_in_range(uintptr_t addr,bool slid)374 exclaves_upcall_in_range(uintptr_t addr, bool slid)
375 {
376 	return slid ?
377 	       exclaves_in_range(addr, (uintptr_t)&exclaves_upcall_start_label, (uintptr_t)&exclaves_upcall_end_label) :
378 	       exclaves_in_range(addr, exclaves_upcall_range_start, exclaves_upcall_range_end);
379 }
380 
381 OS_NOINLINE
382 kern_return_t
exclaves_call_upcall_handler(exclaves_id_t upcall_id)383 exclaves_call_upcall_handler(exclaves_id_t upcall_id)
384 {
385 	kern_return_t kr = KERN_INVALID_CAPABILITY;
386 
387 	__assert_only thread_t thread = current_thread();
388 	assert3u(thread->th_exclaves_state & TH_EXCLAVES_UPCALL, !=, 0);
389 
390 	exclaves_tag_t tag = Exclaves_L4_GetMessageTag();
391 
392 	Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
393 	exclaves_badge_t badge = XNUPROXY_CR_UPCALL_BADGE(ipcb);
394 
395 	exclaves_upcall_handler_registration_t upcall_handler = {};
396 
397 	if (upcall_id < NUM_XNUPROXY_UPCALLS) {
398 		upcall_handler = exclaves_upcall_handlers[upcall_id];
399 	}
400 	if (upcall_handler.handler) {
401 		__asm__ volatile ( "EXCLAVES_UPCALL_START: nop\n\t");
402 		kr = upcall_handler.handler(upcall_handler.context, &tag, badge);
403 		__asm__ volatile ("EXCLAVES_UPCALL_END: nop\n\t");
404 		Exclaves_L4_SetMessageTag(tag);
405 	}
406 
407 	return kr;
408 }
409 
410 /* -------------------------------------------------------------------------- */
411 #pragma mark Testing
412 
413 
414 static tb_error_t
415 exclaves_helloupcall(const uint64_t arg, tb_error_t (^completion)(uint64_t))
416 {
417 #if DEVELOPMENT || DEBUG
418 	exclaves_debug_printf(show_test_output,
419 	    "%s: Hello Tightbeam Upcall!\n", __func__);
420 	tb_error_t ret = completion(~arg);
421 	task_stop_conclave_upcall();
422 	STACKSHOT_TESTPOINT(TP_UPCALL);
423 	/* Emit kdebug event for kperf sampling testing */
424 	KDBG(BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 0xaa));
425 	return ret;
426 #else
427 	(void)arg;
428 	(void)completion;
429 
430 	return TB_ERROR_SUCCESS;
431 #endif /* DEVELOPMENT || DEBUG */
432 }
433 
434 #if DEVELOPMENT || DEBUG
435 
436 #ifdef EXCLAVES_OBSOLETE_UPCALL_TESTING
437 static kern_return_t
exclaves_test_upcall_handler(void * context,exclaves_tag_t * tag,exclaves_badge_t badge)438 exclaves_test_upcall_handler(void *context, exclaves_tag_t *tag,
439     exclaves_badge_t badge)
440 {
441 #pragma unused(context, badge)
442 	Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
443 	assert(ipcb != NULL);
444 
445 	Exclaves_L4_Word_t mrs = Exclaves_L4_MessageTag_Mrs(*tag);
446 	assert(mrs < Exclaves_L4_IpcBuffer_Mrs);
447 	Exclaves_L4_Word_t crs = Exclaves_L4_MessageTag_Crs(*tag);
448 	assert(crs == 0);
449 	Exclaves_L4_Word_t label = Exclaves_L4_MessageTag_Label(*tag);
450 
451 	/* setup test reply message */
452 	*tag = Exclaves_L4_MessageTag(mrs, 0, ~label, Exclaves_L4_False);
453 	for (int i = 0; i < mrs; i++) {
454 		Exclaves_L4_SetMessageMr(i, ~Exclaves_L4_GetMessageMr(i));
455 	}
456 
457 	return KERN_SUCCESS;
458 }
459 #endif // EXCLAVES_OBSOLETE_UPCALL_TESTING
460 
461 static int
exclaves_hello_upcall_test(__unused int64_t in,int64_t * out)462 exclaves_hello_upcall_test(__unused int64_t in, int64_t *out)
463 {
464 	tb_error_t tb_result;
465 	exclaveschelloserver_tests_s client;
466 	const unsigned long request = 0xdecafbadfeedfaceul;
467 
468 	if (exclaves_get_status() != EXCLAVES_STATUS_AVAILABLE) {
469 		exclaves_debug_printf(show_test_output,
470 		    "%s: SKIPPED: Exclaves not available\n", __func__);
471 		*out = -1;
472 		return 0;
473 	}
474 
475 	exclaves_debug_printf(show_test_output, "%s: STARTING\n", __func__);
476 
477 	tb_endpoint_t ep = tb_endpoint_create_with_value(TB_TRANSPORT_TYPE_XNU,
478 	    EXCLAVES_ID_HELLO_EXCLAVE_EP, TB_ENDPOINT_OPTIONS_NONE);
479 
480 	tb_result = exclaveschelloserver_tests__init(&client, ep);
481 	assert3u(tb_result, ==, TB_ERROR_SUCCESS);
482 
483 	tb_result = exclaveschelloserver_tests_default_upcall(&client, request, ^(exclaveschelloserver_result_s result) {
484 		assert3u(tb_result, ==, TB_ERROR_SUCCESS);
485 		assert3u(result.result, ==, 1);
486 		assert3u(result.reply, ==, ((request >> 32) | (request << 32)));
487 	});
488 
489 	exclaves_debug_printf(show_test_output, "%s: SUCCESS\n", __func__);
490 	*out = 1;
491 
492 	return KERN_SUCCESS;
493 }
494 SYSCTL_TEST_REGISTER(exclaves_hello_upcall_test, exclaves_hello_upcall_test);
495 
496 #ifdef EXCLAVES_OBSOLETE_UPCALL_TESTING
497 static kern_return_t
exclaves_test_hello_upcall_handler(void * context,exclaves_tag_t * tag,exclaves_badge_t badge)498 exclaves_test_hello_upcall_handler(void *context, exclaves_tag_t *tag,
499     exclaves_badge_t badge)
500 {
501 	/* HelloUpcall test handler */
502 	assert(context == NULL);
503 	exclaves_debug_printf(show_test_output, "%s: Hello Upcall!\n", __func__);
504 	task_stop_conclave_upcall();
505 	STACKSHOT_TESTPOINT(TP_UPCALL);
506 	/* Emit kdebug event for kperf sampling testing */
507 	KDBG(BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 0xaa));
508 	return exclaves_test_upcall_handler(context, tag, badge);
509 }
510 #endif // EXCLAVES_OBSOLETE_UPCALL_TESTING
511 
512 #endif /* DEVELOPMENT || DEBUG */
513 
514 #endif /* __has_include(<Tightbeam/tightbeam.h>) */
515 
516 #else /* CONFIG_EXCLAVES */
517 
518 kern_return_t
exclaves_call_upcall_handler(exclaves_id_t upcall_id)519 exclaves_call_upcall_handler(exclaves_id_t upcall_id)
520 {
521 	(void)upcall_id;
522 	return KERN_NOT_SUPPORTED;
523 }
524 
525 kern_return_t
exclaves_register_upcall_handler(exclaves_id_t upcall_id,void * upcall_context,exclaves_upcall_handler_t upcall_handler)526 exclaves_register_upcall_handler(exclaves_id_t upcall_id, void *upcall_context,
527     exclaves_upcall_handler_t upcall_handler)
528 {
529 	(void)upcall_id;
530 	(void)upcall_context;
531 	(void)upcall_handler;
532 
533 	return KERN_NOT_SUPPORTED;
534 }
535 
536 #endif /* CONFIG_EXCLAVES */
537