valloc(timeouts, struct timeoutout, ntimeout);
valloc(timeouts, struct timeout, ntimeout);
static char *hexstr __P((int, int));static void reboot_sync __P((void));int  reboot2 __P((int, char *)); /* share with sunos_misc.c */void straytrap __P((struct trapframe));	/* called from locore.s *//* * Console initialization: called early on from main, * before vm init or startup.  Do enough configuration * to choose and initialize a console. */voidconsinit(){	cninit();#ifdef KGDB	/* XXX - Ask on console for kgdb_dev? */	zs_kgdb_init();		/* XXX */	/* Note: kgdb_connect() will just return if kgdb_dev<0 */	if (boothowto & RB_KDB)		kgdb_connect(1);#endif#ifdef DDB	/* Now that we have a console, we can stop in DDB. */	db_machine_init();	ddb_init();	if (boothowto & RB_KDB)		Debugger();#endif}/* * allocsys() - Private routine used by cpu_startup() below. * * Allocate space for system data structures.  We are given * a starting virtual address and we return a final virtual * address; along the way we set each data structure pointer. * * We call allocsys() with 0 to find out how much space we want, * allocate that much and fill it with zeroes, and then call * allocsys() again with the correct base virtual address. */#define	valloc(name, type, num) \	v = (caddr_t)(((name) = (type *)v) + (num))static caddr_tallocsys(v)	register caddr_t v;{#ifdef REAL_CLISTS	valloc(cfree, struct cblock, nclist);#endif	valloc(timeouts, struct timeoutout, ntimeout);#ifdef SYSVSHM	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);#endif#ifdef SYSVSEM	valloc(sema, struct semid_ds, seminfo.semmni);	valloc(sem, struct sem, seminfo.semmns);	/* This is pretty disgusting! */	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));#endif#ifdef SYSVMSG	valloc(msgpool, char, msginfo.msgmax);	valloc(msgmaps, struct msgmap, msginfo.msgseg);	valloc(msghdrs, struct msg, msginfo.msgtql);	valloc(msqids, struct msqid_ds, msginfo.msgmni);#endif#ifndef BUFCACHEPERCENT#define BUFCACHEPERCENT 5#endif	/*	 * Determine how many buffers to allocate. By default we allocate	 * the BSD standard of use 10% of memory for the first 2 Meg,	 * 5% of remaining.  But this might cause systems with large 	 * core (32MB) to fail to boot due to small KVM space.  Reduce	 * BUFCACHEPERCENT in this case.	 * Insure a minimum of 16 buffers.	 * Allocate 1/2 as many swap buffer headers as file i/o buffers.	 */	if (bufpages == 0) {		/* We always have more than 2MB of memory. */		bufpages = (btoc(2 * 1024 * 1024) + physmem) /			((100/BUFCACHEPERCENT) * CLSIZE);	}	if (nbuf == 0) {		nbuf = bufpages;		if (nbuf < 16)			nbuf = 16;	}	/* Restrict to at most 70% filled kvm */	if (nbuf * MAXBSIZE >	    (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) * 7 / 10)		nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /			MAXBSIZE * 7 / 10;		/* More buffer pages than fits into the buffers is senseless.  */	if (bufpages > nbuf * MAXBSIZE / CLBYTES)		bufpages = nbuf * MAXBSIZE / CLBYTES;	if (nswbuf == 0) {		nswbuf = (nbuf / 2) &~ 1;	/* force even */		if (nswbuf > 256)			nswbuf = 256;		/* sanity */	}	valloc(swbuf, struct buf, nswbuf);	valloc(buf, struct buf, nbuf);	return v;}#undef	valloc/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. * * This is called early in init_main.c:main(), after the * kernel memory allocator is ready for use, but before * the creation of processes 1,2, and mountroot, etc. */voidcpu_startup(){	caddr_t v;	int sz, i;	vm_size_t size;		int base, residual;	vm_offset_t minaddr, maxaddr;		/*	 * The msgbuf was set up earlier (in sun3_startup.c)	 * just because it was more convenient to do there.	 */		/*	 * Good {morning,afternoon,evening,night}.	 */	printf(version);	identifycpu();	initfpu();	/* also prints FPU type */	printf("real mem = %d\n", ctob(physmem));	/*	 * Find out how much space we need, allocate it,	 * and then give everything true virtual addresses.	 */	sz = (int)allocsys((caddr_t)0);	if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)		panic("startup: no room for tables");	if (allocsys(v) - v != sz)		panic("startup: table size inconsistency");	/*	 * Now allocate buffers proper.  They are different than the above	 * in that they usually occupy more virtual memory than physical.	 */	size = MAXBSIZE * nbuf;	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,				   &maxaddr, size, TRUE);	minaddr = (vm_offset_t)buffers;	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,			&minaddr, size, FALSE) != KERN_SUCCESS)		panic("startup: cannot allocate buffers");	if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {		/* don't want to alloc more physical mem than needed */		bufpages = btoc(MAXBSIZE) * nbuf;	}	base = bufpages / nbuf;	residual = bufpages % nbuf;	for (i = 0; i < nbuf; i++) {		vm_size_t curbufsize;		vm_offset_t curbuf;		/*		 * First <residual> buffers get (base+1) physical pages		 * allocated for them.  The rest get (base) physical pages.		 *		 * The rest of each buffer occupies virtual space,		 * but has no physical memory allocated for it.		 */		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;		curbufsize = CLBYTES * (i < residual ? base+1 : base);		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);		vm_map_simplify(buffer_map, curbuf);	}	/*	 * Allocate a submap for exec arguments.  This map effectively	 * limits the number of processes exec'ing at any time.	 */	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,				 16*NCARGS, TRUE);	/*	 * We don't use a submap for physio, and use a separate map	 * for DVMA allocations.  Our vmapbuf just maps pages into	 * the kernel map (any kernel mapping is OK) and then the	 * device drivers clone the kernel mappings into DVMA space.	 */	/*	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size	 * we use the more space efficient malloc in place of kmem_alloc.	 */	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,				   M_MBUF, M_NOWAIT);	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,			       VM_MBUF_SIZE, FALSE);	/*	 * Initialize timeouts	 */	timeout_init();	printf("avail mem = %ld\n", ptoa(cnt.v_free_count));	printf("using %d buffers containing %d bytes of memory\n",		   nbuf, bufpages * CLBYTES);	/*	 * Allocate a virtual page (for use by /dev/mem)	 * This page is handed to pmap_enter() therefore	 * it has to be in the normal kernel VA range.	 */	vmmap = kmem_alloc_wait(kernel_map, NBPG);	/*	 * Create the DVMA maps.	 */	dvma_init();	/*	 * Set up CPU-specific registers, cache, etc.	 */	initcpu();	/*	 * Set up buffers, so they can be used to read disk labels.	 */	bufinit();	/*	 * Configure the system.	 */	if (boothowto & RB_CONFIG) {#ifdef BOOT_CONFIG		user_config();#else		printf("kernel does not support -c; continuing..\n");#endif	}	configure();}/* * Set registers on exec. */voidsetregs(p, pack, stack, retval)	register struct proc *p;	struct exec_package *pack;	u_long stack;	register_t *retval;{	struct frame *frame = (struct frame *)p->p_md.md_regs;	frame->f_sr = PSL_USERSET;	frame->f_pc = pack->ep_entry & ~1;	frame->f_regs[D0] = 0;	frame->f_regs[D1] = 0;	frame->f_regs[D2] = 0;	frame->f_regs[D3] = 0;	frame->f_regs[D4] = 0;	frame->f_regs[D5] = 0;	frame->f_regs[D6] = 0;	frame->f_regs[D7] = 0;	frame->f_regs[A0] = 0;	frame->f_regs[A1] = 0;	frame->f_regs[A2] = (int)PS_STRINGS;	frame->f_regs[A3] = 0;	frame->f_regs[A4] = 0;	frame->f_regs[A5] = 0;	frame->f_regs[A6] = 0;	frame->f_regs[SP] = stack;	/* restore a null state frame */	p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;	if (fputype) {		m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);	}	/* XXX - HPUX sigcode hack would go here... */}/* * Info for CTL_HW */char	machine[] = "sun3";		/* cpu "architecture" */char	cpu_model[120];extern	long hostid;static voididentifycpu(){    /*     * actual identification done earlier because i felt like it,     * and i believe i will need the info to deal with some VAC, and awful     * framebuffer placement problems.  could be moved later.     */	strcpy(cpu_model, "Sun 3/");    /* should eventually include whether it has a VAC, mc6888x version, etc */	strcat(cpu_model, cpu_string);	printf("Model: %s (hostid %lx)\n", cpu_model, hostid);}/* * machine dependent system variables. */intcpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)	int *name;	u_int namelen;	void *oldp;	size_t *oldlenp;	void *newp;	size_t newlen;	struct proc *p;{	dev_t consdev;	/* all sysctl names at this level are terminal */	if (namelen != 1)		return (ENOTDIR);		/* overloaded */	switch (name[0]) {	case CPU_CONSDEV:		if (cn_tab != NULL)			consdev = cn_tab->cn_dev;		else			consdev = NODEV;		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,		    sizeof consdev));	default:		return (EOPNOTSUPP);	}	/* NOTREACHED */}#define SS_RTEFRAME	1#define SS_FPSTATE	2#define SS_USERREGS	4struct sigstate {	int	ss_flags;		/* which of the following are valid */	struct	frame ss_frame;		/* original exception frame */	struct	fpframe ss_fpstate;	/* 68881/68882 state info */};/* * WARNING: code in locore.s assumes the layout shown for sf_signum * thru sf_handler so... don't screw with them! */struct sigframe {	int	sf_signum;		/* signo for handler */	siginfo_t *sf_sip;		/* values for SA_SIGINFO */	struct	sigcontext *sf_scp;	/* context ptr for handler */	sig_t	sf_handler;		/* handler addr for u_sigc */	struct	sigstate sf_state;	/* state of the hardware */	struct	sigcontext sf_sc;	/* actual context */	siginfo_t sf_si;};#ifdef DEBUGint sigdebug = 0;int sigpid = 0;#define SDB_FOLLOW	0x01#define SDB_KSTACK	0x02#define SDB_FPSTATE	0x04#endif/* * Do a sync in preparation for a reboot. * XXX - This could probably be common code. * XXX - And now, most of it is in vfs_shutdown() * XXX - Put waittime checks in there too? */int waittime = -1;	/* XXX - Who else looks at this? -gwr */static voidreboot_sync(){	extern struct proc proc0;	/* Check waittime here to localize its use to this function. */	if (waittime >= 0)		return;	/* fix curproc */	if (curproc == NULL)		curproc = &proc0;	waittime = 0;	vfs_shutdown();}/* * Common part of the BSD and SunOS reboot system calls. */intreboot2(howto, user_boot_string)	int howto;	char *user_boot_string;{	char *bs, *p;	char default_boot_string[8];	/* If system is cold, just halt. (early panic?) */	if (cold)		goto haltsys;	if ((howto & RB_NOSYNC) == 0) {		reboot_sync();		/*		 * If we've been adjusting the clock, the todr		 * will be out of synch; adjust it now unless		 * the system was sitting in ddb.		 */		if ((howto & RB_TIMEBAD) == 0) {			resettodr();		} else {			printf("WARNING: not updating battery clock\n");		}	}	/* Disable interrupts. */	splhigh();	/* Write out a crash dump if asked. */	if (howto & RB_DUMP)		dumpsys();	/* run any shutdown hooks */	doshutdownhooks();	if (howto & RB_HALT) {	haltsys:		printf("Kernel halted.\n");		sun3_mon_halt();	}	/*	 * Automatic reboot.	 */	bs = user_boot_string;	if (bs == NULL) {		/*		 * Build our own boot string with an empty		 * boot device/file and (maybe) some flags.		 * The PROM will supply the device/file name.		 */		bs = default_boot_string;		*bs = '\0';		if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) {			/* Append the boot flags. */			p = bs;			*p++ = ' ';			*p++ = '-';			if (howto & RB_KDB)				*p++ = 'd';			if (howto & RB_ASKNAME)				*p++ = 'a';			if (howto & RB_SINGLE)				*p++ = 's';			*p = '\0';		}	}	printf("Kernel rebooting...\n");	sun3_mon_reboot(bs);	for (;;) ;	/*NOTREACHED*/}/* * BSD reboot system call * XXX - Should be named: cpu_reboot maybe? -gwr * XXX - It would be nice to allow a second argument * that specifies a machine-dependent boot string that * is passed to the boot program if RB_STRING is set. */voidboot(howto)	int howto;{	(void) reboot2(howto, NULL);	for(;;);	/* NOTREACHED */}/* * These variables are needed by /sbin/savecore */u_long	dumpmag = 0x8fca0101;	/* magic number */int 	dumpsize = 0;		/* pages */long	dumplo = 0; 		/* blocks *//* Our private scratch page for dumping the MMU. */vm_offset_t dumppage_va;vm_offset_t dumppage_pa;#define		DUMP_EXTRA	3	/* CPU-dependent extra pages *//* * This is called by cpu_startup to set dumplo, dumpsize. * Dumps always skip the first CLBYTES of disk space * in case there might be a disk label stored there. * If there is extra space, put dump at the end to * reduce the chance that swapping trashes it. */voiddumpconf(){	int nblks;	/* size of dump area */	int maj;	int (*getsize) __P((dev_t));	if (dumpdev == NODEV)		return;	maj = major(dumpdev);	if (maj < 0 || maj >= nblkdev)		panic("dumpconf: bad dumpdev=0x%x", dumpdev);	getsize = bdevsw[maj].d_psize;	if (getsize == NULL)		return;	nblks = (*getsize)(dumpdev);	if (nblks <= ctod(1))		return;	/* Position dump image near end of space, page aligned. */	dumpsize = physmem + DUMP_EXTRA; /* pages */	dumplo = nblks - ctod(dumpsize);	dumplo &= ~(ctod(1)-1);	/* If it does not fit, truncate it by moving dumplo. */	/* Note: Must force signed comparison (fixes PR#887) */	if (dumplo < ((long)ctod(1))) {		dumplo = ctod(1);		dumpsize = dtoc(nblks - dumplo);	}}struct pcb dumppcb;extern vm_offset_t avail_start;/* * Write a crash dump.  The format while in swap is: *   kcore_seg_t cpu_hdr; *   cpu_kcore_hdr_t cpu_data; *   padding (NBPG-sizeof(kcore_seg_t)) *   pagemap (2*NBPG) *   physical memory... */voiddumpsys(){	struct bdevsw *dsw;	kcore_seg_t	*kseg_p;	cpu_kcore_hdr_t	*chdr_p;	char *vaddr;	vm_offset_t paddr;	int psize, todo, chunk;	daddr_t blkno;	int error = 0;	if (dumpdev == NODEV)		return;	if (dumppage_va == 0)		return;	/* 	 * For dumps during autoconfiguration,	 * if dump device has already configured...	 */	if (dumpsize == 0)		dumpconf();	if (dumplo <= 0)		return;	savectx(&dumppcb);	dsw = &bdevsw[major(dumpdev)];	psize = (*(dsw->d_psize))(dumpdev);	if (psize == -1) {		printf("dump area unavailable\n");		return;	}	printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);	/*	 * Write the dump header, including MMU state.	 */	blkno = dumplo;	todo = dumpsize - DUMP_EXTRA;	/* pages */	vaddr = (char *)dumppage_va;	bzero(vaddr, NBPG);	/* kcore header */	kseg_p = (kcore_seg_t *)vaddr;	CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);	kseg_p->c_size = (ctob(DUMP_EXTRA) - sizeof(kcore_seg_t));	/* MMU state */	chdr_p = (cpu_kcore_hdr_t *) (kseg_p + 1);	pmap_get_ksegmap(chdr_p->ksegmap);	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);	if (error)		goto fail;	blkno += btodb(NBPG);	/* translation RAM (page zero) */	pmap_get_pagemap((int *)vaddr, 0);	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);	if (error)		goto fail;	blkno += btodb(NBPG);	/* translation RAM (page one) */	pmap_get_pagemap((int *)vaddr, NBPG);	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);	if (error)		goto fail;	blkno += btodb(NBPG);	/*	 * Now dump physical memory.  Have to do it in two chunks.	 * The first chunk is "unmanaged" (by the VM code) and its	 * range of physical addresses is not allow in pmap_enter.	 * However, that segment is mapped linearly, so we can just	 * use the virtual mappings already in place.  The second	 * chunk is done the normal way, using pmap_enter.	 *	 * Note that vaddr==(paddr+KERNBASE) for paddr=0 through etext.	 */	/* Do the first chunk (0 <= PA < avail_start) */	paddr = 0;	chunk = btoc(avail_start);	if (chunk > todo)		chunk = todo;	do {		if ((todo & 0xf) == 0)			printf("\r%4d", todo);		vaddr = (char*)(paddr + KERNBASE);		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);		if (error)			goto fail;		paddr += NBPG;		blkno += btodb(NBPG);		--todo;	} while (--chunk > 0);	/* Do the second chunk (avail_start <= PA < dumpsize) */	vaddr = (char*)vmmap;	/* Borrow /dev/mem VA */	do {		if ((todo & 0xf) == 0)			printf("\r%4d", todo);		pmap_enter(pmap_kernel(), vmmap, paddr | PMAP_NC,			VM_PROT_READ, FALSE, VM_PROT_READ);		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);		pmap_remove(pmap_kernel(), vmmap, vmmap + NBPG);		if (error)			goto fail;		paddr += NBPG;		blkno += btodb(NBPG);	} while (--todo > 0);	printf("\rdump succeeded\n");	return;fail:	printf(" dump error=%d\n", error);}voidinitcpu(){	/* XXX: Enable RAM parity/ECC checking? */	/* XXX: parityenable(); */	nofault = NULL;	/* XXX - needed? */#ifdef	HAVECACHE	cache_enable();#endif}voidstraytrap(frame)	struct trapframe frame;{	printf("unexpected trap; vector offset 0x%x from 0x%x\n",		frame.tf_vector, frame.tf_pc);#ifdef	DDB	kdb_trap(-1, (db_regs_t *) &frame);#endif}/* XXX: parityenable() ? *//* * Print a register and stack dump. */voidregdump(fp, sbytes)	struct frame *fp; /* must not be register */	int sbytes;{	static int doingdump = 0;	register int i;	int s;	if (doingdump)		return;	s = splhigh();	doingdump = 1;	printf("pid = %d, pc = %s, ",	       curproc ? curproc->p_pid : -1, hexstr(fp->f_pc, 8));	printf("ps = %s, ", hexstr(fp->f_sr, 4));	printf("sfc = %s, ", hexstr(getsfc(), 4));	printf("dfc = %s\n", hexstr(getdfc(), 4));	printf("Registers:\n     ");	for (i = 0; i < 8; i++)		printf("        %d", i);	printf("\ndreg:");	for (i = 0; i < 8; i++)		printf(" %s", hexstr(fp->f_regs[i], 8));	printf("\nareg:");	for (i = 0; i < 8; i++)		printf(" %s", hexstr(fp->f_regs[i+8], 8));	if (sbytes > 0) {		if (fp->f_sr & PSL_S) {			printf("\n\nKernel stack (%s):",			       hexstr((int)(((int *)&fp)-1), 8));			dumpmem(((int *)&fp)-1, sbytes, 0);		} else {			printf("\n\nUser stack (%s):", hexstr(fp->f_regs[SP], 8));			dumpmem((int *)fp->f_regs[SP], sbytes, 1);		}	}	doingdump = 0;	splx(s);}#define KSADDR	((int *)((u_int)curproc->p_addr + USPACE - NBPG))static voiddumpmem(ptr, sz, ustack)	register int *ptr;	int sz, ustack;{	register int i, val;	for (i = 0; i < sz; i++) {		if ((i & 7) == 0)			printf("\n%s: ", hexstr((int)ptr, 6));		else			printf(" ");		if (ustack == 1) {			if ((val = fuword(ptr++)) == -1)				break;		} else {			if (ustack == 0 &&			    (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1)))				break;			val = *ptr++;		}		printf("%s", hexstr(val, 8));	}	printf("\n");}char *hexstr(val, len)	register int val;	int len;{	static char nbuf[9];	register int x, i;	if (len > 8)		return("");	nbuf[len] = '\0';	for (i = len-1; i >= 0; --i) {		x = val & 0xF;		/* Isn't this a cool trick? */		nbuf[i] = "0123456789ABCDEF"[x];		val >>= 4;	}	return(nbuf);}