77571736af8e72e580b04753fc2b09d7f4a9f6bc
[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/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>
26 #include "capops.h"
27 #include "caplock.h"
28 #include "send_cap.h"
29
30 // the monitor's loopback binding to itself
31 static struct monitor_binding monitor_self_binding;
32
33 /* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */
34
35 struct multiboot_cap_state {
36     struct monitor_msg_queue_elem elem;
37     cslot_t slot;
38 };
39
40 struct proc_mgmt_bind_st {
41     errval_t err;
42     bool present;
43 };
44
45 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot);
46
47 static void ms_multiboot_cap_request_handler(struct monitor_binding *b,
48                                              struct monitor_msg_queue_elem *e)
49 {
50     struct multiboot_cap_state *ms = (struct multiboot_cap_state*)e;
51     ms_multiboot_cap_request(b, ms->slot);
52     free(ms);
53 }
54
55 static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot)
56 {
57     errval_t err1, err2;
58
59     struct capref cap = {
60         .cnode = cnode_module,
61         .slot  = slot,
62     };
63
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);
69     } else {
70         err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1);
71     }
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));
77             assert(ms);
78             ms->slot = slot;
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");
84             }
85         } else {
86             USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed");
87         }
88     }
89 }
90
91 /* ----------------------- MULTIBOOT REQUEST CODE END ----------------------- */
92
93 static void alloc_iref_reply_handler(struct monitor_binding *b,
94                                        struct monitor_msg_queue_elem *e);
95
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;
100 };
101
102 static void alloc_iref_reply_cont(struct monitor_binding *b,
103                                     uintptr_t service_id,
104                                     iref_t iref, errval_t reterr)
105 {
106     errval_t err;
107
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));
113             assert(me != NULL);
114             struct monitor_state *ist = b->st;
115             assert(ist != NULL);
116             me->args.service_id = service_id;
117             me->args.iref = iref;
118             me->args.err = reterr;
119             me->b = b;
120             me->elem.cont = alloc_iref_reply_handler;
121
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");
126             }
127             return;
128         }
129
130         USER_PANIC_ERR(err, "reply failed");
131     }
132 }
133
134 static void alloc_iref_reply_handler(struct monitor_binding *b,
135                                        struct monitor_msg_queue_elem *e)
136 {
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,
139                           st->args.err);
140     free(e);
141 }
142
143 static void alloc_iref_request(struct monitor_binding *b,
144                                uintptr_t service_id)
145 {
146     errval_t reterr;
147
148     iref_t iref = 0;
149     reterr = iref_alloc(b, service_id, &iref);
150     alloc_iref_reply_cont(b, service_id, iref, reterr);
151 }
152
153
154 static void get_service_id_reply_handler(struct monitor_binding *b,
155                                          struct monitor_msg_queue_elem *e);
156
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;
161 };
162
163 static void get_service_id_reply_cont(struct monitor_binding *b, errval_t reterr,
164                                       iref_t iref, uintptr_t service_id)
165 {
166     errval_t err;
167
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));
173             assert(me != NULL);
174             struct monitor_state *ist = b->st;
175             assert(ist != NULL);
176             me->args.err = reterr;
177             me->args.iref = iref;
178             me->args.service_id = service_id;
179             me->b = b;
180             me->elem.cont = get_service_id_reply_handler;
181
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");
186             }
187             return;
188         }
189
190         USER_PANIC_ERR(err, "reply failed");
191     }
192 }
193
194 static void get_service_id_reply_handler(struct monitor_binding *b,
195                                        struct monitor_msg_queue_elem *e)
196 {
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);
199     free(e);
200 }
201
202 static void get_service_id_request(struct monitor_binding *b, iref_t iref)
203 {
204     errval_t err;
205     struct monitor_binding *serv_binding = NULL;
206
207     /* Look up core_id from the iref */
208     uint8_t core_id;
209     iref_get_core_id(iref, &core_id);
210     
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);
214         return;
215     }
216
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);
221         return;
222     }
223
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);
228 }
229
230 /******* stack-ripped bind_lmp_service_request *******/
231
232 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
233                                                   struct monitor_msg_queue_elem *e);
234
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;
239     struct capref ep;
240 };
241
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,
245                                           struct capref ep)
246 {
247     errval_t err2;
248
249     err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id,
250                                             NULL_CAP);
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));
255             assert(me != NULL);
256             struct monitor_state *ist = b->st;
257             assert(ist != NULL);
258             me->args.err = err;
259             me->args.conn_id = domain_id;
260             me->serv_binding = serv_binding;
261             me->ep = ep;
262             me->elem.cont = bind_lmp_client_request_error_handler;
263
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");
268             }
269             return;
270         }
271
272         USER_PANIC_ERR(err2, "error reply failed");
273         USER_PANIC_ERR(err, "The reason for lmp failure");
274     }
275
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");
282         }
283     }
284 }
285
286 static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
287                                                   struct monitor_msg_queue_elem *e)
288 {
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);
292     free(e);
293 }
294
295 static void bind_lmp_service_request_handler(struct monitor_binding *b,
296                                              struct monitor_msg_queue_elem *e);
297
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;
302     uintptr_t domain_id;
303 };
304
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,
309                                           uintptr_t domain_id)
310 {
311     errval_t err, err2;
312
313     struct monitor_state *ist = serv_binding->st;
314     struct event_closure send_cont = NOP_CONT;
315     struct capref *capp = NULL;
316
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);
321     }
322
323     err = serv_binding->tx_vtbl.
324         bind_lmp_service_request(serv_binding, send_cont, service_id,
325                                  con_id, buflen, ep);
326     if (err_is_fail(err)) {
327         free(capp);
328
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));
332             assert(me != NULL);
333             me->args.service_id = service_id;
334             me->args.mon_id = con_id;
335             me->args.buflen = buflen;
336             me->args.ep = ep;
337             me->b = b;
338             me->domain_id = domain_id;
339             me->elem.cont = bind_lmp_service_request_handler;
340
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");
345             }
346             return;
347         }
348
349         err2 = lmp_conn_free(con_id);
350         if (err_is_fail(err2)) {
351             USER_PANIC_ERR(err2, "lmp_conn_free failed");
352         }
353         bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
354         return;
355     }
356 }
357
358 static void bind_lmp_service_request_handler(struct monitor_binding *b,
359                                              struct monitor_msg_queue_elem *e)
360 {
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,
364                                   st->domain_id);
365     free(e);
366 }
367
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)
371 {
372     errval_t err;
373     struct monitor_binding *serv_binding = NULL;
374
375     /* Look up core_id from the iref */
376     uint8_t core_id;
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);
380         return;
381     }
382
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);
387         return;
388     }
389
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);
394         return;
395     }
396
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);
402         return;
403     }
404
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);
408         return;
409     }
410
411     /* Allocate a new monitor connection */
412     uintptr_t con_id;
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);
417         return;
418     }
419
420     conn->domain_id = domain_id;
421     conn->domain_binding = b;
422
423     /* Send request to the server */
424     bind_lmp_service_request_cont(serv_binding, service_id, con_id, buflen, ep,
425                                   b, domain_id);
426 }
427
428 /******* stack-ripped bind_lmp_reply *******/
429
430 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
431                                           struct monitor_msg_queue_elem *e);
432
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;
437 };
438
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,
442                                        struct capref ep,
443                                        struct monitor_binding *b)
444 {
445     errval_t err;
446
447     struct monitor_state *ist = client_binding->st;
448     struct event_closure send_cont = NOP_CONT;
449     struct capref *capp = NULL;
450
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);
455     }
456
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)) {
461         free(capp);
462
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));
466             assert(me != NULL);
467             me->args.err = msgerr;
468             me->args.mon_id = mon_conn_id;
469             me->args.conn_id = client_conn_id;
470             me->args.ep = ep;
471             me->b = b;
472             me->elem.cont = bind_lmp_reply_client_handler;
473
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");
478             }
479             return;
480         }
481
482         USER_PANIC_ERR(err, "failed sending IDC bind reply");
483     }
484
485     if(err_is_fail(msgerr)) {
486         return;
487     }
488 }
489
490 static void bind_lmp_reply_client_handler(struct monitor_binding *b,
491                                           struct monitor_msg_queue_elem *e)
492 {
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,
495                                st->args.ep, st->b);
496     free(e);
497 }
498
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)
502 {
503     errval_t err;
504     struct monitor_binding *client_binding = NULL;
505
506     struct lmp_conn_state *conn = lmp_conn_lookup(mon_conn_id);
507     if (conn == NULL) {
508         DEBUG_ERR(0, "invalid connection ID");
509         goto cleanup;
510     }
511
512     client_binding = conn->domain_binding;
513     uintptr_t client_conn_id = conn->domain_id;
514
515     err = lmp_conn_free(mon_conn_id);
516     assert(err_is_ok(err));
517
518     if (err_is_fail(msgerr)) {
519         bind_lmp_reply_client_cont(client_binding, msgerr, 0, client_conn_id,
520                                    ep, b);
521     } else {
522         bind_lmp_reply_client_cont(client_binding, SYS_ERR_OK, mon_conn_id,
523                                    client_conn_id, ep, b);
524     }
525     return;
526
527 cleanup:
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");
534         }
535     }
536 }
537
538 /* ---------------------- NEW MONITOR BINDING CODE START -------------------- */
539
540 struct new_monitor_binding_reply_state {
541     struct monitor_msg_queue_elem elem;
542     struct monitor_new_monitor_binding_reply__tx_args args;
543 };
544
545 static void
546 new_monitor_binding_reply_cont(struct monitor_binding *b,
547                                errval_t reterr, struct capref retcap,
548                                uintptr_t st);
549
550 static void new_monitor_binding_reply_handler(struct monitor_binding *b,
551                                               struct monitor_msg_queue_elem *e)
552 {
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);
556     free(st);
557 }
558
559 static void
560 new_monitor_binding_reply_cont(struct monitor_binding *b,
561                                errval_t reterr, struct capref retcap,
562                                uintptr_t st)
563 {
564     errval_t err =
565         b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st);
566
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));
572             assert(me != NULL);
573             me->args.err = reterr;
574             me->args.ep = retcap;
575             me->args.st = st;
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");
581             }
582             return;
583         }
584
585         USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply");
586     }
587 }
588
589 /**
590  * \brief Setup a new idc channel between monitor and domain
591  *
592  * \bug on error send message back to domain
593  */
594 static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st)
595 {
596     struct capref retcap = NULL_CAP;
597     errval_t err, reterr = SYS_ERR_OK;
598
599     struct monitor_lmp_binding *lmpb =
600         malloc(sizeof(struct monitor_lmp_binding));
601     assert(lmpb != NULL);
602
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)) {
607         free(lmpb);
608         reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
609         goto out;
610     }
611
612     retcap = lmpb->chan.local_cap;
613     monitor_server_init(&lmpb->b);
614
615 out:
616     new_monitor_binding_reply_cont(b, reterr, retcap, st);
617 }
618
619 /* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */
620
621 static void get_mem_iref_request(struct monitor_binding *b)
622 {
623     errval_t err;
624
625     // Mem serv not registered yet
626     assert(mem_serv_iref != 0);
627
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");
631     }
632 }
633
634 static void get_name_iref_request(struct monitor_binding *b, uintptr_t st)
635 {
636     errval_t err;
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");
640     }
641 }
642
643 static void get_ramfs_iref_request(struct monitor_binding *b, uintptr_t st)
644 {
645     errval_t err;
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");
649     }
650 }
651
652 static void set_mem_iref_request(struct monitor_binding *b,
653                                  iref_t iref)
654 {
655     mem_serv_iref = iref;
656     update_ram_alloc_binding = true;
657 }
658
659 static void get_monitor_rpc_iref_request(struct monitor_binding *b,
660                                          uintptr_t st_arg)
661 {
662     errval_t err;
663
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");
667     }
668
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");
673     }
674 }
675
676
677 void set_monitor_rpc_iref(iref_t iref)
678 {
679     if (monitor_rpc_iref != 0) {
680         // Called multiple times, return error
681         DEBUG_ERR(0, "Attempt to reset monitor rpc IREF ignored");
682         return;
683     }
684
685     monitor_rpc_iref = iref;
686 }
687
688
689 static void set_name_iref_request(struct monitor_binding *b,
690                                   iref_t iref)
691 {
692     if (name_serv_iref != 0) {
693         // Called multiple times, return error
694         DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
695         return;
696     }
697
698     name_serv_iref = iref;
699 }
700
701 static void set_ramfs_iref_request(struct monitor_binding *b,
702                                   iref_t iref)
703 {
704     if (ramfs_serv_iref != 0) {
705         // Called multiple times, return error
706         DEBUG_ERR(0, "Attempt to reset name serv IREF ignored");
707         return;
708     }
709
710     ramfs_serv_iref = iref;
711 }
712
713 static void proc_mgmt_bind_cont(void *st,
714                                 errval_t err,
715                                 struct proc_mgmt_binding *b)
716 {
717     struct proc_mgmt_bind_st* bind_st = (struct proc_mgmt_bind_st*) st;
718     assert(!bind_st->present);
719     bind_st->err = err;
720     bind_st->present = true;
721 }
722
723 static void set_proc_mgmt_ep_request(struct monitor_binding *b,
724                                      struct capref ep)
725 {
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);
731
732     set_proc_mgmt_binding(&lmpb->b);
733
734     struct proc_mgmt_bind_st bind_st = {
735         .present = false
736     };
737     errval_t err = proc_mgmt_client_lmp_bind(lmpb,
738                                              ep,
739                                              proc_mgmt_bind_cont,
740                                              &bind_st,
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");
745     }
746
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");
752         }
753     }
754
755     if(err_is_fail(bind_st.err)) {
756         USER_PANIC_ERR(err, "during proc_mgmt bind initialization");
757     }
758
759     proc_mgmt_rpc_client_init(&lmpb->b);
760 }
761
762 static void set_spawn_iref_request(struct monitor_binding *b, iref_t iref)
763 {
764     if (spawn_iref != 0) {
765         // Called multiple times, return error
766         DEBUG_ERR(0, "Attempt to reset spawn IREF ignored");
767         return;
768     }
769
770     spawn_iref = iref;
771 }
772
773 struct send_cap_st {
774     struct intermon_msg_queue_elem qe; // must be first
775     uintptr_t my_mon_id;
776     struct capref cap;
777     uint32_t capid;
778     uint8_t give_away;
779     struct captx_prepare_state captx_state;
780     intermon_captx_t captx;
781 };
782
783 static void
784 cap_send_tx_cont(struct intermon_binding *b,
785                  struct intermon_msg_queue_elem *e)
786 {
787     DEBUG_CAPOPS("%s: %p %p\n", __FUNCTION__, b, e);
788     errval_t send_err;
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");
795     }
796     free(st);
797 }
798
799 static void
800 cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st,
801                          intermon_captx_t *captx, void *st_)
802 {
803     DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0));
804     errval_t queue_err;
805     struct send_cap_st *send_st = (struct send_cap_st*)st_;
806
807     if (err_is_fail(err)) {
808         // XXX: should forward error here
809         DEBUG_ERR(err, "preparing cap tx failed");
810         free(send_st);
811         return;
812     }
813
814     send_st->captx = *captx;
815
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,
822                                       binding->waitset,
823                                       (struct msg_queue_elem*)send_st);
824     if (err_is_fail(queue_err)) {
825         DEBUG_ERR(queue_err, "enqueuing cap_send_request failed");
826         free(send_st);
827     }
828 }
829
830 static void
831 cap_send_request(struct monitor_binding *b, uintptr_t my_mon_id,
832                  struct capref cap, uint32_t capid)
833 {
834     DEBUG_CAPOPS("cap_send_request\n");
835     errval_t err;
836     struct remote_conn_state *conn = remote_conn_lookup(my_mon_id);
837
838     struct send_cap_st *st;
839     st = calloc(1, sizeof(*st));
840     if (!st) {
841         err = LIB_ERR_MALLOC_FAIL;
842         DEBUG_ERR(err, "Failed to allocate cap_send_request state");
843         // XXX: should forward error here
844         return;
845     }
846     st->my_mon_id = my_mon_id;
847     st->cap = cap;
848     st->capid = capid;
849
850     captx_prepare_send(cap, conn->core_id, true, &st->captx_state,
851                        cap_send_request_tx_cont, st);
852 }
853
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)
857 {
858     errval_t err, err2;
859
860     trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN0, core_id);
861
862     struct span_state *state;
863     uintptr_t state_id;
864
865     err = span_state_alloc(&state, &state_id);
866     if (err_is_fail(err)) {
867         err_push(err, MON_ERR_SPAN_STATE_ALLOC);
868         goto reply;
869     }
870
871     state->core_id   = core_id;
872     state->vroot     = vroot;
873     state->mb        = mb;
874     state->domain_id = domain_id;
875
876     trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN1, core_id);
877
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)) {
882         goto reply;
883     }
884
885     /* Idenfity vroot */
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);
890         goto reply;
891     }
892     if (vroot_cap.type != ObjType_VNode_x86_64_pml4) { /* Check type */
893         err = MON_ERR_WRONG_CAP_TYPE;
894         goto reply;
895     }
896
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);
902         goto reply;
903     }
904
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");
908         return;
909     }
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");
913         return;
914     }
915
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);
921
922     if (err_is_fail(err)) {
923         err_push(err, MON_ERR_SEND_REMOTE_MSG);
924         goto reply;
925     }
926     goto cleanup;
927
928  reply:
929     err2 = mb->tx_vtbl.span_domain_reply(mb, NOP_CONT, err, domain_id);
930     if (err_is_fail(err2)) {
931         // XXX: Cleanup?
932         USER_PANIC_ERR(err2, "Failed to reply to the user domain");
933     }
934     if(state_id != 0) {
935         err2 = span_state_free(state_id);
936         if (err_is_fail(err2)) {
937             USER_PANIC_ERR(err2, "Failed to free span state");
938         }
939     }
940
941  cleanup:
942     err2 = cap_destroy(vroot);
943     if (err_is_fail(err2)) {
944         USER_PANIC_ERR(err2, "Failed to destroy span_vroot cap");
945     }
946     err2 = cap_destroy(disp);
947     if (err_is_fail(err2)) {
948         USER_PANIC_ERR(err2, "Failed to destroy disp cap");
949     }
950 }
951
952 static void migrate_dispatcher_request(struct monitor_binding *b,
953                                   coreid_t coreid, struct capref vroot,
954                                   struct capref disp)
955 {
956    printf("%s:%d\n", __FUNCTION__, __LINE__);
957 }
958
959 struct monitor_rx_vtbl the_table = {
960     .alloc_iref_request = alloc_iref_request,
961     .get_service_id_request = get_service_id_request,
962
963     .bind_lmp_client_request= bind_lmp_client_request,
964     .bind_lmp_reply_monitor = bind_lmp_reply,
965
966     .boot_core_request = boot_core_request,
967     .multiboot_cap_request = ms_multiboot_cap_request,
968
969     .new_monitor_binding_request = new_monitor_binding_request,
970
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,
980
981     .cap_send_request = cap_send_request,
982     .cap_move_request = cap_send_request,
983
984     .span_domain_request    = span_domain_request,
985
986     .migrate_dispatcher_request = migrate_dispatcher_request,
987 };
988
989 errval_t monitor_client_setup(struct spawninfo *si)
990 {
991     errval_t err;
992
993     struct monitor_lmp_binding *b =
994         malloc(sizeof(struct monitor_lmp_binding));
995     assert(b != NULL);
996
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)) {
1001         free(b);
1002         return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT);
1003     }
1004
1005     // copy the endpoint cap to the recipient
1006     struct capref dest = {
1007         .cnode = si->taskcn,
1008         .slot  = TASKCN_SLOT_MONITOREP,
1009     };
1010
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);
1015     }
1016
1017     // Copy the performance monitoring cap to all spawned processes.
1018     struct capref src;
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);
1026     }
1027
1028     // copy our receive vtable to the binding
1029     monitor_server_init(&b->b);
1030
1031     return SYS_ERR_OK;
1032 }
1033
1034 errval_t monitor_client_setup_mem_serv(void)
1035 {
1036     /* construct special-case LMP connection to mem_serv */
1037     static struct monitor_lmp_binding mcb;
1038     struct waitset *ws = get_default_waitset();
1039     errval_t err;
1040
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");
1044     }
1045     assert(err_is_ok(err));
1046
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");
1051     }
1052
1053     // copy our receive vtable to the binding
1054     monitor_server_init(&mcb.b);
1055
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);
1062         }
1063     }
1064
1065     return SYS_ERR_OK;
1066 }
1067
1068 /// Setup a dummy monitor binding that "sends" all requests to the local handlers
1069 errval_t monitor_client_setup_monitor(void)
1070 {
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());
1075     idc_init();
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();
1079
1080     return SYS_ERR_OK;
1081 }
1082
1083 errval_t monitor_server_init(struct monitor_binding *b)
1084 {
1085     struct monitor_state *lst = malloc(sizeof(struct monitor_state));
1086     assert(lst != NULL);
1087     lst->queue.head = lst->queue.tail = NULL;
1088
1089     // copy our receive vtable to the new binding
1090     b->rx_vtbl = the_table;
1091     b->st = lst;
1092     // TODO: set error_handler
1093
1094 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
1095     errval_t err;
1096     err = ump_monitor_init(b);
1097     if (err_is_fail(err)) {
1098         USER_PANIC_ERR(err, "ump_monitor_init failed");
1099     }
1100 #endif
1101
1102 #ifdef CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1103     errval_t err2;
1104     err2 = multihop_monitor_init(b);
1105     if (err_is_fail(err2)) {
1106         USER_PANIC_ERR(err2, "multihop_monitor_init failed");
1107     }
1108 #endif // CONFIG_INTERCONNECT_DRIVER_MULTIHOP
1109
1110 #ifdef CONFIG_TRACE
1111     errval_t err3;
1112     err3 = bfscope_monitor_init(b);
1113     if (err_is_fail(err3)) {
1114         USER_PANIC_ERR(err3, "bfscope_monitor_init failed");
1115     }
1116
1117     err3 = trace_monitor_init(b);
1118     if (err_is_fail(err3)) {
1119         USER_PANIC_ERR(err3, "trace_monitor_init failed");
1120     }
1121 #endif // CONFIG_TRACE
1122
1123     return monitor_server_arch_init(b);
1124 }