diff options
Diffstat (limited to 'kernel/vm/pagefault.c')
-rw-r--r-- | kernel/vm/pagefault.c | 81 |
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); } |