Example #1
0
void
update_owner__rx_handler(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st)
{
    errval_t err;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;
    coreid_t from = inter_st->core_id;
    struct capref capref;
    struct capability cap;
    caprep_to_capability(&caprep, &cap);

    err = slot_alloc(&capref);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "failed to allocate slot for owner update");
    }

    err = monitor_copy_if_exists(&cap, capref);
    if (err_is_ok(err)) {
        err = monitor_set_cap_owner(cap_root, get_cap_addr(capref),
                                    get_cap_valid_bits(capref), from);
    }
    if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) {
        err = SYS_ERR_OK;
    }

    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "failed to update cap ownership");
    }

    cap_destroy(capref);

    err = owner_updated(from, st);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "failed to send ownership update response");
    }
}
Example #2
0
void
find_descendants__rx_handler(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st)
{
    errval_t err;

    struct intermon_state *inter_st = (struct intermon_state*)b->st;
    coreid_t from = inter_st->core_id;

    struct capability cap;
    caprep_to_capability(&caprep, &cap);

    bool has_descendants;
    err = monitor_has_descendants(&cap, &has_descendants);
    assert(err_is_ok(err));

    struct find_descendants_result_msg_st *msg_st;
    msg_st = malloc(sizeof(*msg_st));
    if (!msg_st) {
        err = LIB_ERR_MALLOC_FAIL;
        USER_PANIC_ERR(err, "could not alloc find_descendants_result_msg_st");
    }
    msg_st->queue_elem.cont = find_descendants_result_send_cont;
    msg_st->st = st;

    if (err_is_ok(err)) {
        err = has_descendants ? SYS_ERR_OK : SYS_ERR_CAP_NOT_FOUND;
    }
    msg_st->status = err;

    err = capsend_target(from, (struct msg_queue_elem*)msg_st);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "could not enqueue find_descendants_result msg");
    }
}
Example #3
0
void
revoke_mark__rx(struct intermon_binding *b,
                intermon_caprep_t caprep,
                genvaddr_t st)
{
    DEBUG_CAPOPS("%s\n", __FUNCTION__);
    errval_t err;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;

    struct revoke_slave_st *rvk_st;
    err = calloce(1, sizeof(*rvk_st), &rvk_st);
    PANIC_IF_ERR(err, "allocating revoke slave state");

    rvk_st->from = inter_st->core_id;
    rvk_st->st = st;
    caprep_to_capability(&caprep, &rvk_st->rawcap);

    if (!slaves_head) {
        assert(!slaves_tail);
        slaves_head = slaves_tail = rvk_st;
    }
    else {
        assert(slaves_tail);
        assert(!slaves_tail->next);
        slaves_tail->next = rvk_st;
        slaves_tail = rvk_st;
    }

    // pause any ongoing "delete stepping" as mark phases on other nodes need
    // to delete all foreign copies before we can delete locally owned caps
    delete_steps_pause();

    // XXX: this invocation could create a scheduling hole that could be
    // problematic in RT systems and should probably be done in a loop.
    err = monitor_revoke_mark_relations(&rvk_st->rawcap);
    if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) {
        // found no copies or descendants of capability on this core,
        // do nothing. -SG
        DEBUG_CAPOPS("no copies on core %d\n", disp_get_core_id());
    } else if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "marking revoke");
    }

    rvk_st->im_qn.cont = revoke_ready__send;
    err = capsend_target(rvk_st->from, (struct msg_queue_elem*)rvk_st);
    PANIC_IF_ERR(err, "enqueing revoke_ready");
}
Example #4
0
void
find_cap__rx_handler(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st)
{
    errval_t err, cleanup_err;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;
    coreid_t from = inter_st->core_id;
    struct capability cap;
    caprep_to_capability(&caprep, &cap);
    struct capref capref;

    err = slot_alloc(&capref);
    if (err_is_fail(err)) {
        goto send_err;
    }

    err = monitor_copy_if_exists(&cap, capref);
    if (err_is_fail(err)) {
        goto free_slot;
    }

    cleanup_err = cap_delete(capref);
    if (err_is_fail(cleanup_err)) {
        USER_PANIC_ERR(err, "failed to delete temporary cap");
    }

free_slot:
    cleanup_err = slot_free(capref);
    if (err_is_fail(cleanup_err)) {
        USER_PANIC_ERR(err, "failed to free slot for temporary cap");
    }

send_err:
    cleanup_err = find_cap_result(from, err, st);
    if (err_is_fail(cleanup_err)) {
        USER_PANIC_ERR(err, "failed to send find_cap result");
    }
}
Example #5
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");
    }
}
Example #6
0
void
retrieve_request__rx(struct intermon_binding *b,
                     intermon_caprep_t caprep,
                     genvaddr_t st)
{
    errval_t err, err2;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;

    struct retrieve_response_st *rst;
    err = calloce(1, sizeof(*rst), &rst);
    PANIC_IF_ERR(err, "allocating retrieve respones state");
    rst->st = st;
    rst->from = inter_st->core_id;

    struct capability rawcap;
    caprep_to_capability(&caprep, &rawcap);

    struct capref cap;
    err = slot_alloc(&cap);
    GOTO_IF_ERR(err, respond_err);

    err = monitor_copy_if_exists(&rawcap, cap);
    GOTO_IF_ERR(err, free_slot);

    distcap_state_t state;
    err = dom_cnode_get_state(get_cap_domref(cap), &state);
    GOTO_IF_ERR(err, delete_cap);

    if (distcap_state_is_busy(state)) {
        err = MON_ERR_REMOTE_CAP_RETRY;
        goto delete_cap;
    }
    if (distcap_state_is_foreign(state)) {
        err = MON_ERR_CAP_FOREIGN;
        goto delete_cap;
    }

    uint8_t relations, remote_relations;
    err = monitor_cap_has_relations(cap, 0xFF, &relations);
    GOTO_IF_ERR(err, delete_cap);

    err = monitor_remote_relations(cap, 0, 0, &remote_relations);
    GOTO_IF_ERR(err, delete_cap);

    rst->relations = relations | remote_relations | RRELS_COPY_BIT;

    err = monitor_set_cap_owner(cap_root, get_cap_addr(cap),
                                get_cap_valid_bits(cap),
                                rst->from);

delete_cap:
    err2 = cap_delete(cap);
    DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve");

free_slot:
    err2 = slot_free(cap);
    DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve");

respond_err:
    retrieve_result__enq(err, rst);
}
Example #7
0
static void intermon_bind_ump_reply(struct intermon_binding *ib, 
                                    uint64_t my_mon_id, uint64_t your_mon_id,
                                    errval_t msgerr, 
                                    intermon_caprep_t caprep)
{
    errval_t err;
    struct remote_conn_state *con = remote_conn_lookup(my_mon_id);
    if (con == NULL) {
        USER_PANIC_ERR(0, "unknown mon_id in UMP bind reply");
        return;
    }

    uintptr_t domain_id = con->domain_id;
    struct monitor_binding *domain_binding = con->domain_binding;
    struct capref notify_cap = NULL_CAP;

    if (err_is_ok(msgerr)) { /* bind succeeded */
        con->mon_id = your_mon_id;
        con->mon_binding = ib;

#if 0
        /* map in UMP channel state */
        void *buf;
        err = vspace_map_one_frame_attr(&buf,
              2 * (UMP_CHANNEL_SIZE + con->localchan.size * sizeof(uintptr_t)),
                                        con->frame, VREGION_FLAGS_READ,
                                        NULL, NULL);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "vspace_map_one_frame failed");
            // XXX: should not be an assert, but we don't have any way to do
            // connection teardown here!
            assert(buf != NULL);
        }
        con->sharedchan = buf;
        con->localchan.buf = buf + 2 * UMP_CHANNEL_SIZE;

        // XXX: Put frame cap on a separate allocator as it is not deleted anymore
        struct capref frame_copy;
        err = slot_alloc(&frame_copy);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "Failed to allocator slot from channel_alloc");
        }
        err = cap_copy(frame_copy, con->frame);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "Failed create copy of frame cap");
        }
        err = cap_destroy(con->frame);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "cap_destroy_default failed");
        }
        con->frame = frame_copy;
#endif

        struct capability capability;
        caprep_to_capability(&caprep, &capability);

        if(capability.type != ObjType_Null) {
            // Get core id of sender
            coreid_t core_id = ((struct intermon_state *)ib->st)->core_id;

            // Construct the notify cap
            err = slot_alloc(&notify_cap);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
            }

            err = monitor_cap_create(notify_cap, &capability, core_id);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "monitor_cap_create failed");
            }
        }
    } else { /* bind refused */
        err = cap_destroy(con->x.ump.frame);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "cap_destroy_default failed");
        }
        err = remote_conn_free(my_mon_id);
        assert(err_is_ok(err));
    }

    bind_ump_reply_client_cont(domain_binding, my_mon_id, domain_id, msgerr,
                               notify_cap);
}
Example #8
0
static void intermon_bind_ump_request(struct intermon_binding *ib,
                                      iref_t iref, con_id_t your_mon_id,
                                      uint32_t channel_length_in,
                                      uint32_t channel_length_out,
                                      genpaddr_t framebase, uint8_t framebits,
                                      intermon_caprep_t caprep)
{
    errval_t err;

    /* Get client's core_id */
    struct intermon_state *ist = ib->st;
    assert(ist != NULL);
    coreid_t core_id = ist->core_id;

    /* Construct the frame capability */
    struct capability frame_cap = {
        .type = ObjType_Frame,
        .rights = CAPRIGHTS_READ_WRITE, // XXX
        .u.frame = {
            .base = framebase,
            .bits = framebits
        }
    };

    // Construct the notify cap
    struct capref notify_cap = NULL_CAP;
    struct capability capability;
    caprep_to_capability(&caprep, &capability);
    if(capability.type != ObjType_Null) {
        err = slot_alloc(&notify_cap);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
        }
        err = monitor_cap_create(notify_cap, &capability, core_id);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "monitor_cap_create failed");
        }
    }

    // XXX: Put frame cap on a separate allocator as it is not deleted anymore
    struct capref frame;
    err = slot_alloc(&frame);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc");
    }
    err = monitor_cap_create(frame, &frame_cap, core_id);
    if (err_is_fail(err)) {
        USER_PANIC_ERR(err, "monitor_cap_create failed");
    }

    /* Get the server's connection */
    struct monitor_binding *domain_binding = NULL;
    err = iref_get_binding(iref, &domain_binding);
    assert(err_is_ok(err));

    /* Get the service id */
    uintptr_t service_id = 0;
    err = iref_get_service_id(iref, &service_id);
    assert(err_is_ok(err));

    /* Create a new connection state */
    uintptr_t my_mon_id;
    struct remote_conn_state *con;
    err = remote_conn_alloc(&con, &my_mon_id, REMOTE_CONN_UMP);
    assert(err_is_ok(err));

    // Set the monitor portion of it
    con->mon_id = your_mon_id;
    con->mon_binding = ib;
    con->x.ump.frame = frame;
    con->core_id = core_id;

    bind_ump_service_request_cont(domain_binding, service_id, my_mon_id,
                                  frame, channel_length_in, channel_length_out,
                                  notify_cap, ib, your_mon_id);
}