FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *  Initialize a preallocated and zeroed pmap structure,
 *  such as one in a vmspace structure.
 */
Initialize a preallocated and zeroed pmap structure,
such as one in a vmspace structure.
Initialize a preallocated and zeroed pmap structure such as one in a vmspace structure .
int
pmap_pinit(pmap_t pmap)
{
	pt1_entry_t *pte1p;
	pt2_entry_t *pte2p;
	vm_paddr_t pa, pt2tab_pa;
	u_int i;
	PDEBUG(6, printf("%s: pmap = %p, pm_pt1 = %p\n", __func__, pmap,
	    pmap->pm_pt1));
	if (pmap->pm_pt1 == NULL) {
		pmap->pm_pt1 = (pt1_entry_t *)kmem_alloc_contig(kernel_arena,
		    NB_IN_PT1, M_NOWAIT | M_ZERO, 0, -1UL, NB_IN_PT1, 0,
		    pt_memattr);
		if (pmap->pm_pt1 == NULL)
			return (0);
	}
	if (pmap->pm_pt2tab == NULL) {
		pmap->pm_pt2tab = (pt2_entry_t *)kmem_alloc_attr(kernel_arena,
		    NB_IN_PT2TAB, M_NOWAIT | M_ZERO, 0, -1UL, pt_memattr);
		if (pmap->pm_pt2tab == NULL) {
			kmem_free(kernel_arena, (vm_offset_t)pmap->pm_pt1,
			    NB_IN_PT1);
			pmap->pm_pt1 = NULL;
			return (0);
		}
	}
	mtx_lock_spin(&allpmaps_lock);
	pte1_copy_nosync(kern_pt1, pmap->pm_pt1, KERNBASE,
	    kernel_vm_end_new - 1);
	pte1_copy_nosync(kern_pt1, pmap->pm_pt1, vm_max_kernel_address,
	    0xFFFFFFFF);
	pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, KERNBASE,
	    kernel_vm_end_new - 1);
	pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, vm_max_kernel_address,
	    0xFFFFFFFF);
	LIST_INSERT_HEAD(&allpmaps, pmap, pm_list);
	mtx_unlock_spin(&allpmaps_lock);
	pt2tab_pa = vtophys(pmap->pm_pt2tab);
	pte2p = pmap_pt2tab_entry(pmap, (vm_offset_t)PT2MAP);
	for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) {
		pt2tab_store(pte2p++, PTE2_KPT_NG(pa));
	}
	pte1p = pmap_pte1(pmap, (vm_offset_t)PT2MAP);
	for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) {
		pte1_store(pte1p++, PTE1_LINK(pa));
	}
	pte1_sync_range(pmap->pm_pt1, NB_IN_PT1);
	pte2_sync_range(pmap->pm_pt2tab, NB_IN_PT2TAB);
	CPU_ZERO(&pmap->pm_active);
	TAILQ_INIT(&pmap->pm_pvchunk);
	bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
	return (1);
}
int pmap_pinit ( pmap_t pmap ) { pt1_entry_t * pte1p ; pt2_entry_t * pte2p ; vm_paddr_t pa , pt2tab_pa ; u_int i ; PDEBUG ( 6 , printf ( " \n " , __func__ , pmap , pmap -> pm_pt1 ) ) ; if ( pmap -> pm_pt1 == NULL ) { pmap -> pm_pt1 = ( pt1_entry_t * ) kmem_alloc_contig ( kernel_arena , NB_IN_PT1 , M_NOWAIT | M_ZERO , 0 , -1UL , NB_IN_PT1 , 0 , pt_memattr ) ; if ( pmap -> pm_pt1 == NULL ) return ( 0 ) ; } if ( pmap -> pm_pt2tab == NULL ) { pmap -> pm_pt2tab = ( pt2_entry_t * ) kmem_alloc_attr ( kernel_arena , NB_IN_PT2TAB , M_NOWAIT | M_ZERO , 0 , -1UL , pt_memattr ) ; if ( pmap -> pm_pt2tab == NULL ) { kmem_free ( kernel_arena , ( vm_offset_t ) pmap -> pm_pt1 , NB_IN_PT1 ) ; pmap -> pm_pt1 = NULL ; return ( 0 ) ; } } mtx_lock_spin ( & allpmaps_lock ) ; pte1_copy_nosync ( kern_pt1 , pmap -> pm_pt1 , KERNBASE , kernel_vm_end_new - 1 ) ; pte1_copy_nosync ( kern_pt1 , pmap -> pm_pt1 , vm_max_kernel_address , 0xFFFFFFFF ) ; pt2tab_copy_nosync ( kern_pt2tab , pmap -> pm_pt2tab , KERNBASE , kernel_vm_end_new - 1 ) ; pt2tab_copy_nosync ( kern_pt2tab , pmap -> pm_pt2tab , vm_max_kernel_address , 0xFFFFFFFF ) ; LIST_INSERT_HEAD ( & allpmaps , pmap , pm_list ) ; mtx_unlock_spin ( & allpmaps_lock ) ; pt2tab_pa = vtophys ( pmap -> pm_pt2tab ) ; pte2p = pmap_pt2tab_entry ( pmap , ( vm_offset_t ) PT2MAP ) ; for ( pa = pt2tab_pa , i = 0 ; i < NPG_IN_PT2TAB ; i ++ , pa += PTE2_SIZE ) { pt2tab_store ( pte2p ++ , PTE2_KPT_NG ( pa ) ) ; } pte1p = pmap_pte1 ( pmap , ( vm_offset_t ) PT2MAP ) ; for ( pa = pt2tab_pa , i = 0 ; i < NPT2_IN_PT2TAB ; i ++ , pa += NB_IN_PT2 ) { pte1_store ( pte1p ++ , PTE1_LINK ( pa ) ) ; } pte1_sync_range ( pmap -> pm_pt1 , NB_IN_PT1 ) ; pte2_sync_range ( pmap -> pm_pt2tab , NB_IN_PT2TAB ) ; CPU_ZERO ( & pmap -> pm_active ) ; TAILQ_INIT ( & pmap -> pm_pvchunk ) ; bzero ( & pmap -> pm_stats , sizeof pmap -> pm_stats ) ; return ( 1 ) ; }
Initialize a preallocated and zeroed pmap structure,
  such as one in a vmspace structure.
Initialize a preallocated and zeroed pmap structure such as one in a vmspace structure .
/*
	 * No need to allocate L2 page table space yet but we do need
	 * a valid L1 page table and PT2TAB table.
	 *
	 * Install shared kernel mappings to these tables. It's a little
	 * tricky as some parts of KVA are reserved for vectors, devices,
	 * and whatever else. These parts are supposed to be above
	 * vm_max_kernel_address. Thus two regions should be installed:
	 *
	 *   (1) <KERNBASE, kernel_vm_end),
	 *   (2) <vm_max_kernel_address, 0xFFFFFFFF>.
	 *
	 * QQQ: The second region should be stable enough to be installed
	 *      only once in time when the tables are allocated.
	 * QQQ: Maybe copy of both regions at once could be faster ...
	 * QQQ: Maybe the other TTBR is an option.
	 *
	 * Finally, install own PT2TAB table to these tables.
	 */ /*
		 * QQQ: (1) PT2TAB must be contiguous. If PT2TAB is one page
		 *      only, what should be the only size for 32 bit systems,
		 *      then we could allocate it with vm_page_alloc() and all
		 *      the stuff needed as other L2 page table pages.
		 *      (2) Note that a process PT2TAB is special L2 page table
		 *      page. Its mapping in kernel_arena is permanent and can
		 *      be used no matter which process is current. Its mapping
		 *      in PT2MAP can be used only for current process.
		 */ /*
			 * QQQ: As struct pmap is allocated from UMA with
			 *      UMA_ZONE_NOFREE flag, it's important to leave
			 *      no allocation in pmap if initialization failed.
			 */ /*
		 * QQQ: Each L2 page table page vm_page_t has pindex set to
		 *      pte1 index of virtual address mapped by this page.
		 *      It's not valid for non kernel PT2TABs themselves.
		 *      The pindex of these pages can not be altered because
		 *      of the way how they are allocated now. However, it
		 *      should not be a problem.
		 */ /*
	 * To avoid race with pmap_kenter_pte1() and pmap_kenter_pt2tab(),
	 * kernel_vm_end_new is used here instead of kernel_vm_end.
	 */ /*
	 * Store PT2MAP PT2 pages (a.k.a. PT2TAB) in PT2TAB itself.
	 * I.e. self reference mapping.  The PT2TAB is private, however mapped
	 * into shared PT2MAP space, so the mapping should be not global.
	 */ /* Insert PT2MAP PT2s into pmap PT1. */ /*
	 * Now synchronize new mapping which was made above.
	 */