FreeBSD/sys/arm/arm/pmap-v4.c
/*
 * Atomically extract and hold the physical page with the given
 * pmap and virtual address pair if that mapping permits the given
 * protection.
 *
 */
Atomically extract and hold the physical page with the given
pmap and virtual address pair if that mapping permits the given
protection.
Atomically extract and hold the physical page with the given pmap and virtual address pair if that mapping permits the given protection .
vm_page_t
pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
	struct l2_dtable *l2;
	pd_entry_t l1pd;
	pt_entry_t *ptep, pte;
	vm_paddr_t pa, paddr;
	vm_page_t m = NULL;
	u_int l1idx;
	l1idx = L1_IDX(va);
	paddr = 0;
 	PMAP_LOCK(pmap);
retry:
	l1pd = pmap->pm_l1->l1_kva[l1idx];
	if (l1pte_section_p(l1pd)) {
		KASSERT(pmap == kernel_pmap, ("huh"));
		if (l1pd & L1_S_SUPERSEC)
			pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
		else
			pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
		if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
			goto retry;
		if (l1pd & L1_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
			m = PHYS_TO_VM_PAGE(pa);
			vm_page_hold(m);
		}
	} else {
		l2 = pmap->pm_l2[L2_IDX(l1idx)];
		if (l2 == NULL ||
		    (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
		 	PMAP_UNLOCK(pmap);
			return (NULL);
		}
		ptep = &ptep[l2pte_index(va)];
		pte = *ptep;
		if (pte == 0) {
		 	PMAP_UNLOCK(pmap);
			return (NULL);
		}
		if (pte & L2_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
			if ((pte & L2_TYPE_MASK) == L2_TYPE_L)
				pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
			else
				pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
			if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
				goto retry;
			m = PHYS_TO_VM_PAGE(pa);
			vm_page_hold(m);
		}
	}
 	PMAP_UNLOCK(pmap);
	PA_UNLOCK_COND(paddr);
	return (m);
}
vm_page_t pmap_extract_and_hold ( pmap_t pmap , vm_offset_t va , vm_prot_t prot ) { struct l2_dtable * l2 ; pd_entry_t l1pd ; pt_entry_t * ptep , pte ; vm_paddr_t pa , paddr ; vm_page_t m = NULL ; u_int l1idx ; l1idx = L1_IDX ( va ) ; paddr = 0 ; PMAP_LOCK ( pmap ) ; retry : l1pd = pmap -> pm_l1 -> l1_kva [ l1idx ] ; if ( l1pte_section_p ( l1pd ) ) { KASSERT ( pmap == kernel_pmap , ( " " ) ) ; if ( l1pd & L1_S_SUPERSEC ) pa = ( l1pd & L1_SUP_FRAME ) | ( va & L1_SUP_OFFSET ) ; else pa = ( l1pd & L1_S_FRAME ) | ( va & L1_S_OFFSET ) ; if ( vm_page_pa_tryrelock ( pmap , pa & PG_FRAME , & paddr ) ) goto retry ; if ( l1pd & L1_S_PROT_W || ( prot & VM_PROT_WRITE ) == 0 ) { m = PHYS_TO_VM_PAGE ( pa ) ; vm_page_hold ( m ) ; } } else { l2 = pmap -> pm_l2 [ L2_IDX ( l1idx ) ] ; if ( l2 == NULL || ( ptep = l2 -> l2_bucket [ L2_BUCKET ( l1idx ) ] . l2b_kva ) == NULL ) { PMAP_UNLOCK ( pmap ) ; return ( NULL ) ; } ptep = & ptep [ l2pte_index ( va ) ] ; pte = * ptep ; if ( pte == 0 ) { PMAP_UNLOCK ( pmap ) ; return ( NULL ) ; } if ( pte & L2_S_PROT_W || ( prot & VM_PROT_WRITE ) == 0 ) { if ( ( pte & L2_TYPE_MASK ) == L2_TYPE_L ) pa = ( pte & L2_L_FRAME ) | ( va & L2_L_OFFSET ) ; else pa = ( pte & L2_S_FRAME ) | ( va & L2_S_OFFSET ) ; if ( vm_page_pa_tryrelock ( pmap , pa & PG_FRAME , & paddr ) ) goto retry ; m = PHYS_TO_VM_PAGE ( pa ) ; vm_page_hold ( m ) ; } } PMAP_UNLOCK ( pmap ) ; PA_UNLOCK_COND ( paddr ) ; return ( m ) ; }
Atomically extract and hold the physical page with the given
 pmap and virtual address pair if that mapping permits the given
 protection.
Atomically extract and hold the physical page with the given pmap and virtual address pair if that mapping permits the given protection .
/*
		 * These should only happen for kernel_pmap
		 */ /* XXX: what to do about the bits > 32 ? */ /*
		 * Note that we can't rely on the validity of the L1
		 * descriptor as an indication that a mapping exists.
		 * We have to look it up in the L2 dtable.
		 */