1/* 2 * Copyright (c) 2010, 2011, 2012, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich, 8 * Attn: Systems Group. 9 */ 10 11#include <barrelfish/barrelfish.h> 12#include <barrelfish/nameservice_client.h> 13#include <flounder/flounder_txqueue.h> 14 15#include <xomp/xomp.h> 16#include <xomp_gateway.h> 17#include <xomp_debug.h> 18#include <bomp_internal.h> 19 20#include <if/xomp_gateway_defs.h> 21 22 23 24/** 25 * \brief represents a registered memory which can be obtained by the other 26 * domains 27 */ 28struct mem_reg 29{ 30 struct mem_reg *next; ///< next chunk of registered memory 31 lpaddr_t addr; ///< physical address of registered memory 32 struct capref frame; ///< capability of the frame 33}; 34 35/** 36 * \brief Message states for the TX queue 37 */ 38struct xh_msg_st 39{ 40 struct txq_msg_st common; ///< common msg state 41 /* union of arguments */ 42 struct capref frame; ///< the replied frame 43}; 44 45/// our token 46volatile uint64_t xgw_token = 0x0; 47 48/* 49 * ---------------------------------------------------------------------------- 50 * XOMP helper memory management 51 * ---------------------------------------------------------------------------- 52 * 53 * We are using a normal linked list here and put the new memory memory regions 54 * in front. When a new memory region is added, its likely that it will be 55 * requested soon. Once requested by all workers of the node, the likelyhood that 56 * it is requested later should be small 57 * 58 * Note: we are using virtual addresses here since when sharing a frame, 59 * it should be mapped at the very same address for pointers to it 60 * being valid in all worker domains 61 */ 62 63/// list of registered memory 64static struct mem_reg *mem_regs; 65 66/** 67 * \brief allocates a new registered memory region and fills it 68 * 69 * \param addr virtual mapped address of the region 70 * \param frame frame backing this memory 71 * 72 * \return pointer to the memory struct 73 * NULL if we could not allocate memory 74 */ 75static inline struct mem_reg *xgw_mem_alloc(lpaddr_t addr, 76 struct capref frame) 77{ 78 struct mem_reg *mem = calloc(1, sizeof(*mem)); 79 if (mem == NULL) { 80 return NULL; 81 } 82 83 mem->addr = addr; 84 mem->frame = frame; 85 86 return mem; 87} 88 89/** 90 * \brief looks up a memory region in the list of registered memory regions 91 * 92 * \param addr the address to look for 93 * 94 * \return pointer ot the memory struct 95 * NULL if there is no such memory region 96 */ 97static struct mem_reg *xgw_do_lookup_mem(lpaddr_t addr) 98{ 99 struct mem_reg *mem = mem_regs; 100 while (mem) { 101 if (mem->addr == addr) { 102 break; 103 } 104 mem = mem->next; 105 } 106 return mem; 107} 108 109/** 110 * \brief inserts a new memory region into the list 111 * 112 * \param addr the virtual address of the region 113 * \param frame frame capability backing the address 114 * 115 * \return pointer to the newly allocated memory region 116 * NULL if there was a failure 117 */ 118static struct mem_reg *xgw_do_insert_mem(lpaddr_t addr, 119 struct capref frame) 120{ 121 struct mem_reg *new_mem = xgw_mem_alloc(addr, frame); 122 if (new_mem == NULL) { 123 return NULL; 124 } 125 126 if (mem_regs) { 127 new_mem->next = mem_regs; 128 mem_regs = new_mem; 129 } else { 130 mem_regs = new_mem; 131 } 132 133 return new_mem; 134} 135 136/** 137 * \brief registers a new memory region that it can be requested lateron 138 * 139 * \param addr the virtual address of the region 140 * \param frame frame capability backing the address 141 * 142 * \return SYS_ERR_OK on success 143 * LIB_ERR_MALLOC_FAIL on failure 144 */ 145errval_t xomp_gateway_mem_insert(struct capref frame, 146 lpaddr_t addr) 147{ 148 XWG_DEBUG("inserting memory: [0x%016lx]", addr); 149 if (xgw_do_insert_mem(addr, frame)) { 150 return SYS_ERR_OK; 151 } 152 153 return LIB_ERR_MALLOC_FAIL; 154} 155 156/* 157 * ---------------------------------------------------------------------------- 158 * XOMP helper send handlers 159 * ---------------------------------------------------------------------------- 160 */ 161 162static errval_t get_memory_response_tx(struct txq_msg_st *msg_st) 163{ 164 struct xh_msg_st *st = (struct xh_msg_st *) msg_st; 165 166 return xomp_gateway_get_memory_response__tx(msg_st->queue->binding, 167 TXQCONT(msg_st), msg_st->err, 168 st->frame); 169} 170 171/* 172 * ---------------------------------------------------------------------------- 173 * XOMP helper receive handlers 174 * ---------------------------------------------------------------------------- 175 */ 176 177static void get_memory_call_rx(struct xomp_gateway_binding *b, 178 lpaddr_t addr, 179 uint64_t token) 180{ 181 XWG_DEBUG("get_memory_call_rx: [0x%016lx]", addr); 182 183 struct tx_queue *txq = b->st; 184 struct txq_msg_st *msg_st = txq_msg_st_alloc(txq); 185 assert(msg_st != NULL); 186 187 msg_st->cleanup = NULL; 188 msg_st->send = get_memory_response_tx; 189 190 if (token != xgw_token) { 191 XWG_DEBUG("get_memory_call_rx token do not match: %lx %lx\n", token, 192 xgw_token); 193 msg_st->err = XOMP_ERR_INVALID_TOKEN; 194 txq_send(msg_st); 195 return; 196 } 197 198 struct xh_msg_st *st = (struct xh_msg_st *) msg_st; 199 200 struct mem_reg *mem = xgw_do_lookup_mem(addr); 201 if (mem == NULL) { 202 XWG_DEBUG("get_memory_call_rx: memory lookup failed\n"); 203 msg_st->err = XOMP_ERR_INVALID_MEMORY; 204 } else { 205 msg_st->err = SYS_ERR_OK; 206 st->frame = mem->frame; 207 } 208 209 txq_send(msg_st); 210} 211 212static struct xomp_gateway_rx_vtbl rx_vtbl = { 213 .get_memory_call = get_memory_call_rx, 214}; 215 216/* 217 * ---------------------------------------------------------------------------- 218 * XOMP helper connect / export callbacks 219 * ---------------------------------------------------------------------------- 220 */ 221 222static errval_t xgw_svc_connect_cb(void *st, 223 struct xomp_gateway_binding *xb) 224{ 225 XWG_DEBUG("new connection from client\n"); 226 227 struct tx_queue *queue = calloc(1, sizeof(*queue)); 228 if (queue == NULL) { 229 return LIB_ERR_MALLOC_FAIL; 230 } 231 232 txq_init(queue, xb, xb->waitset, (txq_register_fn_t) xb->register_send, 233 sizeof(struct xh_msg_st)); 234 235 xb->rx_vtbl = rx_vtbl; 236 xb->st = queue; 237 238 return SYS_ERR_OK; 239} 240 241static void xh_svc_export_cb(void *st, 242 errval_t err, 243 iref_t iref) 244{ 245 XWG_DEBUG("gateway service exported %s\n", err_getstring(err)); 246 247 if (err_is_fail(err)) { 248 USER_PANIC_ERR(err, "export failed"); 249 } 250 251 char svc_name[40]; 252 snprintf(svc_name, 40, "%s.%s", disp_name(), "xgw"); 253 254 err = nameservice_register(svc_name, iref); 255 if (err_is_fail(err)) { 256 USER_PANIC_ERR(err, "nameservice registration failed"); 257 } 258 259 xgw_token = xomp_gateway_make_token(); 260 261 XWG_DEBUG("gateway iref:%"PRIxIREF" @ {%s} with token: %lx\n", iref, svc_name, 262 xgw_token); 263} 264 265/* 266 * ---------------------------------------------------------------------------- 267 * XOMP gateway service initialization 268 * ---------------------------------------------------------------------------- 269 */ 270 271/** 272 * \brief initializes the xomp gatway service 273 * 274 * \return SYS_ERR_OK on success 275 * errval on failure 276 */ 277errval_t xomp_gateway_init(void) 278{ 279 errval_t err; 280 281 XWG_DEBUG("xomp gateway initialization\n"); 282 283 err = xomp_gateway_export(NULL, xh_svc_export_cb, xgw_svc_connect_cb, 284 get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT); 285 if (err_is_fail(err)) { 286 return err; 287 } 288 289 while (!xgw_token) { 290 messages_wait_and_handle_next(); 291 } 292 293 return SYS_ERR_OK; 294} 295