FreeBSD/sys/arm64/arm64/pmap.c
/*
 *	Bootstrap the system enough to run with virtual memory.
 */
Bootstrap the system enough to run with virtual memory.
Bootstrap the system enough to run with virtual memory .
void
pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_paddr_t kernstart,
    vm_size_t kernlen)
{
	u_int l1_slot, l2_slot, avail_slot, map_slot, used_map_slot;
	uint64_t kern_delta;
	pt_entry_t *l2;
	vm_offset_t va, freemempos;
	vm_offset_t dpcpu, msgbufpv;
	vm_paddr_t pa, max_pa, min_pa;
	int i;
	kern_delta = KERNBASE - kernstart;
	physmem = 0;
	printf("pmap_bootstrap %lx %lx %lx\n", l1pt, kernstart, kernlen);
	printf("%lx\n", l1pt);
	printf("%lx\n", (KERNBASE >> L1_SHIFT) & Ln_ADDR_MASK);
	kernel_pmap_store.pm_l0 = (pd_entry_t *)l0pt;
	PMAP_LOCK_INIT(kernel_pmap);
	rw_init(&pvh_global_lock, "pmap pv global");
	min_pa = max_pa = KERNBASE - kern_delta;
	for (i = 0; i < (physmap_idx * 2); i += 2) {
		if (physmap[i] == physmap[i + 1])
			continue;
		if (physmap[i] <= min_pa)
			min_pa = physmap[i];
		if (physmap[i + 1] > max_pa)
			max_pa = physmap[i + 1];
	}
	pmap_bootstrap_dmap(l1pt, min_pa, max_pa);
	va = KERNBASE;
	pa = KERNBASE - kern_delta;
	map_slot = avail_slot = 0;
	for (; map_slot < (physmap_idx * 2) &&
	    avail_slot < (PHYS_AVAIL_SIZE - 2); map_slot += 2) {
		if (physmap[map_slot] == physmap[map_slot + 1])
			continue;
		if (physmap[map_slot] <= pa &&
		    physmap[map_slot + 1] > pa)
			break;
		phys_avail[avail_slot] = physmap[map_slot];
		phys_avail[avail_slot + 1] = physmap[map_slot + 1];
		physmem += (phys_avail[avail_slot + 1] -
		    phys_avail[avail_slot]) >> PAGE_SHIFT;
		avail_slot += 2;
	}
	if (physmap[avail_slot] < pa && avail_slot < (PHYS_AVAIL_SIZE - 2)) {
		phys_avail[avail_slot] = physmap[map_slot];
		phys_avail[avail_slot + 1] = pa;
		physmem += (phys_avail[avail_slot + 1] -
		    phys_avail[avail_slot]) >> PAGE_SHIFT;
		avail_slot += 2;
	}
	used_map_slot = map_slot;
	l2 = pmap_early_page_idx(l1pt, KERNBASE, &l1_slot, &l2_slot);
	KASSERT(l2_slot == 0, ("The L2 index is non-zero"));
	for (; l2_slot < Ln_ENTRIES; l2_slot++) {
		if ((l2[l2_slot] & ATTR_DESCR_MASK) == 0)
			break;
		KASSERT((l2[l2_slot] & ATTR_DESCR_MASK) == L2_BLOCK,
		    ("Invalid bootstrap L2 table"));
		KASSERT((l2[l2_slot] & ~ATTR_MASK) == pa,
		    ("Incorrect PA in L2 table"));
		va += L2_SIZE;
		pa += L2_SIZE;
	}
	va = roundup2(va, L1_SIZE);
	freemempos = KERNBASE + kernlen;
	freemempos = roundup2(freemempos, PAGE_SIZE);
	freemempos = pmap_bootstrap_l2(l1pt, va, freemempos);
	freemempos = pmap_bootstrap_l3(l1pt,
	    VM_MAX_KERNEL_ADDRESS - L2_SIZE, freemempos);
	cpu_tlb_flushID();
#define alloc_pages(var, np)						\
	(var) = freemempos;						\
	freemempos += (np * PAGE_SIZE);					\
	memset((char *)(var), 0, ((np) * PAGE_SIZE));
	alloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
	dpcpu_init((void *)dpcpu, 0);
	alloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
	msgbufp = (void *)msgbufpv;
	virtual_avail = roundup2(freemempos, L1_SIZE);
	virtual_end = VM_MAX_KERNEL_ADDRESS - L2_SIZE;
	kernel_vm_end = virtual_avail;
	pa = pmap_early_vtophys(l1pt, freemempos);
	map_slot = used_map_slot;
	for (; avail_slot < (PHYS_AVAIL_SIZE - 2) &&
	    map_slot < (physmap_idx * 2); map_slot += 2) {
		if (physmap[map_slot] == physmap[map_slot + 1])
			continue;
		if (physmap[map_slot + 1] <= pa)
			continue;
		if (physmap[map_slot] < pa) {
			phys_avail[avail_slot] = pa;
			phys_avail[avail_slot + 1] = physmap[map_slot + 1];
		} else {
			phys_avail[avail_slot] = physmap[map_slot];
			phys_avail[avail_slot + 1] = physmap[map_slot + 1];
		}
		physmem += (phys_avail[avail_slot + 1] -
		    phys_avail[avail_slot]) >> PAGE_SHIFT;
		avail_slot += 2;
	}
	phys_avail[avail_slot] = 0;
	phys_avail[avail_slot + 1] = 0;
	Maxmem = atop(phys_avail[avail_slot - 1]);
	cpu_tlb_flushID();
}
void pmap_bootstrap ( vm_offset_t l0pt , vm_offset_t l1pt , vm_paddr_t kernstart , vm_size_t kernlen ) { u_int l1_slot , l2_slot , avail_slot , map_slot , used_map_slot ; uint64_t kern_delta ; pt_entry_t * l2 ; vm_offset_t va , freemempos ; vm_offset_t dpcpu , msgbufpv ; vm_paddr_t pa , max_pa , min_pa ; int i ; kern_delta = KERNBASE - kernstart ; physmem = 0 ; printf ( " \n " , l1pt , kernstart , kernlen ) ; printf ( " \n " , l1pt ) ; printf ( " \n " , ( KERNBASE >> L1_SHIFT ) & Ln_ADDR_MASK ) ; kernel_pmap_store . pm_l0 = ( pd_entry_t * ) l0pt ; PMAP_LOCK_INIT ( kernel_pmap ) ; rw_init ( & pvh_global_lock , " " ) ; min_pa = max_pa = KERNBASE - kern_delta ; for ( i = 0 ; i < ( physmap_idx * 2 ) ; i += 2 ) { if ( physmap [ i ] == physmap [ i + 1 ] ) continue ; if ( physmap [ i ] <= min_pa ) min_pa = physmap [ i ] ; if ( physmap [ i + 1 ] > max_pa ) max_pa = physmap [ i + 1 ] ; } pmap_bootstrap_dmap ( l1pt , min_pa , max_pa ) ; va = KERNBASE ; pa = KERNBASE - kern_delta ; map_slot = avail_slot = 0 ; for ( ; map_slot < ( physmap_idx * 2 ) && avail_slot < ( PHYS_AVAIL_SIZE - 2 ) ; map_slot += 2 ) { if ( physmap [ map_slot ] == physmap [ map_slot + 1 ] ) continue ; if ( physmap [ map_slot ] <= pa && physmap [ map_slot + 1 ] > pa ) break ; phys_avail [ avail_slot ] = physmap [ map_slot ] ; phys_avail [ avail_slot + 1 ] = physmap [ map_slot + 1 ] ; physmem += ( phys_avail [ avail_slot + 1 ] - phys_avail [ avail_slot ] ) >> PAGE_SHIFT ; avail_slot += 2 ; } if ( physmap [ avail_slot ] < pa && avail_slot < ( PHYS_AVAIL_SIZE - 2 ) ) { phys_avail [ avail_slot ] = physmap [ map_slot ] ; phys_avail [ avail_slot + 1 ] = pa ; physmem += ( phys_avail [ avail_slot + 1 ] - phys_avail [ avail_slot ] ) >> PAGE_SHIFT ; avail_slot += 2 ; } used_map_slot = map_slot ; l2 = pmap_early_page_idx ( l1pt , KERNBASE , & l1_slot , & l2_slot ) ; KASSERT ( l2_slot == 0 , ( " " ) ) ; for ( ; l2_slot < Ln_ENTRIES ; l2_slot ++ ) { if ( ( l2 [ l2_slot ] & ATTR_DESCR_MASK ) == 0 ) break ; KASSERT ( ( l2 [ l2_slot ] & ATTR_DESCR_MASK ) == L2_BLOCK , ( " " ) ) ; KASSERT ( ( l2 [ l2_slot ] & ~ ATTR_MASK ) == pa , ( " " ) ) ; va += L2_SIZE ; pa += L2_SIZE ; } va = roundup2 ( va , L1_SIZE ) ; freemempos = KERNBASE + kernlen ; freemempos = roundup2 ( freemempos , PAGE_SIZE ) ; freemempos = pmap_bootstrap_l2 ( l1pt , va , freemempos ) ; freemempos = pmap_bootstrap_l3 ( l1pt , VM_MAX_KERNEL_ADDRESS - L2_SIZE , freemempos ) ; cpu_tlb_flushID ( ) ; #define alloc_pages ( var , np ) 						\
	(var) = freemempos;						\
	freemempos += (np * PAGE_SIZE);					\
	memset((char *)(var), 0, ((np) * PAGE_SIZE)); alloc_pages ( dpcpu , DPCPU_SIZE / PAGE_SIZE ) ; dpcpu_init ( ( void * ) dpcpu , 0 ) ; alloc_pages ( msgbufpv , round_page ( msgbufsize ) / PAGE_SIZE ) ; msgbufp = ( void * ) msgbufpv ; virtual_avail = roundup2 ( freemempos , L1_SIZE ) ; virtual_end = VM_MAX_KERNEL_ADDRESS - L2_SIZE ; kernel_vm_end = virtual_avail ; pa = pmap_early_vtophys ( l1pt , freemempos ) ; map_slot = used_map_slot ; for ( ; avail_slot < ( PHYS_AVAIL_SIZE - 2 ) && map_slot < ( physmap_idx * 2 ) ; map_slot += 2 ) { if ( physmap [ map_slot ] == physmap [ map_slot + 1 ] ) continue ; if ( physmap [ map_slot + 1 ] <= pa ) continue ; if ( physmap [ map_slot ] < pa ) { phys_avail [ avail_slot ] = pa ; phys_avail [ avail_slot + 1 ] = physmap [ map_slot + 1 ] ; } else { phys_avail [ avail_slot ] = physmap [ map_slot ] ; phys_avail [ avail_slot + 1 ] = physmap [ map_slot + 1 ] ; } physmem += ( phys_avail [ avail_slot + 1 ] - phys_avail [ avail_slot ] ) >> PAGE_SHIFT ; avail_slot += 2 ; } phys_avail [ avail_slot ] = 0 ; phys_avail [ avail_slot + 1 ] = 0 ; Maxmem = atop ( phys_avail [ avail_slot - 1 ] ) ; cpu_tlb_flushID ( ) ; }
Bootstrap the system enough to run with virtual memory.
Bootstrap the system enough to run with virtual memory .
/* Set this early so we can use the pagetable walking functions */ /*
	 * Initialize the global pv list lock.
	 */ /* Assume the address we were loaded to is a valid physical address */ /*
	 * Find the minimum physical address. physmap is sorted,
	 * but may contain empty ranges.
	 */ /* Create a direct map region early so we can use it for pa -> va */ /*
	 * Start to initialise phys_avail by copying from physmap
	 * up to the physical address KERNBASE points at.
	 */ /* Add the memory before the kernel */ /*
	 * Read the page table to find out what is already mapped.
	 * This assumes we have mapped a block of memory from KERNBASE
	 * using a single L1 entry.
	 */ /* Sanity check the index, KERNBASE should be the first VA */ /* Find how many pages we have mapped */ /* Check locore used L2 blocks */ /* Create the l2 tables up to VM_MAX_KERNEL_ADDRESS */ /* And the l3 tables for the early devmap */ /* Allocate dynamic per-cpu area. */ /* Allocate memory for the msgbuf, e.g. for /sbin/dmesg */ /* Finish initialising physmap */ /* Have we used the current range? */ /* Do we need to split the entry? */ /*
	 * Maxmem isn't the "maximum memory", it's one larger than the
	 * highest page of the physical address space.  It should be
	 * called something like "Maxphyspage".
	 */