diff --git a/conts/posix/mm0/include/task.h b/conts/posix/mm0/include/task.h index b5b8308..c42fbb2 100644 --- a/conts/posix/mm0/include/task.h +++ b/conts/posix/mm0/include/task.h @@ -149,7 +149,6 @@ struct tcb_head { struct tcb *find_task(int tid); void global_add_task(struct tcb *task); void global_remove_task(struct tcb *task); -void task_map_prefault_utcb(struct tcb *mapper, struct tcb *owner); int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_desc *efd, struct args_struct *args, struct args_struct *env); int task_setup_registers(struct tcb *task, unsigned int pc, @@ -159,13 +158,11 @@ int tcb_destroy(struct tcb *task); int task_start(struct tcb *task); int copy_tcb(struct tcb *to, struct tcb *from, unsigned int flags); int task_release_vmas(struct task_vma_head *vma_head); -int task_prefault_regions(struct tcb *task, struct vm_file *f); struct tcb *task_create(struct tcb *orig, struct task_ids *ids, unsigned int ctrl_flags, unsigned int alloc_flags); - -int prefault_range(struct tcb *task, unsigned long start, - unsigned long end, unsigned int vm_flags); +int task_prefault_range(struct tcb *task, unsigned long start, + unsigned long end, unsigned int vm_flags); #endif /* __TASK_H__ */ diff --git a/conts/posix/mm0/include/vm_area.h b/conts/posix/mm0/include/vm_area.h index ee3d1a8..f68f0a4 100644 --- a/conts/posix/mm0/include/vm_area.h +++ b/conts/posix/mm0/include/vm_area.h @@ -227,19 +227,13 @@ void vm_print_objects(struct link *vmo_list); void vm_print_files(struct link *file_list); /* Used for pre-faulting a page from mm0 */ -int prefault_page(struct tcb *task, unsigned long address, - unsigned int vmflags); +struct page *task_prefault_page(struct tcb *task, unsigned long address, + unsigned int vmflags); struct page *page_init(struct page *page); struct page *find_page(struct vm_object *vmo, unsigned long page_offset); void *pager_map_page(struct vm_file *f, unsigned long page_offset); void pager_unmap_page(void *vaddr); -/* To get currently mapped page of a virtual address on a task */ -struct page *task_virt_to_page(struct tcb *t, unsigned long virtual, - unsigned int vm_flags); -int validate_task_range(struct tcb *t, unsigned long start, - unsigned long end, unsigned int vmflags); - /* Changes all shadows and their ptes to read-only */ int vm_freeze_shadows(struct tcb *task); @@ -247,7 +241,7 @@ int vm_compare_prot_flags(unsigned int current, unsigned int needed); int task_insert_vma(struct vm_area *vma, struct link *vma_list); /* Main page fault entry point */ -int page_fault_handler(struct tcb *faulty_task, fault_kdata_t *fkdata); +struct page *page_fault_handler(struct tcb *faulty_task, fault_kdata_t *fkdata); int vma_copy_links(struct vm_area *new_vma, struct vm_area *vma); int vma_drop_merge_delete(struct vm_area *vma, struct vm_obj_link *link); diff --git a/conts/posix/mm0/main.c b/conts/posix/mm0/main.c index e4de096..3f5023e 100644 --- a/conts/posix/mm0/main.c +++ b/conts/posix/mm0/main.c @@ -78,10 +78,16 @@ void handle_requests(void) /* This has no receive phase */ return; - case L4_IPC_TAG_PFAULT: + case L4_IPC_TAG_PFAULT: { + struct page *p; + /* Handle page fault. */ - ret = page_fault_handler(sender, (fault_kdata_t *)&mr[0]); + if (IS_ERR(p = page_fault_handler(sender, (fault_kdata_t *)&mr[0]))) + ret = (int)p; + else + ret = 0; break; + } case L4_IPC_TAG_SHMGET: { ret = sys_shmget((key_t)mr[0], (int)mr[1], (int)mr[2]); diff --git a/conts/posix/mm0/mm/fault.c b/conts/posix/mm0/mm/fault.c index 3fb45a8..28a6aff 100644 --- a/conts/posix/mm0/mm/fault.c +++ b/conts/posix/mm0/mm/fault.c @@ -649,7 +649,7 @@ struct page *copy_on_write(struct fault_data *fault) * FIXME: Add VM_DIRTY bit for every page that has write-faulted. */ -int __do_page_fault(struct fault_data *fault) +struct page *__do_page_fault(struct fault_data *fault) { unsigned int reason = fault->reason; unsigned int vma_flags = fault->vma->flags; @@ -741,7 +741,7 @@ out_success: page_align(fault->address), fault->task->tid); // vm_object_print(page->owner); - return 0; + return page; } /* @@ -841,7 +841,7 @@ int vm_freeze_shadows(struct tcb *task) * - page needs write access: * action: read the page in, give write access. */ -int do_page_fault(struct fault_data *fault) +struct page *do_page_fault(struct fault_data *fault) { unsigned int vma_flags = (fault->vma) ? fault->vma->flags : VM_NONE; unsigned int reason = fault->reason; @@ -869,9 +869,8 @@ int do_page_fault(struct fault_data *fault) return __do_page_fault(fault); } -int page_fault_handler(struct tcb *sender, fault_kdata_t *fkdata) +struct page *page_fault_handler(struct tcb *sender, fault_kdata_t *fkdata) { - int err; struct fault_data fault = { /* Fault data from kernel */ .kdata = fkdata, @@ -888,14 +887,7 @@ int page_fault_handler(struct tcb *sender, fault_kdata_t *fkdata) "Bad things will happen.\n"); /* Handle the actual fault */ - err = do_page_fault(&fault); - - /* - * Return the ipc and by doing so restart the faulty thread. - * FIXME: We could kill the thread if there was an error??? - * Perhaps via a kill message to kernel? - */ - return err; + return do_page_fault(&fault); } int vm_compare_prot_flags(unsigned int current, unsigned int needed) @@ -914,75 +906,15 @@ int vm_compare_prot_flags(unsigned int current, unsigned int needed) return 0; } -/* - * Makes the virtual to page translation for a given user task. - * It traverses the vm_objects and returns the first encountered - * instance of the page. If page is not mapped in the task's address - * space, (not faulted at all), returns error. - */ -struct page *task_virt_to_page(struct tcb *t, unsigned long virtual, unsigned int vm_flags) -{ - unsigned long vma_offset; - unsigned long file_offset; - struct vm_obj_link *vmo_link; - struct vm_area *vma; - struct page *page; - - /* First find the vma that maps that virtual address */ - if (!(vma = find_vma(virtual, &t->vm_area_head->list))) { - //printf("%s: No VMA found for 0x%x on task: %d\n", - // __FUNCTION__, virtual, t->tid); - return PTR_ERR(-EINVAL); - } - - /* Find the pfn offset of virtual address in this vma */ - BUG_ON(__pfn(virtual) < vma->pfn_start || - __pfn(virtual) > vma->pfn_end); - vma_offset = __pfn(virtual) - vma->pfn_start; - - /* Find the file offset of virtual address in this file */ - file_offset = vma->file_offset + vma_offset; - - /* Get the first object, either original file or a shadow */ - if (!(vmo_link = vma_next_link(&vma->vm_obj_list, &vma->vm_obj_list))) { - printf("%s:%s: No vm object in vma!\n", - __TASKNAME__, __FUNCTION__); - BUG(); - } - - /* Traverse the list of read-only vm objects and search for the page */ - while (IS_ERR(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, - file_offset))) { - if (!(vmo_link = vma_next_link(&vmo_link->list, - &vma->vm_obj_list))) { - printf("%s:%s: Traversed all shadows and the original " - "file's vm_object, but could not find the " - "page in this vma.\n",__TASKNAME__, - __FUNCTION__); - BUG(); - } - } - - /* Found one, but does it have the right permissions */ - if (!vm_compare_prot_flags(vmo_link->obj->flags, vm_flags)) - return PTR_ERR(-EFAULT); - - // printf("%s: %s: Found page with file_offset: 0x%x\n", - // __TASKNAME__, __FUNCTION__, page->offset); - // vm_object_print(vmo_link->obj); - - return page; -} - /* * Prefaults the page with given virtual address, to given task * with given reasons. Multiple reasons are allowed, they are * handled separately in order. */ -int prefault_page(struct tcb *task, unsigned long address, - unsigned int vmflags) +struct page *task_prefault_page(struct tcb *task, unsigned long address, + unsigned int vmflags) { - int err; + struct page *p; struct fault_data fault = { .task = task, .address = address, @@ -994,30 +926,29 @@ int prefault_page(struct tcb *task, unsigned long address, /* Find the vma */ if (!(fault.vma = find_vma(fault.address, &fault.task->vm_area_head->list))) { - err = -EINVAL; dprintf("%s: Invalid: No vma for given address. %d\n", - __FUNCTION__, err); - return err; + __FUNCTION__, -EINVAL); + return PTR_ERR(-EINVAL); } /* Flags may indicate multiple fault reasons. First do the read */ if (vmflags & VM_READ) { fault.pte_flags = VM_NONE; fault.reason = VM_READ; - if ((err = do_page_fault(&fault)) < 0) - return err; + if (IS_ERR(p = do_page_fault(&fault))) + return p; } /* Now write */ if (vmflags & VM_WRITE) { fault.pte_flags = VM_READ; fault.reason = VM_WRITE; - if ((err = do_page_fault(&fault)) < 0) - return err; + if (IS_ERR(p = do_page_fault(&fault))) + return p; } /* No exec or any other fault reason allowed. */ BUG_ON(vmflags & ~(VM_READ | VM_WRITE)); - return 0; + return p; } diff --git a/conts/posix/mm0/mm/file.c b/conts/posix/mm0/mm/file.c index 3c887ff..6d508a5 100644 --- a/conts/posix/mm0/mm/file.c +++ b/conts/posix/mm0/mm/file.c @@ -552,16 +552,16 @@ int copy_cache_pages(struct vm_file *vmfile, struct tcb *task, void *buf, copysize = min(copysize, PAGE_SIZE - page_offset(task_offset)); if (read) - page_copy(task_virt_to_page(task, task_offset, - VM_READ | VM_WRITE), + page_copy(task_prefault_page(task, task_offset, + VM_READ | VM_WRITE), file_page, page_offset(task_offset), page_offset(file_offset), copysize); else page_copy(file_page, - task_virt_to_page(task, task_offset, - VM_READ), + task_prefault_page(task, task_offset, + VM_READ), page_offset(file_offset), page_offset(task_offset), copysize); diff --git a/conts/posix/mm0/mm/init.c b/conts/posix/mm0/mm/init.c index 51e65a6..9d3d228 100644 --- a/conts/posix/mm0/mm/init.c +++ b/conts/posix/mm0/mm/init.c @@ -150,8 +150,7 @@ int pager_setup_task(void) } /* Pager must prefault its utcb */ - prefault_page(task, task->utcb_address, - VM_READ | VM_WRITE); + task_prefault_page(task, task->utcb_address, VM_READ | VM_WRITE); /* Add the task to the global task list */ global_add_task(task); @@ -557,9 +556,9 @@ void copy_init_process(void) } /* Prefault it */ - if ((err = prefault_range(self, (unsigned long)mapped, - img_size, - VM_READ | VM_WRITE)) < 0) { + if ((err = task_prefault_range(self, (unsigned long)mapped, + img_size, VM_READ | VM_WRITE)) + < 0) { printf("FATAL: Prefaulting init image failed.\n"); BUG(); } diff --git a/conts/posix/mm0/mm/memory.c b/conts/posix/mm0/mm/memory.c index 6ff662c..789e9a9 100644 --- a/conts/posix/mm0/mm/memory.c +++ b/conts/posix/mm0/mm/memory.c @@ -179,7 +179,7 @@ void *pager_validate_map_user_range2(struct tcb *user, void *userptr, /* Map every page contiguously in the allocated virtual address range */ for (unsigned long addr = start; addr < end; addr += PAGE_SIZE) { - struct page *p = task_virt_to_page(user, addr, vm_flags); + struct page *p = task_prefault_page(user, addr, vm_flags); if (IS_ERR(p)) { /* Unmap pages mapped so far */ @@ -191,7 +191,7 @@ void *pager_validate_map_user_range2(struct tcb *user, void *userptr, return p; } - l4_map((void *)page_to_phys(task_virt_to_page(user, addr, vm_flags)), + l4_map((void *)page_to_phys(p), virt, 1, MAP_USR_RW_FLAGS, self_tid()); virt += PAGE_SIZE; } diff --git a/conts/posix/mm0/mm/shm.c b/conts/posix/mm0/mm/shm.c index 0ef7c2e..9c701ed 100644 --- a/conts/posix/mm0/mm/shm.c +++ b/conts/posix/mm0/mm/shm.c @@ -383,7 +383,7 @@ int shpage_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags /* Prefault the owner's shared page to mapper's address space */ if (flags & SHPAGE_PREFAULT) for (int i = 0; i < __pfn(DEFAULT_SHPAGE_SIZE); i++) - prefault_page(mapper, (unsigned long)owner->shared_page + + task_prefault_page(mapper, (unsigned long)owner->shared_page + __pfn_to_addr(i), VM_READ | VM_WRITE); return 0; } diff --git a/conts/posix/mm0/mm/task.c b/conts/posix/mm0/mm/task.c index 885f2cb..41e643f 100644 --- a/conts/posix/mm0/mm/task.c +++ b/conts/posix/mm0/mm/task.c @@ -504,14 +504,14 @@ int task_copy_args_to_user(char *user_stack, return 0; } -int prefault_range(struct tcb *task, unsigned long start, - unsigned long size, unsigned int vm_flags) +int task_prefault_range(struct tcb *task, unsigned long start, + unsigned long size, unsigned int vm_flags) { - int err; + struct page *p; for (unsigned long i = start; i < start + size; i += PAGE_SIZE) - if ((err = prefault_page(task, i, vm_flags)) < 0) - return err; + if (IS_ERR(p = task_prefault_page(task, i, vm_flags))) + return (int)p; return 0; } @@ -553,9 +553,8 @@ int task_map_stack(struct vm_file *f, struct exec_file_desc *efd, return (int)mapped; } - /* Prefault the stack for writing. */ - BUG_ON(prefault_range(task, task->args_start, - stack_used, VM_READ | VM_WRITE) < 0); + /* FIXME: Probably not necessary anymore. Prefault the stack for writing. */ + //BUG_ON(task_prefault_range(task, task->args_start, stack_used, VM_READ | VM_WRITE) < 0); /* Map the stack's part that will contain args and environment */ if (IS_ERR(args_on_stack = @@ -597,12 +596,9 @@ int task_map_bss(struct vm_file *f, struct exec_file_desc *efd, struct tcb *task struct page *last_data_page; void *pagebuf, *bss; - /* Prefault the last data page */ - BUG_ON(prefault_page(task, task->data_end, - VM_READ | VM_WRITE) < 0); /* Get the page */ - last_data_page = task_virt_to_page(task, task->data_end, - VM_READ | VM_WRITE); + last_data_page = task_prefault_page(task, task->data_end, + VM_READ | VM_WRITE); /* Map the page. FIXME: PAGE COLOR!!! */ pagebuf = l4_map_helper((void *)page_to_phys(last_data_page), 1); @@ -759,26 +755,3 @@ int task_start(struct tcb *task) return 0; } - -/* - * Prefaults all mapped regions of a task. The reason we have this is - * some servers are in the page fault handling path (e.g. fs0), and we - * don't want them to fault and cause deadlocks and circular deps. - * - * Normally fs0 faults dont cause dependencies because its faults - * are handled by the boot pager, which is part of mm0. BUT: It may - * cause deadlocks because fs0 may fault while serving a request - * from mm0.(Which is expected to also handle the fault). - */ -int task_prefault_regions(struct tcb *task, struct vm_file *f) -{ - struct vm_area *vma; - - list_foreach_struct(vma, &task->vm_area_head->list, list) { - for (int pfn = vma->pfn_start; pfn < vma->pfn_end; pfn++) - BUG_ON(prefault_page(task, __pfn_to_addr(pfn), - VM_READ | VM_WRITE) < 0); - } - return 0; -} - diff --git a/conts/posix/mm0/mm/user.c b/conts/posix/mm0/mm/user.c index 8b3edbb..30bc691 100644 --- a/conts/posix/mm0/mm/user.c +++ b/conts/posix/mm0/mm/user.c @@ -58,16 +58,16 @@ void *pager_validate_map_user_range(struct tcb *user, void *userptr, return 0; /* Map first page and calculate the mapped address of pointer */ - mapped = l4_map_helper((void *)page_to_phys(task_virt_to_page(user, start, - vm_flags)), 1); + mapped = l4_map_helper((void *)page_to_phys(task_prefault_page(user, start, + vm_flags)), 1); mapped = (void *)(((unsigned long)mapped) | ((unsigned long)(PAGE_MASK & (unsigned long)userptr))); /* Map the rest of the pages, if any */ for (unsigned long i = start + PAGE_SIZE; i < end; i += PAGE_SIZE) - l4_map_helper((void *)page_to_phys(task_virt_to_page(user, - start + i, - vm_flags)), 1); + l4_map_helper((void *) + page_to_phys(task_prefault_page(user, start + i, + vm_flags)), 1); return mapped; } diff --git a/conts/posix/test0/src/test_exec/test_exec.c b/conts/posix/test0/src/test_exec/test_exec.c index 4379735..3955b0e 100644 --- a/conts/posix/test0/src/test_exec/test_exec.c +++ b/conts/posix/test0/src/test_exec/test_exec.c @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) char *parent_of_all; char pidbuf[10]; - printf("New task started: %d\n", __raw_tid(getpid())); + // printf("New task started: %d\n", __raw_tid(getpid())); /* Convert current pid to string */ sprintf(pidbuf, "%d", getpid()); @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) goto out; } - printf("New task continues: %d\n", __raw_tid(getpid())); + // printf("New task continues: %d\n", __raw_tid(getpid())); /* Get parent of all pid as a string from environment */ parent_of_all = getenv("parent_of_all");