1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <stdio.h> 8#include <stdlib.h> 9#include <string.h> 10 11#include <sel4/sel4.h> 12#include <vka/vka.h> 13#include <vka/capops.h> 14 15#include <sel4vm/guest_vm.h> 16#include <sel4vm/guest_memory.h> 17#include <sel4vm/guest_memory_helpers.h> 18 19#include <sel4vmmplatsupport/guest_memory_util.h> 20 21struct device_frame_cookie { 22 vka_object_t frame; 23 cspacepath_t mapped_frame; 24 vm_t *vm; 25 uintptr_t addr; 26 vm_memory_reservation_t *reservation; 27 seL4_CapRights_t rights; 28}; 29 30struct ut_alloc_iterator_cookie { 31 vm_t *vm; 32 vm_memory_reservation_t *reservation; 33 uintptr_t paddr; 34 bool with_paddr; 35}; 36 37static vm_frame_t device_frame_iterator(uintptr_t addr, void *cookie) 38{ 39 cspacepath_t return_frame; 40 vm_t *vm; 41 int page_size; 42 vm_frame_t frame_result = { seL4_CapNull, seL4_NoRights, 0, 0 }; 43 44 struct device_frame_cookie *device_cookie = (struct device_frame_cookie *)cookie; 45 if (!device_cookie) { 46 return frame_result; 47 } 48 vm = device_cookie->vm; 49 page_size = seL4_PageBits; 50 51 int ret = vka_cspace_alloc_path(vm->vka, &return_frame); 52 if (ret) { 53 ZF_LOGE("Failed to allocate cspace path from device frame"); 54 return frame_result; 55 } 56 ret = vka_cnode_copy(&return_frame, &device_cookie->mapped_frame, seL4_AllRights); 57 if (ret) { 58 ZF_LOGE("Failed to cnode_copy for device frame"); 59 vka_cspace_free_path(vm->vka, return_frame); 60 return frame_result; 61 } 62 frame_result.cptr = return_frame.capPtr; 63 frame_result.rights = device_cookie->rights; 64 frame_result.vaddr = device_cookie->addr; 65 frame_result.size_bits = page_size; 66 67 return frame_result; 68} 69 70static vm_frame_t ut_alloc_iterator(uintptr_t addr, void *cookie) 71{ 72 int ret; 73 int error; 74 vka_object_t object; 75 uintptr_t alloc_addr; 76 cspacepath_t path; 77 vm_frame_t frame_result = { seL4_CapNull, seL4_NoRights, 0, 0 }; 78 struct ut_alloc_iterator_cookie *alloc_cookie = (struct ut_alloc_iterator_cookie *)cookie; 79 vm_t *vm = alloc_cookie->vm; 80 int page_size = seL4_PageBits; 81 uintptr_t frame_start = ROUND_DOWN(addr, BIT(page_size)); 82 83 if (alloc_cookie->with_paddr) { 84 uintptr_t base_vaddr; 85 size_t size; 86 vm_get_reservation_memory_region(alloc_cookie->reservation, &base_vaddr, &size); 87 alloc_addr = ROUND_DOWN(alloc_cookie->paddr + (addr - base_vaddr), BIT(page_size)); 88 } else { 89 alloc_addr = frame_start; 90 } 91 error = vka_cspace_alloc_path(vm->vka, &path); 92 if (error) { 93 ZF_LOGE("Failed to allocate path"); 94 return frame_result; 95 } 96 error = simple_get_frame_cap(vm->simple, (void *)alloc_addr, page_size, &path); 97 if (error) { 98 /* attempt to allocate */ 99 uintptr_t vka_cookie; 100 error = vka_utspace_alloc_at(vm->vka, &path, kobject_get_type(KOBJECT_FRAME, page_size), page_size, alloc_addr, 101 &vka_cookie); 102 } 103 if (error) { 104 ZF_LOGE("Failed to allocate page"); 105 vka_cspace_free_path(vm->vka, path); 106 return frame_result; 107 } 108 109 frame_result.cptr = path.capPtr; 110 frame_result.rights = seL4_AllRights; 111 frame_result.vaddr = frame_start; 112 frame_result.size_bits = page_size; 113 return frame_result; 114} 115 116static vm_frame_t maybe_device_alloc_iterator(uintptr_t addr, void *cookie) 117{ 118 int ret; 119 vka_object_t object; 120 vm_frame_t frame_result = { seL4_CapNull, seL4_NoRights, 0, 0 }; 121 vm_t *vm = (vm_t *)cookie; 122 if (!vm) { 123 return frame_result; 124 } 125 int page_size = seL4_PageBits; 126 uintptr_t frame_start = ROUND_DOWN(addr, BIT(page_size)); 127 ret = vka_alloc_frame_maybe_device(vm->vka, page_size, true, &object); 128 if (ret) { 129 ZF_LOGE("Failed to allocate frame for address 0x%x", addr); 130 return frame_result; 131 } 132 frame_result.cptr = object.cptr; 133 frame_result.rights = seL4_AllRights; 134 frame_result.vaddr = frame_start; 135 frame_result.size_bits = page_size; 136 return frame_result; 137} 138 139static vm_frame_t frame_alloc_iterator(uintptr_t addr, void *cookie) 140{ 141 int ret; 142 vka_object_t object; 143 vm_frame_t frame_result = { seL4_CapNull, seL4_NoRights, 0, 0 }; 144 vm_t *vm = (vm_t *)cookie; 145 if (!vm) { 146 return frame_result; 147 } 148 int page_size = seL4_PageBits; 149 uintptr_t frame_start = ROUND_DOWN(addr, BIT(page_size)); 150 ret = vka_alloc_frame(vm->vka, page_size, &object); 151 if (ret) { 152 ZF_LOGE("Failed to allocate frame for address 0x%x", addr); 153 return frame_result; 154 } 155 frame_result.cptr = object.cptr; 156 frame_result.rights = seL4_AllRights; 157 frame_result.vaddr = frame_start; 158 frame_result.size_bits = page_size; 159 return frame_result; 160} 161 162void *create_allocated_reservation_frame(vm_t *vm, uintptr_t addr, seL4_CapRights_t rights, 163 memory_fault_callback_fn alloc_fault_callback, void *alloc_fault_cookie) 164{ 165 int err; 166 struct device_frame_cookie *cookie; 167 int page_size = seL4_PageBits; 168 void *alloc_addr; 169 vspace_t *vmm_vspace = &vm->mem.vmm_vspace; 170 ps_io_ops_t *ops = vm->io_ops; 171 172 err = ps_calloc(&ops->malloc_ops, 1, sizeof(struct device_frame_cookie), (void **)&cookie); 173 if (err) { 174 ZF_LOGE("Failed to create allocated vm frame: Unable to allocate cookie"); 175 return NULL; 176 } 177 178 /* Reserve emulated vm frame */ 179 cookie->reservation = vm_reserve_memory_at(vm, addr, PAGE_SIZE_4K, 180 alloc_fault_callback, (void *)alloc_fault_cookie); 181 if (!cookie->reservation) { 182 ZF_LOGE("Failed to create allocated vm frame: Unable to reservate emulated frame"); 183 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 184 return NULL; 185 } 186 187 err = vka_alloc_frame(vm->vka, page_size, &cookie->frame); 188 if (err) { 189 ZF_LOGE("Failed vka_alloc_frame for allocated device frame"); 190 vm_free_reserved_memory(vm, cookie->reservation); 191 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 192 return NULL; 193 } 194 vka_cspace_make_path(vm->vka, cookie->frame.cptr, &cookie->mapped_frame); 195 alloc_addr = vspace_map_pages(vmm_vspace, &cookie->mapped_frame.capPtr, 196 NULL, seL4_AllRights, 1, page_size, 0); 197 if (!alloc_addr) { 198 ZF_LOGE("Failed to map allocated frame into vmm vspace"); 199 vka_free_object(vm->vka, &cookie->frame); 200 vm_free_reserved_memory(vm, cookie->reservation); 201 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 202 return NULL; 203 } 204 205 cookie->vm = vm; 206 cookie->addr = addr; 207 cookie->rights = rights; 208 209 /* Map the allocated frame */ 210 err = vm_map_reservation(vm, cookie->reservation, device_frame_iterator, (void *)cookie); 211 if (err) { 212 ZF_LOGE("Failed to map allocated frame into vm"); 213 vka_free_object(vm->vka, &cookie->frame); 214 vm_free_reserved_memory(vm, cookie->reservation); 215 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 216 return NULL; 217 } 218 219 return alloc_addr; 220} 221 222void *create_device_reservation_frame(vm_t *vm, uintptr_t addr, seL4_CapRights_t rights, 223 memory_fault_callback_fn fault_callback, void *fault_cookie) 224{ 225 int err; 226 struct device_frame_cookie *cookie; 227 int page_size = seL4_PageBits; 228 void *dev_addr; 229 vspace_t *vmm_vspace = &vm->mem.vmm_vspace; 230 ps_io_ops_t *ops = vm->io_ops; 231 232 err = ps_calloc(&ops->malloc_ops, 1, sizeof(struct device_frame_cookie), (void **)&cookie); 233 if (err) { 234 ZF_LOGE("Failed to create device vm frame: Unable to allocate cookie"); 235 return NULL; 236 } 237 238 /* Reserve emulated vm frame */ 239 cookie->reservation = vm_reserve_memory_at(vm, addr, PAGE_SIZE_4K, 240 fault_callback, (void *)fault_cookie); 241 if (!cookie->reservation) { 242 ZF_LOGE("Failed to create device vm frame: Unable to reservate emulated frame"); 243 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 244 return NULL; 245 } 246 247 err = vka_cspace_alloc_path(vm->vka, &cookie->mapped_frame); 248 if (err) { 249 ZF_LOGE("Failed to create device vm frame: Unable to allocate cslot"); 250 vm_free_reserved_memory(vm, cookie->reservation); 251 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 252 return NULL; 253 } 254 255 err = simple_get_frame_cap(vm->simple, (void *)addr, page_size, &cookie->mapped_frame); 256 if (err) { 257 /* attempt to allocate */ 258 uintptr_t vka_cookie; 259 err = vka_utspace_alloc_at(vm->vka, &cookie->mapped_frame, kobject_get_type(KOBJECT_FRAME, page_size), page_size, addr, 260 &vka_cookie); 261 } 262 if (err) { 263 ZF_LOGE("Failed to allocate page"); 264 vka_cspace_free_path(vm->vka, cookie->mapped_frame); 265 vm_free_reserved_memory(vm, cookie->reservation); 266 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 267 return NULL; 268 } 269 dev_addr = vspace_map_pages(vmm_vspace, &cookie->mapped_frame.capPtr, 270 NULL, seL4_AllRights, 1, page_size, 0); 271 if (!dev_addr) { 272 ZF_LOGE("Failed to map device frame into vmm vspace"); 273 vka_cspace_free_path(vm->vka, cookie->mapped_frame); 274 vm_free_reserved_memory(vm, cookie->reservation); 275 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 276 return NULL; 277 } 278 279 cookie->vm = vm; 280 cookie->addr = addr; 281 cookie->rights = rights; 282 283 /* Map the emulated frame */ 284 err = vm_map_reservation(vm, cookie->reservation, device_frame_iterator, (void *)cookie); 285 if (err) { 286 ZF_LOGE("Failed to map device frame into vm"); 287 vspace_unmap_pages(vmm_vspace, dev_addr, 1, page_size, NULL); 288 vka_cspace_free_path(vm->vka, cookie->mapped_frame); 289 vm_free_reserved_memory(vm, cookie->reservation); 290 ps_free(&ops->malloc_ops, sizeof(struct device_frame_cookie), (void **)&cookie); 291 return NULL; 292 } 293 294 return dev_addr; 295} 296 297int map_ut_alloc_reservation(vm_t *vm, vm_memory_reservation_t *reservation) 298{ 299 struct ut_alloc_iterator_cookie *cookie; 300 ps_io_ops_t *ops = vm->io_ops; 301 int err = ps_calloc(&ops->malloc_ops, 1, sizeof(struct ut_alloc_iterator_cookie), (void **)&cookie); 302 if (err) { 303 ZF_LOGE("Failed to map ut alloc reservation: Unable to allocate cookie"); 304 return -1; 305 } 306 cookie->vm = vm; 307 cookie->with_paddr = false; 308 cookie->reservation = reservation; 309 return vm_map_reservation(vm, reservation, ut_alloc_iterator, (void *)cookie); 310} 311 312int map_ut_alloc_reservation_with_base_paddr(vm_t *vm, uintptr_t paddr, vm_memory_reservation_t *reservation) 313{ 314 struct ut_alloc_iterator_cookie *cookie; 315 ps_io_ops_t *ops = vm->io_ops; 316 int err = ps_calloc(&ops->malloc_ops, 1, sizeof(struct ut_alloc_iterator_cookie), (void **)&cookie); 317 if (err) { 318 ZF_LOGE("Failed to map ut alloc reservation: Unable to allocate cookie"); 319 return -1; 320 } 321 cookie->vm = vm; 322 cookie->paddr = paddr; 323 cookie->with_paddr = true; 324 cookie->reservation = reservation; 325 return vm_map_reservation(vm, reservation, ut_alloc_iterator, (void *)cookie); 326} 327 328int map_frame_alloc_reservation(vm_t *vm, vm_memory_reservation_t *reservation) 329{ 330 return vm_map_reservation(vm, reservation, frame_alloc_iterator, (void *)vm); 331} 332 333int map_maybe_device_reservation(vm_t *vm, vm_memory_reservation_t *reservation) 334{ 335 return vm_map_reservation(vm, reservation, maybe_device_alloc_iterator, (void *)vm); 336} 337