FreeBSD/sys/powerpc/aim/mmu_oea64.c
/*
 * Map the given physical page at the specified virtual address in the
 * target pmap with the protection requested.  If specified the page
 * will be wired down.
 */
Map the given physical page at the specified virtual address in the
target pmap with the protection requested.  If specified the page
will be wired down.
Map the given physical page at the specified virtual address in the target pmap with the protection requested . If specified the page will be wired down .
int
moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, 
    vm_prot_t prot, u_int flags, int8_t psind)
{
	struct		pvo_entry *pvo, *oldpvo;
	struct		pvo_head *pvo_head;
	uint64_t	pte_lo;
	int		error;
	if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
		VM_OBJECT_ASSERT_LOCKED(m->object);
	pvo = alloc_pvo_entry(0);
	pvo->pvo_pmap = NULL; 
	pvo->pvo_pte.prot = prot;
	pte_lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m), pmap_page_get_memattr(m));
	pvo->pvo_pte.pa = VM_PAGE_TO_PHYS(m) | pte_lo;
	if ((flags & PMAP_ENTER_WIRED) != 0)
		pvo->pvo_vaddr |= PVO_WIRED;
	if ((m->oflags & VPO_UNMANAGED) != 0 || !moea64_initialized) {
		pvo_head = NULL;
	} else {
		pvo_head = &m->md.mdpg_pvoh;
		pvo->pvo_vaddr |= PVO_MANAGED;
	}
	for (;;) {
		PV_PAGE_LOCK(m);
		PMAP_LOCK(pmap);
		if (pvo->pvo_pmap == NULL)
			init_pvo_entry(pvo, pmap, va);
		if (prot & VM_PROT_WRITE)
			if (pmap_bootstrapped &&
			    (m->oflags & VPO_UNMANAGED) == 0)
				vm_page_aflag_set(m, PGA_WRITEABLE);
		oldpvo = moea64_pvo_find_va(pmap, va);
		if (oldpvo != NULL) {
			if (oldpvo->pvo_vaddr == pvo->pvo_vaddr &&
			    oldpvo->pvo_pte.pa == pvo->pvo_pte.pa &&
			    oldpvo->pvo_pte.prot == prot) {
				error = 0;
				if (MOEA64_PTE_SYNCH(mmu, oldpvo) < 0) {
					moea64_pte_overflow--;
					MOEA64_PTE_INSERT(mmu, oldpvo);
				}
				PV_PAGE_UNLOCK(m);
				PMAP_UNLOCK(pmap);
				free_pvo_entry(pvo);
				break;
			}
			KASSERT(oldpvo->pvo_pmap == pmap, ("pmap of old "
			    "mapping does not match new mapping"));
			moea64_pvo_remove_from_pmap(mmu, oldpvo);
		}
		error = moea64_pvo_enter(mmu, pvo, pvo_head);
		PV_PAGE_UNLOCK(m);
		PMAP_UNLOCK(pmap);
		if (oldpvo != NULL) {
			PV_LOCK(oldpvo->pvo_pte.pa & LPTE_RPGN);
			moea64_pvo_remove_from_page(mmu, oldpvo);
			PV_UNLOCK(oldpvo->pvo_pte.pa & LPTE_RPGN);
			free_pvo_entry(oldpvo);
		}
		if (error != ENOMEM)
			break;
		if ((flags & PMAP_ENTER_NOSLEEP) != 0)
			return (KERN_RESOURCE_SHORTAGE);
		VM_OBJECT_ASSERT_UNLOCKED(m->object);
		VM_WAIT;
	}
	if (pmap != kernel_pmap && !(m->aflags & PGA_EXECUTABLE) &&
	    (pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
		vm_page_aflag_set(m, PGA_EXECUTABLE);
		moea64_syncicache(mmu, pmap, va, VM_PAGE_TO_PHYS(m), PAGE_SIZE);
	}
	return (KERN_SUCCESS);
}
int moea64_enter ( mmu_t mmu , pmap_t pmap , vm_offset_t va , vm_page_t m , vm_prot_t prot , u_int flags , int8_t psind ) { struct pvo_entry * pvo , * oldpvo ; struct pvo_head * pvo_head ; uint64_t pte_lo ; int error ; if ( ( m -> oflags & VPO_UNMANAGED ) == 0 && ! vm_page_xbusied ( m ) ) VM_OBJECT_ASSERT_LOCKED ( m -> object ) ; pvo = alloc_pvo_entry ( 0 ) ; pvo -> pvo_pmap = NULL ; pvo -> pvo_pte . prot = prot ; pte_lo = moea64_calc_wimg ( VM_PAGE_TO_PHYS ( m ) , pmap_page_get_memattr ( m ) ) ; pvo -> pvo_pte . pa = VM_PAGE_TO_PHYS ( m ) | pte_lo ; if ( ( flags & PMAP_ENTER_WIRED ) != 0 ) pvo -> pvo_vaddr |= PVO_WIRED ; if ( ( m -> oflags & VPO_UNMANAGED ) != 0 || ! moea64_initialized ) { pvo_head = NULL ; } else { pvo_head = & m -> md . mdpg_pvoh ; pvo -> pvo_vaddr |= PVO_MANAGED ; } for ( ; ; ) { PV_PAGE_LOCK ( m ) ; PMAP_LOCK ( pmap ) ; if ( pvo -> pvo_pmap == NULL ) init_pvo_entry ( pvo , pmap , va ) ; if ( prot & VM_PROT_WRITE ) if ( pmap_bootstrapped && ( m -> oflags & VPO_UNMANAGED ) == 0 ) vm_page_aflag_set ( m , PGA_WRITEABLE ) ; oldpvo = moea64_pvo_find_va ( pmap , va ) ; if ( oldpvo != NULL ) { if ( oldpvo -> pvo_vaddr == pvo -> pvo_vaddr && oldpvo -> pvo_pte . pa == pvo -> pvo_pte . pa && oldpvo -> pvo_pte . prot == prot ) { error = 0 ; if ( MOEA64_PTE_SYNCH ( mmu , oldpvo ) < 0 ) { moea64_pte_overflow -- ; MOEA64_PTE_INSERT ( mmu , oldpvo ) ; } PV_PAGE_UNLOCK ( m ) ; PMAP_UNLOCK ( pmap ) ; free_pvo_entry ( pvo ) ; break ; } KASSERT ( oldpvo -> pvo_pmap == pmap , ( " " " " ) ) ; moea64_pvo_remove_from_pmap ( mmu , oldpvo ) ; } error = moea64_pvo_enter ( mmu , pvo , pvo_head ) ; PV_PAGE_UNLOCK ( m ) ; PMAP_UNLOCK ( pmap ) ; if ( oldpvo != NULL ) { PV_LOCK ( oldpvo -> pvo_pte . pa & LPTE_RPGN ) ; moea64_pvo_remove_from_page ( mmu , oldpvo ) ; PV_UNLOCK ( oldpvo -> pvo_pte . pa & LPTE_RPGN ) ; free_pvo_entry ( oldpvo ) ; } if ( error != ENOMEM ) break ; if ( ( flags & PMAP_ENTER_NOSLEEP ) != 0 ) return ( KERN_RESOURCE_SHORTAGE ) ; VM_OBJECT_ASSERT_UNLOCKED ( m -> object ) ; VM_WAIT ; } if ( pmap != kernel_pmap && ! ( m -> aflags & PGA_EXECUTABLE ) && ( pte_lo & ( LPTE_I | LPTE_G | LPTE_NOEXEC ) ) == 0 ) { vm_page_aflag_set ( m , PGA_EXECUTABLE ) ; moea64_syncicache ( mmu , pmap , va , VM_PAGE_TO_PHYS ( m ) , PAGE_SIZE ) ; } return ( KERN_SUCCESS ) ; }
Map the given physical page at the specified virtual address in the
 target pmap with the protection requested.
Map the given physical page at the specified virtual address in the target pmap with the protection requested .
/* to be filled in later */ /* Identical mapping already exists */ /* If not in page table, reinsert it */ /* Then just clean up and go home */ /* Otherwise, need to kill it first */ /* Free any dead pages */ /*
	 * Flush the page from the instruction cache if this page is
	 * mapped executable and cacheable.
	 */