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 <barrelfish/monitor_client.h>
22 #include <barrelfish/proc_mgmt_client.h>
23 #include <barrelfish/syscalls.h>
24 #include <barrelfish_kpi/distcaps.h>
25 #include <if/monitor_loopback_defs.h>
30 // the monitor's loopback binding to itself
31 static struct monitor_binding monitor_self_binding;
33 /* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */
35 struct multiboot_cap_state {
36 struct monitor_msg_queue_elem elem;
40 struct proc_mgmt_bind_st {
45 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot);
47 static void ms_multiboot_cap_request_handler(struct monitor_binding *b,
48 struct monitor_msg_queue_elem *e)
50 struct multiboot_cap_state *ms = (struct multiboot_cap_state*)e;
51 ms_multiboot_cap_request(b, ms->slot);
55 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot)
60 .cnode = cnode_module,
64 // Call frame_identify to check if cap exists
65 struct frame_identity id;
66 err1 = invoke_frame_identify(cap, &id);
67 if (err_is_fail(err1)) {
68 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, NULL_CAP, err1);
70 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1);
72 if (err_is_fail(err2)) {
73 if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
74 struct monitor_state *mon_state = b->st;
75 struct multiboot_cap_state *ms =
76 malloc(sizeof(struct multiboot_cap_state));
79 ms->elem.cont = ms_multiboot_cap_request_handler;
80 err1 = monitor_enqueue_send(b, &mon_state->queue,
81 get_default_waitset(), &ms->elem.queue);
82 if (err_is_fail(err1)) {
83 USER_PANIC_ERR(err1, "monitor_enqueue_send failed");
86 USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed");
91 /* ----------------------- MULTIBOOT REQUEST CODE END ----------------------- */
93 static void alloc_iref_reply_handler(struct monitor_binding *b,
94 struct monitor_msg_queue_elem *e);
96 struct alloc_iref_reply_state {
97 struct monitor_msg_queue_elem elem;
98 struct monitor_alloc_iref_reply__tx_args args;
99 struct monitor_binding *b;
102 static void alloc_iref_reply_cont(struct monitor_binding *b,
103 uintptr_t service_id,
104 iref_t iref, errval_t reterr)
108 err = b->tx_vtbl.alloc_iref_reply(b, NOP_CONT, service_id, iref, reterr);
109 if (err_is_fail(err)) {
110 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
111 struct alloc_iref_reply_state *me =
112 malloc(sizeof(struct alloc_iref_reply_state));
114 struct monitor_state *ist = b->st;
116 me->args.service_id = service_id;
117 me->args.iref = iref;
118 me->args.err = reterr;
120 me->elem.cont = alloc_iref_reply_handler;
122 err = monitor_enqueue_send(b, &ist->queue,
123 get_default_waitset(), &me->elem.queue);
124 if (err_is_fail(err)) {
125 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
130 USER_PANIC_ERR(err, "reply failed");
134 static void alloc_iref_reply_handler(struct monitor_binding *b,
135 struct monitor_msg_queue_elem *e)
137 struct alloc_iref_reply_state *st = (struct alloc_iref_reply_state *)e;
138 alloc_iref_reply_cont(b, st->args.service_id, st->args.iref,
143 static void alloc_iref_request(struct monitor_binding *b,
144 uintptr_t service_id)
149 reterr = iref_alloc(b, service_id, &iref);
150 alloc_iref_reply_cont(b, service_id, iref, reterr);
154 static void get_service_id_reply_handler(struct monitor_binding *b,
155 struct monitor_msg_queue_elem *e);
157 struct get_service_id_reply_state {
158 struct monitor_msg_queue_elem elem;
159 struct monitor_get_service_id_reply__tx_args args;
160 struct monitor_binding *b;
163 static void get_service_id_reply_cont(struct monitor_binding *b, errval_t reterr,
164 iref_t iref, uintptr_t service_id)
168 err = b->tx_vtbl.get_service_id_reply(b, NOP_CONT, reterr, iref, service_id);
169 if (err_is_fail(err)) {
170 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
171 struct get_service_id_reply_state *me =
172 malloc(sizeof(struct get_service_id_reply_state));
174 struct monitor_state *ist = b->st;
176 me->args.err = reterr;
177 me->args.iref = iref;
178 me->args.service_id = service_id;
180 me->elem.cont = get_service_id_reply_handler;
182 err = monitor_enqueue_send(b, &ist->queue,
183 get_default_waitset(), &me->elem.queue);
184 if (err_is_fail(err)) {
185 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
190 USER_PANIC_ERR(err, "reply failed");
194 static void get_service_id_reply_handler(struct monitor_binding *b,
195 struct monitor_msg_queue_elem *e)
197 struct get_service_id_reply_state *st = (struct get_service_id_reply_state *)e;
198 get_service_id_reply_cont(b, st->args.err, st->args.iref, st->args.service_id);
202 static void get_service_id_request(struct monitor_binding *b, iref_t iref)
205 struct monitor_binding *serv_binding = NULL;
207 /* Look up core_id from the iref */
209 iref_get_core_id(iref, &core_id);
211 // Return error if service on different core
212 if (core_id != my_core_id) {
213 get_service_id_reply_cont(b, MON_ERR_IDC_BIND_NOT_SAME_CORE, iref, 0);
217 /* Lookup the server's connection to monitor */
218 err = iref_get_binding(iref, &serv_binding);
219 if (err_is_fail(err)) {
220 get_service_id_reply_cont(b, err, iref, 0);
224 /* Lookup the server's service_id */
225 uintptr_t service_id;
226 err = iref_get_service_id(iref, &service_id);
227 get_service_id_reply_cont(b, err, iref, service_id);
230 /******* stack-ripped bind_lmp_service_request *******/
232 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
233 struct monitor_msg_queue_elem *e);
235 struct bind_lmp_client_request_error_state {
236 struct monitor_msg_queue_elem elem;
237 struct monitor_bind_lmp_reply_client__tx_args args;
238 struct monitor_binding *serv_binding;
242 static void bind_lmp_client_request_error(struct monitor_binding *b,
243 errval_t err, uintptr_t domain_id,
244 struct monitor_binding *serv_binding,
249 err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id,
251 if (err_is_fail(err2)) {
252 if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
253 struct bind_lmp_client_request_error_state *me =
254 malloc(sizeof(struct bind_lmp_client_request_error_state));
256 struct monitor_state *ist = b->st;
259 me->args.conn_id = domain_id;
260 me->serv_binding = serv_binding;
262 me->elem.cont = bind_lmp_client_request_error_handler;
264 err = monitor_enqueue_send(b, &ist->queue,
265 get_default_waitset(), &me->elem.queue);
266 if (err_is_fail(err)) {
267 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
272 USER_PANIC_ERR(err2, "error reply failed");
273 USER_PANIC_ERR(err, "The reason for lmp failure");
276 /* Delete the EP cap */
277 // Do not delete the cap if client or service is monitor itself
278 if (b != &monitor_self_binding && serv_binding != &monitor_self_binding) {
279 err = cap_destroy(ep);
280 if (err_is_fail(err)) {
281 USER_PANIC_ERR(err, "cap_destroy failed");
286 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
287 struct monitor_msg_queue_elem *e)
289 struct bind_lmp_client_request_error_state *st = (struct bind_lmp_client_request_error_state *)e;
290 bind_lmp_client_request_error(b, st->args.err, st->args.conn_id,
291 st->serv_binding, st->ep);
295 static void bind_lmp_service_request_handler(struct monitor_binding *b,
296 struct monitor_msg_queue_elem *e);
298 struct bind_lmp_service_request_state {
299 struct monitor_msg_queue_elem elem;
300 struct monitor_bind_lmp_service_request__tx_args args;
301 struct monitor_binding *b;
305 static void bind_lmp_service_request_cont(struct monitor_binding *serv_binding,
306 uintptr_t service_id, uintptr_t con_id,
307 size_t buflen, struct capref ep,
308 struct monitor_binding *b,
313 struct monitor_state *ist = serv_binding->st;
314 struct event_closure send_cont = NOP_CONT;
315 struct capref *capp = NULL;
317 if (serv_binding != &monitor_self_binding && b != &monitor_self_binding) {
318 // save EP cap to be destroyed after the send is done
319 capp = caprefdup(ep);
320 send_cont = MKCONT(destroy_outgoing_cap, capp);
323 err = serv_binding->tx_vtbl.
324 bind_lmp_service_request(serv_binding, send_cont, service_id,
326 if (err_is_fail(err)) {
329 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
330 struct bind_lmp_service_request_state *me =
331 malloc(sizeof(struct bind_lmp_service_request_state));
333 me->args.service_id = service_id;
334 me->args.mon_id = con_id;
335 me->args.buflen = buflen;
338 me->domain_id = domain_id;
339 me->elem.cont = bind_lmp_service_request_handler;
341 err = monitor_enqueue_send(serv_binding, &ist->queue,
342 get_default_waitset(), &me->elem.queue);
343 if (err_is_fail(err)) {
344 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
349 err2 = lmp_conn_free(con_id);
350 if (err_is_fail(err2)) {
351 USER_PANIC_ERR(err2, "lmp_conn_free failed");
353 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
358 static void bind_lmp_service_request_handler(struct monitor_binding *b,
359 struct monitor_msg_queue_elem *e)
361 struct bind_lmp_service_request_state *st = (struct bind_lmp_service_request_state *)e;
362 bind_lmp_service_request_cont(b, st->args.service_id, st->args.mon_id,
363 st->args.buflen, st->args.ep, st->b,
368 static void bind_lmp_client_request(struct monitor_binding *b,
369 iref_t iref, uintptr_t domain_id,
370 size_t buflen, struct capref ep)
373 struct monitor_binding *serv_binding = NULL;
375 /* Look up core_id from the iref */
377 err = iref_get_core_id(iref, &core_id);
378 if (err_is_fail(err)) {
379 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
383 // Return error if service on different core
384 if (core_id != my_core_id) {
385 err = MON_ERR_IDC_BIND_NOT_SAME_CORE;
386 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
390 /* Lookup the server's connection to monitor */
391 err = iref_get_binding(iref, &serv_binding);
392 if (err_is_fail(err)) {
393 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
397 /* Lookup the server's service_id */
398 uintptr_t service_id;
399 err = iref_get_service_id(iref, &service_id);
400 if (err_is_fail(err)) {
401 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
405 /* Check for intra-domain connection */
406 if (b == serv_binding) {
407 bind_lmp_client_request_error(b, MON_ERR_IDC_BIND_LOCAL, domain_id, serv_binding, ep);
411 /* Allocate a new monitor connection */
413 struct lmp_conn_state *conn;
414 err = lmp_conn_alloc(&conn, &con_id);
415 if (err_is_fail(err)) {
416 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
420 conn->domain_id = domain_id;
421 conn->domain_binding = b;
423 /* Send request to the server */
424 bind_lmp_service_request_cont(serv_binding, service_id, con_id, buflen, ep,
428 /******* stack-ripped bind_lmp_reply *******/
430 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
431 struct monitor_msg_queue_elem *e);
433 struct bind_lmp_reply_client_state {
434 struct monitor_msg_queue_elem elem;
435 struct monitor_bind_lmp_reply_client__tx_args args;
436 struct monitor_binding *b;
439 static void bind_lmp_reply_client_cont(struct monitor_binding *client_binding,
440 errval_t msgerr, uintptr_t mon_conn_id,
441 uintptr_t client_conn_id,
443 struct monitor_binding *b)
447 struct monitor_state *ist = client_binding->st;
448 struct event_closure send_cont = NOP_CONT;
449 struct capref *capp = NULL;
451 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
452 // save EP cap to be destroyed after the send is done
453 capp = caprefdup(ep);
454 send_cont = MKCONT(destroy_outgoing_cap, capp);
457 err = client_binding->tx_vtbl.
458 bind_lmp_reply_client(client_binding, send_cont,
459 SYS_ERR_OK, mon_conn_id, client_conn_id, ep);
460 if (err_is_fail(err)) {
463 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
464 struct bind_lmp_reply_client_state *me =
465 malloc(sizeof(struct bind_lmp_reply_client_state));
467 me->args.err = msgerr;
468 me->args.mon_id = mon_conn_id;
469 me->args.conn_id = client_conn_id;
472 me->elem.cont = bind_lmp_reply_client_handler;
474 err = monitor_enqueue_send(client_binding, &ist->queue,
475 get_default_waitset(), &me->elem.queue);
476 if (err_is_fail(err)) {
477 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
482 USER_PANIC_ERR(err, "failed sending IDC bind reply");
485 if(err_is_fail(msgerr)) {
490 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
491 struct monitor_msg_queue_elem *e)
493 struct bind_lmp_reply_client_state *st = (struct bind_lmp_reply_client_state *)e;
494 bind_lmp_reply_client_cont(b, st->args.err, st->args.mon_id, st->args.conn_id,
499 static void bind_lmp_reply(struct monitor_binding *b,
500 errval_t msgerr, uintptr_t mon_conn_id,
501 uintptr_t user_conn_id, struct capref ep)
504 struct monitor_binding *client_binding = NULL;
506 struct lmp_conn_state *conn = lmp_conn_lookup(mon_conn_id);
508 DEBUG_ERR(0, "invalid connection ID");
512 client_binding = conn->domain_binding;
513 uintptr_t client_conn_id = conn->domain_id;
515 err = lmp_conn_free(mon_conn_id);
516 assert(err_is_ok(err));
518 if (err_is_fail(msgerr)) {
519 bind_lmp_reply_client_cont(client_binding, msgerr, 0, client_conn_id,
522 bind_lmp_reply_client_cont(client_binding, SYS_ERR_OK, mon_conn_id,
523 client_conn_id, ep, b);
528 /* Delete the ep cap */
529 // XXX: Do not delete the cap if client or service is monitor
530 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
531 err = cap_destroy(ep);
532 if (err_is_fail(err)) {
533 USER_PANIC_ERR(err, "cap_destroy failed");
538 /* ---------------------- NEW MONITOR BINDING CODE START -------------------- */
540 struct new_monitor_binding_reply_state {
541 struct monitor_msg_queue_elem elem;
542 struct monitor_new_monitor_binding_reply__tx_args args;
546 new_monitor_binding_reply_cont(struct monitor_binding *b,
547 errval_t reterr, struct capref retcap,
550 static void new_monitor_binding_reply_handler(struct monitor_binding *b,
551 struct monitor_msg_queue_elem *e)
553 struct new_monitor_binding_reply_state *st =
554 (struct new_monitor_binding_reply_state *)e;
555 new_monitor_binding_reply_cont(b, st->args.err, st->args.ep, st->args.st);
560 new_monitor_binding_reply_cont(struct monitor_binding *b,
561 errval_t reterr, struct capref retcap,
565 b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st);
567 if (err_is_fail(err)) {
568 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
569 struct monitor_state *ms = b->st;
570 struct new_monitor_binding_reply_state *me =
571 malloc(sizeof(struct new_monitor_binding_reply_state));
573 me->args.err = reterr;
574 me->args.ep = retcap;
576 me->elem.cont = new_monitor_binding_reply_handler;
577 err = monitor_enqueue_send(b, &ms->queue,
578 get_default_waitset(), &me->elem.queue);
579 if (err_is_fail(err)) {
580 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
585 USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply");
590 * \brief Setup a new idc channel between monitor and domain
592 * \bug on error send message back to domain
594 static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st)
596 struct capref retcap = NULL_CAP;
597 errval_t err, reterr = SYS_ERR_OK;
599 struct monitor_lmp_binding *lmpb =
600 malloc(sizeof(struct monitor_lmp_binding));
601 assert(lmpb != NULL);
603 // setup our end of the binding
604 err = monitor_client_lmp_accept(lmpb, get_default_waitset(),
605 DEFAULT_LMP_BUF_WORDS);
606 if (err_is_fail(err)) {
608 reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
612 retcap = lmpb->chan.local_cap;
613 monitor_server_init(&lmpb->b);
616 new_monitor_binding_reply_cont(b, reterr, retcap, st);
619 /* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */
621 static void get_mem_iref_request(struct monitor_binding *b)
625 // Mem serv not registered yet
626 assert(mem_serv_iref != 0);
628 err = b->tx_vtbl.get_mem_iref_reply(b, NOP_CONT, mem_serv_iref);
629 if (err_is_fail(err)) {
630 USER_PANIC_ERR(err, "reply failed");
634 static void get_name_iref_request(struct monitor_binding *b, uintptr_t st)
637 err = b->tx_vtbl.get_name_iref_reply(b, NOP_CONT, name_serv_iref, st);
638 if (err_is_fail(err)) {
639 USER_PANIC_ERR(err, "reply failed");
643 static void get_ramfs_iref_request(struct monitor_binding *b, uintptr_t st)
646 err = b->tx_vtbl.get_ramfs_iref_reply(b, NOP_CONT, ramfs_serv_iref, st);
647 if (err_is_fail(err)) {
648 USER_PANIC_ERR(err, "reply failed");
652 static void set_mem_iref_request(struct monitor_binding *b,
655 mem_serv_iref = iref;
656 update_ram_alloc_binding = true;
659 static void get_monitor_rpc_iref_request(struct monitor_binding *b,
664 if (monitor_rpc_iref == 0) {
665 // Monitor rpc not registered yet
666 DEBUG_ERR(LIB_ERR_GET_MON_BLOCKING_IREF, "got monitor rpc iref request but iref is 0");
669 err = b->tx_vtbl.get_monitor_rpc_iref_reply(b, NOP_CONT,
670 monitor_rpc_iref, st_arg);
671 if (err_is_fail(err)) {
672 USER_PANIC_ERR(err, "reply failed");
677 void set_monitor_rpc_iref(iref_t iref)
679 if (monitor_rpc_iref != 0) {
680 // Called multiple times, return error
681 DEBUG_ERR(0, "Attempt to reset monitor rpc IREF ignored");
685 monitor_rpc_iref = iref;
689 static void set_name_iref_request(struct monitor_binding *b,
692 if (name_serv_iref != 0) {
693 // Called multiple times, return error
694 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
698 name_serv_iref = iref;
701 static void set_ramfs_iref_request(struct monitor_binding *b,
704 if (ramfs_serv_iref != 0) {
705 // Called multiple times, return error
706 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
710 ramfs_serv_iref = iref;
713 static void proc_mgmt_bind_cont(void *st,
715 struct proc_mgmt_binding *b)
717 struct proc_mgmt_bind_st* bind_st = (struct proc_mgmt_bind_st*) st;
718 assert(!bind_st->present);
720 bind_st->present = true;
723 static void set_proc_mgmt_ep_request(struct monitor_binding *b,
726 // We got the endpoint which the process manager has allocated for us.
727 // Time to set up our part of the LMP connection and finish the handshake.
728 struct proc_mgmt_lmp_binding *lmpb =
729 malloc(sizeof(struct proc_mgmt_lmp_binding));
730 assert(lmpb != NULL);
732 set_proc_mgmt_binding(&lmpb->b);
734 struct proc_mgmt_bind_st bind_st = {
737 errval_t err = proc_mgmt_client_lmp_bind(lmpb,
741 get_default_waitset(),
742 DEFAULT_LMP_BUF_WORDS);
743 if (err_is_fail(err)) {
744 USER_PANIC_ERR(err, "proc_mgmt_client_lmp_bind");
747 // Dispatch events on the waitset until proc_mgmt binding completes.
748 while (!bind_st.present) {
749 err = event_dispatch(get_default_waitset());
750 if (err_is_fail(err)) {
751 USER_PANIC_ERR(err, "monitor event dispatch");
755 if(err_is_fail(bind_st.err)) {
756 USER_PANIC_ERR(err, "during proc_mgmt bind initialization");
759 proc_mgmt_rpc_client_init(&lmpb->b);
762 static void set_spawn_iref_request(struct monitor_binding *b, iref_t iref)
764 if (spawn_iref != 0) {
765 // Called multiple times, return error
766 DEBUG_ERR(0, "Attempt to reset spawn IREF ignored");
774 struct intermon_msg_queue_elem qe; // must be first
779 struct captx_prepare_state captx_state;
780 intermon_captx_t captx;
784 cap_send_tx_cont(struct intermon_binding *b,
785 struct intermon_msg_queue_elem *e)
787 DEBUG_CAPOPS("%s: %p %p\n", __FUNCTION__, b, e);
789 struct send_cap_st *st = (struct send_cap_st*)e;
790 struct remote_conn_state *conn = remote_conn_lookup(st->my_mon_id);
791 send_err = intermon_cap_send_request__tx(b, NOP_CONT, conn->mon_id,
792 st->capid, st->captx);
793 if (err_is_fail(send_err)) {
794 DEBUG_ERR(send_err, "sending cap_send_request failed");
800 cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st,
801 intermon_captx_t *captx, void *st_)
803 DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0));
805 struct send_cap_st *send_st = (struct send_cap_st*)st_;
807 if (err_is_fail(err)) {
808 // XXX: should forward error here
809 DEBUG_ERR(err, "preparing cap tx failed");
814 send_st->captx = *captx;
816 DEBUG_CAPOPS("%s: enqueueing send\n", __FUNCTION__);
817 send_st->qe.cont = cap_send_tx_cont;
818 struct remote_conn_state *conn = remote_conn_lookup(send_st->my_mon_id);
819 struct intermon_binding *binding = conn->mon_binding;
820 struct intermon_state *inter_st = (struct intermon_state*)binding->st;
821 queue_err = intermon_enqueue_send(binding, &inter_st->queue,
823 (struct msg_queue_elem*)send_st);
824 if (err_is_fail(queue_err)) {
825 DEBUG_ERR(queue_err, "enqueuing cap_send_request failed");
831 cap_send_request(struct monitor_binding *b, uintptr_t my_mon_id,
832 struct capref cap, uint32_t capid)
834 DEBUG_CAPOPS("cap_send_request\n");
836 struct remote_conn_state *conn = remote_conn_lookup(my_mon_id);
838 struct send_cap_st *st;
839 st = calloc(1, sizeof(*st));
841 err = LIB_ERR_MALLOC_FAIL;
842 DEBUG_ERR(err, "Failed to allocate cap_send_request state");
843 // XXX: should forward error here
846 st->my_mon_id = my_mon_id;
850 captx_prepare_send(cap, conn->core_id, true, &st->captx_state,
851 cap_send_request_tx_cont, st);
854 static void span_domain_request(struct monitor_binding *mb,
855 uintptr_t domain_id, uint8_t core_id,
856 struct capref vroot, struct capref disp)
860 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN0, core_id);
862 struct span_state *state;
865 err = span_state_alloc(&state, &state_id);
866 if (err_is_fail(err)) {
867 err_push(err, MON_ERR_SPAN_STATE_ALLOC);
871 state->core_id = core_id;
872 state->vroot = vroot;
874 state->domain_id = domain_id;
876 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN1, core_id);
878 /* Look up the destination monitor */
879 struct intermon_binding *ib;
880 err = intermon_binding_get(core_id, &ib);
881 if (err_is_fail(err)) {
886 struct capability vroot_cap;
887 err = monitor_cap_identify(vroot, &vroot_cap);
888 if (err_is_fail(err)) {
889 err_push(err, MON_ERR_CAP_IDENTIFY);
892 if (vroot_cap.type != ObjType_VNode_x86_64_pml4) { /* Check type */
893 err = MON_ERR_WRONG_CAP_TYPE;
897 /* Identify the dispatcher frame */
898 struct frame_identity frameid;
899 err = invoke_frame_identify(disp, &frameid);
900 if (err_is_fail(err)) {
901 err_push(err, LIB_ERR_FRAME_IDENTIFY);
905 err = monitor_remote_relations(disp, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
906 if (err_is_fail(err)) {
907 USER_PANIC_ERR(err, "monitor_remote_relations failed");
910 err = monitor_remote_relations(vroot, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
911 if (err_is_fail(err)) {
912 USER_PANIC_ERR(err, "monitor_remote_relations failed");
916 assert((1UL << log2ceil(frameid.bytes)) == frameid.bytes);
917 /* Send msg to destination monitor */
918 err = ib->tx_vtbl.span_domain_request(ib, NOP_CONT, state_id,
919 get_address(&vroot_cap),
920 frameid.base, frameid.bytes);
922 if (err_is_fail(err)) {
923 err_push(err, MON_ERR_SEND_REMOTE_MSG);
929 err2 = mb->tx_vtbl.span_domain_reply(mb, NOP_CONT, err, domain_id);
930 if (err_is_fail(err2)) {
932 USER_PANIC_ERR(err2, "Failed to reply to the user domain");
935 err2 = span_state_free(state_id);
936 if (err_is_fail(err2)) {
937 USER_PANIC_ERR(err2, "Failed to free span state");
942 err2 = cap_destroy(vroot);
943 if (err_is_fail(err2)) {
944 USER_PANIC_ERR(err2, "Failed to destroy span_vroot cap");
946 err2 = cap_destroy(disp);
947 if (err_is_fail(err2)) {
948 USER_PANIC_ERR(err2, "Failed to destroy disp cap");
952 static void migrate_dispatcher_request(struct monitor_binding *b,
953 coreid_t coreid, struct capref vroot,
956 printf("%s:%d\n", __FUNCTION__, __LINE__);
959 struct monitor_rx_vtbl the_table = {
960 .alloc_iref_request = alloc_iref_request,
961 .get_service_id_request = get_service_id_request,
963 .bind_lmp_client_request= bind_lmp_client_request,
964 .bind_lmp_reply_monitor = bind_lmp_reply,
966 .boot_core_request = boot_core_request,
967 .multiboot_cap_request = ms_multiboot_cap_request,
969 .new_monitor_binding_request = new_monitor_binding_request,
971 .get_mem_iref_request = get_mem_iref_request,
972 .get_name_iref_request = get_name_iref_request,
973 .get_ramfs_iref_request = get_ramfs_iref_request,
974 .set_mem_iref_request = set_mem_iref_request,
975 .set_name_iref_request = set_name_iref_request,
976 .set_ramfs_iref_request = set_ramfs_iref_request,
977 .set_proc_mgmt_ep_request = set_proc_mgmt_ep_request,
978 .set_spawn_iref_request = set_spawn_iref_request,
979 .get_monitor_rpc_iref_request = get_monitor_rpc_iref_request,
981 .cap_send_request = cap_send_request,
982 .cap_move_request = cap_send_request,
984 .span_domain_request = span_domain_request,
986 .migrate_dispatcher_request = migrate_dispatcher_request,
989 errval_t monitor_client_setup(struct spawninfo *si)
993 struct monitor_lmp_binding *b =
994 malloc(sizeof(struct monitor_lmp_binding));
997 // setup our end of the binding
998 err = monitor_client_lmp_accept(b, get_default_waitset(),
999 DEFAULT_LMP_BUF_WORDS);
1000 if (err_is_fail(err)) {
1002 return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
1005 // copy the endpoint cap to the recipient
1006 struct capref dest = {
1007 .cnode = si->taskcn,
1008 .slot = TASKCN_SLOT_MONITOREP,
1011 err = cap_copy(dest, b->chan.local_cap);
1012 if (err_is_fail(err)) {
1013 // TODO: destroy binding
1014 return err_push(err, LIB_ERR_CAP_COPY);
1017 // Copy the performance monitoring cap to all spawned processes.
1019 dest.cnode = si->taskcn;
1020 dest.slot = TASKCN_SLOT_PERF_MON;
1021 src.cnode = cnode_task;
1022 src.slot = TASKCN_SLOT_PERF_MON;
1023 err = cap_copy(dest, src);
1024 if (err_is_fail(err)) {
1025 return err_push(err, INIT_ERR_COPY_PERF_MON);
1028 // copy our receive vtable to the binding
1029 monitor_server_init(&b->b);
1034 errval_t monitor_client_setup_mem_serv(void)
1036 /* construct special-case LMP connection to mem_serv */
1037 static struct monitor_lmp_binding mcb;
1038 struct waitset *ws = get_default_waitset();
1041 err = monitor_client_lmp_accept(&mcb, ws, DEFAULT_LMP_BUF_WORDS);
1042 if(err_is_fail(err)) {
1043 USER_PANIC_ERR(err, "monitor_client_setup_mem_serv");
1045 assert(err_is_ok(err));
1047 /* Send the cap for this endpoint to init, who will pass it to the monitor */
1048 err = lmp_ep_send0(cap_initep, 0, mcb.chan.local_cap);
1049 if (err_is_fail(err)) {
1050 USER_PANIC_ERR(err, "lmp_ep_send0 failed");
1053 // copy our receive vtable to the binding
1054 monitor_server_init(&mcb.b);
1056 // XXX: handle messages (ie. block) until the monitor binding is ready
1057 while (capref_is_null(mcb.chan.remote_cap)) {
1058 err = event_dispatch(ws);
1059 if (err_is_fail(err)) {
1060 DEBUG_ERR(err, "in event_dispatch waiting for mem_serv binding");
1061 return err_push(err, LIB_ERR_EVENT_DISPATCH);
1068 /// Setup a dummy monitor binding that "sends" all requests to the local handlers
1069 errval_t monitor_client_setup_monitor(void)
1071 monitor_loopback_init(&monitor_self_binding);
1072 monitor_server_init(&monitor_self_binding);
1073 set_monitor_binding(&monitor_self_binding);
1074 caplock_init(get_default_waitset());
1076 // XXX: Need a waitset here or loopback won't work as expected
1077 // when binding to the ram_alloc service
1078 monitor_self_binding.mutex.equeue.waitset = get_default_waitset();
1083 errval_t monitor_server_init(struct monitor_binding *b)
1085 struct monitor_state *lst = malloc(sizeof(struct monitor_state));
1086 assert(lst != NULL);
1087 lst->queue.head = lst->queue.tail = NULL;
1089 // copy our receive vtable to the new binding
1090 b->rx_vtbl = the_table;
1092 // TODO: set error_handler
1094 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
1096 err = ump_monitor_init(b);
1097 if (err_is_fail(err)) {
1098 USER_PANIC_ERR(err, "ump_monitor_init failed");
1102 #ifdef CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1104 err2 = multihop_monitor_init(b);
1105 if (err_is_fail(err2)) {
1106 USER_PANIC_ERR(err2, "multihop_monitor_init failed");
1108 #endif // CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1112 err3 = bfscope_monitor_init(b);
1113 if (err_is_fail(err3)) {
1114 USER_PANIC_ERR(err3, "bfscope_monitor_init failed");
1117 err3 = trace_monitor_init(b);
1118 if (err_is_fail(err3)) {
1119 USER_PANIC_ERR(err3, "trace_monitor_init failed");
1121 #endif // CONFIG_TRACE
1123 return monitor_server_arch_init(b);