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