1106686Stjr/* 2106686Stjr * Copyright 2017, Data61 3106686Stjr * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4106686Stjr * ABN 41 687 119 230. 5106686Stjr * 6106686Stjr * This software may be distributed and modified according to the terms of 7106686Stjr * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8106686Stjr * See "LICENSE_BSD2.txt" for details. 9106686Stjr * 10106686Stjr * @TAG(DATA61_BSD) 11106686Stjr */ 12106686Stjr 13106686Stjr#include <allocman/allocman.h> 14106686Stjr#include <allocman/util.h> 15106686Stjr#include <stdlib.h> 16106686Stjr#include <assert.h> 17106686Stjr#include <string.h> 18106686Stjr#include <sel4/sel4.h> 19106686Stjr#include <allocman/vka.h> 20106686Stjr#include <vka/object.h> 21106686Stjr#include <allocman/cspace/vka.h> 22106686Stjr#include <allocman/utspace/vka.h> 23106686Stjr#include <allocman/mspace/malloc.h> 24106686Stjr 25106686Stjr/** 26106686Stjr * Allocate a slot in a cspace. 27106686Stjr * 28106686Stjr * @param data cookie for the underlying allocator 29106686Stjr * @param res pointer to a cptr to store the allocated slot 30106686Stjr * @return 0 on success 31106686Stjr */ 32106686Stjrstatic int am_vka_cspace_alloc(void *data, seL4_CPtr *res) 33106686Stjr{ 34106686Stjr int error; 35106686Stjr cspacepath_t path; 36106686Stjr 37106686Stjr assert(data); 38106686Stjr assert(res); 39106686Stjr 40106686Stjr error = allocman_cspace_alloc((allocman_t *) data, &path); 41106686Stjr if (!error) { 42106686Stjr *res = path.capPtr; 43106686Stjr } 44106686Stjr 45106686Stjr return error; 46106686Stjr} 47106686Stjr 48106686Stjr/** 49106686Stjr * Convert an allocated cptr to a cspacepath, for use in 50106686Stjr * operations such as Untyped_Retype 51106686Stjr * 52106686Stjr * @param data cookie for the underlying allocator 53106686Stjr * @param slot a cslot allocated by the cspace alloc function 54106686Stjr * @param res pointer to a cspacepath struct to fill out 55106686Stjr */ 56106686Stjrstatic void am_vka_cspace_make_path (void *data, seL4_CPtr slot, cspacepath_t *res) 57137587Snik{ 58137587Snik assert(data); 59106686Stjr assert(res); 60106686Stjr 61106686Stjr *res = allocman_cspace_make_path((allocman_t*) data, slot); 62106686Stjr} 63106686Stjr 64106686Stjr/** 65106686Stjr * Free an allocated cslot 66106686Stjr * 67106686Stjr * @param data cookie for the underlying allocator 68106686Stjr * @param slot a cslot allocated by the cspace alloc function 69106686Stjr */ 70106686Stjrstatic void am_vka_cspace_free (void *data, seL4_CPtr slot) 71106686Stjr{ 72106686Stjr cspacepath_t path; 73106686Stjr assert(data); 74106686Stjr path = allocman_cspace_make_path((allocman_t*)data, slot); 75106686Stjr 76106686Stjr allocman_cspace_free((allocman_t *) data, &path); 77106686Stjr} 78106686Stjr 79106686Stjr/** 80106686Stjr * Allocate a portion of an untyped into an object 81106686Stjr * 82106686Stjr * @param data cookie for the underlying allocator 83106686Stjr * @param dest path to an empty cslot to place the cap to the allocated object 84106686Stjr * @param type the seL4 object type to allocate (as passed to Untyped_Retype) 85106686Stjr * @param size_bits the size of the object to allocate (as passed to Untyped_Retype) 86106686Stjr * @param can_use_dev whether the allocator can use device untyped instead of regular untyped 87106686Stjr * @param res pointer to a location to store the cookie representing this allocation 88106686Stjr * @return 0 on success 89106686Stjr */ 90106686Stjrstatic int am_vka_utspace_alloc_maybe_device (void *data, const cspacepath_t *dest, 91106686Stjr seL4_Word type, seL4_Word size_bits, bool can_use_dev, seL4_Word *res) 92106686Stjr{ 93106686Stjr int error; 94106686Stjr 95106686Stjr assert(data); 96106686Stjr assert(res); 97106686Stjr assert(dest); 98106686Stjr 99106686Stjr /* allocman uses the size in memory internally, where as vka expects size_bits 100106686Stjr * as passed to Untyped_Retype, so do a conversion here */ 101106686Stjr size_bits = vka_get_object_size(type, size_bits); 102106686Stjr 103106686Stjr *res = allocman_utspace_alloc((allocman_t *) data, size_bits, type, (cspacepath_t*)dest, can_use_dev, &error); 104106686Stjr 105106686Stjr return error; 106106686Stjr} 107106686Stjr 108106686Stjr/** 109106686Stjr * Allocate a portion of an untyped into an object 110106686Stjr * 111106686Stjr * @param data cookie for the underlying allocator 112106686Stjr * @param dest path to an empty cslot to place the cap to the allocated object 113106686Stjr * @param type the seL4 object type to allocate (as passed to Untyped_Retype) 114106686Stjr * @param size_bits the size of the object to allocate (as passed to Untyped_Retype) 115106686Stjr * @param res pointer to a location to store the cookie representing this allocation 116106686Stjr * @return 0 on success 117106686Stjr */ 118106686Stjrstatic int am_vka_utspace_alloc (void *data, const cspacepath_t *dest, seL4_Word type, seL4_Word size_bits, seL4_Word *res) 119106686Stjr{ 120106686Stjr return am_vka_utspace_alloc_maybe_device(data, dest, type, size_bits, false, res); 121106686Stjr} 122106686Stjr 123106686Stjr/** 124106686Stjr * Allocate a portion of an untyped into an object 125106686Stjr * 126137587Snik * @param data cookie for the underlying allocator 127106686Stjr * @param dest path to an empty cslot to place the cap to the allocated object 128106686Stjr * @param type the seL4 object type to allocate (as passed to Untyped_Retype) 129106686Stjr * @param size_bits the size of the object to allocate (as passed to Untyped_Retype) 130 * @param paddr the desired physical address of the start of the allocated object 131 * @param res pointer to a location to store the cookie representing this allocation 132 * @return 0 on success 133 */ 134static int am_vka_utspace_alloc_at (void *data, const cspacepath_t *dest, seL4_Word type, seL4_Word size_bits, uintptr_t paddr, seL4_Word *res) 135{ 136 int error; 137 138 assert(data); 139 assert(res); 140 assert(dest); 141 142 /* allocman uses the size in memory internally, where as vka expects size_bits 143 * as passed to Untyped_Retype, so do a conversion here */ 144 size_bits = vka_get_object_size(type, size_bits); 145 146 *res = allocman_utspace_alloc_at((allocman_t *) data, size_bits, type, (cspacepath_t*)dest, paddr, true, &error); 147 148 return error; 149} 150 151/** 152 * Free a portion of an allocated untyped. Is the responsibility of the caller to 153 * have already deleted the object (by deleting all capabilities) first 154 * 155 * @param data cookie for the underlying allocator 156 * @param type the seL4 object type that was allocated (as passed to Untyped_Retype) 157 * @param size_bits the size of the object that was allocated (as passed to Untyped_Retype) 158 * @param target cookie to the allocation as given by the utspace alloc function 159 */ 160static void am_vka_utspace_free (void *data, seL4_Word type, seL4_Word size_bits, seL4_Word target) 161{ 162 assert(data); 163 164 /* allocman uses the size in memory internally, where as vka expects size_bits 165 * as passed to Untyped_Retype, so do a conversion here */ 166 size_bits = vka_get_object_size(type, size_bits); 167 168 allocman_utspace_free((allocman_t *)data, target, size_bits); 169} 170 171static uintptr_t am_vka_utspace_paddr (void *data, seL4_Word target, seL4_Word type, seL4_Word size_bits) 172{ 173 assert(data); 174 175 /* allocman uses the size in memory internally, where as vka expects size_bits 176 * as passed to Untyped_Retype, so do a conversion here */ 177 size_bits = vka_get_object_size(type, size_bits); 178 179 return allocman_utspace_paddr((allocman_t *)data, target, size_bits); 180} 181 182/** 183 * Make a VKA object using this allocman 184 * 185 * @param structure for the vka interface object 186 * @param allocator to be used with this vka 187 */ 188void allocman_make_vka(vka_t *vka, allocman_t *alloc) 189{ 190 assert(vka); 191 assert(alloc); 192 193 vka->data = alloc; 194 vka->cspace_alloc = &am_vka_cspace_alloc; 195 vka->cspace_make_path = &am_vka_cspace_make_path; 196 vka->utspace_alloc = &am_vka_utspace_alloc; 197 vka->utspace_alloc_maybe_device = &am_vka_utspace_alloc_maybe_device; 198 vka->utspace_alloc_at = &am_vka_utspace_alloc_at; 199 vka->cspace_free = &am_vka_cspace_free; 200 vka->utspace_free = &am_vka_utspace_free; 201 vka->utspace_paddr = &am_vka_utspace_paddr; 202} 203 204int allocman_make_from_vka(vka_t *vka, allocman_t *alloc) 205{ 206 int error; 207 assert(vka); 208 assert(alloc); 209 210 error = allocman_create(alloc, mspace_malloc_interface); 211 if (error) { 212 return error; 213 } 214 error = allocman_attach_utspace(alloc, utspace_vka_make_interface(vka)); 215 assert(!error); 216 error = allocman_attach_cspace(alloc, cspace_vka_make_interface(vka)); 217 assert(!error); 218 return 0; 219} 220