FreeBSD/sys/i386/i386/pmap.c
/*
 *	Copy the range specified by src_addr/len
 *	from the source map to the range dst_addr/len
 *	in the destination map.
 *
 *	This routine is only advisory and need not do anything.
 */
Copy the range specified by src_addr/len
from the source map to the range dst_addr/len
in the destination map.

This routine is only advisory and need not do anything.
Copy the range specified by src_addr / len from the source map to the range dst_addr / len in the destination map . This routine is only advisory and need not do anything .
void
pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
    vm_offset_t src_addr)
{
	struct spglist free;
	vm_offset_t addr;
	vm_offset_t end_addr = src_addr + len;
	vm_offset_t pdnxt;
	if (dst_addr != src_addr)
		return;
	if (!pmap_is_current(src_pmap))
		return;
	rw_wlock(&pvh_global_lock);
	if (dst_pmap < src_pmap) {
		PMAP_LOCK(dst_pmap);
		PMAP_LOCK(src_pmap);
	} else {
		PMAP_LOCK(src_pmap);
		PMAP_LOCK(dst_pmap);
	}
	sched_pin();
	for (addr = src_addr; addr < end_addr; addr = pdnxt) {
		pt_entry_t *src_pte, *dst_pte;
		vm_page_t dstmpte, srcmpte;
		pd_entry_t srcptepaddr;
		u_int ptepindex;
		KASSERT(addr < UPT_MIN_ADDRESS,
		    ("pmap_copy: invalid to pmap_copy page tables"));
		pdnxt = (addr + NBPDR) & ~PDRMASK;
		if (pdnxt < addr)
			pdnxt = end_addr;
		ptepindex = addr >> PDRSHIFT;
		srcptepaddr = src_pmap->pm_pdir[ptepindex];
		if (srcptepaddr == 0)
			continue;
		if (srcptepaddr & PG_PS) {
			if ((addr & PDRMASK) != 0 || addr + NBPDR > end_addr)
				continue;
			if (dst_pmap->pm_pdir[ptepindex] == 0 &&
			    ((srcptepaddr & PG_MANAGED) == 0 ||
			    pmap_pv_insert_pde(dst_pmap, addr, srcptepaddr &
			    PG_PS_FRAME))) {
				dst_pmap->pm_pdir[ptepindex] = srcptepaddr &
				    ~PG_W;
				dst_pmap->pm_stats.resident_count +=
				    NBPDR / PAGE_SIZE;
				pmap_pde_mappings++;
			}
			continue;
		}
		srcmpte = PHYS_TO_VM_PAGE(srcptepaddr & PG_FRAME);
		KASSERT(srcmpte->wire_count > 0,
		    ("pmap_copy: source page table page is unused"));
		if (pdnxt > end_addr)
			pdnxt = end_addr;
		src_pte = vtopte(addr);
		while (addr < pdnxt) {
			pt_entry_t ptetemp;
			ptetemp = *src_pte;
			if ((ptetemp & PG_MANAGED) != 0) {
				dstmpte = pmap_allocpte(dst_pmap, addr,
				    PMAP_ENTER_NOSLEEP);
				if (dstmpte == NULL)
					goto out;
				dst_pte = pmap_pte_quick(dst_pmap, addr);
				if (*dst_pte == 0 &&
				    pmap_try_insert_pv_entry(dst_pmap, addr,
				    PHYS_TO_VM_PAGE(ptetemp & PG_FRAME))) {
					*dst_pte = ptetemp & ~(PG_W | PG_M |
					    PG_A);
					dst_pmap->pm_stats.resident_count++;
	 			} else {
					SLIST_INIT(&free);
					if (pmap_unwire_ptp(dst_pmap, dstmpte,
					    &free)) {
						pmap_invalidate_page(dst_pmap,
						    addr);
						pmap_free_zero_pages(&free);
					}
					goto out;
				}
				if (dstmpte->wire_count >= srcmpte->wire_count)
					break;
			}
			addr += PAGE_SIZE;
			src_pte++;
		}
	}
out:
	sched_unpin();
	rw_wunlock(&pvh_global_lock);
	PMAP_UNLOCK(src_pmap);
	PMAP_UNLOCK(dst_pmap);
}
void pmap_copy ( pmap_t dst_pmap , pmap_t src_pmap , vm_offset_t dst_addr , vm_size_t len , vm_offset_t src_addr ) { struct spglist free ; vm_offset_t addr ; vm_offset_t end_addr = src_addr + len ; vm_offset_t pdnxt ; if ( dst_addr != src_addr ) return ; if ( ! pmap_is_current ( src_pmap ) ) return ; rw_wlock ( & pvh_global_lock ) ; if ( dst_pmap < src_pmap ) { PMAP_LOCK ( dst_pmap ) ; PMAP_LOCK ( src_pmap ) ; } else { PMAP_LOCK ( src_pmap ) ; PMAP_LOCK ( dst_pmap ) ; } sched_pin ( ) ; for ( addr = src_addr ; addr < end_addr ; addr = pdnxt ) { pt_entry_t * src_pte , * dst_pte ; vm_page_t dstmpte , srcmpte ; pd_entry_t srcptepaddr ; u_int ptepindex ; KASSERT ( addr < UPT_MIN_ADDRESS , ( " " ) ) ; pdnxt = ( addr + NBPDR ) & ~ PDRMASK ; if ( pdnxt < addr ) pdnxt = end_addr ; ptepindex = addr >> PDRSHIFT ; srcptepaddr = src_pmap -> pm_pdir [ ptepindex ] ; if ( srcptepaddr == 0 ) continue ; if ( srcptepaddr & PG_PS ) { if ( ( addr & PDRMASK ) != 0 || addr + NBPDR > end_addr ) continue ; if ( dst_pmap -> pm_pdir [ ptepindex ] == 0 && ( ( srcptepaddr & PG_MANAGED ) == 0 || pmap_pv_insert_pde ( dst_pmap , addr , srcptepaddr & PG_PS_FRAME ) ) ) { dst_pmap -> pm_pdir [ ptepindex ] = srcptepaddr & ~ PG_W ; dst_pmap -> pm_stats . resident_count += NBPDR / PAGE_SIZE ; pmap_pde_mappings ++ ; } continue ; } srcmpte = PHYS_TO_VM_PAGE ( srcptepaddr & PG_FRAME ) ; KASSERT ( srcmpte -> wire_count > 0 , ( " " ) ) ; if ( pdnxt > end_addr ) pdnxt = end_addr ; src_pte = vtopte ( addr ) ; while ( addr < pdnxt ) { pt_entry_t ptetemp ; ptetemp = * src_pte ; if ( ( ptetemp & PG_MANAGED ) != 0 ) { dstmpte = pmap_allocpte ( dst_pmap , addr , PMAP_ENTER_NOSLEEP ) ; if ( dstmpte == NULL ) goto out ; dst_pte = pmap_pte_quick ( dst_pmap , addr ) ; if ( * dst_pte == 0 && pmap_try_insert_pv_entry ( dst_pmap , addr , PHYS_TO_VM_PAGE ( ptetemp & PG_FRAME ) ) ) { * dst_pte = ptetemp & ~ ( PG_W | PG_M | PG_A ) ; dst_pmap -> pm_stats . resident_count ++ ; } else { SLIST_INIT ( & free ) ; if ( pmap_unwire_ptp ( dst_pmap , dstmpte , & free ) ) { pmap_invalidate_page ( dst_pmap , addr ) ; pmap_free_zero_pages ( & free ) ; } goto out ; } if ( dstmpte -> wire_count >= srcmpte -> wire_count ) break ; } addr += PAGE_SIZE ; src_pte ++ ; } } out : sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; PMAP_UNLOCK ( src_pmap ) ; PMAP_UNLOCK ( dst_pmap ) ; }
Copy the range specified by src_addr/len
      from the source map to the range dst_addr/len
      in the destination map.
Copy the range specified by src_addr / len from the source map to the range dst_addr / len in the destination map .
/*
			 * we only virtual copy managed pages
			 */ /*
					 * Clear the wired, modified, and
					 * accessed (referenced) bits
					 * during the copy.
					 */