static errval_t reclaim_memory(genpaddr_t base, uint8_t bits) { /* XXX: mem client is only defined for the bsp core. * For app cores, just return */ if (get_mem_client() == NULL) { return SYS_ERR_OK; } // Fabricate new RAM cap and hand back to mem_serv struct capability c = { .type = ObjType_RAM, .u.ram = { .base = base, .bits = bits, } }; struct capref ramcap; errval_t err = slot_alloc(&ramcap); if(err_is_fail(err)) { return err; } err = monitor_cap_create(ramcap, &c, my_core_id); if(err_is_fail(err)) { return err; } struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state(); errval_t result; thread_mutex_lock(&ram_alloc_state->ram_alloc_lock); struct mem_rpc_client *b = get_mem_client(); // XXX: This should not be an RPC! It could stall the monitor, but // we trust mem_serv for the moment. err = b->vtbl.free_monitor(b, ramcap, base, bits, &result); thread_mutex_unlock(&ram_alloc_state->ram_alloc_lock); if(err_is_fail(err)) { return err; } if(err_is_fail(result)) { return result; } // XXX: this shouldn't be necessary as free_monitor uses give_away_cap err = cap_destroy(ramcap); if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) { err = SYS_ERR_OK; } if (err_is_fail(err)) { DEBUG_ERR(err, "destroying reclaimed cap"); } return err; }
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(¬ify_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); }
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(¬ify_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); }