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 | |
49 | #include "kern/exclaves.tightbeam.h" |
50 | |
51 | #include "exclaves_boot.h" |
52 | #include "exclaves_debug.h" |
53 | #include "exclaves_driverkit.h" |
54 | #include "exclaves_storage.h" |
55 | #include "exclaves_test_stackshot.h" |
56 | #include "exclaves_conclave.h" |
57 | #include "exclaves_memory.h" |
58 | |
59 | #include <sys/errno.h> |
60 | |
61 | #define EXCLAVES_ID_HELLO_EXCLAVE_EP \ |
62 | (exclaves_service_lookup(EXCLAVES_DOMAIN_KERNEL, \ |
63 | "com.apple.service.HelloExclave")) |
64 | |
65 | #define EXCLAVES_ID_TIGHTBEAM_UPCALL \ |
66 | ((exclaves_id_t)XNUPROXY_UPCALL_TIGHTBEAM) |
67 | |
68 | extern lck_mtx_t exclaves_boot_lock; |
69 | |
70 | typedef struct exclaves_upcall_handler_registration { |
71 | exclaves_upcall_handler_t handler; |
72 | void *context; |
73 | } exclaves_upcall_handler_registration_t; |
74 | |
75 | static exclaves_upcall_handler_registration_t |
76 | exclaves_upcall_handlers[NUM_XNUPROXY_UPCALLS]; |
77 | |
78 | #if DEVELOPMENT || DEBUG |
79 | static kern_return_t |
80 | exclaves_test_hello_upcall_handler(void *, exclaves_tag_t *, exclaves_badge_t); |
81 | #endif /* DEVELOPMENT || DEBUG */ |
82 | |
83 | extern kern_return_t exclaves_xnu_proxy_send(xnuproxy_msg_t *, |
84 | Exclaves_L4_Word_t *); |
85 | |
86 | /* -------------------------------------------------------------------------- */ |
87 | #pragma mark Upcall Callouts |
88 | |
89 | static tb_error_t |
90 | exclaves_helloupcall(const uint64_t arg, tb_error_t (^completion)(uint64_t)); |
91 | |
92 | /* |
93 | * Tightbeam upcall callout table. |
94 | * Don't add inline functionality here, instead call directly into your |
95 | * sub-system. |
96 | */ |
97 | |
98 | static const xnuupcalls_xnuupcalls__server_s exclaves_tightbeam_upcalls = { |
99 | /* BEGIN IGNORE CODESTYLE */ |
100 | /* Uncrustify doesn't deal well with Blocks. */ |
101 | .helloupcall = ^(const uint64_t arg, tb_error_t (^completion)(uint64_t)) { |
102 | return exclaves_helloupcall(arg, completion); |
103 | }, |
104 | |
105 | .alloc = ^(const uint32_t npages, xnuupcalls_pagekind_s kind, |
106 | tb_error_t (^completion)(xnuupcalls_pagelist_s)) { |
107 | return exclaves_memory_upcall_alloc(npages, kind, completion); |
108 | }, |
109 | |
110 | .free = ^(const uint32_t pages[_Nonnull EXCLAVES_MEMORY_MAX_REQUEST], |
111 | const uint32_t npages, const xnuupcalls_pagekind_s kind, |
112 | tb_error_t (^completion)(void)) { |
113 | return exclaves_memory_upcall_free(pages, npages, kind, completion); |
114 | }, |
115 | |
116 | .root = ^(const uint8_t exclaveid[_Nonnull 32], |
117 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_root__result_s)) { |
118 | return exclaves_storage_upcall_root(exclaveid, completion); |
119 | }, |
120 | |
121 | .open = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid, |
122 | const uint8_t name[_Nonnull 256], |
123 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_open__result_s)) { |
124 | return exclaves_storage_upcall_open(fstag, rootid, name, completion); |
125 | }, |
126 | |
127 | .close = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid, |
128 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_close__result_s)) { |
129 | return exclaves_storage_upcall_close(fstag, fileid, completion); |
130 | }, |
131 | |
132 | .create = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid, |
133 | const uint8_t name[_Nonnull 256], |
134 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_create__result_s)) { |
135 | return exclaves_storage_upcall_create(fstag, rootid, name, completion); |
136 | }, |
137 | |
138 | .read = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid, |
139 | const struct xnuupcalls_iodesc_s *descriptor, |
140 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_read__result_s)) { |
141 | return exclaves_storage_upcall_read(fstag, fileid, descriptor, completion); |
142 | }, |
143 | |
144 | .write = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid, |
145 | const struct xnuupcalls_iodesc_s *descriptor, |
146 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_write__result_s)) { |
147 | return exclaves_storage_upcall_write(fstag, fileid, descriptor, completion); |
148 | }, |
149 | |
150 | .remove = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t rootid, |
151 | const uint8_t name[_Nonnull 256], |
152 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_remove__result_s)) { |
153 | return exclaves_storage_upcall_remove(fstag, rootid, name, completion); |
154 | }, |
155 | |
156 | .sync = ^(const enum xnuupcalls_fstag_s fstag, |
157 | const enum xnuupcalls_syncop_s op, |
158 | const uint64_t fileid, |
159 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_sync__result_s)) { |
160 | return exclaves_storage_upcall_sync(fstag, op, fileid, completion); |
161 | }, |
162 | |
163 | .readdir = ^(const enum xnuupcalls_fstag_s fstag, |
164 | const uint64_t fileid, const uint64_t buf, |
165 | const uint32_t length, |
166 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_readdir__result_s)) { |
167 | return exclaves_storage_upcall_readdir(fstag, fileid, buf, length, completion); |
168 | }, |
169 | |
170 | .getsize = ^(const enum xnuupcalls_fstag_s fstag, const uint64_t fileid, |
171 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_getsize__result_s)) { |
172 | return exclaves_storage_upcall_getsize(fstag, fileid, completion); |
173 | }, |
174 | |
175 | .sealstate = ^(const enum xnuupcalls_fstag_s fstag, |
176 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_sealstate__result_s)) { |
177 | return exclaves_storage_upcall_sealstate(fstag, completion); |
178 | }, |
179 | |
180 | .irq_register = ^(const uint64_t id, const int32_t index, |
181 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_register__result_s)) { |
182 | return exclaves_driverkit_upcall_irq_register(id, index, completion); |
183 | }, |
184 | |
185 | .irq_remove = ^(const uint64_t id, const int32_t index, |
186 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_remove__result_s)) { |
187 | return exclaves_driverkit_upcall_irq_remove(id, index, completion); |
188 | }, |
189 | |
190 | .irq_enable = ^(const uint64_t id, const int32_t index, |
191 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_enable__result_s)) { |
192 | return exclaves_driverkit_upcall_irq_enable(id, index, completion); |
193 | }, |
194 | |
195 | .irq_disable = ^(const uint64_t id, const int32_t index, |
196 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_irq_disable__result_s)) { |
197 | return exclaves_driverkit_upcall_irq_disable(id, index, completion); |
198 | }, |
199 | |
200 | .timer_register = ^(const uint64_t id, |
201 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_register__result_s)) { |
202 | return exclaves_driverkit_upcall_timer_register(id, completion); |
203 | }, |
204 | |
205 | .timer_remove = ^(const uint64_t id, const uint32_t timer_id, |
206 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_remove__result_s)) { |
207 | return exclaves_driverkit_upcall_timer_remove(id, timer_id, completion); |
208 | }, |
209 | |
210 | .timer_enable = ^(const uint64_t id, const uint32_t timer_id, |
211 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_enable__result_s)) { |
212 | return exclaves_driverkit_upcall_timer_enable(id, timer_id, completion); |
213 | }, |
214 | |
215 | .timer_disable = ^(const uint64_t id, const uint32_t timer_id, |
216 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_disable__result_s)) { |
217 | return exclaves_driverkit_upcall_timer_disable(id, timer_id, completion); |
218 | }, |
219 | |
220 | .timer_set_timeout = ^(const uint64_t id, const uint32_t timer_id, |
221 | const struct xnuupcalls_drivertimerspecification_s *duration, |
222 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_set_timeout__result_s)) { |
223 | return exclaves_driverkit_upcall_timer_set_timeout(id, timer_id, duration, completion); |
224 | }, |
225 | |
226 | .timer_cancel_timeout = ^(const uint64_t id, const uint32_t timer_id, |
227 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_timer_cancel_timeout__result_s)) { |
228 | return exclaves_driverkit_upcall_timer_cancel_timeout(id, timer_id, completion); |
229 | }, |
230 | |
231 | .lock_wl = ^(const uint64_t id, |
232 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_lock_wl__result_s)) { |
233 | return exclaves_driverkit_upcall_lock_wl(id, completion); |
234 | }, |
235 | |
236 | .unlock_wl = ^(const uint64_t id, |
237 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_unlock_wl__result_s)) { |
238 | return exclaves_driverkit_upcall_unlock_wl(id, completion); |
239 | }, |
240 | |
241 | .async_notification_signal = ^(const uint64_t id, |
242 | const uint32_t notificationID, |
243 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_async_notification_signal__result_s)) { |
244 | return exclaves_driverkit_upcall_async_notification_signal(id, |
245 | notificationID, completion); |
246 | }, |
247 | |
248 | .mapper_activate = ^(const uint64_t id, const uint32_t mapperIndex, |
249 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_mapper_activate__result_s)) { |
250 | return exclaves_driverkit_upcall_mapper_activate(id, |
251 | mapperIndex, completion); |
252 | }, |
253 | |
254 | .mapper_deactivate = ^(const uint64_t id, const uint32_t mapperIndex, |
255 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_mapper_deactivate__result_s)) { |
256 | return exclaves_driverkit_upcall_mapper_deactivate(id, |
257 | mapperIndex, completion); |
258 | }, |
259 | |
260 | .notification_signal = ^(const uint64_t id, const uint32_t mask, |
261 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_notification_signal__result_s)) { |
262 | return exclaves_driverkit_upcall_notification_signal(id, mask, |
263 | completion); |
264 | }, |
265 | |
266 | .ane_setpowerstate = ^(const uint64_t id, const uint32_t desiredState, |
267 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_setpowerstate__result_s)) { |
268 | return exclaves_driverkit_upcall_ane_setpowerstate(id, desiredState, |
269 | completion); |
270 | }, |
271 | |
272 | .ane_worksubmit = ^(const uint64_t id, const uint64_t requestID, |
273 | const uint32_t taskDescriptorCount, const uint64_t submitTimestamp, |
274 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_worksubmit__result_s)) { |
275 | return exclaves_driverkit_upcall_ane_worksubmit(id, requestID, |
276 | taskDescriptorCount, submitTimestamp, completion); |
277 | }, |
278 | |
279 | .ane_workbegin = ^(const uint64_t id, const uint64_t requestID, |
280 | const uint64_t beginTimestamp, |
281 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_workbegin__result_s)) { |
282 | return exclaves_driverkit_upcall_ane_workbegin(id, requestID, |
283 | beginTimestamp, completion); |
284 | }, |
285 | |
286 | .ane_workend = ^(const uint64_t id, const uint64_t requestID, |
287 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_ane_workend__result_s)) { |
288 | return exclaves_driverkit_upcall_ane_workend(id, requestID, completion); |
289 | }, |
290 | |
291 | .conclave_suspend = ^(const uint32_t flags, |
292 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_suspend__result_s)) { |
293 | return exclaves_conclave_upcall_suspend(flags, completion); |
294 | }, |
295 | |
296 | .conclave_stop = ^(const uint32_t flags, |
297 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_stop__result_s)) { |
298 | return exclaves_conclave_upcall_stop(flags, completion); |
299 | }, |
300 | .conclave_crash_info = ^(const xnuupcalls_conclavesharedbuffer_s *shared_buf, |
301 | const uint32_t length, |
302 | tb_error_t (^completion)(xnuupcalls_xnuupcalls_conclave_crash_info__result_s)) { |
303 | return exclaves_conclave_upcall_crash_info(shared_buf, length, completion); |
304 | }, |
305 | /* END IGNORE CODESTYLE */ |
306 | }; |
307 | |
308 | kern_return_t |
309 | exclaves_register_upcall_handler(exclaves_id_t upcall_id, void *upcall_context, |
310 | exclaves_upcall_handler_t upcall_handler) |
311 | { |
312 | assert3u(upcall_id, <, NUM_XNUPROXY_UPCALLS); |
313 | assert(upcall_handler != NULL); |
314 | |
315 | lck_mtx_assert(&exclaves_boot_lock, LCK_MTX_ASSERT_OWNED); |
316 | assert(exclaves_upcall_handlers[upcall_id].handler == NULL); |
317 | |
318 | exclaves_upcall_handlers[upcall_id] = |
319 | (exclaves_upcall_handler_registration_t){ |
320 | .handler = upcall_handler, |
321 | .context = upcall_context, |
322 | }; |
323 | |
324 | return KERN_SUCCESS; |
325 | } |
326 | |
327 | kern_return_t |
328 | exclaves_upcall_early_init(void) |
329 | { |
330 | lck_mtx_assert(&exclaves_boot_lock, LCK_MTX_ASSERT_OWNED); |
331 | |
332 | #if DEVELOPMENT || DEBUG |
333 | kern_return_t kr; |
334 | kr = exclaves_register_upcall_handler( |
335 | XNUPROXY_UPCALL_HELLOUPCALL, NULL, |
336 | exclaves_test_hello_upcall_handler); |
337 | assert3u(kr, ==, KERN_SUCCESS); |
338 | #endif /* DEVELOPMENT || DEBUG */ |
339 | |
340 | tb_endpoint_t tb_upcall_ep = tb_endpoint_create_with_value( |
341 | TB_TRANSPORT_TYPE_XNU, EXCLAVES_ID_TIGHTBEAM_UPCALL, |
342 | TB_ENDPOINT_OPTIONS_NONE); |
343 | #pragma clang diagnostic push |
344 | #pragma clang diagnostic ignored "-Wcast-qual" /* FIXME: rdar://103647654 */ |
345 | tb_error_t error = xnuupcalls_xnuupcalls__server_start(tb_upcall_ep, |
346 | (xnuupcalls_xnuupcalls__server_s *)&exclaves_tightbeam_upcalls); |
347 | #pragma clang diagnostic pop |
348 | |
349 | return error == TB_ERROR_SUCCESS ? KERN_SUCCESS : KERN_FAILURE; |
350 | } |
351 | |
352 | static kern_return_t |
353 | exclaves_upcall_init(void) |
354 | { |
355 | lck_mtx_assert(&exclaves_boot_lock, LCK_MTX_ASSERT_OWNED); |
356 | |
357 | #if XNUPROXY_MSG_VERSION >= 2 |
358 | kern_return_t kkr; |
359 | xnuproxy_msg_t msg = { |
360 | .cmd = XNUPROXY_CMD_UPCALL_READY, |
361 | }; |
362 | kkr = exclaves_xnu_proxy_send(&msg, NULL); |
363 | assert3u(kkr, ==, KERN_SUCCESS); |
364 | #endif /* XNUPROXY_MSG_VERSION >= 2 */ |
365 | |
366 | return kkr; |
367 | } |
368 | |
369 | EXCLAVES_BOOT_TASK(exclaves_upcall_init, EXCLAVES_BOOT_RANK_FIRST); |
370 | |
371 | OS_NOINLINE |
372 | kern_return_t |
373 | exclaves_call_upcall_handler(exclaves_id_t upcall_id) |
374 | { |
375 | kern_return_t kr = KERN_INVALID_CAPABILITY; |
376 | |
377 | __assert_only thread_t thread = current_thread(); |
378 | assert3u(thread->th_exclaves_state & TH_EXCLAVES_UPCALL, !=, 0); |
379 | |
380 | exclaves_tag_t tag = Exclaves_L4_GetMessageTag(); |
381 | |
382 | Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer(); |
383 | exclaves_badge_t badge = XNUPROXY_CR_UPCALL_BADGE(ipcb); |
384 | |
385 | exclaves_upcall_handler_registration_t upcall_handler = {}; |
386 | |
387 | if (upcall_id < NUM_XNUPROXY_UPCALLS) { |
388 | upcall_handler = exclaves_upcall_handlers[upcall_id]; |
389 | } |
390 | if (upcall_handler.handler) { |
391 | kr = upcall_handler.handler(upcall_handler.context, &tag, badge); |
392 | Exclaves_L4_SetMessageTag(tag); |
393 | } |
394 | |
395 | return kr; |
396 | } |
397 | |
398 | /* -------------------------------------------------------------------------- */ |
399 | #pragma mark Testing |
400 | |
401 | |
402 | static tb_error_t |
403 | exclaves_helloupcall(const uint64_t arg, tb_error_t (^completion)(uint64_t)) |
404 | { |
405 | #if DEVELOPMENT || DEBUG |
406 | exclaves_debug_printf(show_test_output, |
407 | "%s: Hello Tightbeam Upcall!\n" , __func__); |
408 | tb_error_t ret = completion(~arg); |
409 | STACKSHOT_TESTPOINT(TP_UPCALL); |
410 | /* Emit kdebug event for kperf sampling testing */ |
411 | KDBG(BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 0xaa)); |
412 | return ret; |
413 | #else |
414 | (void)arg; |
415 | (void)completion; |
416 | |
417 | return TB_ERROR_SUCCESS; |
418 | #endif /* DEVELOPMENT || DEBUG */ |
419 | } |
420 | |
421 | #if DEVELOPMENT || DEBUG |
422 | |
423 | static kern_return_t |
424 | exclaves_test_upcall_handler(void *context, exclaves_tag_t *tag, |
425 | exclaves_badge_t badge) |
426 | { |
427 | #pragma unused(context, badge) |
428 | Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer(); |
429 | assert(ipcb != NULL); |
430 | |
431 | Exclaves_L4_Word_t mrs = Exclaves_L4_MessageTag_Mrs(*tag); |
432 | assert(mrs < Exclaves_L4_IpcBuffer_Mrs); |
433 | Exclaves_L4_Word_t crs = Exclaves_L4_MessageTag_Crs(*tag); |
434 | assert(crs == 0); |
435 | Exclaves_L4_Word_t label = Exclaves_L4_MessageTag_Label(*tag); |
436 | |
437 | /* setup test reply message */ |
438 | *tag = Exclaves_L4_MessageTag(mrs, 0, ~label, Exclaves_L4_False); |
439 | for (int i = 0; i < mrs; i++) { |
440 | Exclaves_L4_SetMessageMr(i, ~Exclaves_L4_GetMessageMr(i)); |
441 | } |
442 | |
443 | return KERN_SUCCESS; |
444 | } |
445 | |
446 | static int |
447 | exclaves_hello_upcall_test(__unused int64_t in, int64_t *out) |
448 | { |
449 | kern_return_t kr = KERN_SUCCESS; |
450 | |
451 | if (exclaves_get_status() != EXCLAVES_STATUS_AVAILABLE) { |
452 | exclaves_debug_printf(show_test_output, |
453 | "%s: SKIPPED: Exclaves not available\n" , __func__); |
454 | *out = -1; |
455 | return 0; |
456 | } |
457 | |
458 | exclaves_debug_printf(show_test_output, "%s: STARTING\n" , __func__); |
459 | |
460 | Exclaves_L4_IpcBuffer_t *ipcb; |
461 | kr = exclaves_allocate_ipc_buffer((void**)&ipcb); |
462 | assert(kr == KERN_SUCCESS); |
463 | assert(ipcb != NULL); |
464 | |
465 | const Exclaves_L4_Word_t request = 0xdecafbadfeedfaceul; |
466 | Exclaves_L4_SetMessageMr(0, request); |
467 | exclaves_tag_t tag = Exclaves_L4_MessageTag(1, 0, 0x1330ul, |
468 | Exclaves_L4_False); |
469 | |
470 | exclaves_debug_printf(show_test_output, |
471 | "exclaves: exclaves_endpoint_call() sending request 0x%lx, " |
472 | "tag 0x%llx, label 0x%lx\n" , request, tag, |
473 | Exclaves_L4_MessageTag_Label(tag)); |
474 | |
475 | exclaves_error_t error; |
476 | kr = exclaves_endpoint_call(IPC_PORT_NULL, EXCLAVES_ID_HELLO_EXCLAVE_EP, |
477 | &tag, &error); |
478 | assert(kr == KERN_SUCCESS); |
479 | |
480 | Exclaves_L4_Word_t reply = Exclaves_L4_GetMessageMr(0); |
481 | exclaves_debug_printf(show_test_output, |
482 | "exclaves: exclaves_endpoint_call() returned reply 0x%lx, " |
483 | "tag 0x%llx, label 0x%lx, error 0x%llx\n" , reply, tag, |
484 | Exclaves_L4_MessageTag_Label(tag), error); |
485 | |
486 | assert(error == Exclaves_L4_Success); |
487 | assert(Exclaves_L4_MessageTag_Mrs(tag) == 1); |
488 | assert(reply == ((request >> 32) | (request << 32))); |
489 | assert((uint16_t)Exclaves_L4_MessageTag_Label(tag) == (uint16_t)0x1331ul); |
490 | |
491 | kr = exclaves_free_ipc_buffer(); |
492 | assert(kr == KERN_SUCCESS); |
493 | |
494 | exclaves_debug_printf(show_test_output, "%s: SUCCESS\n" , __func__); |
495 | *out = 1; |
496 | |
497 | return 0; |
498 | } |
499 | SYSCTL_TEST_REGISTER(exclaves_hello_upcall_test, exclaves_hello_upcall_test); |
500 | |
501 | static kern_return_t |
502 | exclaves_test_hello_upcall_handler(void *context, exclaves_tag_t *tag, |
503 | exclaves_badge_t badge) |
504 | { |
505 | /* HelloUpcall test handler */ |
506 | assert(context == NULL); |
507 | exclaves_debug_printf(show_test_output, "%s: Hello Upcall!\n" , __func__); |
508 | task_stop_conclave_upcall(); |
509 | STACKSHOT_TESTPOINT(TP_UPCALL); |
510 | /* Emit kdebug event for kperf sampling testing */ |
511 | KDBG(BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 0xaa)); |
512 | return exclaves_test_upcall_handler(context, tag, badge); |
513 | } |
514 | #endif /* DEVELOPMENT || DEBUG */ |
515 | |
516 | #endif /* __has_include(<Tightbeam/tightbeam.h>) */ |
517 | |
518 | #else /* CONFIG_EXCLAVES */ |
519 | |
520 | kern_return_t |
521 | exclaves_call_upcall_handler(exclaves_id_t upcall_id) |
522 | { |
523 | (void)upcall_id; |
524 | return KERN_NOT_SUPPORTED; |
525 | } |
526 | |
527 | kern_return_t |
528 | exclaves_register_upcall_handler(exclaves_id_t upcall_id, void *upcall_context, |
529 | exclaves_upcall_handler_t upcall_handler) |
530 | { |
531 | (void)upcall_id; |
532 | (void)upcall_context; |
533 | (void)upcall_handler; |
534 | |
535 | return KERN_NOT_SUPPORTED; |
536 | } |
537 | |
538 | #endif /* CONFIG_EXCLAVES */ |
539 | |