T119: implement syscall and monitor interface to debug_print_capabilities
[barrelfish] / usr / monitor / monitor_server.c
1 /** \file
2  * \brief Monitor's connection with the dispatchers on the same core
3  */
4
5 /*
6  * Copyright (c) 2009, 2010, 2011, 2013, ETH Zurich.
7  * All rights reserved.
8  *
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.
12  */
13
14 #include "monitor.h"
15 #include <barrelfish/debug.h> // XXX: To set the cap_identify_reply handler
16 #include <barrelfish/sys_debug.h> // XXX: for sys_debug_send_ipi
17 #include <trace/trace.h>
18 #include <trace_definitions/trace_defs.h>
19 #include <if/mem_defs.h>
20 #include <barrelfish/monitor_client.h>
21 #include <barrelfish/syscalls.h>
22 #include <barrelfish_kpi/distcaps.h>
23 #include <if/monitor_loopback_defs.h>
24 #include "capops.h"
25 #include "caplock.h"
26 #include "send_cap.h"
27
28 // the monitor's loopback binding to itself
29 static struct monitor_binding monitor_self_binding;
30
31 /* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */
32
33 struct multiboot_cap_state {
34     struct monitor_msg_queue_elem elem;
35     cslot_t slot;
36 };
37
38 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot);
39
40 static void ms_multiboot_cap_request_handler(struct monitor_binding *b,
41                                              struct monitor_msg_queue_elem *e)
42 {
43     struct multiboot_cap_state *ms = (struct multiboot_cap_state*)e;
44     ms_multiboot_cap_request(b, ms->slot);
45     free(ms);
46 }
47
48 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot)
49 {
50     errval_t err1, err2;
51
52     struct capref cap = {
53         .cnode = cnode_module,
54         .slot  = slot,
55     };
56
57     // Call frame_identify to check if cap exists
58     struct frame_identity id;
59     err1 = invoke_frame_identify(cap, &id);
60     if (err_is_fail(err1)) {
61         err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, NULL_CAP, err1);
62     } else {
63         err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1);
64     }
65     if (err_is_fail(err2)) {
66         if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
67             struct monitor_state *mon_state = b->st;
68             struct multiboot_cap_state *ms =
69                 malloc(sizeof(struct multiboot_cap_state));
70             assert(ms);
71             ms->slot = slot;
72             ms->elem.cont = ms_multiboot_cap_request_handler;
73             err1 = monitor_enqueue_send(b, &mon_state->queue,
74                                        get_default_waitset(), &ms->elem.queue);
75             if (err_is_fail(err1)) {
76                 USER_PANIC_ERR(err1, "monitor_enqueue_send failed");
77             }
78         } else {
79             USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed");
80         }
81     }
82 }
83
84 /* ----------------------- MULTIBOOT REQUEST CODE END ----------------------- */
85
86 static void alloc_iref_reply_handler(struct monitor_binding *b,
87                                        struct monitor_msg_queue_elem *e);
88
89 struct alloc_iref_reply_state {
90     struct monitor_msg_queue_elem elem;
91     struct monitor_alloc_iref_reply__args args;
92     struct monitor_binding *b;
93 };
94
95 static void alloc_iref_reply_cont(struct monitor_binding *b,
96                                     uintptr_t service_id,
97                                     iref_t iref, errval_t reterr)
98 {
99     errval_t err;
100
101     err = b->tx_vtbl.alloc_iref_reply(b, NOP_CONT, service_id, iref, reterr);
102     if (err_is_fail(err)) {
103         if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
104             struct alloc_iref_reply_state *me =
105                 malloc(sizeof(struct alloc_iref_reply_state));
106             assert(me != NULL);
107             struct monitor_state *ist = b->st;
108             assert(ist != NULL);
109             me->args.service_id = service_id;
110             me->args.iref = iref;
111             me->args.err = reterr;
112             me->b = b;
113             me->elem.cont = alloc_iref_reply_handler;
114
115             err = monitor_enqueue_send(b, &ist->queue,
116                                        get_default_waitset(), &me->elem.queue);
117             if (err_is_fail(err)) {
118                 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
119             }
120             return;
121         }
122
123         USER_PANIC_ERR(err, "reply failed");
124     }
125 }
126
127 static void alloc_iref_reply_handler(struct monitor_binding *b,
128                                        struct monitor_msg_queue_elem *e)
129 {
130     struct alloc_iref_reply_state *st = (struct alloc_iref_reply_state *)e;
131     alloc_iref_reply_cont(b, st->args.service_id, st->args.iref,
132                           st->args.err);
133     free(e);
134 }
135
136 static void alloc_iref_request(struct monitor_binding *b,
137                                uintptr_t service_id)
138 {
139     errval_t reterr;
140
141     iref_t iref = 0;
142     reterr = iref_alloc(b, service_id, &iref);
143     alloc_iref_reply_cont(b, service_id, iref, reterr);
144 }
145
146 /******* stack-ripped bind_lmp_service_request *******/
147
148 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
149                                                   struct monitor_msg_queue_elem *e);
150
151 struct bind_lmp_client_request_error_state {
152     struct monitor_msg_queue_elem elem;
153     struct monitor_bind_lmp_reply_client__args args;
154     struct monitor_binding *serv_binding;
155     struct capref ep;
156 };
157
158 static void bind_lmp_client_request_error(struct monitor_binding *b,
159                                           errval_t err, uintptr_t domain_id,
160                                           struct monitor_binding *serv_binding,
161                                           struct capref ep)
162 {
163     errval_t err2;
164
165     err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id,
166                                             NULL_CAP);
167     if (err_is_fail(err2)) {
168         if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
169             struct bind_lmp_client_request_error_state *me =
170                 malloc(sizeof(struct bind_lmp_client_request_error_state));
171             assert(me != NULL);
172             struct monitor_state *ist = b->st;
173             assert(ist != NULL);
174             me->args.err = err;
175             me->args.conn_id = domain_id;
176             me->serv_binding = serv_binding;
177             me->ep = ep;
178             me->elem.cont = bind_lmp_client_request_error_handler;
179
180             err = monitor_enqueue_send(b, &ist->queue,
181                                        get_default_waitset(), &me->elem.queue);
182             if (err_is_fail(err)) {
183                 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
184             }
185             return;
186         }
187
188         USER_PANIC_ERR(err2, "error reply failed");
189         USER_PANIC_ERR(err, "The reason for lmp failure");
190     }
191
192     /* Delete the EP cap */
193     // Do not delete the cap if client or service is monitor itself
194     if (b != &monitor_self_binding && serv_binding != &monitor_self_binding) {
195         err = cap_destroy(ep);
196         if (err_is_fail(err)) {
197             USER_PANIC_ERR(err, "cap_destroy failed");
198         }
199     }
200 }
201
202 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
203                                                   struct monitor_msg_queue_elem *e)
204 {
205     struct bind_lmp_client_request_error_state *st = (struct bind_lmp_client_request_error_state *)e;
206     bind_lmp_client_request_error(b, st->args.err, st->args.conn_id,
207                                   st->serv_binding, st->ep);
208     free(e);
209 }
210
211 static void bind_lmp_service_request_handler(struct monitor_binding *b,
212                                              struct monitor_msg_queue_elem *e);
213
214 struct bind_lmp_service_request_state {
215     struct monitor_msg_queue_elem elem;
216     struct monitor_bind_lmp_service_request__args args;
217     struct monitor_binding *b;
218     uintptr_t domain_id;
219 };
220
221 static void bind_lmp_service_request_cont(struct monitor_binding *serv_binding,
222                                           uintptr_t service_id, uintptr_t con_id,
223                                           size_t buflen, struct capref ep,
224                                           struct monitor_binding *b,
225                                           uintptr_t domain_id)
226 {
227     errval_t err, err2;
228
229     struct monitor_state *ist = serv_binding->st;
230     struct event_closure send_cont = NOP_CONT;
231     struct capref *capp = NULL;
232
233     if (serv_binding != &monitor_self_binding && b != &monitor_self_binding) {
234         // save EP cap to be destroyed after the send is done
235         capp = caprefdup(ep);
236         send_cont = MKCONT(destroy_outgoing_cap, capp);
237     }
238
239     err = serv_binding->tx_vtbl.
240         bind_lmp_service_request(serv_binding, send_cont, service_id,
241                                  con_id, buflen, ep);
242     if (err_is_fail(err)) {
243         free(capp);
244
245         if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
246             struct bind_lmp_service_request_state *me =
247                 malloc(sizeof(struct bind_lmp_service_request_state));
248             assert(me != NULL);
249             me->args.service_id = service_id;
250             me->args.mon_id = con_id;
251             me->args.buflen = buflen;
252             me->args.ep = ep;
253             me->b = b;
254             me->domain_id = domain_id;
255             me->elem.cont = bind_lmp_service_request_handler;
256
257             err = monitor_enqueue_send(serv_binding, &ist->queue,
258                                        get_default_waitset(), &me->elem.queue);
259             if (err_is_fail(err)) {
260                 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
261             }
262             return;
263         }
264
265         err2 = lmp_conn_free(con_id);
266         if (err_is_fail(err2)) {
267             USER_PANIC_ERR(err2, "lmp_conn_free failed");
268         }
269         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
270         return;
271     }
272 }
273
274 static void bind_lmp_service_request_handler(struct monitor_binding *b,
275                                              struct monitor_msg_queue_elem *e)
276 {
277     struct bind_lmp_service_request_state *st = (struct bind_lmp_service_request_state *)e;
278     bind_lmp_service_request_cont(b, st->args.service_id, st->args.mon_id,
279                                   st->args.buflen, st->args.ep, st->b,
280                                   st->domain_id);
281     free(e);
282 }
283
284 static void bind_lmp_client_request(struct monitor_binding *b,
285                                     iref_t iref, uintptr_t domain_id,
286                                     size_t buflen, struct capref ep)
287 {
288     errval_t err;
289     struct monitor_binding *serv_binding = NULL;
290
291     /* Look up core_id from the iref */
292     uint8_t core_id;
293     err = iref_get_core_id(iref, &core_id);
294     if (err_is_fail(err)) {
295         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
296         return;
297     }
298
299     // Return error if service on different core
300     if (core_id != my_core_id) {
301         err = MON_ERR_IDC_BIND_NOT_SAME_CORE;
302         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
303         return;
304     }
305
306     /* Lookup the server's connection to monitor */
307     err = iref_get_binding(iref, &serv_binding);
308     if (err_is_fail(err)) {
309         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
310         return;
311     }
312
313     /* Lookup the server's service_id */
314     uintptr_t service_id;
315     err = iref_get_service_id(iref, &service_id);
316     if (err_is_fail(err)) {
317         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
318         return;
319     }
320
321     /* Allocate a new monitor connection */
322     uintptr_t con_id;
323     struct lmp_conn_state *conn;
324     err = lmp_conn_alloc(&conn, &con_id);
325     if (err_is_fail(err)) {
326         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
327         return;
328     }
329
330     conn->domain_id = domain_id;
331     conn->domain_binding = b;
332
333     /* Send request to the server */
334     bind_lmp_service_request_cont(serv_binding, service_id, con_id, buflen, ep,
335                                   b, domain_id);
336 }
337
338 /******* stack-ripped bind_lmp_reply *******/
339
340 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
341                                           struct monitor_msg_queue_elem *e);
342
343 struct bind_lmp_reply_client_state {
344     struct monitor_msg_queue_elem elem;
345     struct monitor_bind_lmp_reply_client__args args;
346     struct monitor_binding *b;
347 };
348
349 static void bind_lmp_reply_client_cont(struct monitor_binding *client_binding,
350                                        errval_t msgerr, uintptr_t mon_conn_id,
351                                        uintptr_t client_conn_id,
352                                        struct capref ep,
353                                        struct monitor_binding *b)
354 {
355     errval_t err;
356
357     struct monitor_state *ist = client_binding->st;
358     struct event_closure send_cont = NOP_CONT;
359     struct capref *capp = NULL;
360
361     if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
362         // save EP cap to be destroyed after the send is done
363         capp = caprefdup(ep);
364         send_cont = MKCONT(destroy_outgoing_cap, capp);
365     }
366
367     err = client_binding->tx_vtbl.
368         bind_lmp_reply_client(client_binding, send_cont,
369                               SYS_ERR_OK, mon_conn_id, client_conn_id, ep);
370     if (err_is_fail(err)) {
371         free(capp);
372
373         if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
374             struct bind_lmp_reply_client_state *me =
375                 malloc(sizeof(struct bind_lmp_reply_client_state));
376             assert(me != NULL);
377             me->args.err = msgerr;
378             me->args.mon_id = mon_conn_id;
379             me->args.conn_id = client_conn_id;
380             me->args.ep = ep;
381             me->b = b;
382             me->elem.cont = bind_lmp_reply_client_handler;
383
384             err = monitor_enqueue_send(client_binding, &ist->queue,
385                                        get_default_waitset(), &me->elem.queue);
386             if (err_is_fail(err)) {
387                 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
388             }
389             return;
390         }
391
392         USER_PANIC_ERR(err, "failed sending IDC bind reply");
393     }
394
395     if(err_is_fail(msgerr)) {
396         return;
397     }
398 }
399
400 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
401                                           struct monitor_msg_queue_elem *e)
402 {
403     struct bind_lmp_reply_client_state *st = (struct bind_lmp_reply_client_state *)e;
404     bind_lmp_reply_client_cont(b, st->args.err, st->args.mon_id, st->args.conn_id,
405                                st->args.ep, st->b);
406     free(e);
407 }
408
409 static void bind_lmp_reply(struct monitor_binding *b,
410                            errval_t msgerr, uintptr_t mon_conn_id,
411                            uintptr_t user_conn_id, struct capref ep)
412 {
413     errval_t err;
414     struct monitor_binding *client_binding = NULL;
415
416     struct lmp_conn_state *conn = lmp_conn_lookup(mon_conn_id);
417     if (conn == NULL) {
418         DEBUG_ERR(0, "invalid connection ID");
419         goto cleanup;
420     }
421
422     client_binding = conn->domain_binding;
423     uintptr_t client_conn_id = conn->domain_id;
424
425     err = lmp_conn_free(mon_conn_id);
426     assert(err_is_ok(err));
427
428     if (err_is_fail(msgerr)) {
429         bind_lmp_reply_client_cont(client_binding, msgerr, 0, client_conn_id,
430                                    ep, b);
431     } else {
432         bind_lmp_reply_client_cont(client_binding, SYS_ERR_OK, mon_conn_id,
433                                    client_conn_id, ep, b);
434     }
435     return;
436
437 cleanup:
438     /* Delete the ep cap */
439     // XXX: Do not delete the cap if client or service is monitor
440     if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
441         err = cap_destroy(ep);
442         if (err_is_fail(err)) {
443             USER_PANIC_ERR(err, "cap_destroy failed");
444         }
445     }
446 }
447
448 /* ---------------------- NEW MONITOR BINDING CODE START -------------------- */
449
450 struct new_monitor_binding_reply_state {
451     struct monitor_msg_queue_elem elem;
452     struct monitor_new_monitor_binding_reply__args args;
453 };
454
455 static void
456 new_monitor_binding_reply_cont(struct monitor_binding *b,
457                                errval_t reterr, struct capref retcap,
458                                uintptr_t st);
459
460 static void new_monitor_binding_reply_handler(struct monitor_binding *b,
461                                               struct monitor_msg_queue_elem *e)
462 {
463     struct new_monitor_binding_reply_state *st =
464         (struct new_monitor_binding_reply_state *)e;
465     new_monitor_binding_reply_cont(b, st->args.err, st->args.ep, st->args.st);
466     free(st);
467 }
468
469 static void
470 new_monitor_binding_reply_cont(struct monitor_binding *b,
471                                errval_t reterr, struct capref retcap,
472                                uintptr_t st)
473 {
474     errval_t err =
475         b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st);
476
477     if (err_is_fail(err)) {
478         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
479             struct monitor_state *ms = b->st;
480             struct new_monitor_binding_reply_state *me =
481                 malloc(sizeof(struct new_monitor_binding_reply_state));
482             assert(me != NULL);
483             me->args.err = reterr;
484             me->args.ep = retcap;
485             me->args.st = st;
486             me->elem.cont = new_monitor_binding_reply_handler;
487             err = monitor_enqueue_send(b, &ms->queue,
488                                        get_default_waitset(), &me->elem.queue);
489             if (err_is_fail(err)) {
490                 USER_PANIC_ERR(err, "monitor_enqueue_send failed");
491             }
492             return;
493         }
494
495         USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply");
496     }
497 }
498
499 /**
500  * \brief Setup a new idc channel between monitor and domain
501  *
502  * \bug on error send message back to domain
503  */
504 static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st)
505 {
506     struct capref retcap = NULL_CAP;
507     errval_t err, reterr = SYS_ERR_OK;
508
509     struct monitor_lmp_binding *lmpb =
510         malloc(sizeof(struct monitor_lmp_binding));
511     assert(lmpb != NULL);
512
513     // setup our end of the binding
514     err = monitor_client_lmp_accept(lmpb, get_default_waitset(),
515                                     DEFAULT_LMP_BUF_WORDS);
516     if (err_is_fail(err)) {
517         free(lmpb);
518         reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
519         goto out;
520     }
521
522     retcap = lmpb->chan.local_cap;
523     monitor_server_init(&lmpb->b);
524
525 out:
526     new_monitor_binding_reply_cont(b, reterr, retcap, st);
527 }
528
529 /* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */
530
531 static void get_mem_iref_request(struct monitor_binding *b)
532 {
533     errval_t err;
534
535     // Mem serv not registered yet
536     assert(mem_serv_iref != 0);
537
538     err = b->tx_vtbl.get_mem_iref_reply(b, NOP_CONT, mem_serv_iref);
539     if (err_is_fail(err)) {
540         USER_PANIC_ERR(err, "reply failed");
541     }
542 }
543
544 static void get_name_iref_request(struct monitor_binding *b, uintptr_t st)
545 {
546     errval_t err;
547     err = b->tx_vtbl.get_name_iref_reply(b, NOP_CONT, name_serv_iref, st);
548     if (err_is_fail(err)) {
549         USER_PANIC_ERR(err, "reply failed");
550     }
551 }
552
553 static void get_ramfs_iref_request(struct monitor_binding *b, uintptr_t st)
554 {
555     errval_t err;
556     err = b->tx_vtbl.get_ramfs_iref_reply(b, NOP_CONT, ramfs_serv_iref, st);
557     if (err_is_fail(err)) {
558         USER_PANIC_ERR(err, "reply failed");
559     }
560 }
561
562 static void set_mem_iref_request(struct monitor_binding *b,
563                                  iref_t iref)
564 {
565     mem_serv_iref = iref;
566     update_ram_alloc_binding = true;
567 }
568
569 static void get_monitor_rpc_iref_request(struct monitor_binding *b,
570                                          uintptr_t st_arg)
571 {
572     errval_t err;
573
574     if (monitor_rpc_iref == 0) {
575         // Monitor rpc not registered yet
576         DEBUG_ERR(LIB_ERR_GET_MON_BLOCKING_IREF, "got monitor rpc iref request but iref is 0");
577     }
578
579     err = b->tx_vtbl.get_monitor_rpc_iref_reply(b, NOP_CONT,
580                                                 monitor_rpc_iref, st_arg);
581     if (err_is_fail(err)) {
582         USER_PANIC_ERR(err, "reply failed");
583     }
584 }
585
586
587 void set_monitor_rpc_iref(iref_t iref)
588 {
589     if (monitor_rpc_iref != 0) {
590         // Called multiple times, return error
591         DEBUG_ERR(0, "Attempt to reset monitor rpc IREF ignored");
592         return;
593     }
594
595     monitor_rpc_iref = iref;
596 }
597
598
599 static void set_name_iref_request(struct monitor_binding *b,
600                                   iref_t iref)
601 {
602     if (name_serv_iref != 0) {
603         // Called multiple times, return error
604         DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
605         return;
606     }
607
608     name_serv_iref = iref;
609 }
610
611 static void set_ramfs_iref_request(struct monitor_binding *b,
612                                   iref_t iref)
613 {
614     if (ramfs_serv_iref != 0) {
615         // Called multiple times, return error
616         DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
617         return;
618     }
619
620     ramfs_serv_iref = iref;
621 }
622
623 struct send_cap_st {
624     struct intermon_msg_queue_elem qe; // must be first
625     uintptr_t my_mon_id;
626     struct capref cap;
627     uint32_t capid;
628     uint8_t give_away;
629     struct captx_prepare_state captx_state;
630     intermon_captx_t captx;
631 };
632
633 static void
634 cap_send_tx_cont(struct intermon_binding *b,
635                  struct intermon_msg_queue_elem *e)
636 {
637     DEBUG_CAPOPS("%s: %p %p\n", __FUNCTION__, b, e);
638     errval_t send_err;
639     struct send_cap_st *st = (struct send_cap_st*)e;
640     struct remote_conn_state *conn = remote_conn_lookup(st->my_mon_id);
641     send_err = intermon_cap_send_request__tx(b, NOP_CONT, conn->mon_id,
642                                                 st->capid, st->captx);
643     if (err_is_fail(send_err)) {
644         DEBUG_ERR(send_err, "sending cap_send_request failed");
645     }
646     free(st);
647 }
648
649 static void
650 cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st,
651                          intermon_captx_t *captx, void *st_)
652 {
653     DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0));
654     errval_t queue_err;
655     struct send_cap_st *send_st = (struct send_cap_st*)st_;
656
657     if (err_is_fail(err)) {
658         // XXX: should forward error here
659         DEBUG_ERR(err, "preparing cap tx failed");
660         free(send_st);
661         return;
662     }
663
664     send_st->captx = *captx;
665
666     DEBUG_CAPOPS("%s: enqueueing send\n", __FUNCTION__);
667     send_st->qe.cont = cap_send_tx_cont;
668     struct remote_conn_state *conn = remote_conn_lookup(send_st->my_mon_id);
669     struct intermon_binding *binding = conn->mon_binding;
670     struct intermon_state *inter_st = (struct intermon_state*)binding->st;
671     queue_err = intermon_enqueue_send(binding, &inter_st->queue,
672                                       binding->waitset,
673                                       (struct msg_queue_elem*)send_st);
674     if (err_is_fail(queue_err)) {
675         DEBUG_ERR(queue_err, "enqueuing cap_send_request failed");
676         free(send_st);
677     }
678 }
679
680 static void
681 cap_send_request(struct monitor_binding *b, uintptr_t my_mon_id,
682                  struct capref cap, uint32_t capid)
683 {
684     DEBUG_CAPOPS("cap_send_request\n");
685     errval_t err;
686     struct remote_conn_state *conn = remote_conn_lookup(my_mon_id);
687
688     struct send_cap_st *st;
689     st = calloc(1, sizeof(*st));
690     if (!st) {
691         err = LIB_ERR_MALLOC_FAIL;
692         DEBUG_ERR(err, "Failed to allocate cap_send_request state");
693         // XXX: should forward error here
694         return;
695     }
696     st->my_mon_id = my_mon_id;
697     st->cap = cap;
698     st->capid = capid;
699
700     captx_prepare_send(cap, conn->core_id, true, &st->captx_state,
701                        cap_send_request_tx_cont, st);
702 }
703
704 static void span_domain_request(struct monitor_binding *mb,
705                                 uintptr_t domain_id, uint8_t core_id,
706                                 struct capref vroot, struct capref disp)
707 {
708     errval_t err, err2;
709
710     trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN0, core_id);
711
712     struct span_state *state;
713     uintptr_t state_id;
714
715     err = span_state_alloc(&state, &state_id);
716     if (err_is_fail(err)) {
717         err_push(err, MON_ERR_SPAN_STATE_ALLOC);
718         goto reply;
719     }
720
721     state->core_id   = core_id;
722     state->vroot     = vroot;
723     state->mb        = mb;
724     state->domain_id = domain_id;
725
726     trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN1, core_id);
727
728     /* Look up the destination monitor */
729     struct intermon_binding *ib;
730     err = intermon_binding_get(core_id, &ib);
731     if (err_is_fail(err)) {
732         goto reply;
733     }
734
735     /* Idenfity vroot */
736     struct capability vroot_cap;
737     err = monitor_cap_identify(vroot, &vroot_cap);
738     if (err_is_fail(err)) {
739         err_push(err, MON_ERR_CAP_IDENTIFY);
740         goto reply;
741     }
742     if (vroot_cap.type != ObjType_VNode_x86_64_pml4) { /* Check type */
743         err = MON_ERR_WRONG_CAP_TYPE;
744         goto reply;
745     }
746
747     /* Identify the dispatcher frame */
748     struct frame_identity frameid;
749     err = invoke_frame_identify(disp, &frameid);
750     if (err_is_fail(err)) {
751         err_push(err, LIB_ERR_FRAME_IDENTIFY);
752         goto reply;
753     }
754
755     err = monitor_remote_relations(disp, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
756     if (err_is_fail(err)) {
757         USER_PANIC_ERR(err, "monitor_remote_relations failed");
758         return;
759     }
760     err = monitor_remote_relations(vroot, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
761     if (err_is_fail(err)) {
762         USER_PANIC_ERR(err, "monitor_remote_relations failed");
763         return;
764     }
765
766     /* Send msg to destination monitor */
767     err = ib->tx_vtbl.span_domain_request(ib, NOP_CONT, state_id,
768                                           vroot_cap.u.vnode_x86_64_pml4.base,
769                                           frameid.base, frameid.bits);
770
771     if (err_is_fail(err)) {
772         err_push(err, MON_ERR_SEND_REMOTE_MSG);
773         goto reply;
774     }
775     goto cleanup;
776
777  reply:
778     err2 = mb->tx_vtbl.span_domain_reply(mb, NOP_CONT, err, domain_id);
779     if (err_is_fail(err2)) {
780         // XXX: Cleanup?
781         USER_PANIC_ERR(err2, "Failed to reply to the user domain");
782     }
783     if(state_id != 0) {
784         err2 = span_state_free(state_id);
785         if (err_is_fail(err2)) {
786             USER_PANIC_ERR(err2, "Failed to free span state");
787         }
788     }
789
790  cleanup:
791     err2 = cap_destroy(vroot);
792     if (err_is_fail(err2)) {
793         USER_PANIC_ERR(err2, "Failed to destroy span_vroot cap");
794     }
795     err2 = cap_destroy(disp);
796     if (err_is_fail(err2)) {
797         USER_PANIC_ERR(err2, "Failed to destroy disp cap");
798     }
799 }
800
801 static void migrate_dispatcher_request(struct monitor_binding *b,
802                                   coreid_t coreid, struct capref vroot,
803                                   struct capref disp)
804 {
805    printf("%s:%d\n", __FUNCTION__, __LINE__);
806 }
807
808 static void debug_print_capabilities(struct monitor_binding *b) {
809     sys_debug_print_capabilities();
810 }
811
812 struct monitor_rx_vtbl the_table = {
813     .alloc_iref_request = alloc_iref_request,
814
815     .bind_lmp_client_request= bind_lmp_client_request,
816     .bind_lmp_reply_monitor = bind_lmp_reply,
817
818     .boot_core_request = boot_core_request,
819     .multiboot_cap_request = ms_multiboot_cap_request,
820
821     .new_monitor_binding_request = new_monitor_binding_request,
822
823     .get_mem_iref_request  = get_mem_iref_request,
824     .get_name_iref_request = get_name_iref_request,
825     .get_ramfs_iref_request = get_ramfs_iref_request,
826     .set_mem_iref_request  = set_mem_iref_request,
827     .set_name_iref_request = set_name_iref_request,
828     .set_ramfs_iref_request = set_ramfs_iref_request,
829     .get_monitor_rpc_iref_request  = get_monitor_rpc_iref_request,
830
831     .cap_send_request = cap_send_request,
832     .cap_move_request = cap_send_request,
833
834     .span_domain_request    = span_domain_request,
835
836     .migrate_dispatcher_request = migrate_dispatcher_request,
837
838     .debug_print_capabilities = debug_print_capabilities
839 };
840
841 errval_t monitor_client_setup(struct spawninfo *si)
842 {
843     errval_t err;
844
845     struct monitor_lmp_binding *b =
846         malloc(sizeof(struct monitor_lmp_binding));
847     assert(b != NULL);
848
849     // setup our end of the binding
850     err = monitor_client_lmp_accept(b, get_default_waitset(),
851                                     DEFAULT_LMP_BUF_WORDS);
852     if (err_is_fail(err)) {
853         free(b);
854         return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
855     }
856
857     // copy the endpoint cap to the recipient
858     struct capref dest = {
859         .cnode = si->rootcn,
860         .slot  = ROOTCN_SLOT_MONITOREP,
861     };
862
863     err = cap_copy(dest, b->chan.local_cap);
864     if (err_is_fail(err)) {
865         // TODO: destroy binding
866         return err_push(err, LIB_ERR_CAP_COPY);
867     }
868
869     // Copy the performance monitoring cap to all spawned processes.
870     struct capref src;
871     dest.cnode = si->taskcn;
872     dest.slot = TASKCN_SLOT_PERF_MON;
873     src.cnode = cnode_task;
874     src.slot = TASKCN_SLOT_PERF_MON;
875     err = cap_copy(dest, src);
876     if (err_is_fail(err)) {
877         return err_push(err, INIT_ERR_COPY_PERF_MON);
878     }
879
880     // copy our receive vtable to the binding
881     monitor_server_init(&b->b);
882
883     return SYS_ERR_OK;
884 }
885
886 errval_t monitor_client_setup_mem_serv(void)
887 {
888     /* construct special-case LMP connection to mem_serv */
889     static struct monitor_lmp_binding mcb;
890     struct waitset *ws = get_default_waitset();
891     errval_t err;
892
893     err = monitor_client_lmp_accept(&mcb, ws, DEFAULT_LMP_BUF_WORDS);
894     if(err_is_fail(err)) {
895         USER_PANIC_ERR(err, "monitor_client_setup_mem_serv");
896     }
897     assert(err_is_ok(err));
898
899     /* Send the cap for this endpoint to init, who will pass it to the monitor */
900     err = lmp_ep_send0(cap_initep, 0, mcb.chan.local_cap);
901     if (err_is_fail(err)) {
902         USER_PANIC_ERR(err, "lmp_ep_send0 failed");
903     }
904
905     // copy our receive vtable to the binding
906     monitor_server_init(&mcb.b);
907
908     // XXX: handle messages (ie. block) until the monitor binding is ready
909     while (capref_is_null(mcb.chan.remote_cap)) {
910         err = event_dispatch(ws);
911         if (err_is_fail(err)) {
912             DEBUG_ERR(err, "in event_dispatch waiting for mem_serv binding");
913             return err_push(err, LIB_ERR_EVENT_DISPATCH);
914         }
915     }
916
917     return SYS_ERR_OK;
918 }
919
920 /// Setup a dummy monitor binding that "sends" all requests to the local handlers
921 errval_t monitor_client_setup_monitor(void)
922 {
923     monitor_loopback_init(&monitor_self_binding);
924     monitor_server_init(&monitor_self_binding);
925     set_monitor_binding(&monitor_self_binding);
926     caplock_init(get_default_waitset());
927     idc_init();
928     // XXX: Need a waitset here or loopback won't work as expected
929     // when binding to the ram_alloc service
930     monitor_self_binding.mutex.equeue.waitset = get_default_waitset();
931
932     return SYS_ERR_OK;
933 }
934
935 errval_t monitor_server_init(struct monitor_binding *b)
936 {
937     struct monitor_state *lst = malloc(sizeof(struct monitor_state));
938     assert(lst != NULL);
939     lst->queue.head = lst->queue.tail = NULL;
940
941     // copy our receive vtable to the new binding
942     b->rx_vtbl = the_table;
943     b->st = lst;
944     // TODO: set error_handler
945
946 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
947     errval_t err;
948     err = ump_monitor_init(b);
949     if (err_is_fail(err)) {
950         USER_PANIC_ERR(err, "ump_monitor_init failed");
951     }
952 #endif
953
954 #ifdef CONFIG_INTERCONNECT_DRIVER_MULTIHOP
955     errval_t err2;
956     err2 = multihop_monitor_init(b);
957     if (err_is_fail(err2)) {
958         USER_PANIC_ERR(err2, "multihop_monitor_init failed");
959     }
960 #endif // CONFIG_INTERCONNECT_DRIVER_MULTIHOP
961
962 #ifdef CONFIG_TRACE
963     errval_t err3;
964     err3 = bfscope_monitor_init(b);
965     if (err_is_fail(err3)) {
966         USER_PANIC_ERR(err3, "bfscope_monitor_init failed");
967     }
968
969     err3 = trace_monitor_init(b);
970     if (err_is_fail(err3)) {
971         USER_PANIC_ERR(err3, "trace_monitor_init failed");
972     }
973 #endif // CONFIG_TRACE
974
975     return monitor_server_arch_init(b);
976 }