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); } }
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"); } }
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); } }
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); }
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)); } } }
/** * \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, ¬ify_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, ¬ify_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"); } }