⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 machdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1982, 1987, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)machdep.c	8.2 (Berkeley) 1/12/94 */#include <sys/param.h>#include <sys/systm.h>#include <sys/signalvar.h>#include <sys/kernel.h>#include <sys/map.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/buf.h>#include <sys/reboot.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/clist.h>#include <sys/callout.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/msgbuf.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/sysctl.h>#include <net/netisr.h>#include <vm/vm.h>#include <vm/vm_kern.h>#include <vm/vm_page.h>vm_map_t buffer_map;extern vm_offset_t avail_end;#include <machine/cpu.h>#include <machine/reg.h>#include <machine/psl.h>#include <machine/specialreg.h>#include <i386/isa/rtc.h>#include <i386/i386/cons.h>/* * Declare these as initialized data so we can patch them. */int	nswbuf = 0;#ifdef	NBUFint	nbuf = NBUF;#elseint	nbuf = 0;#endif#ifdef	BUFPAGESint	bufpages = BUFPAGES;#elseint	bufpages = 0;#endifint	msgbufmapped;		/* set when safe to use msgbuf *//* * Machine-dependent startup code */int boothowto = 0, Maxmem = 0;long dumplo;int physmem, maxmem;extern int bootdev;#ifdef SMALLextern int forcemaxmem;#endifint biosmem;extern cyloffset;cpu_startup(firstaddr)	int firstaddr;{	register int unixsize;	register unsigned i;	register struct pte *pte;	int mapaddr, j;	register caddr_t v;	int maxbufs, base, residual;	extern long Usrptsize;	vm_offset_t minaddr, maxaddr;	vm_size_t size;	/*	 * Initialize error message buffer (at end of core).	 */	/* avail_end was pre-decremented in pmap_bootstrap to compensate */	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)		pmap_enter(kernel_pmap, msgbufp, avail_end + i * NBPG,			   VM_PROT_ALL, TRUE);	msgbufmapped = 1;#ifdef KDB	kdb_init();			/* startup kernel debugger */#endif	/*	 * Good {morning,afternoon,evening,night}.	 */	printf(version);	printf("real mem  = %d\n", ctob(physmem));	/*	 * Allocate space for system data structures.	 * The first available real memory address is in "firstaddr".	 * The first available kernel virtual address is in "v".	 * As pages of kernel virtual memory are allocated, "v" is incremented.	 * As pages of memory are allocated and cleared,	 * "firstaddr" is incremented.	 * An index into the kernel page table corresponding to the	 * virtual memory address maintained in "v" is kept in "mapaddr".	 */	/*	 * Make two passes.  The first pass calculates how much memory is	 * needed and allocates it.  The second pass assigns virtual	 * addresses to the various data structures.	 */	firstaddr = 0;again:	v = (caddr_t)firstaddr;#define	valloc(name, type, num) \	    (name) = (type *)v; v = (caddr_t)((name)+(num))#define	valloclim(name, type, num, lim) \	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))	valloc(cfree, struct cblock, nclist);	valloc(callout, struct callout, ncallout);	valloc(swapmap, struct map, nswapmap = maxproc * 2);#ifdef SYSVSHM	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);#endif	/*	 * Determine how many buffers to allocate.	 * Use 10% of memory for the first 2 Meg, 5% of the remaining	 * memory. Insure a minimum of 16 buffers.	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.	 */	if (bufpages == 0)		if (physmem < (2 * 1024 * 1024))			bufpages = physmem / 10 / CLSIZE;		else			bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;	if (nbuf == 0) {		nbuf = bufpages / 2;		if (nbuf < 16)			nbuf = 16;	}	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);	/*	 * End of first pass, size has been calculated so allocate memory	 */	if (firstaddr == 0) {		size = (vm_size_t)(v - firstaddr);		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));		if (firstaddr == 0)			panic("startup: no room for tables");		goto again;	}	/*	 * End of second pass, addresses have been assigned	 */	if ((vm_size_t)(v - firstaddr) != size)		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");	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);	/*	 * Allocate a submap for physio	 */	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,				 VM_PHYS_SIZE, TRUE);	/*	 * 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 callouts	 */	callfree = callout;	for (i = 1; i < ncallout; i++)		callout[i-1].c_next = &callout[i];	callout[i-1].c_next = NULL;	/*printf("avail mem = %d\n", ptoa(vm_page_free_count));*/	printf("using %d buffers containing %d bytes of memory\n",		nbuf, bufpages * CLBYTES);	/*	 * Set up CPU-specific registers, cache, etc.	 */	initcpu();	/*	 * Set up buffers, so they can be used to read disk labels.	 */	bufinit();	/*	 * Configure the system.	 */	configure();}#ifdef PGINPROF/* * Return the difference (in microseconds) * between the  current time and a previous * time as represented  by the arguments. * If there is a pending clock interrupt * which has not been serviced due to high * ipl, return error code. *//*ARGSUSED*/vmtime(otime, olbolt, oicr)	register int otime, olbolt, oicr;{	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);}#endifstruct sigframe {	int	sf_signum;	int	sf_code;	struct	sigcontext *sf_scp;	sig_t	sf_handler;	int	sf_eax;		int	sf_edx;		int	sf_ecx;		struct	sigcontext sf_sc;} ;extern int kstack[];/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below.  After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */voidsendsig(catcher, sig, mask, code)	sig_t catcher;	int sig, mask;	unsigned code;{	register struct proc *p = curproc;	register int *regs;	register struct sigframe *fp;	struct sigacts *psp = p->p_sigacts;	int oonstack, frmtrap;	regs = p->p_md.md_regs;        oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;	frmtrap = curpcb->pcb_flags & FM_TRAP;	/*	 * Allocate and validate space for the signal handler	 * context. Note that if the stack is in P0 space, the	 * call to grow() is a nop, and the useracc() check	 * will fail if the process has not already allocated	 * the space with a `brk'.	 */	if ((psp->ps_flags & SAS_ALTSTACK) &&	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&	    (psp->ps_sigonstack & sigmask(sig))) {		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));		psp->ps_sigstk.ss_flags |= SA_ONSTACK;	} else {		if (frmtrap)			fp = (struct sigframe *)(regs[tESP]				- sizeof(struct sigframe));		else			fp = (struct sigframe *)(regs[sESP]				- sizeof(struct sigframe));	}	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 		(void)grow(p, (unsigned)fp);	if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {		/*		 * Process has trashed its stack; give it an illegal		 * instruction to halt it in its tracks.		 */		SIGACTION(p, SIGILL) = SIG_DFL;		sig = sigmask(SIGILL);		p->p_sigignore &= ~sig;		p->p_sigcatch &= ~sig;		p->p_sigmask &= ~sig;		psignal(p, SIGILL);		return;	}	/* 	 * Build the argument list for the signal handler.	 */	fp->sf_signum = sig;	fp->sf_code = code;	fp->sf_scp = &fp->sf_sc;	fp->sf_handler = catcher;	/* save scratch registers */	if(frmtrap) {		fp->sf_eax = regs[tEAX];		fp->sf_edx = regs[tEDX];		fp->sf_ecx = regs[tECX];	} else {		fp->sf_eax = regs[sEAX];		fp->sf_edx = regs[sEDX];		fp->sf_ecx = regs[sECX];	}	/*	 * Build the signal context to be used by sigreturn.	 */	fp->sf_sc.sc_onstack = oonstack;	fp->sf_sc.sc_mask = mask;	if(frmtrap) {		fp->sf_sc.sc_sp = regs[tESP];		fp->sf_sc.sc_fp = regs[tEBP];		fp->sf_sc.sc_pc = regs[tEIP];		fp->sf_sc.sc_ps = regs[tEFLAGS];		regs[tESP] = (int)fp;		regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;	} else {		fp->sf_sc.sc_sp = regs[sESP];		fp->sf_sc.sc_fp = regs[sEBP];		fp->sf_sc.sc_pc = regs[sEIP];		fp->sf_sc.sc_ps = regs[sEFLAGS];		regs[sESP] = (int)fp;		regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;	}}/* * System call to cleanup state after a signal * has been taken.  Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper priviledges or to cause * a machine fault. */struct sigreturn_args {	struct sigcontext *sigcntxp;};sigreturn(p, uap, retval)	struct proc *p;	struct sigreturn_args *uap;	int *retval;{	register struct sigcontext *scp;	register struct sigframe *fp;	register int *regs = p->p_md.md_regs;	fp = (struct sigframe *) regs[sESP] ;	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)		return(EINVAL);	/* restore scratch registers */	regs[sEAX] = fp->sf_eax ;	regs[sEDX] = fp->sf_edx ;	regs[sECX] = fp->sf_ecx ;	scp = fp->sf_scp;	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)		return(EINVAL);#ifdef notyet	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {		return(EINVAL);	}#endif	if (scp->sc_onstack & 01)		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;	else		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;	p->p_sigmask = scp->sc_mask &~	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));	regs[sEBP] = scp->sc_fp;	regs[sESP] = scp->sc_sp;	regs[sEIP] = scp->sc_pc;	regs[sEFLAGS] = scp->sc_ps;	return(EJUSTRETURN);}int	waittime = -1;boot(arghowto)	int arghowto;{	register long dummy;		/* r12 is reserved */	register int howto;		/* r11 == how to boot */	register int devtype;		/* r10 == major of root dev */	extern char *panicstr;extern int cold;	howto = arghowto;	if ((howto&RB_NOSYNC) == 0 && waittime < 0) {		register struct buf *bp;		int iter, nbusy;		waittime = 0;		(void) splnet();		printf("syncing disks... ");		/*		 * Release inodes held by texts before update.		 */		if (panicstr == 0)			vnode_pager_umount(NULL);		sync((struct sigcontext *)0);		for (iter = 0; iter < 20; iter++) {			nbusy = 0;			for (bp = &buf[nbuf]; --bp >= buf; )				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)					nbusy++;			if (nbusy == 0)				break;			printf("%d ", nbusy);			DELAY(40000 * iter);		}		if (nbusy)			printf("giving up\n");		else			printf("done\n");		DELAY(10000);			/* wait for printf to finish */	}	splhigh();	devtype = major(rootdev);	if (howto&RB_HALT) {		printf("halting (in tight loop); hit reset\n\n");		splx(0xfffd);	/* all but keyboard XXX */		for (;;) ;	} else {		if (howto & RB_DUMP) {			dumpsys();				/*NOTREACHED*/		}	}#ifdef lint	dummy = 0; dummy = dummy;	printf("howto %d, devtype %d\n", arghowto, devtype);#endif#ifdef	notdef	pg("pausing (hit any key to reset)");#endif	reset_cpu();	for(;;) ;	/*NOTREACHED*/}int	dumpmag = 0x8fca0101;	/* magic number for savecore */int	dumpsize = 0;		/* also for savecore *//* * Doadump comes here after turning off memory management and * getting on the dump stack, either when called above, or by * the auto-restart code. */dumpsys(){	if (dumpdev == NODEV)		return;	if ((minor(dumpdev)&07) != 1)		return;	dumpsize = physmem;	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -