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/spawn_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
32static struct monitor_binding monitor_self_binding;
33
34/* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */
35
36struct multiboot_cap_state {
37    struct monitor_msg_queue_elem elem;
38    cslot_t slot;
39};
40
41struct proc_mgmt_bind_st {
42    errval_t err;
43    bool present;
44};
45
46static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot);
47
48static 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
56static 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
94static void alloc_iref_reply_handler(struct monitor_binding *b,
95                                       struct monitor_msg_queue_elem *e);
96
97struct 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
103static 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
135static 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
144static 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
155static void get_service_id_reply_handler(struct monitor_binding *b,
156                                         struct monitor_msg_queue_elem *e);
157
158struct 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
164static 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
195static 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
203static 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
233static void bind_lmp_client_request_error_handler(struct monitor_binding *b,
234                                                  struct monitor_msg_queue_elem *e);
235
236struct 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
243static 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
287static 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
296static void bind_lmp_service_request_handler(struct monitor_binding *b,
297                                             struct monitor_msg_queue_elem *e);
298
299struct 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
306static 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
359static 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
369static 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
431static void bind_lmp_reply_client_handler(struct monitor_binding *b,
432                                          struct monitor_msg_queue_elem *e);
433
434struct 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
440static 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
491static 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
500static 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
528cleanup:
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
541struct new_monitor_binding_reply_state {
542    struct monitor_msg_queue_elem elem;
543    struct monitor_new_monitor_binding_reply__tx_args args;
544};
545
546static void
547new_monitor_binding_reply_cont(struct monitor_binding *b,
548                               errval_t reterr, struct capref retcap,
549                               uintptr_t st);
550
551static 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
560static void
561new_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 */
595static 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
616out:
617    new_monitor_binding_reply_cont(b, reterr, retcap, st);
618}
619
620/* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */
621
622static 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
635static 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
644static 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
653static 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
660static 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
678void 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
690static 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
702static 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
714static 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
724static 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
763static 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
774struct 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
784static void
785cap_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
800static void
801cap_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
831static void
832cap_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
855static 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
953static 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
960struct 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
990errval_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
1035errval_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
1070errval_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
1084errval_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}
1126