// XXX: these look suspicious in combination with distops!
static void forward_kcb_request(struct monitor_blocking_binding *b,
                                coreid_t destination, struct capref kcb)
{
    printf("%s:%s:%d: forward_kcb_request in monitor\n",
           __FILE__, __FUNCTION__, __LINE__);

    errval_t err = SYS_ERR_OK;

    struct capability kcb_cap;
    err = monitor_cap_identify(kcb, &kcb_cap);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "monitor_cap_identify failed");
        err = b->tx_vtbl.forward_kcb_request_response(b, NOP_CONT, err);
        assert(err_is_ok(err));
        return;
    }

    if (destination == my_core_id) {
        uintptr_t kcb_base = (uintptr_t)kcb_cap.u.kernelcontrolblock.kcb;
        printf("%s:%s:%d: Invoke syscall directly, destination==my_core_id; kcb_base = 0x%"PRIxPTR"\n",
               __FILE__, __FUNCTION__, __LINE__, kcb_base);
        err = invoke_monitor_add_kcb(kcb_base);
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "invoke_montitor_add_kcb failed.");
        }

        err = b->tx_vtbl.forward_kcb_request_response(b, NOP_CONT, err);
        assert(err_is_ok(err));
        return;
    }

    struct intermon_binding *ib;
    err = intermon_binding_get(destination, &ib);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "intermon_binding_get failed");
        err = b->tx_vtbl.forward_kcb_request_response(b, NOP_CONT, err);
        assert(err_is_ok(err));
        return;
    }

    intermon_caprep_t kcb_rep;
    capability_to_caprep(&kcb_cap, &kcb_rep);

    ib->st = b;
    err = ib->tx_vtbl.give_kcb_request(ib, NOP_CONT, kcb_rep);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "give_kcb send failed");
        err = b->tx_vtbl.forward_kcb_request_response(b, NOP_CONT, err);
        assert(err_is_ok(err));
        return;
    }
}
Beispiel #2
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);
    }
}
Beispiel #3
0
static errval_t
capsend_mc_init(struct capsend_mc_st *mc_st, struct capability *cap,
                capsend_send_fn send_fn,
                size_t num_dests, bool track_pending)
{
    mc_st->num_queued = 0;
    mc_st->num_pending = track_pending ? 0 : -1;
    mc_st->do_send = true;
    mc_st->send_fn = send_fn;
    if (cap) {
        capability_to_caprep(cap, &mc_st->caprep);
    }
    mc_st->msg_st_arr = calloc(num_dests, sizeof(*mc_st->msg_st_arr));
    if (!mc_st->msg_st_arr) {
        return LIB_ERR_MALLOC_FAIL;
    }
    return SYS_ERR_OK;
}
Beispiel #4
0
static void
retrieve_owner__send(struct intermon_binding *b,
                     struct intermon_msg_queue_elem *e)
{
    errval_t err;
    struct retrieve_rpc_st *st = (struct retrieve_rpc_st*)e;
    intermon_caprep_t caprep;

    err = monitor_set_domcap_owner(st->cap, my_core_id);
    GOTO_IF_ERR(err, report_error);

    capability_to_caprep(&st->rawcap, &caprep);
    err = intermon_capops_retrieve_request__tx(b, NOP_CONT, caprep, (lvaddr_t)st);
    GOTO_IF_ERR(err, report_error);

    return;

report_error:
    retrieve_ownership__rx(err, st);
}
Beispiel #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));
        }
    }
}
Beispiel #6
0
/**
 * \brief Notification of a newly booted monitor.
 *  Setup our connection and request the sender to proxy
 *  the bind request to the monitor
 */
static void new_monitor_notify(struct intermon_binding *b,
                               coreid_t core_id)
{
    errval_t err;

    /* Setup the connection */
    ram_set_affinity(SHARED_MEM_MIN + (PERCORE_MEM_SIZE * my_core_id),
                     SHARED_MEM_MIN + (PERCORE_MEM_SIZE * (my_core_id + 1)));
    struct capref frame;
    err = frame_alloc(&frame, MON_URPC_SIZE, NULL);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "frame_alloc failed");
        return; // FIXME: cleanup
    }
    ram_set_affinity(0, 0);     // Reset affinity

    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)) {
        DEBUG_ERR(err, "vspace_map_one_frame failed");
        assert(buf); // XXX
    }
    // XXX: Clear the frame (kernel can't do it for us)
    memset(buf, 0, MON_URPC_SIZE);

    // 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);

    // init our end of the binding and channel
    struct intermon_ump_ipi_binding *ump_binding =
        malloc(sizeof(struct intermon_ump_ipi_binding));
    assert(ump_binding != NULL);
    err = intermon_ump_ipi_init(ump_binding, get_default_waitset(),
                                buf, MON_URPC_CHANNEL_LEN,
                                buf + MON_URPC_CHANNEL_LEN,
                                MON_URPC_CHANNEL_LEN, NULL_CAP, my_notify_cap,
                                ep, iep);
    assert(err_is_ok(err));
    /* if (err_is_fail(err)) { */
    /*     cap_destroy(frame); */
    /*     return err_push(err, LIB_ERR_UMP_CHAN_BIND); */
    /* } */

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

    err = intermon_init(&ump_binding->b, core_id);
    assert(err_is_ok(err));

    /* Identify the frame cap */
    struct capability frame_cap;
    err = monitor_cap_identify(frame, &frame_cap);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "monitor_cap_identify failed");
        return; // FIXME: cleanup
    }

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

    /* reply to the sending monitor to proxy request */
    err = b->tx_vtbl.bind_monitor_proxy_scc(b, NOP_CONT, core_id,
                                            caprep, chanid, my_core_id);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "bind proxy request failed");
    }
}

errval_t arch_intermon_init(struct intermon_binding *b)
{
    b->rx_vtbl.bind_monitor_request_scc = bind_monitor_request_scc;
    b->rx_vtbl.bind_monitor_reply_scc = bind_monitor_reply_scc;
    b->rx_vtbl.bind_monitor_proxy_scc = bind_monitor_proxy_scc;
    b->rx_vtbl.new_monitor_notify = new_monitor_notify;

    return SYS_ERR_OK;
}