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/*! @file 14 @brief Process Server anon RAM dataspace implementation. 15 16 A dataspace implementation which is backed by physical RAM. Provides methods for creating & 17 deleting ram dataspaces, as well as manages reading and writing to them directly. The actual 18 frames objects are lazily allocated. Dataspace objects support shared strong references through 19 refcounting. 20*/ 21 22#ifndef _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RAM_DATASPACE_H_ 23#define _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RAM_DATASPACE_H_ 24 25#include <stdint.h> 26#include <stdbool.h> 27#include <sel4/sel4.h> 28#include <data_struct/cvector.h> 29#include <data_struct/coat.h> 30#include <vspace/vspace.h> 31#include "../../common.h" 32 33#define RAM_DATASPACE_MAGIC 0xF89D8531 34#define RAM_DATASPACE_LIST_MAGIC 0xC923BE76 35#define RAM_DATASPACE_WAITER_MAGIC 0x351095BC 36#define RAM_DATASPACE_INVALID_ID 0 37 38struct ram_dspace_list; 39 40/*! @brief Ram dataspace structure 41 42 A single ram dataspace backed by physical kernel pages. This structure assumes ownership of its 43 associated pages at all times. 44 */ 45struct ram_dspace { 46 int ID; 47 uint32_t magic; 48 cspacepath_t capability; 49 uint32_t ref; 50 51 /* Anonymous RAM frames. */ 52 vka_object_t *pages; /*< Has ownership. */ 53 uint32_t npages; 54 55 /* Content init state. */ 56 bool contentInitEnabled; 57 cspacepath_t contentInitEP; 58 uint32_t contentInitPID; /* No ownership. */ 59 uint32_t *contentInitBitmask; 60 cvector_t contentInitWaitingList; /* ram_dspace_waiter */ 61 62 /* Physical device state. */ 63 bool physicalAddrEnabled; 64 uint32_t physicalAddr; 65 66 /*! Weak reference to this dataspace's parent. */ 67 struct ram_dspace_list *parentList; /* No ownership. */ 68}; 69 70/*! @brief Ram dataspace list. */ 71struct ram_dspace_list { 72 coat_t allocTable; /* struct ram_dspace */ 73 uint32_t magic; 74}; 75 76/*! @brief Ram dataspace content init waiter structure */ 77struct ram_dspace_waiter { 78 int pageidx; 79 cspacepath_t reply; 80 uint32_t magic; 81}; 82 83/* ------------------------------- RAM dataspace table functions -------------------------------- */ 84 85/*! @brief Initialises an empty ram dataspace list. */ 86void ram_dspace_init(struct ram_dspace_list *rdslist); 87 88/*! @brief De-initialises an empty ram dataspace list. */ 89void ram_dspace_deinit(struct ram_dspace_list *rdslist); 90 91/*! @brief Creates a new ram dataspace and inserts into a ram dataspace list. 92 @param rdslist The ram dataspace list to allocate from. 93 @param size The size of the new dataspace in bytes. 94 @return The newly created ram dataspace if success (No ownership), NULL otherwise. 95 */ 96struct ram_dspace *ram_dspace_create(struct ram_dspace_list *rdslist, size_t size); 97 98/*! @brief Adds a shared reference to ram dataspace from a ram dataspace list. 99 @param rdslist The ram dataspace list to reference the dataspace from. 100 @param ID The ID of target ram dataspace to be refed. 101 */ 102void ram_dspace_ref(struct ram_dspace_list *rdslist, int ID); 103 104/*! @brief Unreference a ram dataspace from a ram dataspace list. If this is the last reference, 105 then the ram dataspace will be deleted from the list. 106 @param rdslist The ram dataspace list to unref the dataspace from. 107 @param ID The ID of target ram dataspace to be unrefed. 108 */ 109void ram_dspace_unref(struct ram_dspace_list *rdslist, int ID); 110 111/*! @brief Checks whether a page in the ram dataspace exists, and finds & returns it if it does. 112 @param dataspace The ram dataspace to find and get the page object from. 113 @param offset Offset into the ram dataspace. 114 @return CPtr to frame if there's a page at the given offset in the given dataspace, 115 0 otherwise. No ownership transfer. 116 */ 117seL4_CPtr ram_dspace_check_page(struct ram_dspace *dataspace, uint32_t offset); 118 119/*! @brief Retrieves a page at a given offset. If the page hasn't been created, it will be 120 allocated. Note that this does NOT perform content init. 121 @param dataspace The ram dataspace to get the page object from. 122 @param offset Offset into the ram dataspace. 123 @return CPtr to frame if success, 0 if offset invalid or out of memory. No ownership transfer. 124 */ 125seL4_CPtr ram_dspace_get_page(struct ram_dspace *dataspace, uint32_t offset); 126 127/*! @brief Finds a ram dataspace in a ram dataspace list by a dataspace ID. 128 @param rdslist The source list of ram dataspaces. (No ownership) 129 @param ID The dataspace ID to locate the ram dataspace in the list. 130 @return The (weak) reference to target ram dataspace if found, NULL otherwise. 131 */ 132struct ram_dspace *ram_dspace_get(struct ram_dspace_list *rdslist, int ID); 133 134/*! @brief Finds a ram dataspace in a ram dataspace list by a dataspace badge. 135 @param rdslist The source list of ram dataspaces. (No ownership) 136 @param badge The dataspace badge to locate the ram dataspace in the list. 137 @return The (weak) reference to target ram dataspace if found, NULL otherwise. 138 */ 139struct ram_dspace *ram_dspace_get_badge(struct ram_dspace_list *rdslist, seL4_Word badge); 140 141/*! @brief Returns the size in bytes of the given dataspace. 142 @param dataspace The dataspace to retrieve size for. 143 @return Size of the given dataspace in bytes on success, 0 otherwise. 144*/ 145uint32_t ram_dspace_get_size(struct ram_dspace *dataspace); 146 147/*! @brief Expands the given dataspace. 148 @param dataspace The dataspace to expand for. 149 @param size The new dataspace size. 150 @return ESUCCESS on success, refos_error otherwise. 151*/ 152int ram_dspace_expand(struct ram_dspace *dataspace, uint32_t size); 153 154/*! @brief Sets the dataspace to start at the given physical address. 155 156 Sets the dataspace to start at the given physical address. The following pages of the 157 dataspace will be mapped to the following contiguous physical memory regions. Used to 158 implement device MMIO mapping. Requires the dataspace to be empty and not initialised by 159 any other content already. 160 This should be called immediately after dataspace creation. 161 162 @param dataspace The dataspace to set physical address for. 163 @param paddr The physical address to start the dataspace at. 164 @return ESUCCESS on success, refos_error otherwise. 165*/ 166int ram_dspace_set_to_paddr(struct ram_dspace *dataspace, uint32_t paddr); 167 168/* --------------------------- RAM dataspace read / write functions ----------------------------- */ 169 170/*! @brief Reads data from a ram dataspace. 171 @param buf The destination buffer to copy data to. (No ownership) 172 @param len The length of the data to be copied. 173 @param dataspace The source ram dataspace. (No ownership) 174 @param offset The offset into the dataspace to read from. 175 @return ESUCCESS if success, refos_error otherwise. 176 */ 177int ram_dspace_read(char *buf, size_t len, struct ram_dspace *dataspace, uint32_t offset); 178 179/*! @brief Writes data to a ram dataspace. 180 @param buf The source buffer containing the data. (No ownership) 181 @param len The length of the data to be written. 182 @param dataspace The target dataspace to be written to. (No ownership) 183 @param offset The offset into the dataspace to write to. 184 @return ESUCCESS if success, refos_error otherwise. 185 */ 186int ram_dspace_write(char *buf, size_t len, struct ram_dspace *dataspace, uint32_t offset); 187 188/* --------------------------- RAM dataspace content init functions ----------------------------- */ 189 190/*! @brief Sets the RAM dataspace to be initialised by another RAM dataspace. 191 @param dataspace The dataspace set content init for. 192 @param initEP The external dspace server that will initialise this dataspace. (Takes ownership) 193 @param initPID The external dspace server PID. 194 @return ESUCCESS if success, refos_error otherwise. 195*/ 196int ram_dspace_content_init(struct ram_dspace *dataspace, cspacepath_t initEP, uint32_t initPID); 197 198/*! @brief Returns whether content initialisation is needed for the given offset. 199 @param dataspace The target dataspace. 200 @param offset The offset into the dataspace to get content init state for. 201 @return TRUE if need content init at given offset, FALSE if already initialised, or -refos_error 202 if content init is not enabled for the given dataspace, or if offset is invalid. 203*/ 204int ram_dspace_need_content_init(struct ram_dspace *dataspace, uint32_t offset); 205 206/*! @brief Add a new content-init blocked waiter. 207 208 Adds a new content-init waiter at the given offset to this dataspace. When the content 209 has been provided, the given endpoint will be replied to. 210 211 @param dataspace The dataspace that the waiter wants to wait on. 212 @param offset The offset at which the client is waiting for, into the dataspace. 213 @param reply The reply endpoint, which will unblock the waiting client. 214 @return ESUCCESS if success, refos_error otherwise. 215*/ 216int ram_dspace_add_content_init_waiter(struct ram_dspace *dataspace, uint32_t offset, 217 cspacepath_t reply); 218 219/*! @brief Add a new content-init blocked waiter using current caller reply cap. 220 @param dataspace The dataspace that the waiter wants to wait on. 221 @param offset The offset at which the client is waiting for, into the dataspace. 222 @return ESUCCESS if success, refos_error otherwise. 223*/ 224int ram_dspace_add_content_init_waiter_save_current_caller(struct ram_dspace *dataspace, 225 uint32_t offset); 226 227/*! @brief Wakes up any waiters waiting at this offset. 228 229 Wakes up any waiter clients waiting at this offset for content-init. This does NOT set the 230 content provided flag, simply loops through the waiting list the replies to clients. 231 232 Note that we do not need to perform and VSpace mapping operations here on the waiting clients, 233 but simply waking them back up is enough, as they will cause another VM fault upon wake-up and 234 then since the content has been initialised now, it will me mapped straight in on the second VM 235 fault. This may be optimised further by performing VSpace mappings right now before waking up 236 the clients. 237 238 @param dataspace The dataspace containing the waiters. 239 @param offset The offset at which the clients are waiting for, into the dataspace. 240*/ 241void ram_dspace_content_init_reply_waiters(struct ram_dspace *dataspace, uint32_t offset); 242 243/*! @brief Set the content-init page of dataspace at offset to be provided. 244 245 Set the provided bitmask flag of the dataspace at the offset to be TRUE, meaning that that page 246 has been content-init provided. Any waiters waiting for the content to be provided should now be 247 woken up, and any further access to these pages should not cause another content-init delegation 248 notification. Does NOT automatically reply to the waiters, that must be separately done via a 249 separate call to ram_dspace_content_init_reply_waiters(). 250 251 @param dataspace The target dataspace. 252 @param offset The offset into the dataspace to get content init state for. 253*/ 254void ram_dspace_set_content_init_provided(struct ram_dspace *dataspace, uint32_t offset); 255 256#endif /* _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RAM_DATASPACE_H_ */