Esempio n. 1
0
static void
cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st,
                         intermon_captx_t *captx, void *st_)
{
    DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0));
    errval_t queue_err;
    struct send_cap_st *send_st = (struct send_cap_st*)st_;

    if (err_is_fail(err)) {
        // XXX: should forward error here
        DEBUG_ERR(err, "preparing cap tx failed");
        free(send_st);
        return;
    }

    send_st->captx = *captx;

    DEBUG_CAPOPS("%s: enqueueing send\n", __FUNCTION__);
    send_st->qe.cont = cap_send_tx_cont;
    struct remote_conn_state *conn = remote_conn_lookup(send_st->my_mon_id);
    struct intermon_binding *binding = conn->mon_binding;
    struct intermon_state *inter_st = (struct intermon_state*)binding->st;
    queue_err = intermon_enqueue_send(binding, &inter_st->queue,
                                      binding->waitset,
                                      (struct msg_queue_elem*)send_st);
    if (err_is_fail(queue_err)) {
        DEBUG_ERR(queue_err, "enqueuing cap_send_request failed");
        free(send_st);
    }
}
Esempio n. 2
0
static void bind_monitor_reply_scc_cont(struct intermon_binding *b,
                                        errval_t err, chanid_t chanid)
{
    errval_t err2;

    err2 = b->tx_vtbl.bind_monitor_reply_scc(b, NOP_CONT, err,
            chanid, my_core_id);
    if (err_is_fail(err2)) {
        if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_monitor_reply_scc_state *me =
                malloc(sizeof(struct bind_monitor_reply_scc_state));
            assert(me != NULL);
            struct intermon_state *ist = b->st;
            assert(ist != NULL);
            me->args.err = err;
            me->args.chan_id = chanid;
            me->elem.cont = bind_monitor_reply_scc_handler;

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

        DEBUG_ERR(err2, "reply failed");
    }
}
Esempio n. 3
0
static void bind_ump_request_cont(struct intermon_binding *intermon_binding,
                                  iref_t iref, uintptr_t conn_id,
                                  uint32_t channel_length_in,
                                  uint32_t channel_length_out,
                                  struct frame_identity frameid,
                                  struct capability capability,
                                  struct monitor_binding *mb,
                                  struct capref frame,
                                  uintptr_t domain_id)
{
    errval_t err;

    intermon_caprep_t caprep;
    capability_to_caprep(&capability, &caprep);

    /* Send the request to the monitor on the server's core */
    err = intermon_binding->tx_vtbl.
        bind_ump_request(intermon_binding, NOP_CONT, iref, conn_id, channel_length_in,
                         channel_length_out, frameid.base, frameid.bits,
                         caprep);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_ump_request_state *me =
                malloc(sizeof(struct bind_ump_request_state));
            struct intermon_state *ist = intermon_binding->st;
            me->args.iref = iref;
            me->args.mon_id = conn_id;
            me->args.channel_length_in = channel_length_in;
            me->args.channel_length_out = channel_length_out;
            me->frameid = frameid;
            me->capability = capability;
            me->mb = mb;
            me->frame = frame;
            me->domain_id = domain_id;
            me->elem.cont = bind_ump_request_handler;

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

        USER_PANIC_ERR(err, "failed forwarding UMP bind request");
        monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err);
    }
}
Esempio n. 4
0
errval_t
capsend_target(coreid_t dest, struct msg_queue_elem *queue_elem)
{
    errval_t err;

    // get destination intermon_binding and _state
    struct intermon_binding *dest_b;
    err = intermon_binding_get(dest, &dest_b);
    if (err_is_fail(err)) {
        return err;
    }
    DEBUG_CAPOPS("capsend_target: ->%d (%p)\n", dest, queue_elem);
    struct intermon_state *inter_st = (struct intermon_state*)dest_b->st;
    if (!inter_st->capops_ready) {
        // XXX: custom error value
        return MON_ERR_CAPOPS_BUSY;
    }

    // enqueue message
    return intermon_enqueue_send(dest_b, &inter_st->queue, dest_b->waitset, queue_elem);
}
Esempio n. 5
0
static void bind_ump_reply_cont(struct intermon_binding *mon_binding,
                                uintptr_t your_mon_id, uintptr_t my_mon_id,
                                uintptr_t msgerr, struct capability capability)
{
    errval_t err;

    intermon_caprep_t caprep;
    capability_to_caprep(&capability, &caprep);

    err = mon_binding->tx_vtbl.
        bind_ump_reply(mon_binding, NOP_CONT, your_mon_id, my_mon_id, msgerr,
                       caprep);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_ump_reply_state *me =
                malloc(sizeof(struct bind_ump_reply_state));
            struct intermon_state *ist = mon_binding->st;
            me->args.con_id = your_mon_id;
            me->args.mon_id = my_mon_id;
            me->args.err = msgerr;
            me->capability = capability;
            me->elem.cont = bind_ump_reply_handler;

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

        USER_PANIC_ERR(err, "failed forwarding UMP bind reply");
        // cleanup
        if (err_is_ok(msgerr)) {
            err = remote_conn_free(my_mon_id);
            assert(err_is_ok(err));
        }
    }
}
Esempio n. 6
0
/**
 * \brief A monitor receives request to setup a connection
 * with another newly booted monitor from a third monitor
 */
static void bind_monitor_request_scc(struct intermon_binding *b,
                                     coreid_t core_id,
                                     intermon_caprep_t caprep,
                                     chanid_t chan_id,
                                     coreid_t from_core_id)
{
    struct intermon_ump_ipi_binding *umpb = NULL;
    errval_t err;

    /* Create the cap */
    struct capability cap_raw;
    caprep_to_capability(&caprep, &cap_raw);
    if (cap_raw.type != ObjType_Frame) {
        err = MON_ERR_WRONG_CAP_TYPE;
        goto error;
    }

    struct capref frame;
    err = slot_alloc(&frame);
    if (err_is_fail(err)) {
        goto error;
    }

    ram_set_affinity(cap_raw.u.frame.base, cap_raw.u.frame.base + ((genpaddr_t)1 << cap_raw.u.frame.bits));
    err = frame_alloc(&frame, ((genpaddr_t)1 << cap_raw.u.frame.bits), NULL);
    ram_set_affinity(0,0);

    /* err = monitor_cap_create(frame, &cap_raw, core_id); */
    if (err_is_fail(err)) {
        goto error;
    }

    struct frame_identity frameid = { .base = 0, .bits = 0 };
    err = invoke_frame_identify(frame, &frameid);
    assert(err == SYS_ERR_OK);

    printf("bind_monitor_request: URPC physical frame at 0x%llx\n", frameid.base);

    /* Setup the connection */
    void *buf;
    err = vspace_map_one_frame_attr(&buf, MON_URPC_SIZE, frame,
                                    VREGION_FLAGS_READ_WRITE_NOCACHE, NULL,
                                    NULL);
    if (err_is_fail(err)) {
        err = err_push(err, LIB_ERR_VSPACE_MAP);
        goto error;
    }

    // Create remote notify cap
    struct capref notify_cap;
    err = notification_create_cap(chan_id, core_id, &notify_cap);
    assert(err == SYS_ERR_OK);

    // Allocate my own notification caps
    struct capref ep, my_notify_cap;
    struct lmp_endpoint *iep;
    int chanid;
    err = endpoint_create(LMP_RECV_LENGTH, &ep, &iep);
    assert(err_is_ok(err));
    err = notification_allocate(ep, &chanid);
    assert(err == SYS_ERR_OK);
    err = notification_create_cap(chanid, my_core_id, &my_notify_cap);
    assert(err == SYS_ERR_OK);

    // setup our side of the binding
    umpb = malloc(sizeof(struct intermon_ump_ipi_binding));
    assert(umpb != NULL);

    err = intermon_ump_ipi_init(umpb, get_default_waitset(),
                                buf + MON_URPC_CHANNEL_LEN,
                                MON_URPC_CHANNEL_LEN,
                                buf, MON_URPC_CHANNEL_LEN, notify_cap,
                                my_notify_cap, ep, iep);
    assert(err_is_ok(err));

    // Identify UMP frame for tracing
    struct frame_identity umpid;
    err = invoke_frame_identify(frame, &umpid);
    assert(err_is_ok(err));
    umpb->ump_state.chan.recvid = (uintptr_t)umpid.base;
    umpb->ump_state.chan.sendid =
        (uintptr_t)(umpid.base + MON_URPC_CHANNEL_LEN);

    // connect it to our request handlers
    err = intermon_init(&umpb->b, core_id);
    assert(err_is_ok(err));

    /* Send reply */
reply:
    assert(umpb != NULL);
    bind_monitor_reply_scc_cont(&umpb->b, err, chanid);
    return;

error:
    assert(!"Argh");
    // FIXME: cleanup!
    goto reply;
}

/**
 * \brief The monitor that proxied the request for one monitor to
 * setup a connection with another monitor gets the reply
 */
static void bind_monitor_reply_scc(struct intermon_binding *binding,
                                   errval_t err, chanid_t chan_id,
                                   coreid_t core_id)
{
    struct intermon_ump_ipi_binding *b = (struct intermon_ump_ipi_binding *)binding;

    // Create notify cap to that core
    struct capref notify_cap;
    err = notification_create_cap(chan_id, core_id, &notify_cap);
    assert(err == SYS_ERR_OK);

    // And assign it to the binding
    err = ipi_notify_set(&b->ipi_notify, notify_cap);
    assert(err_is_ok(err));

    if (err_is_fail(err)) { // XXX
        DEBUG_ERR(err, "Got error in bind monitor reply");
    }
}

/******* stack-ripped bind_monitor_proxy_scc *******/

static void bind_monitor_request_scc_handler(struct intermon_binding *b,
        struct intermon_msg_queue_elem *e);

struct bind_monitor_request_scc_state {
    struct intermon_msg_queue_elem elem;
    struct intermon_bind_monitor_request_scc__args args;
};

static void bind_monitor_request_scc_cont(struct intermon_binding *dst_binding,
        coreid_t src_core_id,
        intermon_caprep_t caprep,
        chanid_t chan_id,
        coreid_t core_id)
{
    errval_t err;

    err = dst_binding->tx_vtbl.
          bind_monitor_request_scc(dst_binding, NOP_CONT, src_core_id,
                                   caprep, chan_id, core_id);
    if (err_is_fail(err)) {
        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            struct bind_monitor_request_scc_state *me =
                malloc(sizeof(struct bind_monitor_request_scc_state));
            assert(me != NULL);
            struct intermon_state *ist = dst_binding->st;
            assert(ist != NULL);
            me->args.core_id = src_core_id;
            me->args.cap = caprep;
            me->args.chan_id = chan_id;
            me->args.from_core_id = core_id;
            me->elem.cont = bind_monitor_request_scc_handler;

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

        DEBUG_ERR(err, "forwarding bind request failed");
    }
}