FreeBSD/sys/i386/i386/pmap.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)
{
	pd_entry_t *pde;
	vm_paddr_t pa, ptepa;
	vm_page_t p;
	int pat_mode;
	VM_OBJECT_ASSERT_WLOCKED(object);
	KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
	    ("pmap_object_init_pt: non-device object"));
	if (pseflag && 
	    (addr & (NBPDR - 1)) == 0 && (size & (NBPDR - 1)) == 0) {
		if (!vm_object_populate(object, pindex, pindex + atop(size)))
			return;
		p = vm_page_lookup(object, pindex);
		KASSERT(p->valid == VM_PAGE_BITS_ALL,
		    ("pmap_object_init_pt: invalid page %p", p));
		pat_mode = p->md.pat_mode;
		ptepa = VM_PAGE_TO_PHYS(p);
		if (ptepa & (NBPDR - 1))
			return;
		p = TAILQ_NEXT(p, listq);
		for (pa = ptepa + PAGE_SIZE; pa < ptepa + size;
		    pa += PAGE_SIZE) {
			KASSERT(p->valid == VM_PAGE_BITS_ALL,
			    ("pmap_object_init_pt: invalid page %p", p));
			if (pa != VM_PAGE_TO_PHYS(p) ||
			    pat_mode != p->md.pat_mode)
				return;
			p = TAILQ_NEXT(p, listq);
		}
		PMAP_LOCK(pmap);
		for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa +
		    size; pa += NBPDR) {
			pde = pmap_pde(pmap, addr);
			if (*pde == 0) {
				pde_store(pde, pa | PG_PS | PG_M | PG_A |
				    PG_U | PG_RW | PG_V);
				pmap->pm_stats.resident_count += NBPDR /
				    PAGE_SIZE;
				pmap_pde_mappings++;
			}
			addr += NBPDR;
		}
		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 ) { pd_entry_t * pde ; vm_paddr_t pa , ptepa ; vm_page_t p ; int pat_mode ; VM_OBJECT_ASSERT_WLOCKED ( object ) ; KASSERT ( object -> type == OBJT_DEVICE || object -> type == OBJT_SG , ( " " ) ) ; if ( pseflag && ( addr & ( NBPDR - 1 ) ) == 0 && ( size & ( NBPDR - 1 ) ) == 0 ) { if ( ! vm_object_populate ( object , pindex , pindex + atop ( size ) ) ) return ; p = vm_page_lookup ( object , pindex ) ; KASSERT ( p -> valid == VM_PAGE_BITS_ALL , ( " " , p ) ) ; pat_mode = p -> md . pat_mode ; ptepa = VM_PAGE_TO_PHYS ( p ) ; if ( ptepa & ( NBPDR - 1 ) ) return ; p = TAILQ_NEXT ( p , listq ) ; for ( pa = ptepa + PAGE_SIZE ; pa < ptepa + size ; pa += PAGE_SIZE ) { KASSERT ( p -> valid == VM_PAGE_BITS_ALL , ( " " , p ) ) ; if ( pa != VM_PAGE_TO_PHYS ( p ) || pat_mode != p -> md . pat_mode ) return ; p = TAILQ_NEXT ( p , listq ) ; } PMAP_LOCK ( pmap ) ; for ( pa = ptepa | pmap_cache_bits ( pat_mode , 1 ) ; pa < ptepa + size ; pa += NBPDR ) { pde = pmap_pde ( pmap , addr ) ; if ( * pde == 0 ) { pde_store ( pde , pa | PG_PS | PG_M | PG_A | PG_U | PG_RW | PG_V ) ; pmap -> pm_stats . resident_count += NBPDR / PAGE_SIZE ; pmap_pde_mappings ++ ; } addr += NBPDR ; } 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 2/4MB 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 2/4MB pages.  Since "ptepa" is 2/4M aligned and
		 * "size" is a multiple of 2/4M, adding the PAT setting to
		 * "pa" will not affect the termination of this loop.
		 */ /* Else continue on if the PDE is already valid. */