aboutsummaryrefslogtreecommitdiff
path: root/kernel/vm/pagefault.c
diff options
context:
space:
mode:
authorMichael Foiani <mfoiani@cs.brown.edu>2024-05-14 17:16:42 -0400
committerMichael Foiani <mfoiani@cs.brown.edu>2024-05-14 17:16:42 -0400
commit53b54f664ed2b4630c23cacc9e216a6a5935b57f (patch)
treef0138f1ed2f8894efa560e0e9721e510883f439b /kernel/vm/pagefault.c
parentb90313ddfa4c03f688c6c1cd5ded34aff1bf39c5 (diff)
fixes to work on dept machine
Diffstat (limited to 'kernel/vm/pagefault.c')
-rw-r--r--kernel/vm/pagefault.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/kernel/vm/pagefault.c b/kernel/vm/pagefault.c
index b289537..39e5776 100644
--- a/kernel/vm/pagefault.c
+++ b/kernel/vm/pagefault.c
@@ -49,80 +49,87 @@ void handle_pagefault(uintptr_t vaddr, uintptr_t cause)
{
dbg(DBG_VM, "vaddr = 0x%p (0x%p), cause = %lu\n", (void *)vaddr,
PAGE_ALIGN_DOWN(vaddr), cause);
+
// NOT_YET_IMPLEMENTED("VM: handle_pagefault");
- // 1) Find the vmarea that contains vaddr, if it exists.
- // check that the vaddr is valid
- if (vaddr < USER_MEM_LOW || vaddr > USER_MEM_HIGH)
+ // Check that the vaddr is valid
+ if (vaddr < USER_MEM_LOW)
{
do_exit(EFAULT);
}
- // lookup the vmarea for this addr
- vmarea_t *vma = vmmap_lookup(curproc->p_vmmap, ADDR_TO_PN(vaddr));
- if (vma == NULL)
+ if (vaddr > USER_MEM_HIGH)
{
do_exit(EFAULT);
}
- // 2) Check the vmarea's protections (see the vmarea_t struct) against the 'cause'
- // error out if the fault has cause write and we don't have write permission in the area
- if ((cause & FAULT_WRITE) && !(vma->vma_prot & PROT_WRITE))
+ // Lookup the vmarea for this address
+ size_t pn = ADDR_TO_PN(vaddr);
+ vmarea_t* vma = vmmap_lookup(curproc->p_vmmap, pn);
+ if (!vma)
{
do_exit(EFAULT);
}
- // error out if the fault has cause exec and we don't have exec permission in the area
- if ((cause & FAULT_EXEC) && !(vma->vma_prot & PROT_EXEC))
+
+ // Error out if we don't have any permission in the area
+ if (vma->vma_prot == PROT_NONE)
{
do_exit(EFAULT);
}
- // error out if we don't have read permission in the area
- if (!(vma->vma_prot & PROT_READ))
+
+ // Check the vmarea's protections (see the vmarea_t struct) against the 'cause' of the pagefault
+ if ((cause & FAULT_WRITE) && !(vma->vma_prot & PROT_WRITE))
{
do_exit(EFAULT);
- }
- // error our if we don't have any permission in the area
- if (vma->vma_prot == PROT_NONE)
+ }
+ else if ((cause & FAULT_EXEC) && !(vma->vma_prot & PROT_EXEC))
+ {
+ do_exit(EFAULT);
+ }
+ else if (!(vma->vma_prot & PROT_READ))
{
do_exit(EFAULT);
}
- // 3) Obtain the corresponding pframe from the vmarea's mobj.
- pframe_t *pf;
+ // Obtain the corresponding pframe from the vmarea's mobj
+ long forwrite = 0;
+ if (cause & FAULT_WRITE)
+ {
+ forwrite = 1;
+ }
+ pframe_t* pfp;
mobj_lock(vma->vma_obj);
- int ret = mobj_get_pframe(
+ long status = mobj_get_pframe(
vma->vma_obj,
- vma->vma_off + ADDR_TO_PN(vaddr) - vma->vma_start,
- cause & FAULT_WRITE ? 1 : 0,
- &pf
+ pn - vma->vma_start + vma->vma_off,
+ forwrite,
+ &pfp
);
mobj_unlock(vma->vma_obj);
- if (ret < 0)
+ if (status < 0)
{
do_exit(EFAULT);
}
- // 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)
+ // Set up a call to pt_map to insert a new mapping into the appropriate pagetable
+ uintptr_t paddr = pt_virt_to_phys((uintptr_t) pfp->pf_addr);
+ pframe_release(&pfp);
+ uint32_t ptflags = PT_PRESENT | PT_USER;
+ if (cause & FAULT_WRITE)
{
ptflags |= PT_WRITE;
}
-
- int err = pt_map(
+ status = pt_map(
curproc->p_pml4,
- paddr,
- (uintptr_t) PAGE_ALIGN_DOWN(vaddr),
- pdflags,
+ paddr,
+ (uintptr_t) PAGE_ALIGN_DOWN(vaddr),
+ PT_PRESENT | PT_USER | PT_WRITE,
ptflags
);
- if (err < 0)
+ if (status < 0)
{
do_exit(EFAULT);
}
- // 5) Flush the TLB
- tlb_flush((uintptr_t) PAGE_ALIGN_DOWN(vaddr));
+ // Flush the TLB
+ tlb_flush(vaddr);
}