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/vmlayout.h> 19#include "badge.h" 20#include "state.h" 21#include "dataspace.h" 22 23 /*! @file 24 @brief File server CPIO dataspace object allocation and management. 25 26 This module contains the concrete implementations for file server CPIO dataspaces. The 27 dispatcher module simple does basic error checking before calling one of the helper functions 28 here. 29*/ 30 31/* --------------------- CPIO Dataspace OAT Callback Functions ---------------------------------- */ 32 33/*! @brief Dataspace object OAT creation function. 34 35 This is called by coat helper library to create a new structure. The first argument is the 36 client's DeathID, second argument is the fileData pointer, 3rd argument is the fileData size, 37 and 4th argument the permissions mask. 38 39 Allocates and fills in a new dataspace structure with the given arguments, and mints a new cap 40 representing this new dataspace. 41 42 @param oat The parent struct fs_dataspace_table structure of dspace object being created. 43 @param id The dataspace object ID that has been allocated for this object to go into. 44 @param arg The arguments (see above). 45 @return A new dataspace (struct fs_dataspace) if success, NULL otherwise. (Passes ownership, it 46 is the caller's responsibility to call dspace_oat_delete on the returned object.) 47*/ 48static cvector_item_t 49dspace_oat_create(coat_t *oat, int id, uint32_t arg[COAT_ARGS]) 50{ 51 /* Allocate and fill in structure. */ 52 struct fs_dataspace *ndspace = malloc(sizeof(struct fs_dataspace)); 53 if (!ndspace) { 54 assert(!"oom"); 55 ROS_ERROR("dspace_oat_create out of memory!"); 56 return NULL; 57 } 58 59 ndspace->magic = FS_DATASPACE_MAGIC; 60 ndspace->dID = id; 61 ndspace->deathID = arg[0]; 62 ndspace->dataspaceCap = csalloc(); 63 ndspace->fileData = (char*) arg[1]; 64 ndspace->fileDataSize = arg[2]; 65 ndspace->permissions = arg[3]; 66 ndspace->fileCreated = false; 67 68 /* Check that the dataspace cap cslot has been successfully allocated, and that 69 the given pointer is valid. */ 70 if (!ndspace->dataspaceCap || !ndspace->fileData) { 71 free(ndspace); 72 return NULL; 73 } 74 75 /* Create the badged cap represending this dataspace. */ 76 int error = seL4_CNode_Mint( 77 REFOS_CSPACE, ndspace->dataspaceCap, REFOS_CDEPTH, 78 REFOS_CSPACE, fileServCommon->anonEP, REFOS_CDEPTH, 79 seL4_AllRights, seL4_CapData_Badge_new(id + FS_DSPACE_BADGE_BASE) 80 ); 81 assert(!error); 82 (void) error; 83 84 return (cvector_item_t) ndspace; 85} 86 87/*! @brief Dataspace object OAT deletion function. 88 @param oat The parent struct fs_dataspace_table structure of dspace object being deleted. 89 @param obj The dataspace object (struct fs_dataspace) to release resources for. 90 (Takes ownership since it frees the given structure.) 91*/ 92static void 93dspace_oat_delete(coat_t *oat, cvector_item_t *obj) 94{ 95 struct fs_dataspace *dspace = (struct fs_dataspace *) obj; 96 assert(dspace && dspace->magic == FS_DATASPACE_MAGIC); 97 dprintf("Deleting dataspace ID %d\n", dspace->dID); 98 99 assert(dspace->dataspaceCap); 100 seL4_CNode_Revoke(REFOS_CSPACE, dspace->dataspaceCap, REFOS_CDEPTH); 101 csfree_delete(dspace->dataspaceCap); 102 103 /* Finally, free the entire structure. */ 104 free(dspace); 105} 106 107/* ----------------------- CPIO Dataspace Table Functions --------------------------------------- */ 108 109void 110dspace_table_init(struct fs_dataspace_table *dt) 111{ 112 /* Configure the object allocation table creation / deletion callback func pointers. */ 113 dt->allocTable.oat_expand = NULL; 114 dt->allocTable.oat_create = dspace_oat_create; 115 dt->allocTable.oat_delete = dspace_oat_delete; 116 117 /* Initialise our data structures. */ 118 coat_init(&dt->allocTable, 1, FILESERVER_MAX_DATASPACES); 119 chash_init(&dt->windowAssocTable, FILESERVER_WINDOW_ASSOC_HASHSIZE); 120 chash_init(&dt->dspaceAssocTable, FILESERVER_DSPACE_ASSOC_HASHSIZE); 121} 122 123void 124dspace_table_release(struct fs_dataspace_table *dt) 125{ 126 for (int i = 0; i < PROCESS_MAX_WINDOWS; i++) { 127 dspace_window_unassociate(dt, i); 128 } 129 coat_release(&dt->allocTable); 130 chash_release(&dt->windowAssocTable); 131} 132 133/* --------------------- CPIO Dataspace Allocation Functions ------------------------------------ */ 134 135struct fs_dataspace* 136dspace_alloc(struct fs_dataspace_table *dt, uint32_t deathID, char *fileData, size_t fileDataSize, 137 seL4_Word permissions) 138{ 139 struct fs_dataspace* ndspace = NULL; 140 141 uint32_t arg[COAT_ARGS]; 142 arg[0] = deathID; 143 arg[1] = (uint32_t) fileData; 144 arg[2] = (uint32_t) fileDataSize; 145 arg[3] = (uint32_t) permissions; 146 147 /* Allocate an ID, and the dspace structure associated with it. */ 148 int ID = coat_alloc(&dt->allocTable, arg, (cvector_item_t *) &ndspace); 149 if (!ndspace) { 150 ROS_ERROR("dspace_alloc couldn't allocate a dataspace."); 151 return NULL; 152 } 153 154 assert(ID != COAT_INVALID_ID); 155 assert(ndspace->magic == FS_DATASPACE_MAGIC); 156 (void) ID; 157 return ndspace; 158} 159 160struct fs_dataspace* 161dspace_get(struct fs_dataspace_table *dt, int id) 162{ 163 if (id < 0 || id >= FILESERVER_MAX_DATASPACES) { 164 /* Invalid ID. */ 165 return NULL; 166 } 167 struct fs_dataspace* ndspace = (struct fs_dataspace*) coat_get(&dt->allocTable, id); 168 if (!ndspace) { 169 /* No such dataspace ID exists. */ 170 return NULL; 171 } 172 assert(ndspace->magic == FS_DATASPACE_MAGIC); 173 return ndspace; 174} 175 176struct fs_dataspace* 177dspace_get_badge(struct fs_dataspace_table *dt, int badge) 178{ 179 if (badge < FS_DSPACE_BADGE_BASE || badge >= FS_DSPACE_BADGE_BASE + FILESERVER_MAX_DATASPACES) { 180 /* Invalid badge. */ 181 return NULL; 182 } 183 return dspace_get(dt, badge - FS_DSPACE_BADGE_BASE); 184} 185 186void 187dspace_delete(struct fs_dataspace_table *dt, int id) 188{ 189 coat_free(&dt->allocTable, id); 190} 191 192/* ----------------------------- CPIO Dataspace Functions --------------------------------------- */ 193 194/*! @brief Internal unassociation helper function. */ 195static void 196dspace_externalID_unassociate(chash_t *ht, int objID) 197{ 198 struct dataspace_association_info *di = (struct dataspace_association_info *) 199 chash_get(ht, objID); 200 if (!di) { 201 /* No association structure here to free. */ 202 return; 203 } 204 chash_set(ht, objID, (chash_item_t) NULL); 205 if (di->objectCap) { 206 seL4_CNode_Revoke(REFOS_CSPACE, di->objectCap, REFOS_CDEPTH); 207 seL4_CNode_Delete(REFOS_CSPACE, di->objectCap, REFOS_CDEPTH); 208 csfree(di->objectCap); 209 } 210 free(di); 211} 212 213/*! @brief Internal association helper function. */ 214static int 215dspace_externalID_associate(chash_t *ht, int objID, int dsID, int dsOffset, 216 seL4_CPtr cap) 217{ 218 dspace_externalID_unassociate(ht, objID); 219 struct dataspace_association_info *di = malloc(sizeof(struct dataspace_association_info)); 220 if (!di) { 221 return ENOMEM; 222 } 223 di->dataspaceID = dsID; 224 di->dataspaceOffset = dsOffset; 225 di->objectCap = cap; 226 chash_set(ht, objID, (chash_item_t) di); 227 return ESUCCESS; 228} 229 230int 231dspace_window_associate(struct fs_dataspace_table *dt, int winID, int dsID, int dsOffset, 232 seL4_CPtr windowCap) 233{ 234 return dspace_externalID_associate(&dt->windowAssocTable, winID, dsID, dsOffset, windowCap); 235} 236 237struct dataspace_association_info * 238dspace_window_find(struct fs_dataspace_table *dt, int winID) 239{ 240 return (struct dataspace_association_info *) chash_get(&dt->windowAssocTable, winID); 241} 242 243void 244dspace_window_unassociate(struct fs_dataspace_table *dt, int winID) 245{ 246 dspace_externalID_unassociate(&dt->windowAssocTable, winID); 247} 248 249int 250dspace_external_associate(struct fs_dataspace_table *dt, int xdsID, int dsID, int dsOffset, 251 seL4_CPtr xdspaceCap) 252{ 253 return dspace_externalID_associate(&dt->dspaceAssocTable, xdsID, dsID, dsOffset, xdspaceCap); 254} 255 256void 257dspace_external_unassociate(struct fs_dataspace_table *dt, int xdsID) 258{ 259 dspace_externalID_unassociate(&dt->dspaceAssocTable, xdsID); 260} 261 262struct dataspace_association_info * 263dspace_external_find(struct fs_dataspace_table *dt, int xdsID) 264{ 265 return (struct dataspace_association_info *) chash_get(&dt->dspaceAssocTable, xdsID); 266} 267