avail_next = *phys_start;
pmap_bootstrap(vm_offset_t load_start,	       vm_offset_t   *phys_start,	       vm_offset_t   *phys_end,	       vm_offset_t   *virt_start,	       vm_offset_t   *virt_end){	kpdt_entry_t	kpdt_virt;	sdt_entry_t	*kmap;	vm_offset_t	vaddr,			virt,			kpdt_phys,			s_text,			e_text,			kernel_pmap_size;	apr_template_t	apr_data;	pt_entry_t	*pte;	int		i;	pmap_table_t	ptable;	extern char	*kernelstart, *etext;	extern void	cmmu_go_virt(void);#ifdef DEBUG 	if ((pmap_con_dbg & (CD_BOOT | CD_NORM)) == (CD_BOOT | CD_NORM)) {		printf("pmap_bootstrap : \"load_start\" 0x%x\n", load_start);	}#endif	if (!PAGE_ALIGNED(load_start)) {		panic("pmap_bootstrap : \"load_start\" not on the m88k page boundary : 0x%x", load_start);	}	simple_lock_init(&kernel_pmap->lock);	/*	 * Allocate the kernel page table from the front of available	 * physical memory,	 * i.e. just after where the kernel image was loaded.	 */	/*	 * The calling sequence is 	 *    ...	 *  pmap_bootstrap(&kernelstart,...) 	 *  kernelstart is the first symbol in the load image.	 *  We link the kernel such that &kernelstart == 0x10000 (size of	 *							BUG ROM)	 *  The expression (&kernelstart - load_start) will end up as	 *	0, making *virt_start == *phys_start, giving a 1-to-1 map)	 */	*phys_start = round_page(*phys_start);	*virt_start = *phys_start +		      (trunc_page((unsigned)&kernelstart) - load_start);	/*	 * Initialize kernel_pmap structure	 */	kernel_pmap->ref_count = 1;	kernel_pmap->cpus_using = 0;	kernel_pmap->sdt_paddr = kmap = (sdt_entry_t *)(*phys_start);	kernel_pmap->sdt_vaddr = (sdt_entry_t *)(*virt_start);	kmapva = *virt_start;#ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		printf("kernel_pmap->sdt_paddr = %x\n",kernel_pmap->sdt_paddr);		printf("kernel_pmap->sdt_vaddr = %x\n",kernel_pmap->sdt_vaddr);	}	/* init double-linked list of pmap structure */	kernel_pmap->next = kernel_pmap;	kernel_pmap->prev = kernel_pmap;#endif	/* 	 * Reserve space for segment table entries.	 * One for the regular segment table and one for the shadow table	 * The shadow table keeps track of the virtual address of page	 * tables. This is used in virtual-to-physical address translation	 * functions. Remember, MMU cares only for physical addresses of	 * segment and page table addresses. For kernel page tables, we	 * really don't need this virtual stuff (since the kernel will	 * be mapped 1-to-1) but for user page tables, this is required.	 * Just to be consistent, we will maintain the shadow table for	 * kernel pmap also.	 */	kernel_pmap_size = 2*SDT_SIZE;#ifdef DEBUG	printf("kernel segment table from 0x%x to 0x%x\n", kernel_pmap->sdt_vaddr, 	       kernel_pmap->sdt_vaddr + kernel_pmap_size);#endif 	/* save pointers to where page table entries start in physical memory */	kpdt_phys = (*phys_start + kernel_pmap_size);	kpdt_virt = (kpdt_entry_t)(*virt_start + kernel_pmap_size);	kernel_pmap_size += MAX_KERNEL_PDT_SIZE;	*phys_start += kernel_pmap_size;	*virt_start += kernel_pmap_size;	/* init all segment and page descriptor to zero */	bzero(kernel_pmap->sdt_vaddr, kernel_pmap_size);#ifdef DEBUG	printf("kernel page table to 0x%x\n", kernel_pmap->sdt_vaddr + kernel_pmap_size);#endif #ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		printf("kpdt_phys = %x\n",kpdt_phys);		printf("kpdt_virt = %x\n",kpdt_virt);		printf("end of kpdt at (virt)0x%08x  ; (phys)0x%08x\n",		       *virt_start,*phys_start);	}#endif	/*	 * init the kpdt queue	 */	kpdt_free = kpdt_virt;	for (i = MAX_KERNEL_PDT_SIZE/PDT_SIZE; i > 0; i--) {		kpdt_virt->next = (kpdt_entry_t)((vm_offset_t)kpdt_virt + PDT_SIZE);		kpdt_virt->phys = kpdt_phys;		kpdt_virt = kpdt_virt->next;		kpdt_phys += PDT_SIZE;	}	kpdt_virt->next = KPDT_ENTRY_NULL; /* terminate the list */	/*	 * Map the kernel image into virtual space	 */	s_text = load_start;	     /* paddr of text */	e_text = load_start + ((unsigned)&etext -			       trunc_page((unsigned)&kernelstart));	/* paddr of end of text section*/	e_text = round_page(e_text);#ifdef OMRON_PMAP   #define PMAPER	pmap_map#else   #define PMAPER	pmap_map_batc#endif	/*  map the first 64k (BUG ROM) read only, cache inhibited (? XXX) */	vaddr = PMAPER(		      0,		      0,		      0x10000,		      (VM_PROT_WRITE | VM_PROT_READ)|(CACHE_INH <<16));	/*  map the kernel text read only */	vaddr = PMAPER(		      (vm_offset_t)trunc_page(((unsigned)&kernelstart)),		      s_text,		      e_text,		      (VM_PROT_WRITE | VM_PROT_READ)|(CACHE_GLOBAL<<16));  /* shouldn't it be RO? XXX*/	vaddr = PMAPER(		      vaddr,		      e_text,		      (vm_offset_t)kmap,		      (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_GLOBAL << 16));	/*	 * Map system segment & page tables - should be cache inhibited?	 * 88200 manual says that CI bit is driven on the Mbus while accessing	 * the translation tree. I don't think we need to map it CACHE_INH	 * here...	 */	if (kmapva != vaddr) {#ifdef DEBUG		if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {			printf("(pmap_bootstrap) correcting vaddr\n");		}#endif		while (vaddr < (*virt_start - kernel_pmap_size))			vaddr = round_page(vaddr + 1);	}	vaddr = PMAPER(		      vaddr,		      (vm_offset_t)kmap,		      *phys_start,		      (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_INH << 16));	if (vaddr != *virt_start) {#ifdef DEBUG		if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {			printf("1:vaddr %x *virt_start %x *phys_start %x\n", vaddr,			       *virt_start, *phys_start);		}#endif		*virt_start = vaddr;		*phys_start = round_page(*phys_start);	}#if defined(MVME187) || defined (MVME197)	/*	 *  Get ethernet buffer - need etherlen bytes physically contiguous.	 *  1 to 1 mapped as well???. There is actually a bug in the macros	 *  used by the 1x7 ethernet driver. Remove this when that is fixed.	 *  XXX -nivas	 */	if (cputyp != CPU_188) { /*  != CPU_188 */		*phys_start = vaddr;		etherlen = ETHERPAGES * NBPG;		etherbuf = (void *)vaddr;		vaddr = PMAPER(			      vaddr,			      *phys_start,			      *phys_start + etherlen,			      (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_INH << 16));		*virt_start += etherlen;		*phys_start += etherlen; 		if (vaddr != *virt_start) {#ifdef DEBUG			if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {				printf("2:vaddr %x *virt_start %x *phys_start %x\n", vaddr,				       *virt_start, *phys_start);			}#endif			*virt_start = vaddr;			*phys_start = round_page(*phys_start);		}	}#endif /* defined(MVME187) || defined (MVME197) */	*virt_start = round_page(*virt_start);	*virt_end = VM_MAX_KERNEL_ADDRESS;	/*	 * Map a few more pages for phys routines and debugger.	 */	phys_map_vaddr1 = round_page(*virt_start);	phys_map_vaddr2 = phys_map_vaddr1 + PAGE_SIZE * max_cpus;	/*	 * To make 1:1 mapping of virt:phys, throw away a few phys pages.	 * XXX what is this? nivas	 */	*phys_start += 2 * PAGE_SIZE * max_cpus;	*virt_start += 2 * PAGE_SIZE * max_cpus;	/*	 * Map all IO space 1-to-1. Ideally, I would like to not do this	 * but have va for the given IO address dynamically allocated. But	 * on the 88200, 2 of the BATCs are hardwired to map the IO space	 * 1-to-1; I decided to map the rest of the IO space 1-to-1.	 * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to	 * execute bug system calls after the MMU has been turned on.	 * OBIO should be mapped cache inhibited.	 */	ptable = pmap_table_build(0);	 /* see pmap_table.c for details */#ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		printf("pmap_bootstrap: -> pmap_table_build\n");	}#endif	for (  ; ptable->size != 0xffffffffU; ptable++)		if (ptable->size) {			/*			 * size-1, 'cause pmap_map rounds up to next pagenumber			 */			PMAPER(ptable->virt_start,			       ptable->phys_start,			       ptable->phys_start + (ptable->size - 1),			       ptable->prot|(ptable->cacheability << 16));		}		/*		 * Allocate all the submaps we need. Note that SYSMAP just allocates		 * kernel virtual address with no physical backing memory. The idea		 * is physical memory will be mapped at this va before using that va.		 * This means that if different physical pages are going to be mapped		 * at different times, we better do a tlb flush before using it -	         		 * else we will be referencing the wrong page.		 */#define	SYSMAP(c, p, v, n)	\({ \	v = (c)virt; \    	if ((p = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL) \    		pmap_expand_kmap(virt, (VM_PROT_READ|VM_PROT_WRITE)|(CACHE_GLOBAL << 16)); \	virt += ((n)*NBPG); \})	virt = *virt_start;	SYSMAP(caddr_t, vmpte , vmmap, 1);	SYSMAP(struct msgbuf *, msgbufmap ,msgbufp, btoc(MSGBUFSIZE));	vmpte->pfn = -1;	vmpte->dtype = DT_INVALID;	*virt_start = virt;	/*	 * Set translation for UPAGES at UADDR. The idea is we want to	 * have translations set up for UADDR. Later on, the ptes for	 * for this address will be set so that kstack will refer	 * to the u area. Make sure pmap knows about this virtual	 * address by doing vm_findspace on kernel_map.	 */	for (i = 0, virt = UADDR; i < UPAGES; i++, virt += PAGE_SIZE) {#ifdef DEBUG		if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {			printf("setting up mapping for Upage %d @ %x\n", i, virt);		}#endif		if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL)			pmap_expand_kmap(virt, VM_PROT_READ|VM_PROT_WRITE|(CACHE_GLOBAL << 16));	}	/*	 * Switch to using new page tables	 */	apr_data.bits = 0;	apr_data.field.st_base = atop(kernel_pmap->sdt_paddr);	apr_data.field.wt = 1;	apr_data.field.g  = 1;	apr_data.field.ci = 0;	apr_data.field.te = 1; /* Translation enable */#ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		show_apr(apr_data.bits);	}#endif 	/* Invalidate entire kernel TLB. */#ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		printf("invalidating tlb %x\n", apr_data.bits);	}#endif	for (i = 0; i < MAX_CPUS; i++)		if (cpu_sets[i]) {			/* Invalidate entire kernel TLB. */			cmmu_flush_remote_tlb(i, 1, 0, -1);#ifdef DEBUG			if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {				printf("After cmmu_flush_remote_tlb()\n");			}#endif			/* still physical */			/*			 * Set valid bit to DT_INVALID so that the very first 			 * pmap_enter() on these won't barf in 			 * pmap_remove_range().			 */			pte = pmap_pte(kernel_pmap, phys_map_vaddr1);			pte->pfn = -1;			pte->dtype = DT_INVALID;			pte = pmap_pte(kernel_pmap, phys_map_vaddr2);			pte->dtype = DT_INVALID;			pte->pfn = -1;			/* Load supervisor pointer to segment table. */			cmmu_remote_set_sapr(i, apr_data.bits);#ifdef DEBUG			if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {				printf("After cmmu_remote_set_sapr()\n");			}#endif			SETBIT_CPUSET(i, &kernel_pmap->cpus_using);		}#ifdef DEBUG	if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) {		printf("running virtual - avail_next 0x%x\n", *phys_start);	}#endif	avail_next = *phys_start;} /* pmap_bootstrap() */