/** Try to find PTE for faulting address * * @param as Address space. * @param badvaddr Faulting virtual address. * @param access Access mode that caused the fault. * @param istate Pointer to interrupted state. * * @return PTE on success, NULL otherwise. * */ static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access, istate_t *istate) { /* * Check if the mapping exists in page tables. */ pte_t *pte = page_mapping_find(as, badvaddr, true); if ((pte) && (pte->present)) { /* * Mapping found in page tables. * Immediately succeed. */ return pte; } /* * Mapping not found in page tables. * Resort to higher-level page fault handler. */ if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) { /* * The higher-level page fault handler succeeded, * The mapping ought to be in place. */ pte = page_mapping_find(as, badvaddr, true); ASSERT((pte) && (pte->present)); return pte; } return NULL; }
/** Try to find PTE for faulting address. * * @param badvaddr Faulting virtual address. * @param access Access mode that caused the fault. * @param istate Pointer to interrupted state. * @param pfrc Pointer to variable where as_page_fault() * return code will be stored. * * @return PTE on success, NULL otherwise. * */ static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) { entry_hi_t hi; hi.value = cp0_entry_hi_read(); /* * Handler cannot succeed if the ASIDs don't match. */ if (hi.asid != AS->asid) { printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid); return NULL; } /* * Check if the mapping exists in page tables. */ pte_t *pte = page_mapping_find(AS, badvaddr, true); if ((pte) && (pte->p) && ((pte->w) || (access != PF_ACCESS_WRITE))) { /* * Mapping found in page tables. * Immediately succeed. */ return pte; } else { int rc; /* * Mapping not found in page tables. * Resort to higher-level page fault handler. */ switch (rc = as_page_fault(badvaddr, access, istate)) { case AS_PF_OK: /* * The higher-level page fault handler succeeded, * The mapping ought to be in place. */ pte = page_mapping_find(AS, badvaddr, true); ASSERT(pte); ASSERT(pte->p); ASSERT((pte->w) || (access != PF_ACCESS_WRITE)); return pte; case AS_PF_DEFER: *pfrc = AS_PF_DEFER; return NULL; case AS_PF_FAULT: *pfrc = AS_PF_FAULT; return NULL; default: panic("Unexpected return code (%d).", rc); } } }
/** Try to find PTE for faulting address * * @param as Address space. * @param badvaddr Faulting virtual address. * @param access Access mode that caused the fault. * @param istate Pointer to interrupted state. * @param pfrc Pointer to variable where as_page_fault() return code * will be stored. * * @return PTE on success, NULL otherwise. * */ static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) { /* * Check if the mapping exists in page tables. */ pte_t *pte = page_mapping_find(as, badvaddr, true); if ((pte) && (pte->present)) { /* * Mapping found in page tables. * Immediately succeed. */ return pte; } else { /* * Mapping not found in page tables. * Resort to higher-level page fault handler. */ int rc = as_page_fault(badvaddr, access, istate); switch (rc) { case AS_PF_OK: /* * The higher-level page fault handler succeeded, * The mapping ought to be in place. */ pte = page_mapping_find(as, badvaddr, true); ASSERT((pte) && (pte->present)); *pfrc = 0; return pte; case AS_PF_DEFER: *pfrc = rc; return NULL; case AS_PF_FAULT: *pfrc = rc; return NULL; default: panic("Unexpected rc (%d).", rc); } } }
/** Try to find PTE for faulting address. * * @param badvaddr Faulting virtual address. * @param access Access mode that caused the fault. * @param istate Pointer to interrupted state. * * @return PTE on success, NULL otherwise. * */ static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate) { entry_hi_t hi; hi.value = cp0_entry_hi_read(); ASSERT(hi.asid == AS->asid); /* * Check if the mapping exists in page tables. */ pte_t *pte = page_mapping_find(AS, badvaddr, true); if ((pte) && (pte->p) && ((pte->w) || (access != PF_ACCESS_WRITE))) { /* * Mapping found in page tables. * Immediately succeed. */ return pte; } /* * Mapping not found in page tables. * Resort to higher-level page fault handler. */ if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) { /* * The higher-level page fault handler succeeded, * The mapping ought to be in place. */ pte = page_mapping_find(AS, badvaddr, true); ASSERT(pte); ASSERT(pte->p); ASSERT((pte->w) || (access != PF_ACCESS_WRITE)); return pte; } return NULL; }