aboutsummaryrefslogtreecommitdiff
path: root/kernel/vm
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/vm')
-rw-r--r--kernel/vm/mmap.c15
-rw-r--r--kernel/vm/pagefault.c6
-rw-r--r--kernel/vm/vmmap.c59
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
);