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