Пример #1
0
/** 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;
}
Пример #2
0
/** 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);
		}
	}
}
Пример #3
0
void page_fault(unsigned int n __attribute__((unused)), istate_t *istate)
{
	uint32_t fault_status = asi_u32_read(ASI_MMUREGS, MMU_FAULT_STATUS);
	uintptr_t fault_address = asi_u32_read(ASI_MMUREGS, MMU_FAULT_ADDRESS);
	mmu_fault_status_t *fault = (mmu_fault_status_t *) &fault_status;
	mmu_fault_type_t type = (mmu_fault_type_t) fault->at;
	
	if ((type == FAULT_TYPE_LOAD_USER_DATA) ||
	    (type == FAULT_TYPE_LOAD_SUPERVISOR_DATA))
		as_page_fault(fault_address, PF_ACCESS_READ, istate);

	if ((type == FAULT_TYPE_EXECUTE_USER) ||
	    (type == FAULT_TYPE_EXECUTE_SUPERVISOR))
		as_page_fault(fault_address, PF_ACCESS_EXEC, istate);

	if ((type == FAULT_TYPE_STORE_USER_DATA) ||
	    (type == FAULT_TYPE_STORE_USER_INSTRUCTION) ||
	    (type == FAULT_TYPE_STORE_SUPERVISOR_INSTRUCTION) ||
	    (type == FAULT_TYPE_STORE_SUPERVISOR_DATA))
		as_page_fault(fault_address, PF_ACCESS_WRITE, istate);
}
Пример #4
0
void page_fault(unsigned int n, istate_t *istate)
{
	uintptr_t badvaddr = read_cr2();
	
	if (istate->error_word & PFERR_CODE_RSVD)
		panic("Reserved bit set in page table entry.");
	
	pf_access_t access;
	
	if (istate->error_word & PFERR_CODE_RW)
		access = PF_ACCESS_WRITE;
	else if (istate->error_word & PFERR_CODE_ID)
		access = PF_ACCESS_EXEC;
	else
		access = PF_ACCESS_READ;
	
	(void) as_page_fault(badvaddr, access, istate);
}
Пример #5
0
/** 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);
		}
	}
}
Пример #6
0
/** 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;
}