2 * \brief Monitor's connection with the dispatchers on the same core
6 * Copyright (c) 2009, 2010, 2011, 2013, ETH Zurich.
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
15 #include <barrelfish/cap_predicates.h>
16 #include <barrelfish/debug.h> // XXX: To set the cap_identify_reply handler
17 #include <barrelfish/sys_debug.h> // XXX: for sys_debug_send_ipi
18 #include <trace/trace.h>
19 #include <trace_definitions/trace_defs.h>
20 #include <if/mem_defs.h>
21 #include <if/proc_mgmt_defs.h>
22 #include <barrelfish/monitor_client.h>
23 #include <barrelfish/proc_mgmt_client.h>
24 #include <barrelfish/syscalls.h>
25 #include <barrelfish_kpi/distcaps.h>
26 #include <if/monitor_loopback_defs.h>
31 // the monitor's loopback binding to itself
32 static struct monitor_binding monitor_self_binding;
34 /* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */
36 struct multiboot_cap_state {
37 struct monitor_msg_queue_elem elem;
41 struct proc_mgmt_bind_st {
46 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot);
48 static void ms_multiboot_cap_request_handler(struct monitor_binding *b,
49 struct monitor_msg_queue_elem *e)
51 struct multiboot_cap_state *ms = (struct multiboot_cap_state*)e;
52 ms_multiboot_cap_request(b, ms->slot);
56 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot)
61 .cnode = cnode_module,
65 // Call frame_identify to check if cap exists
66 struct frame_identity id;
67 err1 = invoke_frame_identify(cap, &id);
68 if (err_is_fail(err1)) {
69 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, NULL_CAP, err1);
71 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1);
73 if (err_is_fail(err2)) {
74 if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
75 struct monitor_state *mon_state = b->st;
76 struct multiboot_cap_state *ms =
77 malloc(sizeof(struct multiboot_cap_state));
80 ms->elem.cont = ms_multiboot_cap_request_handler;
81 err1 = monitor_enqueue_send(b, &mon_state->queue,
82 get_default_waitset(), &ms->elem.queue);
83 if (err_is_fail(err1)) {
84 USER_PANIC_ERR(err1, "monitor_enqueue_send failed");
87 USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed");
92 /* ----------------------- MULTIBOOT REQUEST CODE END ----------------------- */
94 static void alloc_iref_reply_handler(struct monitor_binding *b,
95 struct monitor_msg_queue_elem *e);
97 struct alloc_iref_reply_state {
98 struct monitor_msg_queue_elem elem;
99 struct monitor_alloc_iref_reply__tx_args args;
100 struct monitor_binding *b;
103 static void alloc_iref_reply_cont(struct monitor_binding *b,
104 uintptr_t service_id,
105 iref_t iref, errval_t reterr)
109 err = b->tx_vtbl.alloc_iref_reply(b, NOP_CONT, service_id, iref, reterr);
110 if (err_is_fail(err)) {
111 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
112 struct alloc_iref_reply_state *me =
113 malloc(sizeof(struct alloc_iref_reply_state));
115 struct monitor_state *ist = b->st;
117 me->args.service_id = service_id;
118 me->args.iref = iref;
119 me->args.err = reterr;
121 me->elem.cont = alloc_iref_reply_handler;
123 err = monitor_enqueue_send(b, &ist->queue,
124 get_default_waitset(), &me->elem.queue);
125 if (err_is_fail(err)) {
126 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
131 USER_PANIC_ERR(err, "reply failed");
135 static void alloc_iref_reply_handler(struct monitor_binding *b,
136 struct monitor_msg_queue_elem *e)
138 struct alloc_iref_reply_state *st = (struct alloc_iref_reply_state *)e;
139 alloc_iref_reply_cont(b, st->args.service_id, st->args.iref,
144 static void alloc_iref_request(struct monitor_binding *b,
145 uintptr_t service_id)
150 reterr = iref_alloc(b, service_id, &iref);
151 alloc_iref_reply_cont(b, service_id, iref, reterr);
155 static void get_service_id_reply_handler(struct monitor_binding *b,
156 struct monitor_msg_queue_elem *e);
158 struct get_service_id_reply_state {
159 struct monitor_msg_queue_elem elem;
160 struct monitor_get_service_id_reply__tx_args args;
161 struct monitor_binding *b;
164 static void get_service_id_reply_cont(struct monitor_binding *b, errval_t reterr,
165 iref_t iref, uintptr_t service_id)
169 err = b->tx_vtbl.get_service_id_reply(b, NOP_CONT, reterr, iref, service_id);
170 if (err_is_fail(err)) {
171 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
172 struct get_service_id_reply_state *me =
173 malloc(sizeof(struct get_service_id_reply_state));
175 struct monitor_state *ist = b->st;
177 me->args.err = reterr;
178 me->args.iref = iref;
179 me->args.service_id = service_id;
181 me->elem.cont = get_service_id_reply_handler;
183 err = monitor_enqueue_send(b, &ist->queue,
184 get_default_waitset(), &me->elem.queue);
185 if (err_is_fail(err)) {
186 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
191 USER_PANIC_ERR(err, "reply failed");
195 static void get_service_id_reply_handler(struct monitor_binding *b,
196 struct monitor_msg_queue_elem *e)
198 struct get_service_id_reply_state *st = (struct get_service_id_reply_state *)e;
199 get_service_id_reply_cont(b, st->args.err, st->args.iref, st->args.service_id);
203 static void get_service_id_request(struct monitor_binding *b, iref_t iref)
206 struct monitor_binding *serv_binding = NULL;
208 /* Look up core_id from the iref */
210 iref_get_core_id(iref, &core_id);
212 // Return error if service on different core
213 if (core_id != my_core_id) {
214 get_service_id_reply_cont(b, MON_ERR_IDC_BIND_NOT_SAME_CORE, iref, 0);
218 /* Lookup the server's connection to monitor */
219 err = iref_get_binding(iref, &serv_binding);
220 if (err_is_fail(err)) {
221 get_service_id_reply_cont(b, err, iref, 0);
225 /* Lookup the server's service_id */
226 uintptr_t service_id;
227 err = iref_get_service_id(iref, &service_id);
228 get_service_id_reply_cont(b, err, iref, service_id);
231 /******* stack-ripped bind_lmp_service_request *******/
233 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
234 struct monitor_msg_queue_elem *e);
236 struct bind_lmp_client_request_error_state {
237 struct monitor_msg_queue_elem elem;
238 struct monitor_bind_lmp_reply_client__tx_args args;
239 struct monitor_binding *serv_binding;
243 static void bind_lmp_client_request_error(struct monitor_binding *b,
244 errval_t err, uintptr_t domain_id,
245 struct monitor_binding *serv_binding,
250 err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id,
252 if (err_is_fail(err2)) {
253 if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
254 struct bind_lmp_client_request_error_state *me =
255 malloc(sizeof(struct bind_lmp_client_request_error_state));
257 struct monitor_state *ist = b->st;
260 me->args.conn_id = domain_id;
261 me->serv_binding = serv_binding;
263 me->elem.cont = bind_lmp_client_request_error_handler;
265 err = monitor_enqueue_send(b, &ist->queue,
266 get_default_waitset(), &me->elem.queue);
267 if (err_is_fail(err)) {
268 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
273 USER_PANIC_ERR(err2, "error reply failed");
274 USER_PANIC_ERR(err, "The reason for lmp failure");
277 /* Delete the EP cap */
278 // Do not delete the cap if client or service is monitor itself
279 if (b != &monitor_self_binding && serv_binding != &monitor_self_binding) {
280 err = cap_destroy(ep);
281 if (err_is_fail(err)) {
282 USER_PANIC_ERR(err, "cap_destroy failed");
287 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
288 struct monitor_msg_queue_elem *e)
290 struct bind_lmp_client_request_error_state *st = (struct bind_lmp_client_request_error_state *)e;
291 bind_lmp_client_request_error(b, st->args.err, st->args.conn_id,
292 st->serv_binding, st->ep);
296 static void bind_lmp_service_request_handler(struct monitor_binding *b,
297 struct monitor_msg_queue_elem *e);
299 struct bind_lmp_service_request_state {
300 struct monitor_msg_queue_elem elem;
301 struct monitor_bind_lmp_service_request__tx_args args;
302 struct monitor_binding *b;
306 static void bind_lmp_service_request_cont(struct monitor_binding *serv_binding,
307 uintptr_t service_id, uintptr_t con_id,
308 size_t buflen, struct capref ep,
309 struct monitor_binding *b,
314 struct monitor_state *ist = serv_binding->st;
315 struct event_closure send_cont = NOP_CONT;
316 struct capref *capp = NULL;
318 if (serv_binding != &monitor_self_binding && b != &monitor_self_binding) {
319 // save EP cap to be destroyed after the send is done
320 capp = caprefdup(ep);
321 send_cont = MKCONT(destroy_outgoing_cap, capp);
324 err = serv_binding->tx_vtbl.
325 bind_lmp_service_request(serv_binding, send_cont, service_id,
327 if (err_is_fail(err)) {
330 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
331 struct bind_lmp_service_request_state *me =
332 malloc(sizeof(struct bind_lmp_service_request_state));
334 me->args.service_id = service_id;
335 me->args.mon_id = con_id;
336 me->args.buflen = buflen;
339 me->domain_id = domain_id;
340 me->elem.cont = bind_lmp_service_request_handler;
342 err = monitor_enqueue_send(serv_binding, &ist->queue,
343 get_default_waitset(), &me->elem.queue);
344 if (err_is_fail(err)) {
345 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
350 err2 = lmp_conn_free(con_id);
351 if (err_is_fail(err2)) {
352 USER_PANIC_ERR(err2, "lmp_conn_free failed");
354 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
359 static void bind_lmp_service_request_handler(struct monitor_binding *b,
360 struct monitor_msg_queue_elem *e)
362 struct bind_lmp_service_request_state *st = (struct bind_lmp_service_request_state *)e;
363 bind_lmp_service_request_cont(b, st->args.service_id, st->args.mon_id,
364 st->args.buflen, st->args.ep, st->b,
369 static void bind_lmp_client_request(struct monitor_binding *b,
370 iref_t iref, uintptr_t domain_id,
371 size_t buflen, struct capref ep)
374 struct monitor_binding *serv_binding = NULL;
376 /* Look up core_id from the iref */
378 err = iref_get_core_id(iref, &core_id);
379 if (err_is_fail(err)) {
380 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
384 // Return error if service on different core
385 if (core_id != my_core_id) {
386 err = MON_ERR_IDC_BIND_NOT_SAME_CORE;
387 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
391 /* Lookup the server's connection to monitor */
392 err = iref_get_binding(iref, &serv_binding);
393 if (err_is_fail(err)) {
394 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
398 /* Lookup the server's service_id */
399 uintptr_t service_id;
400 err = iref_get_service_id(iref, &service_id);
401 if (err_is_fail(err)) {
402 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
406 /* Check for intra-domain connection */
407 if (b == serv_binding) {
408 bind_lmp_client_request_error(b, MON_ERR_IDC_BIND_LOCAL, domain_id, serv_binding, ep);
412 /* Allocate a new monitor connection */
414 struct lmp_conn_state *conn;
415 err = lmp_conn_alloc(&conn, &con_id);
416 if (err_is_fail(err)) {
417 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
421 conn->domain_id = domain_id;
422 conn->domain_binding = b;
424 /* Send request to the server */
425 bind_lmp_service_request_cont(serv_binding, service_id, con_id, buflen, ep,
429 /******* stack-ripped bind_lmp_reply *******/
431 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
432 struct monitor_msg_queue_elem *e);
434 struct bind_lmp_reply_client_state {
435 struct monitor_msg_queue_elem elem;
436 struct monitor_bind_lmp_reply_client__tx_args args;
437 struct monitor_binding *b;
440 static void bind_lmp_reply_client_cont(struct monitor_binding *client_binding,
441 errval_t msgerr, uintptr_t mon_conn_id,
442 uintptr_t client_conn_id,
444 struct monitor_binding *b)
448 struct monitor_state *ist = client_binding->st;
449 struct event_closure send_cont = NOP_CONT;
450 struct capref *capp = NULL;
452 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
453 // save EP cap to be destroyed after the send is done
454 capp = caprefdup(ep);
455 send_cont = MKCONT(destroy_outgoing_cap, capp);
458 err = client_binding->tx_vtbl.
459 bind_lmp_reply_client(client_binding, send_cont,
460 SYS_ERR_OK, mon_conn_id, client_conn_id, ep);
461 if (err_is_fail(err)) {
464 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
465 struct bind_lmp_reply_client_state *me =
466 malloc(sizeof(struct bind_lmp_reply_client_state));
468 me->args.err = msgerr;
469 me->args.mon_id = mon_conn_id;
470 me->args.conn_id = client_conn_id;
473 me->elem.cont = bind_lmp_reply_client_handler;
475 err = monitor_enqueue_send(client_binding, &ist->queue,
476 get_default_waitset(), &me->elem.queue);
477 if (err_is_fail(err)) {
478 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
483 USER_PANIC_ERR(err, "failed sending IDC bind reply");
486 if(err_is_fail(msgerr)) {
491 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
492 struct monitor_msg_queue_elem *e)
494 struct bind_lmp_reply_client_state *st = (struct bind_lmp_reply_client_state *)e;
495 bind_lmp_reply_client_cont(b, st->args.err, st->args.mon_id, st->args.conn_id,
500 static void bind_lmp_reply(struct monitor_binding *b,
501 errval_t msgerr, uintptr_t mon_conn_id,
502 uintptr_t user_conn_id, struct capref ep)
505 struct monitor_binding *client_binding = NULL;
507 struct lmp_conn_state *conn = lmp_conn_lookup(mon_conn_id);
509 DEBUG_ERR(0, "invalid connection ID");
513 client_binding = conn->domain_binding;
514 uintptr_t client_conn_id = conn->domain_id;
516 err = lmp_conn_free(mon_conn_id);
517 assert(err_is_ok(err));
519 if (err_is_fail(msgerr)) {
520 bind_lmp_reply_client_cont(client_binding, msgerr, 0, client_conn_id,
523 bind_lmp_reply_client_cont(client_binding, SYS_ERR_OK, mon_conn_id,
524 client_conn_id, ep, b);
529 /* Delete the ep cap */
530 // XXX: Do not delete the cap if client or service is monitor
531 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
532 err = cap_destroy(ep);
533 if (err_is_fail(err)) {
534 USER_PANIC_ERR(err, "cap_destroy failed");
539 /* ---------------------- NEW MONITOR BINDING CODE START -------------------- */
541 struct new_monitor_binding_reply_state {
542 struct monitor_msg_queue_elem elem;
543 struct monitor_new_monitor_binding_reply__tx_args args;
547 new_monitor_binding_reply_cont(struct monitor_binding *b,
548 errval_t reterr, struct capref retcap,
551 static void new_monitor_binding_reply_handler(struct monitor_binding *b,
552 struct monitor_msg_queue_elem *e)
554 struct new_monitor_binding_reply_state *st =
555 (struct new_monitor_binding_reply_state *)e;
556 new_monitor_binding_reply_cont(b, st->args.err, st->args.ep, st->args.st);
561 new_monitor_binding_reply_cont(struct monitor_binding *b,
562 errval_t reterr, struct capref retcap,
566 b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st);
568 if (err_is_fail(err)) {
569 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
570 struct monitor_state *ms = b->st;
571 struct new_monitor_binding_reply_state *me =
572 malloc(sizeof(struct new_monitor_binding_reply_state));
574 me->args.err = reterr;
575 me->args.ep = retcap;
577 me->elem.cont = new_monitor_binding_reply_handler;
578 err = monitor_enqueue_send(b, &ms->queue,
579 get_default_waitset(), &me->elem.queue);
580 if (err_is_fail(err)) {
581 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
586 USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply");
591 * \brief Setup a new idc channel between monitor and domain
593 * \bug on error send message back to domain
595 static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st)
597 struct capref retcap = NULL_CAP;
598 errval_t err, reterr = SYS_ERR_OK;
600 struct monitor_lmp_binding *lmpb =
601 malloc(sizeof(struct monitor_lmp_binding));
602 assert(lmpb != NULL);
604 // setup our end of the binding
605 err = monitor_client_lmp_accept(lmpb, get_default_waitset(),
606 DEFAULT_LMP_BUF_WORDS);
607 if (err_is_fail(err)) {
609 reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
613 retcap = lmpb->chan.local_cap;
614 monitor_server_init(&lmpb->b);
617 new_monitor_binding_reply_cont(b, reterr, retcap, st);
620 /* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */
622 static void get_mem_iref_request(struct monitor_binding *b)
626 // Mem serv not registered yet
627 assert(mem_serv_iref != 0);
629 err = b->tx_vtbl.get_mem_iref_reply(b, NOP_CONT, mem_serv_iref);
630 if (err_is_fail(err)) {
631 USER_PANIC_ERR(err, "reply failed");
635 static void get_name_iref_request(struct monitor_binding *b, uintptr_t st)
638 err = b->tx_vtbl.get_name_iref_reply(b, NOP_CONT, name_serv_iref, st);
639 if (err_is_fail(err)) {
640 USER_PANIC_ERR(err, "reply failed");
644 static void get_ramfs_iref_request(struct monitor_binding *b, uintptr_t st)
647 err = b->tx_vtbl.get_ramfs_iref_reply(b, NOP_CONT, ramfs_serv_iref, st);
648 if (err_is_fail(err)) {
649 USER_PANIC_ERR(err, "reply failed");
653 static void set_mem_iref_request(struct monitor_binding *b,
656 mem_serv_iref = iref;
657 update_ram_alloc_binding = true;
660 static void get_monitor_rpc_iref_request(struct monitor_binding *b,
665 if (monitor_rpc_iref == 0) {
666 // Monitor rpc not registered yet
667 DEBUG_ERR(LIB_ERR_GET_MON_BLOCKING_IREF, "got monitor rpc iref request but iref is 0");
670 err = b->tx_vtbl.get_monitor_rpc_iref_reply(b, NOP_CONT,
671 monitor_rpc_iref, st_arg);
672 if (err_is_fail(err)) {
673 USER_PANIC_ERR(err, "reply failed");
678 void set_monitor_rpc_iref(iref_t iref)
680 if (monitor_rpc_iref != 0) {
681 // Called multiple times, return error
682 DEBUG_ERR(0, "Attempt to reset monitor rpc IREF ignored");
686 monitor_rpc_iref = iref;
690 static void set_name_iref_request(struct monitor_binding *b,
693 if (name_serv_iref != 0) {
694 // Called multiple times, return error
695 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
699 name_serv_iref = iref;
702 static void set_ramfs_iref_request(struct monitor_binding *b,
705 if (ramfs_serv_iref != 0) {
706 // Called multiple times, return error
707 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
711 ramfs_serv_iref = iref;
714 static void proc_mgmt_bind_cont(void *st,
716 struct proc_mgmt_binding *b)
718 struct proc_mgmt_bind_st* bind_st = (struct proc_mgmt_bind_st*) st;
719 assert(!bind_st->present);
721 bind_st->present = true;
724 static void set_proc_mgmt_ep_request(struct monitor_binding *b,
727 // We got the endpoint which the process manager has allocated for us.
728 // Time to set up our part of the LMP connection and finish the handshake.
729 struct proc_mgmt_lmp_binding *lmpb =
730 malloc(sizeof(struct proc_mgmt_lmp_binding));
731 assert(lmpb != NULL);
733 set_proc_mgmt_binding(&lmpb->b);
735 struct proc_mgmt_bind_st bind_st = {
738 errval_t err = proc_mgmt_client_lmp_bind(lmpb,
742 get_default_waitset(),
743 DEFAULT_LMP_BUF_WORDS);
744 if (err_is_fail(err)) {
745 USER_PANIC_ERR(err, "proc_mgmt_client_lmp_bind");
748 // Dispatch events on the waitset until proc_mgmt binding completes.
749 while (!bind_st.present) {
750 err = event_dispatch(get_default_waitset());
751 if (err_is_fail(err)) {
752 USER_PANIC_ERR(err, "monitor event dispatch");
756 if(err_is_fail(bind_st.err)) {
757 USER_PANIC_ERR(err, "during proc_mgmt bind initialization");
760 proc_mgmt_rpc_client_init(&lmpb->b);
763 static void set_spawn_iref_request(struct monitor_binding *b, iref_t iref)
765 if (spawn_iref != 0) {
766 // Called multiple times, return error
767 DEBUG_ERR(0, "Attempt to reset spawn IREF ignored");
775 struct intermon_msg_queue_elem qe; // must be first
780 struct captx_prepare_state captx_state;
781 intermon_captx_t captx;
785 cap_send_tx_cont(struct intermon_binding *b,
786 struct intermon_msg_queue_elem *e)
788 DEBUG_CAPOPS("%s: %p %p\n", __FUNCTION__, b, e);
790 struct send_cap_st *st = (struct send_cap_st*)e;
791 struct remote_conn_state *conn = remote_conn_lookup(st->my_mon_id);
792 send_err = intermon_cap_send_request__tx(b, NOP_CONT, conn->mon_id,
793 st->capid, st->captx);
794 if (err_is_fail(send_err)) {
795 DEBUG_ERR(send_err, "sending cap_send_request failed");
801 cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st,
802 intermon_captx_t *captx, void *st_)
804 DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0));
806 struct send_cap_st *send_st = (struct send_cap_st*)st_;
808 if (err_is_fail(err)) {
809 // XXX: should forward error here
810 DEBUG_ERR(err, "preparing cap tx failed");
815 send_st->captx = *captx;
817 DEBUG_CAPOPS("%s: enqueueing send\n", __FUNCTION__);
818 send_st->qe.cont = cap_send_tx_cont;
819 struct remote_conn_state *conn = remote_conn_lookup(send_st->my_mon_id);
820 struct intermon_binding *binding = conn->mon_binding;
821 struct intermon_state *inter_st = (struct intermon_state*)binding->st;
822 queue_err = intermon_enqueue_send(binding, &inter_st->queue,
824 (struct msg_queue_elem*)send_st);
825 if (err_is_fail(queue_err)) {
826 DEBUG_ERR(queue_err, "enqueuing cap_send_request failed");
832 cap_send_request(struct monitor_binding *b, uintptr_t my_mon_id,
833 struct capref cap, uint32_t capid)
835 DEBUG_CAPOPS("cap_send_request\n");
837 struct remote_conn_state *conn = remote_conn_lookup(my_mon_id);
839 struct send_cap_st *st;
840 st = calloc(1, sizeof(*st));
842 err = LIB_ERR_MALLOC_FAIL;
843 DEBUG_ERR(err, "Failed to allocate cap_send_request state");
844 // XXX: should forward error here
847 st->my_mon_id = my_mon_id;
851 captx_prepare_send(cap, conn->core_id, true, &st->captx_state,
852 cap_send_request_tx_cont, st);
855 static void span_domain_request(struct monitor_binding *mb,
856 uintptr_t domain_id, uint8_t core_id,
857 struct capref vroot, struct capref disp)
861 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN0, core_id);
863 struct span_state *state;
866 err = span_state_alloc(&state, &state_id);
867 if (err_is_fail(err)) {
868 err_push(err, MON_ERR_SPAN_STATE_ALLOC);
872 state->core_id = core_id;
873 state->vroot = vroot;
875 state->domain_id = domain_id;
877 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN1, core_id);
879 /* Look up the destination monitor */
880 struct intermon_binding *ib;
881 err = intermon_binding_get(core_id, &ib);
882 if (err_is_fail(err)) {
887 struct capability vroot_cap;
888 err = monitor_cap_identify(vroot, &vroot_cap);
889 if (err_is_fail(err)) {
890 err_push(err, MON_ERR_CAP_IDENTIFY);
893 if (vroot_cap.type != ObjType_VNode_x86_64_pml4) { /* Check type */
894 err = MON_ERR_WRONG_CAP_TYPE;
898 /* Identify the dispatcher frame */
899 struct frame_identity frameid;
900 err = invoke_frame_identify(disp, &frameid);
901 if (err_is_fail(err)) {
902 err_push(err, LIB_ERR_FRAME_IDENTIFY);
906 err = monitor_remote_relations(disp, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
907 if (err_is_fail(err)) {
908 USER_PANIC_ERR(err, "monitor_remote_relations failed");
911 err = monitor_remote_relations(vroot, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
912 if (err_is_fail(err)) {
913 USER_PANIC_ERR(err, "monitor_remote_relations failed");
917 assert((1UL << log2ceil(frameid.bytes)) == frameid.bytes);
918 /* Send msg to destination monitor */
919 err = ib->tx_vtbl.span_domain_request(ib, NOP_CONT, state_id,
920 get_address(&vroot_cap),
921 frameid.base, frameid.bytes);
923 if (err_is_fail(err)) {
924 err_push(err, MON_ERR_SEND_REMOTE_MSG);
930 err2 = mb->tx_vtbl.span_domain_reply(mb, NOP_CONT, err, domain_id);
931 if (err_is_fail(err2)) {
933 USER_PANIC_ERR(err2, "Failed to reply to the user domain");
936 err2 = span_state_free(state_id);
937 if (err_is_fail(err2)) {
938 USER_PANIC_ERR(err2, "Failed to free span state");
943 err2 = cap_destroy(vroot);
944 if (err_is_fail(err2)) {
945 USER_PANIC_ERR(err2, "Failed to destroy span_vroot cap");
947 err2 = cap_destroy(disp);
948 if (err_is_fail(err2)) {
949 USER_PANIC_ERR(err2, "Failed to destroy disp cap");
953 static void migrate_dispatcher_request(struct monitor_binding *b,
954 coreid_t coreid, struct capref vroot,
957 printf("%s:%d\n", __FUNCTION__, __LINE__);
960 struct monitor_rx_vtbl the_table = {
961 .alloc_iref_request = alloc_iref_request,
962 .get_service_id_request = get_service_id_request,
964 .bind_lmp_client_request= bind_lmp_client_request,
965 .bind_lmp_reply_monitor = bind_lmp_reply,
967 .boot_core_request = boot_core_request,
968 .multiboot_cap_request = ms_multiboot_cap_request,
970 .new_monitor_binding_request = new_monitor_binding_request,
972 .get_mem_iref_request = get_mem_iref_request,
973 .get_name_iref_request = get_name_iref_request,
974 .get_ramfs_iref_request = get_ramfs_iref_request,
975 .set_mem_iref_request = set_mem_iref_request,
976 .set_name_iref_request = set_name_iref_request,
977 .set_ramfs_iref_request = set_ramfs_iref_request,
978 .set_proc_mgmt_ep_request = set_proc_mgmt_ep_request,
979 .set_spawn_iref_request = set_spawn_iref_request,
980 .get_monitor_rpc_iref_request = get_monitor_rpc_iref_request,
982 .cap_send_request = cap_send_request,
983 .cap_move_request = cap_send_request,
985 .span_domain_request = span_domain_request,
987 .migrate_dispatcher_request = migrate_dispatcher_request,
990 errval_t monitor_client_setup(struct spawninfo *si)
994 struct monitor_lmp_binding *b =
995 malloc(sizeof(struct monitor_lmp_binding));
998 // setup our end of the binding
999 err = monitor_client_lmp_accept(b, get_default_waitset(),
1000 DEFAULT_LMP_BUF_WORDS);
1001 if (err_is_fail(err)) {
1003 return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
1006 // copy the endpoint cap to the recipient
1007 struct capref dest = {
1008 .cnode = si->taskcn,
1009 .slot = TASKCN_SLOT_MONITOREP,
1012 err = cap_copy(dest, b->chan.local_cap);
1013 if (err_is_fail(err)) {
1014 // TODO: destroy binding
1015 return err_push(err, LIB_ERR_CAP_COPY);
1018 // Copy the performance monitoring cap to all spawned processes.
1020 dest.cnode = si->taskcn;
1021 dest.slot = TASKCN_SLOT_PERF_MON;
1022 src.cnode = cnode_task;
1023 src.slot = TASKCN_SLOT_PERF_MON;
1024 err = cap_copy(dest, src);
1025 if (err_is_fail(err)) {
1026 return err_push(err, INIT_ERR_COPY_PERF_MON);
1029 // copy our receive vtable to the binding
1030 monitor_server_init(&b->b);
1035 errval_t monitor_client_setup_mem_serv(void)
1037 /* construct special-case LMP connection to mem_serv */
1038 static struct monitor_lmp_binding mcb;
1039 struct waitset *ws = get_default_waitset();
1042 err = monitor_client_lmp_accept(&mcb, ws, DEFAULT_LMP_BUF_WORDS);
1043 if(err_is_fail(err)) {
1044 USER_PANIC_ERR(err, "monitor_client_setup_mem_serv");
1046 assert(err_is_ok(err));
1048 /* Send the cap for this endpoint to init, who will pass it to the monitor */
1049 err = lmp_ep_send0(cap_initep, 0, mcb.chan.local_cap);
1050 if (err_is_fail(err)) {
1051 USER_PANIC_ERR(err, "lmp_ep_send0 failed");
1054 // copy our receive vtable to the binding
1055 monitor_server_init(&mcb.b);
1057 // XXX: handle messages (ie. block) until the monitor binding is ready
1058 while (capref_is_null(mcb.chan.remote_cap)) {
1059 err = event_dispatch(ws);
1060 if (err_is_fail(err)) {
1061 DEBUG_ERR(err, "in event_dispatch waiting for mem_serv binding");
1062 return err_push(err, LIB_ERR_EVENT_DISPATCH);
1069 /// Setup a dummy monitor binding that "sends" all requests to the local handlers
1070 errval_t monitor_client_setup_monitor(void)
1072 monitor_loopback_init(&monitor_self_binding);
1073 monitor_server_init(&monitor_self_binding);
1074 set_monitor_binding(&monitor_self_binding);
1075 caplock_init(get_default_waitset());
1077 // XXX: Need a waitset here or loopback won't work as expected
1078 // when binding to the ram_alloc service
1079 monitor_self_binding.mutex.equeue.waitset = get_default_waitset();
1084 errval_t monitor_server_init(struct monitor_binding *b)
1086 struct monitor_state *lst = malloc(sizeof(struct monitor_state));
1087 assert(lst != NULL);
1088 lst->queue.head = lst->queue.tail = NULL;
1090 // copy our receive vtable to the new binding
1091 b->rx_vtbl = the_table;
1093 // TODO: set error_handler
1095 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
1097 err = ump_monitor_init(b);
1098 if (err_is_fail(err)) {
1099 USER_PANIC_ERR(err, "ump_monitor_init failed");
1103 #ifdef CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1105 err2 = multihop_monitor_init(b);
1106 if (err_is_fail(err2)) {
1107 USER_PANIC_ERR(err2, "multihop_monitor_init failed");
1109 #endif // CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1113 err3 = bfscope_monitor_init(b);
1114 if (err_is_fail(err3)) {
1115 USER_PANIC_ERR(err3, "bfscope_monitor_init failed");
1118 err3 = trace_monitor_init(b);
1119 if (err_is_fail(err3)) {
1120 USER_PANIC_ERR(err3, "trace_monitor_init failed");
1122 #endif // CONFIG_TRACE
1124 return monitor_server_arch_init(b);