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#include <autoconf.h> 14#include <vspace/vspace.h> 15#include <utils/page.h> 16 17void *vspace_new_sized_stack(vspace_t *vspace, size_t n_pages) 18{ 19 int error = 0; 20 void *vaddr = NULL; 21 22 /* one extra page for the guard */ 23 reservation_t reserve = vspace_reserve_range(vspace, (n_pages + 1) * PAGE_SIZE_4K, 24 seL4_AllRights, 1, &vaddr); 25 26 if (reserve.res == NULL) { 27 return NULL; 28 } 29 30 /* reserve the first page as the guard */ 31 uintptr_t stack_bottom = (uintptr_t) vaddr + PAGE_SIZE_4K; 32 33 /* create and map the pages */ 34 error = vspace_new_pages_at_vaddr(vspace, (void *) stack_bottom, n_pages, seL4_PageBits, reserve); 35 36 if (error) { 37 vspace_free_reservation(vspace, reserve); 38 return NULL; 39 } 40 41 return (void *)(stack_bottom + (n_pages * PAGE_SIZE_4K)); 42} 43 44void vspace_free_sized_stack(vspace_t *vspace, void *stack_top, size_t n_pages) 45{ 46 if (n_pages > 0) { 47 uintptr_t stack_bottom = (uintptr_t) stack_top - (n_pages * PAGE_SIZE_4K); 48 vspace_unmap_pages(vspace, (void *) stack_bottom, n_pages, 49 seL4_PageBits, (vka_t *) VSPACE_FREE); 50 vspace_free_reservation_by_vaddr(vspace, (void *)(stack_bottom - PAGE_SIZE_4K)); 51 } else { 52 ZF_LOGW("Freeing 0 sized stack"); 53 } 54} 55 56void *vspace_new_ipc_buffer(vspace_t *vspace, seL4_CPtr *page) 57{ 58 59 void *vaddr = vspace_new_pages(vspace, seL4_AllRights, 1, seL4_PageBits); 60 if (vaddr == NULL) { 61 return NULL; 62 } 63 64 *page = vspace_get_cap(vspace, vaddr); 65 66 return vaddr; 67 68} 69 70void vspace_free_ipc_buffer(vspace_t *vspace, void *addr) 71{ 72 vspace_unmap_pages(vspace, addr, 1, seL4_PageBits, VSPACE_FREE); 73} 74 75void *vspace_share_mem(vspace_t *from, vspace_t *to, void *start, int num_pages, size_t size_bits, 76 seL4_CapRights_t rights, int cacheable) 77{ 78 void *result; 79 80 /* reserve a range to map the shared memory in to */ 81 reservation_t res = vspace_reserve_range_aligned(to, num_pages * (BIT(size_bits)), size_bits, 82 rights, cacheable, &result); 83 84 if (res.res == NULL) { 85 ZF_LOGE("Failed to reserve range"); 86 return NULL; 87 } 88 89 int error = vspace_share_mem_at_vaddr(from, to, start, num_pages, size_bits, result, res); 90 if (error) { 91 /* fail */ 92 result = NULL; 93 } 94 95 /* clean up reservation */ 96 vspace_free_reservation(to, res); 97 98 return result; 99} 100 101int vspace_access_page_with_callback(vspace_t *from, vspace_t *to, void *access_addr, size_t size_bits, 102 seL4_CapRights_t rights, int cacheable, vspace_access_callback_fn callback, void *cookie) 103{ 104 void *to_vaddr; 105 to_vaddr = vspace_share_mem(from, to, access_addr, 1, size_bits, rights, cacheable); 106 if (to_vaddr == NULL) { 107 ZF_LOGE("Failed to access page"); 108 return -1; 109 } 110 111 /* Invoke callback with mapped address */ 112 int res = callback(access_addr, to_vaddr, cookie); 113 114 /* Remove mappings from destination vspace */ 115 vspace_unmap_pages(to, to_vaddr, 1, size_bits, (vka_t *) VSPACE_FREE); 116 117 return res; 118} 119 120void *vspace_new_pages_with_config(vspace_t *vspace, vspace_new_pages_config_t *config, seL4_CapRights_t rights) 121{ 122 reservation_t res; 123 if (config->vaddr == NULL) { 124 res = vspace_reserve_range_aligned(vspace, config->num_pages * SIZE_BITS_TO_BYTES(config->size_bits), 125 config->size_bits, 126 rights, true, &config->vaddr); 127 } else { 128 res = vspace_reserve_range_at(vspace, config->vaddr, 129 config->num_pages * SIZE_BITS_TO_BYTES(config->size_bits), 130 rights, true); 131 } 132 if (res.res == NULL) { 133 ZF_LOGE("Failed to reserve range"); 134 return NULL; 135 } 136 137 UNUSED int error = vspace_new_pages_at_vaddr_with_config(vspace, config, res); 138 vspace_free_reservation(vspace, res); 139 140 if (error) { 141 return NULL; 142 } 143 144 return config->vaddr; 145} 146 147/* this function is for backwards compatibility after interface change */ 148reservation_t vspace_reserve_range(vspace_t *vspace, size_t bytes, 149 seL4_CapRights_t rights, int cacheable, void **vaddr) 150{ 151 return vspace_reserve_range_aligned(vspace, bytes, seL4_PageBits, rights, cacheable, vaddr); 152} 153