/* Some more generic routines for helping with mapping */ void * sel4utils_dup_and_map(vka_t *vka, vspace_t *vspace, seL4_CPtr page, size_t size_bits) { int error; cspacepath_t page_path; cspacepath_t copy_path; void *mapping; /* First need to copy the cap */ error = vka_cspace_alloc_path(vka, ©_path); if (error != seL4_NoError) { return NULL; } vka_cspace_make_path(vka, page, &page_path); error = vka_cnode_copy(©_path, &page_path, seL4_AllRights); if (error != seL4_NoError) { vka_cspace_free(vka, copy_path.capPtr); return NULL; } /* Now map it in */ mapping = vspace_map_pages(vspace, ©_path.capPtr, NULL, seL4_AllRights, 1, size_bits, 1); if (!mapping) { vka_cnode_delete(©_path); vka_cspace_free(vka, copy_path.capPtr); return NULL; } return mapping; }
/* map the init data into the process, and send the address via ipc */ static void * send_init_data(env_t env, seL4_CPtr endpoint, sel4utils_process_t *process) { /* map the cap into remote vspace */ void *remote_vaddr = vspace_map_pages(&process->vspace, &env->init_frame_cap_copy, NULL, seL4_AllRights, 1, PAGE_BITS_4K, 1); assert(remote_vaddr != 0); /* now send a message telling the process what address the data is at */ seL4_MessageInfo_t info = seL4_MessageInfo_new(seL4_NoFault, 0, 0, 1); seL4_SetMR(0, (seL4_Word) remote_vaddr); seL4_Send(endpoint, info); return remote_vaddr; }
int vm_copyout_atags(vm_t* vm, struct atag_list* atags, uint32_t addr) { vspace_t *vm_vspace, *vmm_vspace; void* vm_addr, *vmm_addr, *buf; reservation_t res; vka_t* vka; vka_object_t frame; size_t size; struct atag_list* atag_cur; int err; vka = vm->vka; vm_addr = (void*)(addr & ~0xfff); vm_vspace = vm_get_vspace(vm); vmm_vspace = vm->vmm_vspace; /* Make sure we don't cross a page boundary * NOTE: the next page will usually be used by linux for PT! */ for (size = 0, atag_cur = atags; atag_cur != NULL; atag_cur = atag_cur->next) { size += atags_size_bytes(atag_cur); } size += 8; /* NULL tag */ assert((addr & 0xfff) + size < 0x1000); /* Create a frame (and a copy for the VMM) */ err = vka_alloc_frame(vka, 12, &frame); assert(!err); if (err) { return -1; } /* Map the frame to the VMM */ vmm_addr = vspace_map_pages(vmm_vspace, &frame.cptr, NULL, seL4_AllRights, 1, 12, 0); assert(vmm_addr); /* Copy in the atags */ buf = vmm_addr + (addr & 0xfff); for (atag_cur = atags; atag_cur != NULL; atag_cur = atag_cur->next) { int tag_size = atags_size_bytes(atag_cur); DVM("ATAG copy 0x%x<-0x%x %d\n", (uint32_t)buf, (uint32_t)atag_cur->hdr, tag_size); memcpy(buf, atag_cur->hdr, tag_size); buf += tag_size; } /* NULL tag terminator */ memset(buf, 0, 8); /* Unmap the page and map it into the VM */ vspace_unmap_pages(vmm_vspace, vmm_addr, 1, 12, NULL); res = vspace_reserve_range_at(vm_vspace, vm_addr, 0x1000, seL4_AllRights, 0); assert(res.res); if (!res.res) { vka_free_object(vka, &frame); return -1; } err = vspace_map_pages_at_vaddr(vm_vspace, &frame.cptr, NULL, vm_addr, 1, 12, res); vspace_free_reservation(vm_vspace, res); assert(!err); if (err) { printf("Failed to provide memory\n"); vka_free_object(vka, &frame); return -1; } return 0; }