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