int vm_create(const char* name, int priority, seL4_CPtr vmm_endpoint, seL4_Word vm_badge, vka_t *vka, simple_t *simple, vspace_t *vmm_vspace, ps_io_ops_t* io_ops, vm_t* vm) { seL4_CapData_t null_cap_data = {{0}}; seL4_CapData_t cspace_root_data; cspacepath_t src, dst; int err; vm->name = name; vm->ndevices = 0; vm->onode_head = NULL; vm->entry_point = NULL; vm->vka = vka; vm->simple = simple; vm->vmm_vspace = vmm_vspace; vm->io_ops = io_ops; vm->vchan_num_cons = 0; vm->vchan_cons = NULL; /* Create a cspace */ err = vka_alloc_cnode_object(vka, VM_CSPACE_SIZE_BITS, &vm->cspace); assert(!err); vka_cspace_make_path(vka, vm->cspace.cptr, &src); cspace_root_data = seL4_CapData_Guard_new(0, 32 - VM_CSPACE_SIZE_BITS); dst.root = vm->cspace.cptr; dst.capPtr = VM_CSPACE_SLOT; dst.capDepth = VM_CSPACE_SIZE_BITS; err = vka_cnode_mint(&dst, &src, seL4_AllRights, cspace_root_data); assert(!err); /* Create a vspace */ err = vka_alloc_page_directory(vka, &vm->pd); assert(!err); err = simple_ASIDPool_assign(simple, vm->pd.cptr); assert(err == seL4_NoError); err = sel4utils_get_vspace(vmm_vspace, &vm->vm_vspace, &vm->data, vka, vm->pd.cptr, &vm_object_allocation_cb, (void*)vm); assert(!err); /* Badge the endpoint */ vka_cspace_make_path(vka, vmm_endpoint, &src); err = vka_cspace_alloc_path(vka, &dst); assert(!err); err = vka_cnode_mint(&dst, &src, seL4_AllRights, seL4_CapData_Badge_new(vm_badge)); assert(!err); /* Copy it to the cspace of the VM for fault IPC */ src = dst; dst.root = vm->cspace.cptr; dst.capPtr = VM_FAULT_EP_SLOT; dst.capDepth = VM_CSPACE_SIZE_BITS; err = vka_cnode_copy(&dst, &src, seL4_AllRights); assert(!err); /* Create TCB */ err = vka_alloc_tcb(vka, &vm->tcb); assert(!err); err = seL4_TCB_Configure(vm_get_tcb(vm), VM_FAULT_EP_SLOT, priority - 1, vm->cspace.cptr, cspace_root_data, vm->pd.cptr, null_cap_data, 0, seL4_CapNull); assert(!err); /* Create VCPU */ err = vka_alloc_vcpu(vka, &vm->vcpu); assert(!err); err = seL4_ARM_VCPU_SetTCB(vm->vcpu.cptr, vm_get_tcb(vm)); assert(!err); /* Initialise fault system */ vm->fault = fault_init(vm); assert(vm->fault); return err; }
int sel4utils_map_page(vka_t *vka, seL4_CPtr pd, seL4_CPtr frame, void *vaddr, seL4_CapRights rights, int cacheable, vka_object_t *objects, int *num_objects) { assert(vka != NULL); assert(pd != 0); assert(frame != 0); assert(vaddr != 0); assert(rights != 0); assert(num_objects); seL4_ARCH_VMAttributes attr = 0; int num = 0; #ifdef CONFIG_ARCH_IA32 if (!cacheable) { attr = seL4_IA32_CacheDisabled; } #elif CONFIG_ARCH_ARM /* CONFIG_ARCH_IA32 */ if (cacheable) { attr = seL4_ARM_PageCacheable; } #endif /* CONFIG_ARCH_ARM */ int error = seL4_ARCH_Page_Map(frame, pd, (seL4_Word) vaddr, rights, attr); #ifdef CONFIG_X86_64 page_map_retry: if (error == seL4_FailedLookupPDPT) { error = vka_alloc_page_directory_pointer_table(vka, pagetable); if (!error) { error = seL4_ARCH_PageDirectoryPointerTable_Map(pagetable->cptr, pd, (seL4_Word)vaddr, seL4_ARCH_Default_VMAttributes); } else { LOG_ERROR("Page directory pointer table allocation failed %d", error); } if (!error) { error = seL4_ARCH_Page_Map(frame, pd, (seL4_Word)vaddr, rights, attr); if (error != seL4_NoError) { goto page_map_retry; } } else { LOG_ERROR("Page directory pointer table mapping failed %d\n", error); } } if (error == seL4_FailedLookupPD) { error = vka_alloc_page_directory(vka, pagetable); if (!error) { error = seL4_ARCH_PageDirectory_Map(pagetable->cptr, pd, (seL4_Word)vaddr, seL4_ARCH_Default_VMAttributes); } else { LOG_ERROR("Page direcotry allocation failed %d\n", error); } if (!error) { error = seL4_ARCH_Page_Map(frame, pd, (seL4_Word)vaddr, rights, attr); if (error != seL4_NoError) { goto page_map_retry; } } else { LOG_ERROR("Page directory mapping failed %d\n", error); } } #endif if (error == seL4_FailedLookup) { /* need a page table, allocate one */ assert(objects != NULL); assert(*num_objects > 0); error = vka_alloc_page_table(vka, &objects[0]); /* map in the page table */ if (!error) { error = seL4_ARCH_PageTable_Map(objects[0].cptr, pd, (seL4_Word) vaddr, seL4_ARCH_Default_VMAttributes); } else { LOG_ERROR("Page table allocation failed, %d", error); } if (error == seL4_DeleteFirst) { /* It's possible that in allocated the page table, we needed to allocate/map * in some memory, which caused a page table to get mapped in at the * same location we are wanting one. If this has happened then we can just * delete this page table and try the frame mapping again */ vka_free_object(vka, &objects[0]); error = seL4_NoError; } else { num = 1; } #ifdef CONFIG_PAE_PAGING if (error == seL4_FailedLookup) { /* need a page directory, allocate one */ assert(*num_objects > 1); error = vka_alloc_page_directory(vka, &objects[1]); if (!error) { error = seL4_IA32_PageDirectory_Map(objects[1].cptr, pd, (seL4_Word) vaddr, seL4_ARCH_Default_VMAttributes); } else { LOG_ERROR("Page directory allocation failed, %d", error); } if (error == seL4_DeleteFirst) { vka_free_object(vka, &objects[1]); error = seL4_NoError; } else { num = 2; } if (!error) { error = seL4_ARCH_PageTable_Map(objects[0].cptr, pd, (seL4_Word) vaddr, seL4_ARCH_Default_VMAttributes); } else { LOG_ERROR("Page directory mapping failed, %d", error); } } #endif /* now try mapping the frame in again if nothing else went wrong */ if (!error) { error = seL4_ARCH_Page_Map(frame, pd, (seL4_Word) vaddr, rights, attr); } else { LOG_ERROR("Page table mapping failed, %d", error); } } if (error != seL4_NoError) { LOG_ERROR("Failed to map page at address %p with cap %"PRIuPTR", error: %d", vaddr, frame, error); } *num_objects = num; return error; }