1/**
2 * \file
3 * \brief UMP channel support
4 */
5
6/*
7 * Copyright (c) 2009, 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <inttypes.h>
16#include <if/monitor_blocking_defs.h>
17#include "monitor.h"
18/******* stack-ripped monitor_bind_ump_client_request *******/
19
20static void monitor_bind_ump_client_request_error(struct monitor_binding *b,
21                                                  struct capref frame,
22                                                  uintptr_t conn_id,
23                                                  uintptr_t domain_id,
24                                                  errval_t err)
25{
26    errval_t err2;
27
28    err2 = cap_destroy(frame);
29    if (err_is_fail(err2)) {
30        USER_PANIC_ERR(err, "cap_destroy failed");
31    }
32
33    if (conn_id != 0) {
34        err2 = remote_conn_free(conn_id);
35        if (err_is_fail(err2)) {
36            USER_PANIC_ERR(err2, "remote_conn_free failed");
37        }
38    }
39
40    err2 = b->tx_vtbl.bind_ump_reply_client(b, NOP_CONT, 0, domain_id, err,
41                                            NULL_CAP);
42    if (err_is_fail(err2)) {
43        USER_PANIC_ERR(err2, "error reply failed");
44    }
45}
46
47static void bind_ump_request_handler(struct intermon_binding *b,
48                                     struct intermon_msg_queue_elem *e);
49
50struct bind_ump_request_state {
51    struct intermon_msg_queue_elem elem;
52    struct intermon_bind_ump_request__tx_args args;
53    struct frame_identity frameid;
54    struct capability capability;
55    struct monitor_binding *mb;
56    struct capref frame;
57    uintptr_t domain_id;
58};
59
60static void bind_ump_request_cont(struct intermon_binding *intermon_binding,
61                                  iref_t iref, uintptr_t conn_id,
62                                  uint32_t channel_length_in,
63                                  uint32_t channel_length_out,
64                                  struct frame_identity frameid,
65                                  struct capability capability,
66                                  struct monitor_binding *mb,
67                                  struct capref frame,
68                                  uintptr_t domain_id)
69{
70    errval_t err;
71
72    intermon_caprep_t caprep;
73    capability_to_caprep(&capability, &caprep);
74
75    assert((1UL << log2ceil(frameid.bytes)) == frameid.bytes);
76    /* Send the request to the monitor on the server's core */
77    err = intermon_binding->tx_vtbl.
78        bind_ump_request(intermon_binding, NOP_CONT, iref, conn_id, channel_length_in,
79                         channel_length_out, frameid.base, log2ceil(frameid.bytes),
80                         caprep);
81    if (err_is_fail(err)) {
82        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
83            struct bind_ump_request_state *me =
84                malloc(sizeof(struct bind_ump_request_state));
85            struct intermon_state *ist = intermon_binding->st;
86            me->args.iref = iref;
87            me->args.mon_id = conn_id;
88            me->args.channel_length_in = channel_length_in;
89            me->args.channel_length_out = channel_length_out;
90            me->frameid = frameid;
91            me->capability = capability;
92            me->mb = mb;
93            me->frame = frame;
94            me->domain_id = domain_id;
95            me->elem.cont = bind_ump_request_handler;
96
97            err = intermon_enqueue_send(intermon_binding, &ist->queue,
98                                        get_default_waitset(), &me->elem.queue);
99            assert(err_is_ok(err));
100            return;
101        }
102
103        USER_PANIC_ERR(err, "failed forwarding UMP bind request");
104        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
105    }
106}
107
108static void bind_ump_request_handler(struct intermon_binding *b,
109                                     struct intermon_msg_queue_elem *e)
110{
111    struct bind_ump_request_state *st = (struct bind_ump_request_state *)e;
112    bind_ump_request_cont(b, st->args.iref, st->args.mon_id,
113                          st->args.channel_length_in,
114                          st->args.channel_length_out, st->frameid,
115                          st->capability, st->mb, st->frame, st->domain_id);
116    free(e);
117}
118
119static void monitor_bind_ump_client_request(struct monitor_binding *mb,
120                                            iref_t iref, uintptr_t domain_id,
121                                            struct capref frame,
122                                            size_t channel_length_in,
123                                            size_t channel_length_out,
124                                            struct capref notify)
125{
126    uint8_t core_id;
127    uintptr_t conn_id = 0;
128    errval_t err;
129    struct remote_conn_state *conn = NULL;
130
131    // Get the core id
132    err = iref_get_core_id(iref, &core_id);
133    if (err_is_fail(err)) {
134        debug_err(__FILE__, __func__, __LINE__, err, "iref_get_core_id failed");
135        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
136        return;
137    }
138
139    if (core_id == my_core_id) {
140        USER_PANIC("Same-core UMP binding NYI");
141    }
142
143    /* Identify frame */
144    struct frame_identity frameid;
145    err = frame_identify(frame, &frameid);
146    if (err_is_fail(err)) {
147        debug_err(__FILE__, __func__, __LINE__, err, "frame_identify failed");
148        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
149        return;
150    }
151
152    // Identify notify cap
153    struct capability capability;
154    err = monitor_cap_identify(notify, &capability);
155    if (err_is_fail(err)) {
156        USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
157        return;
158    }
159    assert(capability.type == ObjType_Notify_IPI
160           || capability.type == ObjType_Null);
161    /* assert(capability.u.notify.coreid == my_core_id); */
162
163    /* Forward request to the corresponding monitor */
164    // Create local state
165    err = remote_conn_alloc(&conn, &conn_id, REMOTE_CONN_UMP);
166    if (err_is_fail(err)) {
167        debug_err(__FILE__, __func__, __LINE__, err, "remote_conn_alloc failed");
168        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
169        return;
170    }
171
172    err = monitor_remote_relations(frame, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL);
173    if (err_is_fail(err)) {
174        DEBUG_ERR(err, "setting remote copy bit failed");
175        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
176        return;
177    }
178
179    // Track data
180    conn->domain_id = domain_id;
181    conn->domain_binding = mb;
182    conn->x.ump.frame = frame;
183    conn->core_id = core_id;
184
185    // Get connection to the monitor to forward request to
186    struct intermon_binding *intermon_binding;
187    err = intermon_binding_get(core_id, &intermon_binding);
188    if (err_is_fail(err)) {
189        debug_err(__FILE__, __func__, __LINE__, err, "intermon_binding_get failed");
190        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
191        return;
192    }
193
194    bind_ump_request_cont(intermon_binding, iref, conn_id, channel_length_in,
195                          channel_length_out, frameid, capability, mb, frame,
196                          domain_id);
197}
198
199/******* stack-ripped monitor_bind_ump_reply *******/
200
201static void bind_ump_reply_handler(struct intermon_binding *b,
202                                   struct intermon_msg_queue_elem *e);
203
204struct bind_ump_reply_state {
205    struct intermon_msg_queue_elem elem;
206    struct intermon_bind_ump_reply__tx_args args;
207    struct capability capability;
208};
209
210static void bind_ump_reply_cont(struct intermon_binding *mon_binding,
211                                uintptr_t your_mon_id, uintptr_t my_mon_id,
212                                uintptr_t msgerr, struct capability capability)
213{
214    errval_t err;
215
216    intermon_caprep_t caprep;
217    capability_to_caprep(&capability, &caprep);
218
219    err = mon_binding->tx_vtbl.
220        bind_ump_reply(mon_binding, NOP_CONT, your_mon_id, my_mon_id, msgerr,
221                       caprep);
222    if (err_is_fail(err)) {
223        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
224            struct bind_ump_reply_state *me =
225                malloc(sizeof(struct bind_ump_reply_state));
226            struct intermon_state *ist = mon_binding->st;
227            me->args.con_id = your_mon_id;
228            me->args.mon_id = my_mon_id;
229            me->args.err = msgerr;
230            me->capability = capability;
231            me->elem.cont = bind_ump_reply_handler;
232
233            err = intermon_enqueue_send(mon_binding, &ist->queue,
234                                        get_default_waitset(), &me->elem.queue);
235            assert(err_is_ok(err));
236            return;
237        }
238
239        USER_PANIC_ERR(err, "failed forwarding UMP bind reply");
240        // cleanup
241        if (err_is_ok(msgerr)) {
242            err = remote_conn_free(my_mon_id);
243            assert(err_is_ok(err));
244        }
245    }
246}
247
248static void bind_ump_reply_handler(struct intermon_binding *b,
249                                   struct intermon_msg_queue_elem *e)
250{
251    struct bind_ump_reply_state *st = (struct bind_ump_reply_state *)e;
252    bind_ump_reply_cont(b, st->args.con_id, st->args.mon_id, st->args.err,
253                        st->capability);
254    free(e);
255}
256
257static void monitor_bind_ump_reply(struct monitor_binding *dom_binding,
258                                   uintptr_t my_mon_id, uintptr_t domain_id,
259                                   errval_t msgerr, struct capref notify)
260{
261    errval_t err;
262
263    struct remote_conn_state *conn = remote_conn_lookup(my_mon_id);
264    if (conn == NULL) {
265        USER_PANIC("invalid mon_id in UMP bind reply");
266        return;
267    }
268
269    uintptr_t your_mon_id = conn->mon_id;
270    struct intermon_binding *mon_binding = conn->mon_binding;
271
272    if (err_is_ok(msgerr)) {
273        /* Connection accepted */
274        conn->domain_id = domain_id;
275        conn->domain_binding = dom_binding;
276    } else {
277//error:
278        /* Free the cap */
279        err = cap_destroy(conn->x.ump.frame);
280        assert(err_is_ok(err));
281
282        err = remote_conn_free(my_mon_id);
283        assert(err_is_ok(err));
284    }
285
286    // Identify notify cap
287    struct capability capability;
288    err = monitor_cap_identify(notify, &capability);
289    if (err_is_fail(err)) {
290        USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
291        return;
292    }
293    assert(capability.type == ObjType_Notify_IPI
294           || capability.type == ObjType_Null);
295    /* assert(capability.u.notify.coreid == my_core_id); */
296
297    bind_ump_reply_cont(mon_binding, your_mon_id, my_mon_id, msgerr, capability);
298}
299
300/******* stack-ripped intermon_ump_route_setup_reply *******/
301
302struct ump_route_setup_reply_state {
303    struct intermon_msg_queue_elem elem;
304    struct intermon_ump_route_setup_reply__tx_args args;
305};
306
307static void
308intermon_ump_route_setup_reply_handler(struct intermon_binding *b,
309                                       struct intermon_msg_queue_elem *e);
310
311static void intermon_ump_route_setup_reply_cont(struct intermon_binding *ib,
312                                                uintptr_t myconid, uintptr_t yourconid,
313                                                uintptr_t state, errval_t argerr)
314{
315    errval_t err;
316
317    err = ib->tx_vtbl.ump_route_setup_reply(ib, NOP_CONT, yourconid, myconid,
318                                            state, argerr);
319    if (err_is_fail(err)) {
320        if(err_no(err) != FLOUNDER_ERR_TX_BUSY) {
321            DEBUG_ERR(err, "non transient error in intermon binding\n");
322            return;
323        }
324        struct ump_route_setup_reply_state *rst = calloc(1, sizeof(*rst));
325        if (rst == NULL) {
326            DEBUG_ERR(err, "cannot allocate memory for reply state\n");
327            return;
328        }
329
330        rst->args.state = state;
331        rst->args.myconid = myconid;
332        rst->args.yourconid = yourconid;
333        rst->args.err = argerr;
334        rst->elem.cont = intermon_ump_route_setup_reply_handler;
335
336        struct intermon_state *ist = ib->st;
337        err = intermon_enqueue_send(ib, &ist->queue,
338                                    get_default_waitset(), &rst->elem.queue);
339        if (err_is_fail(err)) {
340            DEBUG_ERR(err, "faield to enqueue send");
341        }
342    }
343}
344
345
346static void
347intermon_ump_route_setup_reply_handler(struct intermon_binding *b,
348                                       struct intermon_msg_queue_elem *e)
349{
350    struct ump_route_setup_reply_state *st;
351
352    st = (struct ump_route_setup_reply_state *)e;
353    intermon_ump_route_setup_reply_cont(b, st->args.myconid, st->args.yourconid,
354                                        st->args.state, st->args.err);
355    free(e);
356}
357
358
359
360static void intermon_ump_route_setup_reply(struct intermon_binding *ib,
361                                           intermon_con_id_t myconid,
362                                           intermon_con_id_t yourconid,
363                                           intermon_mon_id_t state,
364                                           errval_t err)
365{
366    struct remote_conn_state *conn = remote_conn_lookup(myconid);
367
368    conn->mon_id = yourconid;
369    assert(conn->domain_binding);
370
371    struct monitor_lmp_binding *lmpb = (struct monitor_lmp_binding *)conn->domain_binding;
372
373    struct monitor_state *st = lmpb->b.st;
374    st->conn = conn;
375    /* send the reply */
376#ifndef __ARM_ARCH_7A__
377    struct monitor_blocking_binding *b = (void *) state;
378#else
379    struct monitor_blocking_binding *b = (void *)(uint32_t) state;
380#endif
381    err = b->tx_vtbl.new_monitor_binding_response(b, NOP_CONT, lmpb->chan.local_cap, err);
382}
383
384
385
386/******* stack-ripped intermon_ump_route_setup_request *******/
387
388struct ump_route_setup_request_state {
389    struct intermon_msg_queue_elem msgq;
390    struct remote_conn_state *cst;
391    struct monitor_blocking_binding *mb;
392};
393
394static void
395intermon_ump_route_setup_request_handler(struct intermon_binding *b,
396                                         struct intermon_msg_queue_elem *e)
397{
398    errval_t err;
399    struct ump_route_setup_request_state *st;
400
401    st = (struct ump_route_setup_request_state *)e;
402    err = ump_route_setup(b, st->mb, st->cst);
403    if (err_is_fail(err)) {
404        struct remote_conn_state *conn = st->cst;
405        assert(conn);
406        struct monitor_lmp_binding *lmpb = (struct monitor_lmp_binding *)conn->domain_binding;
407        monitor_lmp_destroy(lmpb);
408        free(conn->domain_binding);
409        remote_conn_free(remote_conn_get_id(conn));
410
411        err = st->mb->tx_vtbl.new_monitor_binding_response(st->mb, NOP_CONT,
412                                                           NULL_CAP, err);
413        assert(err_is_ok(err));
414    }
415    free(e);
416}
417
418
419errval_t ump_route_setup(struct intermon_binding *ib,
420                         struct monitor_blocking_binding *mb,
421                         struct remote_conn_state *cst)
422{
423    errval_t err;
424
425    uintptr_t conid = remote_conn_get_id(cst);
426    genpaddr_t ep = cst->x.ump.epid.base;
427    uint16_t type = cst->x.ump.epid.eptype;
428
429    debug_printf("Sending UMP Route Setup Request: conid=%p, mb=%p\n", cst, mb);
430
431    err = ib->tx_vtbl.ump_route_setup_request(ib, NOP_CONT, conid, (uintptr_t)mb,
432                                              my_core_id, ep, type);
433    if (err_is_fail(err)) {
434        if (err_no(err) != FLOUNDER_ERR_TX_BUSY) {
435            return err;
436        }
437
438        struct ump_route_setup_request_state *rst = calloc(1, sizeof(*rst));
439        if (rst == NULL) {
440            return LIB_ERR_MALLOC_FAIL;
441        }
442
443        rst->cst = cst;
444        rst->mb = mb;
445        rst->msgq.cont = intermon_ump_route_setup_request_handler;
446
447        struct intermon_state *ist = ib->st;
448        err =  intermon_enqueue_send(ib, &ist->queue, get_default_waitset(),
449                                    &rst->msgq.queue);
450        if(err_is_fail(err)) {
451            free(rst);
452            return err;
453        }
454    }
455
456    return SYS_ERR_OK;
457}
458
459static void intermon_ump_route_setup_request(struct intermon_binding *ib,
460                                             intermon_con_id_t conid,
461                                             intermon_mon_id_t state,
462                                             intermon_coreid_t core,
463                                             genpaddr_t ep, uint16_t type)
464{
465    errval_t err = SYS_ERR_OK;
466
467    struct remote_conn_state *conn = remote_conn_lookup_by_ep(ep, type);
468    if (conn == NULL) {
469        debug_printf("XXX NO ENDPOINT FOUND\n");
470        err = -1;
471        goto out;
472    }
473
474    conn->mon_binding = ib;
475    conn->mon_id = conid;
476    conn->core_id = core;
477
478    out:
479    intermon_ump_route_setup_reply_cont(ib, remote_conn_get_id(conn), conid,
480                                        state, err);
481}
482
483/******* stack-ripped intermon_bind_ump_request *******/
484
485static void bind_ump_service_request_handler(struct monitor_binding *b,
486                                             struct monitor_msg_queue_elem *e);
487
488struct bind_ump_service_request_state {
489    struct monitor_msg_queue_elem elem;
490    struct monitor_bind_ump_service_request__tx_args args;
491    struct intermon_binding *binding;
492    uintptr_t your_mon_id;
493};
494
495static void bind_ump_service_request_cont(struct monitor_binding *domain_binding,
496                                          uintptr_t service_id,
497                                          con_id_t my_mon_id,
498                                          struct capref frame,
499                                          uint32_t channel_length_in,
500                                          uint32_t channel_length_out,
501                                          struct capref notify_cap,
502                                          struct intermon_binding *binding,
503                                          con_id_t your_mon_id)
504{
505    errval_t err, err2;
506
507    /* Proxy the request */
508    err = domain_binding->tx_vtbl.
509        bind_ump_service_request(domain_binding, NOP_CONT, service_id,
510                                 my_mon_id, frame,
511                                 channel_length_in, channel_length_out,
512                                 notify_cap);
513    if (err_is_fail(err)) {
514        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
515            struct bind_ump_service_request_state *me =
516                malloc(sizeof(struct bind_ump_service_request_state));
517            struct monitor_state *ist = domain_binding->st;
518            me->args.service_id = service_id;
519            me->args.mon_id = my_mon_id;
520            me->args.frame = frame;
521            me->args.channel_length_in = channel_length_in;
522            me->args.channel_length_out = channel_length_out;
523            me->args.notify = notify_cap;
524            me->binding = binding;
525            me->your_mon_id = your_mon_id;
526            me->elem.cont = bind_ump_service_request_handler;
527
528            err = monitor_enqueue_send(domain_binding, &ist->queue,
529                                       get_default_waitset(), &me->elem.queue);
530            assert(err_is_ok(err));
531            return;
532        }
533
534        err2 = cap_destroy(frame);
535        if (err_is_fail(err2)) {
536            USER_PANIC_ERR(err2, "Cap destroy failed");
537        }
538        err2 = remote_conn_free(my_mon_id);
539        if (err_is_fail(err2)) {
540            USER_PANIC_ERR(err2, "remote_conn_free failed");
541        }
542        intermon_caprep_t nullcap = {0,0,0,0};
543        err2 = binding->tx_vtbl.bind_ump_reply(binding, NOP_CONT, your_mon_id, 0, err,
544                                               nullcap);
545        if (err_is_fail(err2)) {
546            USER_PANIC_ERR(err2, "Sending bind_ump_reply1 failed");
547        }
548    }
549}
550
551static void bind_ump_service_request_handler(struct monitor_binding *b,
552                                             struct monitor_msg_queue_elem *e)
553{
554    struct bind_ump_service_request_state *st = (struct bind_ump_service_request_state *)e;
555    bind_ump_service_request_cont(b, st->args.service_id, st->args.mon_id,
556                                  st->args.frame, st->args.channel_length_in,
557                                  st->args.channel_length_out, st->args.notify,
558                                  st->binding, st->your_mon_id);
559    free(e);
560}
561
562static void intermon_bind_ump_request(struct intermon_binding *ib,
563                                      iref_t iref, con_id_t your_mon_id,
564                                      uint32_t channel_length_in,
565                                      uint32_t channel_length_out,
566                                      genpaddr_t framebase, uint8_t framebits,
567                                      intermon_caprep_t caprep)
568{
569    errval_t err;
570
571    /* Get client's core_id */
572    struct intermon_state *ist = ib->st;
573    assert(ist != NULL);
574    coreid_t core_id = ist->core_id;
575
576    /* Construct the frame capability */
577    struct capability frame_cap = {
578        .type = ObjType_Frame,
579        .rights = CAPRIGHTS_READ_WRITE, // XXX
580        .u.frame = {
581            .base = framebase,
582            .bytes = 1UL << framebits
583        }
584    };
585
586    // Construct the notify cap
587    struct capref notify_cap = NULL_CAP;
588    struct capability capability;
589    caprep_to_capability(&caprep, &capability);
590    if(capability.type != ObjType_Null) {
591        err = slot_alloc(&notify_cap);
592        if (err_is_fail(err)) {
593            USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
594        }
595        err = monitor_cap_create(notify_cap, &capability, core_id);
596        if (err_is_fail(err)) {
597            USER_PANIC_ERR(err, "monitor_cap_create failed");
598        }
599    }
600
601    // XXX: Put frame cap on a separate allocator as it is not deleted anymore
602    struct capref frame;
603    err = slot_alloc(&frame);
604    if (err_is_fail(err)) {
605        USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
606    }
607    err = monitor_cap_create(frame, &frame_cap, core_id);
608    if (err_is_fail(err)) {
609        USER_PANIC_ERR(err, "monitor_cap_create failed");
610    }
611
612    /* Get the server's connection */
613    struct monitor_binding *domain_binding = NULL;
614    err = iref_get_binding(iref, &domain_binding);
615    assert(err_is_ok(err));
616
617    /* Get the service id */
618    uintptr_t service_id = 0;
619    err = iref_get_service_id(iref, &service_id);
620    assert(err_is_ok(err));
621
622    /* Create a new connection state */
623    uintptr_t my_mon_id;
624    struct remote_conn_state *con;
625    err = remote_conn_alloc(&con, &my_mon_id, REMOTE_CONN_UMP);
626    assert(err_is_ok(err));
627
628    // Set the monitor portion of it
629    con->mon_id = your_mon_id;
630    con->mon_binding = ib;
631    con->x.ump.frame = frame;
632    con->core_id = core_id;
633
634    bind_ump_service_request_cont(domain_binding, service_id, my_mon_id,
635                                  frame, channel_length_in, channel_length_out,
636                                  notify_cap, ib, your_mon_id);
637}
638
639/******* stack-ripped intermon_bind_ump_reply *******/
640
641static void bind_ump_reply_client_handler(struct monitor_binding *b,
642                                          struct monitor_msg_queue_elem *e);
643
644struct bind_ump_reply_client_state {
645    struct monitor_msg_queue_elem elem;
646    struct monitor_bind_ump_reply_client__tx_args args;
647};
648
649static void bind_ump_reply_client_cont(struct monitor_binding *domain_binding,
650                                       uintptr_t my_mon_id,
651                                       uintptr_t domain_id,
652                                       errval_t msgerr,
653                                       struct capref notify_cap)
654{
655    errval_t err;
656
657    err = domain_binding->tx_vtbl.
658        bind_ump_reply_client(domain_binding, NOP_CONT, my_mon_id, domain_id,
659                              msgerr, notify_cap);
660    if (err_is_fail(err)) {
661        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
662            struct bind_ump_reply_client_state *me =
663                malloc(sizeof(struct bind_ump_reply_client_state));
664            struct monitor_state *ist = domain_binding->st;
665            me->args.mon_id = my_mon_id;
666            me->args.conn_id = domain_id;
667            me->args.err = msgerr;
668            me->args.notify = notify_cap;
669            me->elem.cont = bind_ump_reply_client_handler;
670
671            err = monitor_enqueue_send(domain_binding, &ist->queue,
672                                       get_default_waitset(), &me->elem.queue);
673            assert(err_is_ok(err));
674            return;
675        }
676
677        USER_PANIC_ERR(err, "UMP bind reply failed");
678        // cleanup
679        err = remote_conn_free(my_mon_id);
680        if (err_is_fail(err)) {
681            USER_PANIC_ERR(err, "remote_conn_free failed");
682        }
683    }
684}
685
686static void bind_ump_reply_client_handler(struct monitor_binding *b,
687                                             struct monitor_msg_queue_elem *e)
688{
689    struct bind_ump_reply_client_state *st = (struct bind_ump_reply_client_state *)e;
690    bind_ump_reply_client_cont(b, st->args.mon_id, st->args.conn_id,
691                               st->args.err, st->args.notify);
692    free(e);
693}
694
695static void intermon_bind_ump_reply(struct intermon_binding *ib,
696                                    uint64_t my_mon_id, uint64_t your_mon_id,
697                                    errval_t msgerr,
698                                    intermon_caprep_t caprep)
699{
700    errval_t err;
701    struct remote_conn_state *con = remote_conn_lookup(my_mon_id);
702    if (con == NULL) {
703        USER_PANIC_ERR(0, "unknown mon_id in UMP bind reply");
704        return;
705    }
706
707    uintptr_t domain_id = con->domain_id;
708    struct monitor_binding *domain_binding = con->domain_binding;
709    struct capref notify_cap = NULL_CAP;
710
711    if (err_is_ok(msgerr)) { /* bind succeeded */
712        con->mon_id = your_mon_id;
713        con->mon_binding = ib;
714
715#if 0
716        /* map in UMP channel state */
717        void *buf;
718        err = vspace_map_one_frame_attr(&buf,
719              2 * (UMP_CHANNEL_SIZE + con->localchan.size * sizeof(uintptr_t)),
720                                        con->frame, VREGION_FLAGS_READ,
721                                        NULL, NULL);
722        if (err_is_fail(err)) {
723            USER_PANIC_ERR(err, "vspace_map_one_frame failed");
724            // XXX: should not be an assert, but we don't have any way to do
725            // connection teardown here!
726            assert(buf != NULL);
727        }
728        con->sharedchan = buf;
729        con->localchan.buf = buf + 2 * UMP_CHANNEL_SIZE;
730
731        // XXX: Put frame cap on a separate allocator as it is not deleted anymore
732        struct capref frame_copy;
733        err = slot_alloc(&frame_copy);
734        if (err_is_fail(err)) {
735            USER_PANIC_ERR(err, "Failed to allocator slot from channel_alloc");
736        }
737        err = cap_copy(frame_copy, con->frame);
738        if (err_is_fail(err)) {
739            USER_PANIC_ERR(err, "Failed create copy of frame cap");
740        }
741        err = cap_destroy(con->frame);
742        if (err_is_fail(err)) {
743            USER_PANIC_ERR(err, "cap_destroy_default failed");
744        }
745        con->frame = frame_copy;
746#endif
747
748        struct capability capability;
749        caprep_to_capability(&caprep, &capability);
750
751        if(capability.type != ObjType_Null) {
752            // Get core id of sender
753            coreid_t core_id = ((struct intermon_state *)ib->st)->core_id;
754
755            // Construct the notify cap
756            err = slot_alloc(&notify_cap);
757            if (err_is_fail(err)) {
758                USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
759            }
760
761            err = monitor_cap_create(notify_cap, &capability, core_id);
762            if (err_is_fail(err)) {
763                USER_PANIC_ERR(err, "monitor_cap_create failed");
764            }
765        }
766    } else { /* bind refused */
767        err = cap_destroy(con->x.ump.frame);
768        if (err_is_fail(err)) {
769            USER_PANIC_ERR(err, "cap_destroy_default failed");
770        }
771        err = remote_conn_free(my_mon_id);
772        assert(err_is_ok(err));
773    }
774
775    bind_ump_reply_client_cont(domain_binding, my_mon_id, domain_id, msgerr,
776                               notify_cap);
777}
778
779errval_t ump_intermon_init(struct intermon_binding *ib)
780{
781    ib->rx_vtbl.bind_ump_request = intermon_bind_ump_request;
782    ib->rx_vtbl.bind_ump_reply = intermon_bind_ump_reply;
783    ib->rx_vtbl.ump_route_setup_request = intermon_ump_route_setup_request;
784    ib->rx_vtbl.ump_route_setup_reply = intermon_ump_route_setup_reply;
785    return SYS_ERR_OK;
786}
787
788errval_t ump_monitor_init(struct monitor_binding *mb)
789{
790    mb->rx_vtbl.bind_ump_client_request = monitor_bind_ump_client_request;
791    mb->rx_vtbl.bind_ump_reply_monitor = monitor_bind_ump_reply;
792    return SYS_ERR_OK;
793}
794
795
796
797struct remote_conn_state *local_cst = NULL;
798
799
800errval_t remote_conn_alloc(struct remote_conn_state **con, uintptr_t *con_id,
801                           enum remote_conn_type type)
802{
803    struct remote_conn_state *mem = calloc(1, sizeof(struct remote_conn_state));
804    assert(mem != NULL);
805
806    *con = mem;
807    *con_id = (uintptr_t)mem;
808    mem->type = type;
809
810    mem->next = local_cst;
811    local_cst = mem;
812
813    return SYS_ERR_OK;
814}
815
816errval_t remote_conn_free(uintptr_t con_id)
817{
818    struct remote_conn_state *mem = (struct remote_conn_state*)con_id;
819    assert(mem != NULL);
820
821    if (mem->prev) {
822        mem->prev->next = mem->next;
823    }
824    if (mem->next) {
825        mem->next->prev = mem->prev;
826    }
827    free(mem);
828
829    return SYS_ERR_OK;
830}
831
832struct remote_conn_state *remote_conn_lookup(uintptr_t con_id)
833{
834    return (struct remote_conn_state *)con_id;
835}
836
837struct remote_conn_state *remote_conn_lookup_by_ep(genpaddr_t ep, uint16_t type)
838{
839    struct remote_conn_state *cst = local_cst;
840    while(cst) {
841        //debug_printf("remote_conn_lookup_by_ep %lx==%lx, %u==%u",
842         //            cst->x.ump.epid.base, ep, cst->x.ump.epid.eptype, type);
843        if (cst->x.ump.epid.base == ep && cst->x.ump.epid.eptype == type) {
844            return cst;
845        }
846        cst = cst->next;
847    }
848
849    return NULL;
850}
851