FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *  This code maps large physical mmap regions into the
 *  processor address space.  Note that some shortcuts
 *  are taken, but the code works.
 */
This code maps large physical mmap regions into the
processor address space.  Note that some shortcuts
are taken, but the code works.
This code maps large physical mmap regions into the processor address space . Note that some shortcuts are taken but the code works .
void
pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
    vm_pindex_t pindex, vm_size_t size)
{
	pt1_entry_t *pte1p;
	vm_paddr_t pa, pte2_pa;
	vm_page_t p;
	vm_memattr_t pat_mode;
	u_int l1attr, l1prot;
	VM_OBJECT_ASSERT_WLOCKED(object);
	KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
	    ("%s: non-device object", __func__));
	if ((addr & PTE1_OFFSET) == 0 && (size & PTE1_OFFSET) == 0) {
		if (!vm_object_populate(object, pindex, pindex + atop(size)))
			return;
		p = vm_page_lookup(object, pindex);
		KASSERT(p->valid == VM_PAGE_BITS_ALL,
		    ("%s: invalid page %p", __func__, p));
		pat_mode = p->md.pat_mode;
		pte2_pa = VM_PAGE_TO_PHYS(p);
		if (pte2_pa & PTE1_OFFSET)
			return;
		p = TAILQ_NEXT(p, listq);
		for (pa = pte2_pa + PAGE_SIZE; pa < pte2_pa + size;
		    pa += PAGE_SIZE) {
			KASSERT(p->valid == VM_PAGE_BITS_ALL,
			    ("%s: invalid page %p", __func__, p));
			if (pa != VM_PAGE_TO_PHYS(p) ||
			    pat_mode != p->md.pat_mode)
				return;
			p = TAILQ_NEXT(p, listq);
		}
		l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A;
		l1attr = ATTR_TO_L1(vm_memattr_to_pte2(pat_mode));
		PMAP_LOCK(pmap);
		for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) {
			pte1p = pmap_pte1(pmap, addr);
			if (!pte1_is_valid(pte1_load(pte1p))) {
				pte1_store(pte1p, PTE1(pa, l1prot, l1attr));
				pmap->pm_stats.resident_count += PTE1_SIZE /
				    PAGE_SIZE;
				pmap_pte1_mappings++;
			}
			addr += PTE1_SIZE;
		}
		PMAP_UNLOCK(pmap);
	}
}
void pmap_object_init_pt ( pmap_t pmap , vm_offset_t addr , vm_object_t object , vm_pindex_t pindex , vm_size_t size ) { pt1_entry_t * pte1p ; vm_paddr_t pa , pte2_pa ; vm_page_t p ; vm_memattr_t pat_mode ; u_int l1attr , l1prot ; VM_OBJECT_ASSERT_WLOCKED ( object ) ; KASSERT ( object -> type == OBJT_DEVICE || object -> type == OBJT_SG , ( " " , __func__ ) ) ; if ( ( addr & PTE1_OFFSET ) == 0 && ( size & PTE1_OFFSET ) == 0 ) { if ( ! vm_object_populate ( object , pindex , pindex + atop ( size ) ) ) return ; p = vm_page_lookup ( object , pindex ) ; KASSERT ( p -> valid == VM_PAGE_BITS_ALL , ( " " , __func__ , p ) ) ; pat_mode = p -> md . pat_mode ; pte2_pa = VM_PAGE_TO_PHYS ( p ) ; if ( pte2_pa & PTE1_OFFSET ) return ; p = TAILQ_NEXT ( p , listq ) ; for ( pa = pte2_pa + PAGE_SIZE ; pa < pte2_pa + size ; pa += PAGE_SIZE ) { KASSERT ( p -> valid == VM_PAGE_BITS_ALL , ( " " , __func__ , p ) ) ; if ( pa != VM_PAGE_TO_PHYS ( p ) || pat_mode != p -> md . pat_mode ) return ; p = TAILQ_NEXT ( p , listq ) ; } l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A ; l1attr = ATTR_TO_L1 ( vm_memattr_to_pte2 ( pat_mode ) ) ; PMAP_LOCK ( pmap ) ; for ( pa = pte2_pa ; pa < pte2_pa + size ; pa += PTE1_SIZE ) { pte1p = pmap_pte1 ( pmap , addr ) ; if ( ! pte1_is_valid ( pte1_load ( pte1p ) ) ) { pte1_store ( pte1p , PTE1 ( pa , l1prot , l1attr ) ) ; pmap -> pm_stats . resident_count += PTE1_SIZE / PAGE_SIZE ; pmap_pte1_mappings ++ ; } addr += PTE1_SIZE ; } PMAP_UNLOCK ( pmap ) ; } }
This code maps large physical mmap regions into the
  processor address space.
This code maps large physical mmap regions into the processor address space .
/*
		 * Abort the mapping if the first page is not physically
		 * aligned to a 1MB page boundary.
		 */ /*
		 * Skip the first page. Abort the mapping if the rest of
		 * the pages are not physically contiguous or have differing
		 * memory attributes.
		 */ /*
		 * Map using 1MB pages.
		 *
		 * QQQ: Well, we are mapping a section, so same condition must
		 * be hold like during promotion. It looks that only RW mapping
		 * is done here, so readonly mapping must be done elsewhere.
		 */ /* Else continue on if the PTE1 is already valid. */