1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <assert.h> 16#include <sel4/sel4.h> 17#include <refos/refos.h> 18#include <refos-util/serv_connect.h> 19#include <refos-util/cspace.h> 20 21/*! @file 22 @brief Server client connection module implementation. */ 23 24static cvector_item_t 25client_oat_create(coat_t *oat, int id, uint32_t arg[COAT_ARGS]) 26{ 27 struct srv_client_table *ct = ((struct srv_client_table*) oat); 28 assert(ct && ct->magic == SRC_CLIENT_LIST_MAGIC); 29 30 /* Allocate and set up new client structure. */ 31 struct srv_client *nclient = malloc(sizeof(struct srv_client)); 32 if (!nclient) { 33 printf("ERROR: client_oat_create out of memory!\n"); 34 return NULL; 35 } 36 memset(&nclient->rpcClient, 0, sizeof(nclient->rpcClient)); 37 nclient->magic = ct->clientMagic; 38 nclient->cID = id; 39 nclient->liveness = arg[0]; 40 nclient->deathID = -1; 41 nclient->paramBufferStart = 0; 42 nclient->paramBuffer = 0; 43 44 /* Mint a session cap. */ 45 nclient->session = csalloc(); 46 if (!nclient->session) { 47 printf("ERROR: could not not allocate cslot.\n"); 48 goto exit1; 49 } 50 int error = seL4_CNode_Mint ( 51 REFOS_CSPACE, nclient->session, REFOS_CDEPTH, 52 REFOS_CSPACE, ct->sessionSrcEP, REFOS_CDEPTH, 53 seL4_NoRead, 54 seL4_CapData_Badge_new(nclient->cID + ct->badgeBase) 55 ); 56 if (error != seL4_NoError) { 57 printf("ERROR: failed to mint client session cap.\n"); 58 goto exit2; 59 } 60 61 return (cvector_item_t) nclient; 62 63 /* Exit stack. */ 64exit2: 65 csfree(nclient->session); 66exit1: 67 assert(nclient); 68 free(nclient); 69 return NULL; 70} 71 72static void 73client_oat_delete(coat_t *oat, cvector_item_t *obj) 74{ 75 struct srv_client_table *ct = ((struct srv_client_table*) oat); 76 assert(ct && ct->magic == SRC_CLIENT_LIST_MAGIC); 77 (void) ct; 78 79 struct srv_client *client = (struct srv_client *) obj; 80 assert(client && client->magic == ct->clientMagic); 81 82 /* Clean up client info from cspace. */ 83 if (client->liveness) { 84 //seL4_CNode_Revoke(REFOS_CSPACE, client->liveness, REFOS_CDEPTH); // FIXME REVOKE BUG 85 seL4_CNode_Delete(REFOS_CSPACE, client->liveness, REFOS_CDEPTH); 86 csfree(client->liveness); 87 } 88 if (client->session) { 89 //seL4_CNode_Revoke(REFOS_CSPACE, client->session, REFOS_CDEPTH); // FIXME REVOKE BUG 90 seL4_CNode_Delete(REFOS_CSPACE, client->session, REFOS_CDEPTH); 91 csfree(client->session); 92 } 93 94 if (client->paramBuffer) { 95 //seL4_CNode_Revoke(REFOS_CSPACE, client->paramBuffer, REFOS_CDEPTH); // FIXME REVOKE BUG 96 seL4_CNode_Delete(REFOS_CSPACE, client->paramBuffer, REFOS_CDEPTH); 97 csfree(client->paramBuffer); 98 } 99 100 /* Finally, free the entire structure. */ 101 free(client); 102} 103 104void 105client_table_init(struct srv_client_table *ct, int maxClients, int badgeBase, uint32_t magic, 106 seL4_CPtr sessionSrcEP) 107{ 108 ct->magic = SRC_CLIENT_LIST_MAGIC; 109 ct->maxClients = maxClients; 110 ct->clientMagic = magic; 111 ct->badgeBase = badgeBase; 112 ct->sessionSrcEP = sessionSrcEP; 113 114 /* Configure the object allocation table creation / deletion callback func pointers. */ 115 ct->allocTable.oat_expand = NULL; 116 ct->allocTable.oat_create = client_oat_create; 117 ct->allocTable.oat_delete = client_oat_delete; 118 119 /* Initialise our data structures. */ 120 coat_init(&ct->allocTable, 1, ct->maxClients); 121 cvector_init(&ct->pendingFreeList); 122} 123 124void 125client_table_release(struct srv_client_table *ct) 126{ 127 coat_release(&ct->allocTable); 128 cvector_free(&ct->pendingFreeList); 129} 130 131void 132client_table_postaction(struct srv_client_table *ct) 133{ 134 /* Actually delete all the clients on the pending free list. */ 135 int len = cvector_count(&ct->pendingFreeList); 136 for (int i = 0; i < len; i++) { 137 /* Actually delete this client. */ 138 int id = (int) cvector_get(&ct->pendingFreeList, i); 139 if (!client_get(ct, id)) { 140 assert(!"Client in pending free list doesn't exist. Book keeping error."); 141 continue; 142 } 143 coat_free(&ct->allocTable, id); 144 } 145 /* Clear the pending free list. */ 146 cvector_reset(&ct->pendingFreeList); 147} 148 149struct srv_client* 150client_alloc(struct srv_client_table *ct, seL4_CPtr liveness) 151{ 152 struct srv_client* nclient = NULL; 153 uint32_t arg[COAT_ARGS]; 154 arg[0] = liveness; 155 156 /* Allocate an ID, and the client structure associated with it. */ 157 int ID = coat_alloc(&ct->allocTable, arg, (cvector_item_t *) &nclient); 158 if (!nclient) { 159 printf("ERROR: client_alloc couldn't allocate a client ID.\n"); 160 return NULL; 161 } 162 163 assert(ID != COAT_INVALID_ID); 164 assert(nclient->magic == ct->clientMagic); 165 (void) ID; 166 return nclient; 167} 168 169struct srv_client* 170client_get(struct srv_client_table *ct, int id) 171{ 172 if (id < 0 || id >= ct->maxClients) { 173 /* Invalid ID. */ 174 return NULL; 175 } 176 struct srv_client* nclient = (struct srv_client*) coat_get(&ct->allocTable, id); 177 if (!nclient) { 178 /* No such client ID exists. */ 179 return NULL; 180 } 181 assert(nclient->magic == ct->clientMagic); 182 return nclient; 183} 184 185struct srv_client* 186client_get_badge(struct srv_client_table *ct, int badge) 187{ 188 if (badge < ct->badgeBase || badge >= ct->badgeBase + ct->maxClients) { 189 return NULL; 190 } 191 return client_get(ct, badge - ct->badgeBase ); 192} 193 194void 195client_queue_delete(struct srv_client_table *ct, int id) 196{ 197 /* Sanity check on the given ID. */ 198 if (!client_get(ct, id)) { 199 return; 200 } 201 int len = cvector_count(&ct->pendingFreeList); 202 for (int i = 0; i < len; i++) { 203 int cid = (int) cvector_get(&ct->pendingFreeList, i); 204 if (id == cid) { 205 /* Client already queued for deletion. Ignore. */ 206 return; 207 } 208 } 209 /* Queue this client ID up to be deleted. */ 210 cvector_add(&ct->pendingFreeList, (cvector_item_t) id); 211} 212 213int 214client_queue_delete_deathID(struct srv_client_table *ct, int deathID) 215{ 216 for (int i = 0; i < ct->maxClients; i++) { 217 struct srv_client *c = client_get(ct, i); 218 if (c && c->deathID == deathID) { 219 client_queue_delete(ct, c->cID); 220 return 0; 221 } 222 } 223 return -1; 224} 225