diff options
Diffstat (limited to 'kernel/vm')
-rw-r--r-- | kernel/vm/mmap.c | 15 | ||||
-rw-r--r-- | kernel/vm/pagefault.c | 6 | ||||
-rw-r--r-- | kernel/vm/vmmap.c | 59 |
3 files changed, 50 insertions, 30 deletions
diff --git a/kernel/vm/mmap.c b/kernel/vm/mmap.c index 78aa3b5..ce932de 100644 --- a/kernel/vm/mmap.c +++ b/kernel/vm/mmap.c @@ -161,7 +161,6 @@ long do_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off, VMMAP_DIR_HILO, &vma ); - // check if vmmap_map() failed if (err < 0) { @@ -213,7 +212,7 @@ long do_munmap(void *addr, size_t len) } // Check if len is in bounds - if (len > USER_MEM_HIGH) + if (len > USER_MEM_HIGH || len == 0) { return -EINVAL; } @@ -224,17 +223,13 @@ long do_munmap(void *addr, size_t len) return -EINVAL; } - // Check if len is 0 - if (len == 0) - { - return -EINVAL; - } - // Remove the mapping + size_t start = ADDR_TO_PN(addr); + size_t end = ADDR_TO_PN(PAGE_ALIGN_UP((uintptr_t)addr + len)); long ret = vmmap_remove( curproc->p_vmmap, - ADDR_TO_PN(addr), - ADDR_TO_PN(PAGE_ALIGN_UP((uintptr_t)addr + len)) + start, + end - start ); return ret; }
\ No newline at end of file diff --git a/kernel/vm/pagefault.c b/kernel/vm/pagefault.c index 2e0c92d..b289537 100644 --- a/kernel/vm/pagefault.c +++ b/kernel/vm/pagefault.c @@ -91,7 +91,7 @@ void handle_pagefault(uintptr_t vaddr, uintptr_t cause) mobj_lock(vma->vma_obj); int ret = mobj_get_pframe( vma->vma_obj, - vma->vma_off + (ADDR_TO_PN(vaddr) - vma->vma_start), + vma->vma_off + ADDR_TO_PN(vaddr) - vma->vma_start, cause & FAULT_WRITE ? 1 : 0, &pf ); @@ -102,6 +102,8 @@ void handle_pagefault(uintptr_t vaddr, uintptr_t cause) } // 4) Finally, set up a call to pt_map to insert a new mapping into the appropriate pagetable + uintptr_t paddr = pt_virt_to_phys(pf->pf_addr); + pframe_release(&pf); int pdflags = PT_PRESENT | PT_WRITE | PT_USER; int ptflags = PT_PRESENT | PT_USER; if (cause & FAULT_WRITE) @@ -111,7 +113,7 @@ void handle_pagefault(uintptr_t vaddr, uintptr_t cause) int err = pt_map( curproc->p_pml4, - pt_virt_to_phys((uintptr_t) pf->pf_addr), + paddr, (uintptr_t) PAGE_ALIGN_DOWN(vaddr), pdflags, ptflags diff --git a/kernel/vm/vmmap.c b/kernel/vm/vmmap.c index fd99c55..8789371 100644 --- a/kernel/vm/vmmap.c +++ b/kernel/vm/vmmap.c @@ -172,21 +172,35 @@ ssize_t vmmap_find_range(vmmap_t *map, size_t npages, int dir) // case 1: dir is VMMAP_DIR_LOHI if (dir == VMMAP_DIR_LOHI) { - // iterate over the page numbers + // iterate over the page numbers, going from low to high + // determine the continguous range of free virtual pages + + int start, end = 0; size_t vfn = ADDR_TO_PN(USER_MEM_LOW); - while (vfn <= ADDR_TO_PN(USER_MEM_HIGH) - npages) + while (vfn <= ADDR_TO_PN(USER_MEM_HIGH)) { // Lookup the vmarea for this page number - vmarea_t *vma = vmmap_lookup(map, vfn); - - // if the vmarea is NULL, return the page number + vmarea_t *vma = vmmap_lookup(map, vfn++); if (vma == NULL) { - return vfn; + // if unmapped, document this + end = vfn; + if (start == 0) + { + start = vfn; + } + } + else + { + // if mapped, start over + start, end = 0; } - // if the vmarea is not NULL, set the page number to the end of the vmarea - vfn = vma->vma_end; + // if the range exists, return the start + if (end == npages) + { + return start; + } } } @@ -194,20 +208,28 @@ ssize_t vmmap_find_range(vmmap_t *map, size_t npages, int dir) else if (dir == VMMAP_DIR_HILO) { // iterate over the page numbers - size_t vfn = ADDR_TO_PN(USER_MEM_HIGH) - npages; + int contig = 0; + size_t vfn = ADDR_TO_PN(USER_MEM_HIGH); while (vfn >= ADDR_TO_PN(USER_MEM_LOW)) { // Lookup the vmarea for this page number - vmarea_t *vma = vmmap_lookup(map, vfn); - - // if the vmarea is NULL, return the page number + vmarea_t *vma = vmmap_lookup(map, --vfn); if (vma == NULL) { - return vfn; + // if unmapped, increment the contig + contig++; + } + else + { + // if mapped, reset the contig + contig = 0; } - // if the vmarea is not NULL, set the page number to the start of the vmarea - vfn = vma->vma_start - npages; + // if there are n contiguous pages, return the current vfn + if (contig == npages) + { + return vfn; + } } } @@ -448,6 +470,7 @@ long vmmap_map(vmmap_t *map, vnode_t *file, size_t lopage, size_t npages, mobj_t *shadow_obj = shadow_create(new_vmarea->vma_obj); mobj_unlock(new_vmarea->vma_obj); mobj_unlock(shadow_obj); // unlock the shadow object before use + mobj_put(&new_vmarea->vma_obj); // put the original object if (shadow_obj == NULL) { vmarea_free(new_vmarea); @@ -674,7 +697,7 @@ long vmmap_read(vmmap_t *map, const void *vaddr, void *buf, size_t count) size_t vfn = ADDR_TO_PN(vaddr); size_t end_vfn = ADDR_TO_PN(vaddr + count); size_t bytes_read = 0; - while (vfn < end_vfn) + while (vfn <= end_vfn) { // Lookup the vmarea for this page number vmarea_t *vma = vmmap_lookup(map, vfn); @@ -697,7 +720,7 @@ long vmmap_read(vmmap_t *map, const void *vaddr, void *buf, size_t count) void *cursor = (void *)(bytes_read + vaddr); size_t bytes_this_iteration = MIN(PAGE_SIZE - PAGE_OFFSET(cursor), count - bytes_read); memcpy( - buf + bytes_read, + (void *) buf + bytes_read, (void *)pf->pf_addr + PAGE_OFFSET(cursor), bytes_this_iteration ); @@ -768,7 +791,7 @@ long vmmap_write(vmmap_t *map, void *vaddr, const void *buf, size_t count) size_t bytes_this_iteration = MIN(PAGE_SIZE - PAGE_OFFSET(cursor), count - bytes_written); memcpy( (void *)pf->pf_addr + PAGE_OFFSET(cursor), - buf + bytes_written, + (void *)buf + bytes_written, bytes_this_iteration ); |