FreeBSD/sys/i386/i386/pmap.c
/*
 *	Initialize the pmap module.
 *	Called by vm_init, to initialize any structures that the pmap
 *	system needs to map virtual memory.
 */
Initialize the pmap module.
Called by vm_init, to initialize any structures that the pmap
system needs to map virtual memory.
Initialize the pmap module . Called by vm_init to initialize any structures that the pmap system needs to map virtual memory .
void
pmap_init(void)
{
	struct pmap_preinit_mapping *ppim;
	vm_page_t mpte;
	vm_size_t s;
	int i, pv_npg;
	for (i = 0; i < NKPT; i++) {
		mpte = PHYS_TO_VM_PAGE(KPTphys + (i << PAGE_SHIFT));
		KASSERT(mpte >= vm_page_array &&
		    mpte < &vm_page_array[vm_page_array_size],
		    ("pmap_init: page table page is out of range"));
		mpte->pindex = i + KPTDI;
		mpte->phys_addr = KPTphys + (i << PAGE_SHIFT);
	}
	TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
	pv_entry_max = shpgperproc * maxproc + vm_cnt.v_page_count;
	TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
	pv_entry_max = roundup(pv_entry_max, _NPCPV);
	pv_entry_high_water = 9 * (pv_entry_max / 10);
	if (vm_guest == VM_GUEST_VM && (cpu_feature & CPUID_SS) == 0 &&
	    (cpu_feature2 & (CPUID2_SSSE3 | CPUID2_SSE41 | CPUID2_AESNI |
	    CPUID2_AVX | CPUID2_XSAVE)) == 0 && (amd_feature2 & (AMDID2_XOP |
	    AMDID2_FMA4)) == 0)
		workaround_erratum383 = 1;
	TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled);
	if (pseflag == 0)
		pg_ps_enabled = 0;
	else if (pg_ps_enabled) {
		KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
		    ("pmap_init: can't assign to pagesizes[1]"));
		pagesizes[1] = NBPDR;
	}
	pv_npg = trunc_4mpage(vm_phys_segs[vm_phys_nsegs - 1].end -
	    PAGE_SIZE) / NBPDR + 1;
	s = (vm_size_t)(pv_npg * sizeof(struct md_page));
	s = round_page(s);
	pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
	    M_WAITOK | M_ZERO);
	for (i = 0; i < pv_npg; i++)
		TAILQ_INIT(&pv_table[i].pv_list);
	pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
	pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks);
	if (pv_chunkbase == NULL)
		panic("pmap_init: not enough kvm for pv chunks");
	pmap_ptelist_init(&pv_vafree, pv_chunkbase, pv_maxchunks);
#if defined(PAE) || defined(PAE_TABLES)
	pdptzone = uma_zcreate("PDPT", NPGPTD * sizeof(pdpt_entry_t), NULL,
	    NULL, NULL, NULL, (NPGPTD * sizeof(pdpt_entry_t)) - 1,
	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
	uma_zone_set_allocf(pdptzone, pmap_pdpt_allocf);
#endif
	pmap_initialized = 1;
	if (!bootverbose)
		return;
	for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
		ppim = pmap_preinit_mapping + i;
		if (ppim->va == 0)
			continue;
		printf("PPIM %u: PA=%#jx, VA=%#x, size=%#x, mode=%#x\n", i,
		    (uintmax_t)ppim->pa, ppim->va, ppim->sz, ppim->mode);
	}
}
void pmap_init ( void ) { struct pmap_preinit_mapping * ppim ; vm_page_t mpte ; vm_size_t s ; int i , pv_npg ; for ( i = 0 ; i < NKPT ; i ++ ) { mpte = PHYS_TO_VM_PAGE ( KPTphys + ( i << PAGE_SHIFT ) ) ; KASSERT ( mpte >= vm_page_array && mpte < & vm_page_array [ vm_page_array_size ] , ( " " ) ) ; mpte -> pindex = i + KPTDI ; mpte -> phys_addr = KPTphys + ( i << PAGE_SHIFT ) ; } TUNABLE_INT_FETCH ( " " , & shpgperproc ) ; pv_entry_max = shpgperproc * maxproc + vm_cnt . v_page_count ; TUNABLE_INT_FETCH ( " " , & pv_entry_max ) ; pv_entry_max = roundup ( pv_entry_max , _NPCPV ) ; pv_entry_high_water = 9 * ( pv_entry_max / 10 ) ; if ( vm_guest == VM_GUEST_VM && ( cpu_feature & CPUID_SS ) == 0 && ( cpu_feature2 & ( CPUID2_SSSE3 | CPUID2_SSE41 | CPUID2_AESNI | CPUID2_AVX | CPUID2_XSAVE ) ) == 0 && ( amd_feature2 & ( AMDID2_XOP | AMDID2_FMA4 ) ) == 0 ) workaround_erratum383 = 1 ; TUNABLE_INT_FETCH ( " " , & pg_ps_enabled ) ; if ( pseflag == 0 ) pg_ps_enabled = 0 ; else if ( pg_ps_enabled ) { KASSERT ( MAXPAGESIZES > 1 && pagesizes [ 1 ] == 0 , ( " " ) ) ; pagesizes [ 1 ] = NBPDR ; } pv_npg = trunc_4mpage ( vm_phys_segs [ vm_phys_nsegs - 1 ] . end - PAGE_SIZE ) / NBPDR + 1 ; s = ( vm_size_t ) ( pv_npg * sizeof ( struct md_page ) ) ; s = round_page ( s ) ; pv_table = ( struct md_page * ) kmem_malloc ( kernel_arena , s , M_WAITOK | M_ZERO ) ; for ( i = 0 ; i < pv_npg ; i ++ ) TAILQ_INIT ( & pv_table [ i ] . pv_list ) ; pv_maxchunks = MAX ( pv_entry_max / _NPCPV , maxproc ) ; pv_chunkbase = ( struct pv_chunk * ) kva_alloc ( PAGE_SIZE * pv_maxchunks ) ; if ( pv_chunkbase == NULL ) panic ( " " ) ; pmap_ptelist_init ( & pv_vafree , pv_chunkbase , pv_maxchunks ) ; #if defined ( PAE ) || defined ( PAE_TABLES ) pdptzone = uma_zcreate ( " " , NPGPTD * sizeof ( pdpt_entry_t ) , NULL , NULL , NULL , NULL , ( NPGPTD * sizeof ( pdpt_entry_t ) ) - 1 , UMA_ZONE_VM | UMA_ZONE_NOFREE ) ; uma_zone_set_allocf ( pdptzone , pmap_pdpt_allocf ) ; #endif pmap_initialized = 1 ; if ( ! bootverbose ) return ; for ( i = 0 ; i < PMAP_PREINIT_MAPPING_COUNT ; i ++ ) { ppim = pmap_preinit_mapping + i ; if ( ppim -> va == 0 ) continue ; printf ( " \n " , i , ( uintmax_t ) ppim -> pa , ppim -> va , ppim -> sz , ppim -> mode ) ; } }
Initialize the pmap module.
Initialize the pmap module .
/*
	 * Initialize the vm page array entries for the kernel pmap's
	 * page table pages.
	 */ /*
	 * Initialize the address space (zone) for the pv entries.  Set a
	 * high water mark so that the system can recover from excessive
	 * numbers of pv entries.
	 */ /*
	 * If the kernel is running on a virtual machine, then it must assume
	 * that MCA is enabled by the hypervisor.  Moreover, the kernel must
	 * be prepared for the hypervisor changing the vendor and family that
	 * are reported by CPUID.  Consequently, the workaround for AMD Family
	 * 10h Erratum 383 is enabled if the processor's feature set does not
	 * include at least one feature that is only supported by older Intel
	 * or newer AMD processors.
	 */ /*
	 * Are large page mappings supported and enabled?
	 */ /*
	 * Calculate the size of the pv head table for superpages.
	 * Handle the possibility that "vm_phys_segs[...].end" is zero.
	 */ /*
	 * Allocate memory for the pv head table for superpages.
	 */