1/* 2 * Copyright 2017, 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(DATA61_BSD) 11 */ 12 13/* 14 * An implementation of the vspace virtual memory allocation interface, using a two 15 * level page table. 16 * 17 * This implementation expects malloc to work, although it only uses it for small amounts of 18 * memory. 19 * 20 * Stack size is constant and be configured in menuconfig. 21 * 22 * Stacks are allocated with 1 guard page between them, but they are contiguous in the vmem 23 * region. 24 * 25 * Allocation starts at 0x00001000. 26 * 27 * This library will allow you to map over anything that it doesn't know about, so 28 * make sure you tell it if you do any external mapping. 29 * 30 */ 31#pragma once 32 33#include <autoconf.h> 34#include <sel4utils/gen_config.h> 35 36#include <vspace/vspace.h> 37#include <vka/vka.h> 38#include <sel4utils/util.h> 39#include <sel4utils/arch/vspace.h> 40 41/* These definitions are only here so that you can take the size of them. 42 * TOUCHING THESE DATA STRUCTURES IN ANY WAY WILL BREAK THE WORLD 43 */ 44#define KERNEL_RESERVED_START (ALIGN_DOWN(seL4_UserTop, PAGE_SIZE_4K)) 45#define VSPACE_LEVEL_SIZE BIT(VSPACE_LEVEL_BITS) 46 47typedef struct vspace_mid_level { 48 /* there is a clear optimization that could be done where instead of always pointing to a 49 * sub table, there is the option of pointing directly to a page. This allows more 50 * efficient memory usage for book keeping large pages */ 51 uintptr_t table[VSPACE_LEVEL_SIZE]; 52} vspace_mid_level_t; 53 54typedef struct vspace_bottom_level { 55 seL4_CPtr cap[VSPACE_LEVEL_SIZE]; 56 uintptr_t cookie[VSPACE_LEVEL_SIZE]; 57} vspace_bottom_level_t; 58 59typedef int(*sel4utils_map_page_fn)(vspace_t *vspace, seL4_CPtr cap, void *vaddr, seL4_CapRights_t rights, 60 int cacheable, size_t size_bits); 61 62struct sel4utils_res { 63 uintptr_t start; 64 uintptr_t end; 65 seL4_CapRights_t rights; 66 int cacheable; 67 int malloced; 68 bool rights_deferred; 69 struct sel4utils_res *next; 70}; 71 72typedef struct sel4utils_res sel4utils_res_t; 73 74typedef struct sel4utils_alloc_data { 75 seL4_CPtr vspace_root; 76 vka_t *vka; 77 vspace_mid_level_t *top_level; 78 uintptr_t next_bootstrap_vaddr; 79 uintptr_t last_allocated; 80 vspace_t *bootstrap; 81 sel4utils_map_page_fn map_page; 82 sel4utils_res_t *reservation_head; 83 bool is_empty; 84} sel4utils_alloc_data_t; 85 86static inline sel4utils_res_t *reservation_to_res(reservation_t res) 87{ 88 return (sel4utils_res_t *) res.res; 89} 90 91/** 92 * This is a mostly internal function for constructing a vspace. Allows a vspace to be created 93 * with an arbitrary function to invoke for the mapping of pages. This is useful if you want 94 * a vspace manager, but you do not want to use seL4 page directories 95 * 96 * @param loader vspace of the current process, used to allocate 97 * virtual memory book keeping. 98 * @param new_vspace uninitialised vspace struct to populate. 99 * @param data uninitialised vspace data struct to populate. 100 * @param vka initialised vka that this virtual memory allocator will use to 101 * allocate pages and pagetables. This allocator will never invoke free. 102 * @param vspace_root root object for the new vspace. 103 * @param allocated_object_fn function to call when objects are allocated. Can be null. 104 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 105 * @param map_page Function that will be called to map seL4 pages 106 * 107 * @return 0 on success. 108 */ 109int 110sel4utils_get_vspace_with_map(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data, 111 vka_t *vka, seL4_CPtr vspace_root, 112 vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, sel4utils_map_page_fn map_page); 113/** 114 * Allows for an empty vspace to be created with an arbitrary function to invoke for the mapping of pages. 115 * This is useful if you want a vspace manager, but you do not want parts of the virtual address space to be 116 * pre-reserved e.g the kernel region. The vspace is useful for guest virtual machine-based applications. 117 * 118 * @param loader vspace of the current process, used to allocate 119 * virtual memory book keeping. 120 * @param new_vspace uninitialised vspace struct to populate. 121 * @param data uninitialised vspace data struct to populate. 122 * @param vka initialised vka that this virtual memory allocator will use to 123 * allocate pages and pagetables. This allocator will never invoke free. 124 * @param vspace_root root object for the new vspace. 125 * @param allocated_object_fn function to call when objects are allocated. Can be null. 126 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 127 * @param map_page Function that will be called to map seL4 pages 128 * 129 * @return 0 on success. 130 */ 131int 132sel4utils_get_empty_vspace_with_map(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data, 133 vka_t *vka, seL4_CPtr vspace_root, 134 vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, sel4utils_map_page_fn map_page); 135/** 136 * Initialise a vspace allocator for a new address space (not the current one). 137 * 138 * @param loader vspace of the current process, used to allocate 139 * virtual memory book keeping. 140 * @param new_vspace uninitialised vspace struct to populate. 141 * @param data uninitialised vspace data struct to populate. 142 * @param vka initialised vka that this virtual memory allocator will use to 143 * allocate pages and pagetables. This allocator will never invoke free. 144 * @param vspace_root root object for the new vspace. 145 * @param allocated_object_fn function to call when objects are allocated. Can be null. 146 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 147 * 148 * @return 0 on success. 149 */ 150int sel4utils_get_vspace(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data, 151 vka_t *vka, seL4_CPtr vspace_root, vspace_allocated_object_fn allocated_object_fn, 152 void *allocated_object_cookie); 153 154/** 155 * Allows for an empty vspace to be created. 156 * This is useful if you want a vspace manager, but you do not want parts of the virtual address space to be 157 * pre-reserved e.g the kernel region. The vspace is useful for guest virtual machine-based applications. 158 * 159 * @param loader vspace of the current process, used to allocate 160 * virtual memory book keeping. 161 * @param new_vspace uninitialised vspace struct to populate. 162 * @param data uninitialised vspace data struct to populate. 163 * @param vka initialised vka that this virtual memory allocator will use to 164 * allocate pages and pagetables. This allocator will never invoke free. 165 * @param vspace_root root object for the new vspace. 166 * @param allocated_object_fn function to call when objects are allocated. Can be null. 167 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 168 * 169 * @return 0 on success. 170 */ 171int sel4utils_get_empty_vspace(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data, 172 vka_t *vka, seL4_CPtr vspace_root, vspace_allocated_object_fn allocated_object_fn, 173 void *allocated_object_cookie); 174 175 176#ifdef CONFIG_VTX 177/** 178 * Initialise a vspace allocator for an EPT address space 179 * 180 * @param loader vspace of the current process, used to allocate 181 * virtual memory book keeping. 182 * @param new_vspace uninitialised vspace struct to populate. 183 * @param vka initialised vka that this virtual memory allocator will use to 184 * allocate pages and pagetables. This allocator will never invoke free. 185 * @param ept EPT page directory for the new vspace. 186 * @param allocated_object_fn function to call when objects are allocated. Can be null. 187 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 188 * 189 * @return 0 on success. 190 */ 191int sel4utils_get_vspace_ept(vspace_t *loader, vspace_t *new_vspace, vka_t *vka, 192 seL4_CPtr ept, vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie); 193#endif /* CONFIG_VTX */ 194 195/** 196 * Initialise a vspace allocator for the current address space (this is intended 197 * for use a task that is not the root task but has no vspace, ie one loaded by the capDL loader). 198 * 199 * @param vspace uninitialised vspace struct to populate. 200 * @param data uninitialised vspace data struct to populate. 201 * @param vka initialised vka that this virtual memory allocator will use to 202 * allocate pages and pagetables. This allocator will never invoke free. 203 * @param vspace_root root object for the new vspace. 204 * @param allocated_object_fn function to call when objects are allocated. Can be null. 205 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 206 * @param existing_frames a NULL terminated list of virtual addresses for 4K frames that are 207 * already allocated. For larger frames, just pass in the virtual 208 * address range in 4K addresses. This will prevent the allocator 209 * from overriding these frames. 210 * 211 * @return 0 on succes. 212 * 213 */ 214int sel4utils_bootstrap_vspace(vspace_t *vspace, sel4utils_alloc_data_t *data, 215 seL4_CPtr vspace_root, vka_t *vka, 216 vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, 217 void *existing_frames[]); 218 219/** 220 * Initialise a vspace allocator for the current address space (this is intended 221 * for use by the root task). Take details of existing frames from bootinfo. 222 * 223 * @param vspace uninitialised vspace struct to populate. 224 * @param data uninitialised vspace data struct to populate. 225 * @param vka initialised vka that this virtual memory allocator will use to 226 * allocate pages and pagetables. This allocator will never invoke free. 227 * @param info seL4 boot info 228 * @param vspace_root root object for the new vspace. 229 * @param allocated_object_fn function to call when objects are allocated. Can be null. 230 * @param allocated_object_cookie cookie passed when the above function is called. Can be null. 231 * 232 * @return 0 on succes. 233 * 234 */ 235int sel4utils_bootstrap_vspace_with_bootinfo(vspace_t *vspace, sel4utils_alloc_data_t *data, 236 seL4_CPtr vspace_root, 237 vka_t *vka, seL4_BootInfo *info, vspace_allocated_object_fn allocated_object_fn, 238 void *allocated_object_cookie); 239 240/* Wrapper function that configures a vspaceator such that all allocated objects are not 241 * tracked. 242 */ 243static inline int sel4utils_get_vspace_leaky(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data, 244 vka_t *vka, seL4_CPtr vspace_root) 245{ 246 return sel4utils_get_vspace(loader, new_vspace, data, vka, vspace_root, 247 (vspace_allocated_object_fn) NULL, NULL); 248} 249 250#ifdef CONFIG_VTX 251static inline int sel4utils_get_vspace_ept_leaky(vspace_t *loader, vspace_t *new_vspace, 252 vka_t *vka, seL4_CPtr vspace_root) 253{ 254 return sel4utils_get_vspace_ept(loader, new_vspace, vka, vspace_root, 255 (vspace_allocated_object_fn) NULL, NULL); 256} 257#endif /* CONFIG_VTX */ 258 259static inline int sel4utils_bootstrap_vspace_with_bootinfo_leaky(vspace_t *vspace, sel4utils_alloc_data_t *data, 260 seL4_CPtr vspace_root, 261 vka_t *vka, seL4_BootInfo *info) 262{ 263 return sel4utils_bootstrap_vspace_with_bootinfo(vspace, data, vspace_root, vka, info, NULL, NULL); 264} 265 266static inline int sel4utils_bootstrap_vspace_leaky(vspace_t *vspace, sel4utils_alloc_data_t *data, 267 seL4_CPtr vspace_root, vka_t *vka, 268 void *existing_frames[]) 269{ 270 return sel4utils_bootstrap_vspace(vspace, data, vspace_root, vka, NULL, NULL, existing_frames); 271} 272 273/** 274 * Attempts to create a new vspace reservation. Function behaves similarly to vspace_reserve_range 275 * except a reservation struct is passed in, instead of being malloc'ed. This is intended to be 276 * used during bootstrapping where malloc has not yet been setup. 277 * Reservations created with this function should *only* be freed with sel4utils_reserve_range_at_no_alloc 278 * 279 * Result will be aligned to 4K. 280 * 281 * @param vspace the virtual memory allocator to use. 282 * @param reservation Allocated reservation struct to fill out 283 * @param bytes the size in bytes to map. 284 * @param rights the rights to map the pages in with in this reservation 285 * @param cacheable 1 if the pages should be mapped with cacheable attributes. 0 for DMA. 286 * @param vaddr the virtual address of the reserved range will be returned here. 287 * 288 * @return 0 on success 289 */ 290int sel4utils_reserve_range_no_alloc(vspace_t *vspace, sel4utils_res_t *reservation, size_t size, 291 seL4_CapRights_t rights, int cacheable, void **result); 292 293/* 294 * @see sel4utils_reserve_range_no_alloc, however result is aligned to size_bits. 295 */ 296int sel4utils_reserve_range_no_alloc_aligned(vspace_t *vspace, sel4utils_res_t *reservation, 297 size_t size, size_t size_bits, seL4_CapRights_t rights, int cacheable, void **result); 298 299/** 300 * Attempts to create a new vspace reservation. Function behaves similarly to vspace_reserve_range_at 301 * except a reservation struct is passed in, instead of being malloc'ed. This is intended to be 302 * used during bootstrapping where malloc has not yet been setup. 303 * Reservations created with this function should *only* be freed with sel4utils_reserve_range_at_no_alloc 304 * 305 * @param vspace the virtual memory allocator to use. 306 * @param reservation Allocated reservation struct to fill out 307 * @param vaddr the virtual address to start the range at. 308 * @param bytes the size in bytes to map. 309 * @param rights the rights to map the pages in with in this reservatio 310 * @param cacheable 1 if the pages should be mapped with cacheable attributes. 0 for DMA. 311 * 312 * @return 0 on success 313 */ 314int sel4utils_reserve_range_at_no_alloc(vspace_t *vspace, sel4utils_res_t *reservation, void *vaddr, 315 size_t size, seL4_CapRights_t rights, int cacheable); 316 317/** 318 * Move and/or resizes a reservation in any direction, allowing for both start and/or end address to 319 * be changed. Any overlapping region will keep their reservation, any non-overlapping regions will 320 * be unreserved. Does not make any mapping changes. 321 * @param vspace the virtual memory allocator to use. 322 * @param reservation the reservation to move. 323 * @param vaddr the start virtual address to move the reservation to. 324 * @param bytes the size in bytes of new reservation. 325 * @return 0 on success, -1 if region start could not be moved, -2 if end could not be moved. 326 */ 327int sel4utils_move_resize_reservation(vspace_t *vspace, reservation_t reservation, void *vaddr, 328 size_t bytes); 329 330/* 331 * Copy the code and data segment (the image effectively) from current vspace 332 * into clone vspace. The clone vspace should be initialised. 333 * 334 * @param current the vspace to copy from. 335 * @param clone the vspace to copy to. 336 * @param reservation the previously established reservation in clone to copy. 337 * @return 0 on success. 338 */ 339int sel4utils_bootstrap_clone_into_vspace(vspace_t *current, vspace_t *clone, reservation_t reserve); 340 341/** 342 * Get the bounds of _executable_start and _end. 343 * 344 * @param va_start return va_start. 345 * @param va_end return va_end. 346 */ 347void sel4utils_get_image_region(uintptr_t *va_start, uintptr_t *va_end); 348 349/** 350 * 351 * @return the physical address that vaddr is mapped to. 352 * VKA_NO_PADDR if there is no mapping 353 */ 354uintptr_t sel4utils_get_paddr(vspace_t *vspace, void *vaddr, seL4_Word type, seL4_Word size_bits); 355 356