Beispiel #1
0
static void
new_monitor_binding_reply_cont(struct monitor_binding *b,
                               errval_t reterr, struct capref retcap,
                               uintptr_t st)
{
    errval_t err =
        b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st);

    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct monitor_state *ms = b->st;
            struct new_monitor_binding_reply_state *me =
                malloc(sizeof(struct new_monitor_binding_reply_state));
            assert(me != NULL);
            me->args.err = reterr;
            me->args.ep = retcap;
            me->args.st = st;
            me->elem.cont = new_monitor_binding_reply_handler;
            err = monitor_enqueue_send(b, &ms->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }

        USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply");
    }
}
Beispiel #2
0
static void alloc_iref_reply_cont(struct monitor_binding *b,
                                    uintptr_t service_id,
                                    iref_t iref, errval_t reterr)
{
    errval_t err;

    err = b->tx_vtbl.alloc_iref_reply(b, NOP_CONT, service_id, iref, reterr);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct alloc_iref_reply_state *me =
                malloc(sizeof(struct alloc_iref_reply_state));
            assert(me != NULL);
            struct monitor_state *ist = b->st;
            assert(ist != NULL);
            me->args.service_id = service_id;
            me->args.iref = iref;
            me->args.err = reterr;
            me->b = b;
            me->elem.cont = alloc_iref_reply_handler;

            err = monitor_enqueue_send(b, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }

        USER_PANIC_ERR(err, "reply failed");
    }
}
Beispiel #3
0
static void ipi_alloc_notify_reply_cont(struct monitor_binding *b,
                                        uintptr_t state,
                                        struct capref notify_cap,
                                        errval_t reterr)
{
    errval_t err =
        b->tx_vtbl.ipi_alloc_notify_reply(b, NOP_CONT, state,
                                          notify_cap, reterr);

    if(err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct monitor_state *st = b->st;
            struct ipi_alloc_notify_reply_state *me =
                malloc(sizeof(struct ipi_alloc_notify_reply_state));
            assert(me != NULL);
            me->args.state = state;
            me->args.notify = notify_cap;
            me->args.err = reterr;
            me->elem.cont = ipi_alloc_notify_reply_handler;
            err = monitor_enqueue_send(b, &st->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }
        USER_PANIC_ERR(err, "sending reply");
    }
    assert(err_is_ok(err));
}
Beispiel #4
0
static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot)
{
    errval_t err1, err2;

    struct capref cap = {
        .cnode = cnode_module,
        .slot  = slot,
    };

    // Call frame_identify to check if cap exists
    struct frame_identity id;
    err1 = invoke_frame_identify(cap, &id);
    if (err_is_fail(err1)) {
        err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, NULL_CAP, err1);
    } else {
        err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1);
    }
    if (err_is_fail(err2)) {
        if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
            struct monitor_state *mon_state = b->st;
            struct multiboot_cap_state *ms =
                malloc(sizeof(struct multiboot_cap_state));
            assert(ms);
            ms->slot = slot;
            ms->elem.cont = ms_multiboot_cap_request_handler;
            err1 = monitor_enqueue_send(b, &mon_state->queue,
                                       get_default_waitset(), &ms->elem.queue);
            if (err_is_fail(err1)) {
                USER_PANIC_ERR(err1, "monitor_enqueue_send failed");
            }
        } else {
            USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed");
        }
    }
}
Beispiel #5
0
static void bind_ump_service_request_cont(struct monitor_binding *domain_binding,
                                          uintptr_t service_id,
                                          con_id_t my_mon_id,
                                          struct capref frame,
                                          uint32_t channel_length_in,
                                          uint32_t channel_length_out,
                                          struct capref notify_cap,
                                          struct intermon_binding *binding,
                                          con_id_t your_mon_id)
{
    errval_t err, err2;

    /* Proxy the request */
    err = domain_binding->tx_vtbl.
        bind_ump_service_request(domain_binding, NOP_CONT, service_id,
                                 my_mon_id, frame,
                                 channel_length_in, channel_length_out,
                                 notify_cap);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_ump_service_request_state *me =
                malloc(sizeof(struct bind_ump_service_request_state));
            struct monitor_state *ist = domain_binding->st;
            me->args.service_id = service_id;
            me->args.mon_id = my_mon_id;
            me->args.frame = frame;
            me->args.channel_length_in = channel_length_in;
            me->args.channel_length_out = channel_length_out;
            me->args.notify = notify_cap;
            me->binding = binding;
            me->your_mon_id = your_mon_id;
            me->elem.cont = bind_ump_service_request_handler;

            err = monitor_enqueue_send(domain_binding, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            assert(err_is_ok(err));
            return;
        }

        err2 = cap_delete(frame);
        if (err_is_fail(err2)) {
            USER_PANIC_ERR(err2, "Cap delete failed");
        }
        err2 = slot_free(frame);
        if (err_is_fail(err2)) {
            USER_PANIC_ERR(err2, "Cap destroy default failed");
        }
        err2 = remote_conn_free(my_mon_id);
        if (err_is_fail(err2)) {
            USER_PANIC_ERR(err2, "remote_conn_free failed");
        }
        intermon_caprep_t nullcap = {0,0,0,0};
        err2 = binding->tx_vtbl.bind_ump_reply(binding, NOP_CONT, your_mon_id, 0, err,
                                               nullcap);
        if (err_is_fail(err2)) {
            USER_PANIC_ERR(err2, "Sending bind_ump_reply1 failed");
        }
    }
}
Beispiel #6
0
static void bind_lmp_service_request_cont(struct monitor_binding *serv_binding,
                                          uintptr_t service_id, uintptr_t con_id,
                                          size_t buflen, struct capref ep,
                                          struct monitor_binding *b,
                                          uintptr_t domain_id)
{
    errval_t err, err2;

    struct monitor_state *ist = serv_binding->st;
    struct event_closure send_cont = NOP_CONT;
    struct capref *capp = NULL;

    if (serv_binding != &monitor_self_binding && b != &monitor_self_binding) {
        // save EP cap to be destroyed after the send is done
        capp = caprefdup(ep);
        send_cont = MKCONT(destroy_outgoing_cap, capp);
    }

    err = serv_binding->tx_vtbl.
        bind_lmp_service_request(serv_binding, send_cont, service_id,
                                 con_id, buflen, ep);
    if (err_is_fail(err)) {
        free(capp);

        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_lmp_service_request_state *me =
                malloc(sizeof(struct bind_lmp_service_request_state));
            assert(me != NULL);
            me->args.service_id = service_id;
            me->args.mon_id = con_id;
            me->args.buflen = buflen;
            me->args.ep = ep;
            me->b = b;
            me->domain_id = domain_id;
            me->elem.cont = bind_lmp_service_request_handler;

            err = monitor_enqueue_send(serv_binding, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }

        err2 = lmp_conn_free(con_id);
        if (err_is_fail(err2)) {
            USER_PANIC_ERR(err2, "lmp_conn_free failed");
        }
        bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep);
        return;
    }
}
Beispiel #7
0
static void bind_lmp_reply_client_cont(struct monitor_binding *client_binding,
                                       errval_t msgerr, uintptr_t mon_conn_id,
                                       uintptr_t client_conn_id,
                                       struct capref ep,
                                       struct monitor_binding *b)
{
    errval_t err;

    struct monitor_state *ist = client_binding->st;
    struct event_closure send_cont = NOP_CONT;
    struct capref *capp = NULL;

    if (client_binding != &monitor_self_binding && b != &monitor_self_binding) {
        // save EP cap to be destroyed after the send is done
        capp = caprefdup(ep);
        send_cont = MKCONT(destroy_outgoing_cap, capp);
    }

    err = client_binding->tx_vtbl.
        bind_lmp_reply_client(client_binding, send_cont,
                              SYS_ERR_OK, mon_conn_id, client_conn_id, ep);
    if (err_is_fail(err)) {
        free(capp);

        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_lmp_reply_client_state *me =
                malloc(sizeof(struct bind_lmp_reply_client_state));
            assert(me != NULL);
            me->args.err = msgerr;
            me->args.mon_id = mon_conn_id;
            me->args.conn_id = client_conn_id;
            me->args.ep = ep;
            me->b = b;
            me->elem.cont = bind_lmp_reply_client_handler;

            err = monitor_enqueue_send(client_binding, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }

        USER_PANIC_ERR(err, "failed sending IDC bind reply");
    }

    if(err_is_fail(msgerr)) {
        return;
    }
}
Beispiel #8
0
static void bind_lmp_client_request_error(struct monitor_binding *b,
                                          errval_t err, uintptr_t domain_id,
                                          struct monitor_binding *serv_binding,
                                          struct capref ep)
{
    errval_t err2;

    err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id,
                                            NULL_CAP);
    if (err_is_fail(err2)) {
        if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_lmp_client_request_error_state *me =
                malloc(sizeof(struct bind_lmp_client_request_error_state));
            assert(me != NULL);
            struct monitor_state *ist = b->st;
            assert(ist != NULL);
            me->args.err = err;
            me->args.conn_id = domain_id;
            me->serv_binding = serv_binding;
            me->ep = ep;
            me->elem.cont = bind_lmp_client_request_error_handler;

            err = monitor_enqueue_send(b, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
            }
            return;
        }

        USER_PANIC_ERR(err2, "error reply failed");
        USER_PANIC_ERR(err, "The reason for lmp failure");
    }

    /* Delete the EP cap */
    // Do not delete the cap if client or service is monitor itself
    if (b != &monitor_self_binding && serv_binding != &monitor_self_binding) {
        err = cap_destroy(ep);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "cap_destroy failed");
        }
    }
}
Beispiel #9
0
static void bind_ump_reply_client_cont(struct monitor_binding *domain_binding,
                                       uintptr_t my_mon_id,
                                       uintptr_t domain_id,
                                       errval_t msgerr,
                                       struct capref notify_cap)
{
    errval_t err;

    err = domain_binding->tx_vtbl.
        bind_ump_reply_client(domain_binding, NOP_CONT, my_mon_id, domain_id,
                              msgerr, notify_cap);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_ump_reply_client_state *me =
                malloc(sizeof(struct bind_ump_reply_client_state));
            struct monitor_state *ist = domain_binding->st;
            me->args.mon_id = my_mon_id;
            me->args.conn_id = domain_id;
            me->args.err = msgerr;
            me->args.notify = notify_cap;
            me->elem.cont = bind_ump_reply_client_handler;

            err = monitor_enqueue_send(domain_binding, &ist->queue,
                                       get_default_waitset(), &me->elem.queue);
            assert(err_is_ok(err));
            return;
        }

        USER_PANIC_ERR(err, "UMP bind reply failed");
        // cleanup
        err = remote_conn_free(my_mon_id);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "remote_conn_free failed");
        }
    }
}