1/** 2 * \file 3 * \brief 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2010, 2011, 2012, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include "monitor.h" 16#include "capops.h" 17#include <if/monitor_mem_defs.h> 18#include <if/monitor_mem_defs.h> 19#include <if/mem_defs.h> 20 21static uint8_t mem_core_id; 22static struct monitor_mem_binding *monitor_mem_client; 23static bool mem_setup_complete = false; 24iref_t monitor_mem_iref = 0; 25 26static void mem_alloc_delete_result_handler(errval_t status, void *st) 27{ 28 struct capref *cap = (struct capref*)st; 29 errval_t err; 30 31 if (err_is_fail(status)) { 32 DEBUG_ERR(status, "capops_delete failed, cap will leak"); 33 } 34 else { 35 err = slot_free(*cap); 36 if (err_is_fail(err)) { 37 DEBUG_ERR(err, "slot_free failed, cap will leak"); 38 } 39 } 40 41 free(cap); 42} 43 44/** 45 * \brief Request for some memory (over the memory allocation channel) 46 */ 47static errval_t mem_alloc_handler(struct monitor_mem_binding *b, 48 uint8_t size_bits, genpaddr_t minbase, 49 genpaddr_t maxlimit, coreid_t from, 50 errval_t *out_err, monitor_mem_caprep_t *out_caprep) 51{ 52 struct capref *cap = NULL; 53 monitor_mem_caprep_t caprep = {0,0,0,0}; 54 errval_t err; 55 errval_t reterr = SYS_ERR_OK; 56 57 /* This should only run on the core with the mem_serv. Or else the system 58 will deadlock. */ 59 assert(bsp_monitor); 60 61 cap = malloc(sizeof(*cap)); 62 if (!cap) { 63 reterr = LIB_ERR_MALLOC_FAIL; 64 goto out; 65 } 66 67 err = ram_alloc(cap, size_bits); 68 if (err_is_fail(err)) { 69 reterr = err_push(err, LIB_ERR_RAM_ALLOC); 70 goto out; 71 } 72 73 struct capability cap_raw; 74 err = monitor_cap_identify(*cap, &cap_raw); 75 if (err_is_fail(err)) { 76 reterr = err_push(err, MON_ERR_CAP_IDENTIFY); 77 goto out; 78 } 79 assert(cap_raw.type == ObjType_RAM); 80 intermon_caprep_t caprep2; 81 capability_to_caprep(&cap_raw, &caprep2); 82 // XXX: work around stupid flounder behaviour: these types are identical! 83 STATIC_ASSERT_SIZEOF(caprep, sizeof(caprep2)); 84 memcpy(&caprep, &caprep2, sizeof(caprep)); 85 86 err = monitor_set_cap_owner(cap_root, get_cap_addr(*cap), get_cap_level(*cap), from); 87 if (err_is_fail(err)) { 88 reterr = err; 89 memset(&caprep, 0, sizeof(caprep)); 90 } 91 92out: 93 // RPC protocol, this can never fail with TX_BUSY 94 *out_err = reterr; 95 *out_caprep = caprep; 96 // err = b->tx_vtbl.alloc_response(b, NOP_CONT, reterr, caprep); 97 // if (err_is_fail(err)) { 98 // DEBUG_ERR(err, "reply failed"); 99 // } 100 101 if (cap) { 102 capops_delete(get_cap_domref(*cap), mem_alloc_delete_result_handler, cap); 103 } 104 return SYS_ERR_OK; 105} 106 107static errval_t mem_free_handler(struct monitor_mem_binding *b, 108 monitor_mem_caprep_t caprep, 109 genpaddr_t base, uint8_t bits, errval_t *result) 110{ 111 errval_t err; 112 // this should only run on the bsp monitor 113 assert(bsp_monitor); 114 DEBUG_CAPOPS("%s\n", __FUNCTION__); 115 116 // convert caprep into cap 117 intermon_caprep_t caprep2; 118 // XXX: work around stupid flounder behaviour: these types are identical! 119 STATIC_ASSERT_SIZEOF(caprep, sizeof(caprep2)); 120 memcpy(&caprep2, &caprep, sizeof(caprep)); 121 struct capability cap_raw; 122 caprep_to_capability(&caprep2, &cap_raw); 123 124 DEBUG_CAPOPS("%s: freeing:\n", __FUNCTION__); 125 debug_print_caprep(&caprep2); 126 127 assert(ObjType_RAM == cap_raw.type); 128 129 struct capref cap; 130 err = slot_alloc(&cap); 131 if (err_is_fail(err)) { 132 *result = err_push(err, LIB_ERR_SLOT_ALLOC); 133 goto out; 134 } 135 136 err = monitor_cap_create(cap, &cap_raw, my_core_id); 137 if (err_is_fail(err)) { 138 *result = err_push(err, MON_ERR_CAP_CREATE); 139 goto out; 140 } 141 DEBUG_CAPOPS("%s: created local copy, sending to memserv\n", __FUNCTION__); 142 143 struct mem_binding *mb = get_mem_client(); 144 assert(mb); 145 err = mb->rpc_tx_vtbl.free_monitor(mb, cap, base, bits, result); 146 if (err_is_fail(err)) { 147 *result = err; 148 } 149out: 150 DEBUG_CAPOPS("%s: sending reply: %s\n", __FUNCTION__, err_getstring(*result)); 151 return SYS_ERR_OK; 152} 153 154static errval_t mon_ram_alloc(struct capref *ret, uint8_t size_bits, 155 uint64_t minbase, uint64_t maxlimit) 156{ 157 errval_t err; 158 intermon_caprep_t caprep; 159 errval_t reterr; 160 161 err = monitor_mem_client->rpc_tx_vtbl.alloc(monitor_mem_client, size_bits, 162 minbase, maxlimit, my_core_id, &reterr, 163 (monitor_mem_caprep_t *) &caprep); 164 if (err_is_fail(err)) { 165 return err_push(err, MON_ERR_RAM_ALLOC_ERR); 166 } else if (err_is_fail(reterr)) { 167 return err_push(reterr, MON_ERR_RAM_ALLOC_RETERR); 168 } 169 170 struct capability cap_raw; 171 caprep_to_capability(&caprep, &cap_raw); 172 assert(ObjType_RAM == cap_raw.type); 173 174 err = slot_alloc(ret); 175 if (err_is_fail(err)) { 176 return err_push(err, LIB_ERR_SLOT_ALLOC); 177 } 178 179 err = monitor_cap_create(*ret, &cap_raw, my_core_id); 180 if (err_is_fail(err)) { 181 return err_push(err, MON_ERR_CAP_CREATE); 182 } 183 184 return reterr; 185} 186 187static struct monitor_mem_rpc_rx_vtbl the_monitor_mem_rpc_vtable = { 188 .alloc_call = mem_alloc_handler, 189 .free_call = mem_free_handler, 190}; 191 192static errval_t monitor_mem_connected(void *st, struct monitor_mem_binding *b) 193{ 194 b->rpc_rx_vtbl = the_monitor_mem_rpc_vtable; 195 return SYS_ERR_OK; 196} 197 198static void monitor_mem_listening(void *st, errval_t err, iref_t iref) 199{ 200 if (err_is_fail(err)) { 201 USER_PANIC_ERR(err, "err in monitor_mem_listening failed"); 202 } 203 monitor_mem_iref = iref; 204} 205 206errval_t mon_ram_alloc_serve(void) 207{ 208 errval_t err; 209 210 err = monitor_mem_export(NULL, monitor_mem_listening, monitor_mem_connected, 211 get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT); 212 if (err_is_fail(err)) { 213 return err; 214 } 215 216 return SYS_ERR_OK; 217} 218 219static void bind_cont(void *st, errval_t err, struct monitor_mem_binding *b) 220{ 221 if (err_is_fail(err)) { 222 USER_PANIC_ERR(err, "err in bind_cont failed"); 223 } 224 225 // setup RPC client above binding 226 monitor_mem_client = b; 227 monitor_mem_rpc_client_init(monitor_mem_client); 228 mem_setup_complete = true; 229} 230 231errval_t mon_ram_alloc_init(coreid_t core_id, struct intermon_binding *b) 232{ 233 errval_t err; 234 235 /* Set memcore_id */ 236 mem_core_id = core_id; 237 238 // Get service IREF from core 239 err = b->tx_vtbl.monitor_mem_iref_request(b, NOP_CONT); 240 if (err_is_fail(err)) { 241 return err_push(err, MON_ERR_SEND_REMOTE_MSG); 242 } 243 while(monitor_mem_iref == 0) { 244 messages_wait_and_handle_next(); 245 } 246 247 // Bind to service 248 err = monitor_mem_bind(monitor_mem_iref, bind_cont, NULL, 249 get_default_waitset(), IDC_BIND_FLAGS_DEFAULT); 250 if (err_is_fail(err)) { 251 USER_PANIC_ERR(err, "monitor_mem_bind failed"); 252 } 253 while(!mem_setup_complete) { 254 messages_wait_and_handle_next(); 255 } 256 257 err = ram_alloc_set(mon_ram_alloc); 258 if (err_is_fail(err)) { 259 return err_push(err, LIB_ERR_RAM_ALLOC_SET); 260 } 261 262 return SYS_ERR_OK; 263} 264 265errval_t mon_ram_free(struct capability *cap_raw, genpaddr_t base, uint8_t bits) 266{ 267 errval_t err, status; 268 // get caprep 269 intermon_caprep_t caprep; 270 capability_to_caprep(cap_raw, &caprep); 271 // XXX: work around stupid flounder behaviour: these types are identical! 272 monitor_mem_caprep_t caprep2; 273 STATIC_ASSERT_SIZEOF(caprep, sizeof(caprep2)); 274 memcpy(&caprep2, &caprep, sizeof(caprep)); 275 276 err = monitor_mem_client->rpc_tx_vtbl.free(monitor_mem_client, caprep2, base, bits, &status); 277 if (err_is_fail(err)) { 278 return err; 279 } 280 return status; 281} 282