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

📄 machdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1982, 1986, 1990, 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * 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. * * from: Utah $Hdr: machdep.c 1.63 91/04/24$ * from: hp300/hp300/machdep.c	8.3 (Berkeley) 11/14/93 * *	@(#)machdep.c	8.3 (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/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/mount.h>#include <sys/user.h>#include <sys/exec.h>#include <sys/sysctl.h>#ifdef SYSVSHM#include <sys/shm.h>#endif#include <machine/cpu.h>#include <machine/reg.h>#include <machine/psl.h>#include <luna68k/luna68k/cons.h>#include <luna68k/luna68k/pte.h>#include <net/netisr.h>#define	MAXMEM	64*1024*CLSIZE	/* XXX - from cmap.h */#include <vm/vm_kern.h>/* the following is used externally (sysctl_hw) */char machine[] = "luna68k";		/* cpu "architecture" */vm_map_t buffer_map;extern vm_offset_t avail_end;/* * 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 */int	maxmem;			/* max memory per process */int	physmem = MAXMEM;	/* max supported memory, changes to actual *//* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. */int	safepri = PSL_LOWIPL;extern	u_int lowram;extern	short exframesize[];#ifdef FPCOPROCint	fpptype = -1;#endif/* * Console initialization: called early on from main, * before vm init or startup.  Do enough configuration * to choose and initialize a console. */consinit(){	/*	 * Set cpuspeed immediately since cninit() called routines	 * might use delay.	 */	cpuspeed = MHZ_25;	/*         * Find what hardware is attached to this machine.         */	find_devs();	/*	 * Initialize the console before we print anything out.	 */	cninit();}/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */cpu_startup(){	register unsigned i;	register caddr_t v, firstaddr;	int base, residual;	vm_offset_t minaddr, maxaddr;	vm_size_t size;#ifdef DEBUG	extern int pmapdebug;	int opmapdebug = pmapdebug;	pmapdebug = 0;#endif	/*	 * Initialize error message buffer (at end of core).	 */	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)		pmap_enter(kernel_pmap, (vm_offset_t)msgbufp,		    avail_end + i * NBPG, VM_PROT_ALL, TRUE);	msgbufmapped = 1;	/*	 * Good {morning,afternoon,evening,night}.	 */	printf(version);	identifyfpu();	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.	 * Since HPs tend to be long on memory and short on disk speed,	 * we allocate more buffer space than the BSD standard of	 * use 10% of memory for the first 2 Meg, 5% of remaining.	 * We just allocate a flat 10%.  Insure a minimum of 16 buffers.	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.	 */	if (bufpages == 0)		bufpages = physmem / 10 / CLSIZE;	if (nbuf == 0) {		nbuf = bufpages;		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 = (caddr_t) 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;#ifdef DEBUG	pmapdebug = opmapdebug;#endif	printf("avail mem = %d\n", ptoa(cnt.v_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();}/* * Set registers on exec. * XXX Should clear registers except sp, pc, * but would break init; should be fixed soon. */setregs(p, entry, retval)	register struct proc *p;	u_long entry;	int retval[2];{	struct frame *frame = (struct frame *)p->p_md.md_regs;	frame->f_pc = entry & ~1;#ifdef FPCOPROC	/* restore a null state frame */	p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;	m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);#endif}/* * Info for CTL_HW */extern	char machine[];char	cpu_model[120];extern	char ostype[], osrelease[], version[];identifyfpu(){#ifdef LUNA2	if (machineid == LUNA_II) {		sprintf(cpu_model, "LUNA-II (25MHz MC68040 CPU+MMU+FPU)");		printf("%s\n", cpu_model);		return;	}#endif	if ( fpptype == -1 ) {		printf("unknow FPU type \n");		panic("startup");	}	sprintf(cpu_model, "LUNA-I (20MHz MC68030 CPU+MMU, 20MHz MC6888%d FPU)", fpptype);	printf("%s\n", cpu_model);/*	printf("LUNA(20Mhz MC68030 CPU, 20Mhz MC6888%d FPU)\n",fpptype); */}#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 */	int	sf_code;		/* additional info for handler */	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 */};#ifdef DEBUGint sigdebug = 0;int sigpid = 0;#define SDB_FOLLOW	0x01#define SDB_KSTACK	0x02#define SDB_FPSTATE	0x04#endif/* * Send an interrupt to process. */voidsendsig(catcher, sig, mask, code)	sig_t catcher;	int sig, mask;	unsigned code;{	register struct proc *p = curproc;	register struct sigframe *fp, *kfp;	register struct frame *frame;	register struct sigacts *psp = p->p_sigacts;	register short ft;	int oonstack, fsize;	extern char sigcode[], esigcode[];	frame = (struct frame *)p->p_md.md_regs;	ft = frame->f_format;	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;	/*	 * 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'.	 */	fsize = sizeof(struct sigframe);	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 - fsize);		psp->ps_sigstk.ss_flags |= SA_ONSTACK;	} else		fp = (struct sigframe *)(frame->f_regs[SP] - fsize);	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 		(void)grow(p, (unsigned)fp);#ifdef DEBUG	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)		printf("sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n",		       p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft);#endif	if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {#ifdef DEBUG		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)			printf("sendsig(%d): useracc failed on sig %d\n",			       p->p_pid, sig);#endif		/*		 * 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;	}	kfp = (struct sigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK);	/* 	 * Build the argument list for the signal handler.	 */	kfp->sf_signum = sig;	kfp->sf_code = code;	kfp->sf_scp = &fp->sf_sc;	kfp->sf_handler = catcher;	/*	 * Save necessary hardware state.  Currently this includes:	 *	- general registers	 *	- original exception frame (if not a "normal" frame)	 *	- FP coprocessor state	 */	kfp->sf_state.ss_flags = SS_USERREGS;	bcopy((caddr_t)frame->f_regs,	      (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs);	if (ft >= FMT7) {#ifdef DEBUG		if (ft > 15 || exframesize[ft] < 0)			panic("sendsig: bogus frame type");#endif		kfp->sf_state.ss_flags |= SS_RTEFRAME;		kfp->sf_state.ss_frame.f_format = frame->f_format;		kfp->sf_state.ss_frame.f_vector = frame->f_vector;		bcopy((caddr_t)&frame->F_u,		      (caddr_t)&kfp->sf_state.ss_frame.F_u, exframesize[ft]);		/*		 * Leave an indicator that we need to clean up the kernel		 * stack.  We do this by setting the "pad word" above the		 * hardware stack frame to the amount the stack must be		 * adjusted by.		 *		 * N.B. we increment rather than just set f_stackadj in		 * case we are called from syscall when processing a		 * sigreturn.  In that case, f_stackadj may be non-zero.		 */		frame->f_stackadj += exframesize[ft];		frame->f_format = frame->f_vector = 0;#ifdef DEBUG		if (sigdebug & SDB_FOLLOW)			printf("sendsig(%d): copy out %d of frame %d\n",			       p->p_pid, exframesize[ft], ft);#endif	}#ifdef FPCOPROC	kfp->sf_state.ss_flags |= SS_FPSTATE;	m68881_save(&kfp->sf_state.ss_fpstate);#ifdef DEBUG	if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate)		printf("sendsig(%d): copy out FP state (%x) to %x\n",		       p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate,		       &kfp->sf_state.ss_fpstate);#endif#endif	/*	 * Build the signal context to be used by sigreturn.	 */	kfp->sf_sc.sc_onstack = oonstack;	kfp->sf_sc.sc_mask = mask;	kfp->sf_sc.sc_sp = frame->f_regs[SP];	kfp->sf_sc.sc_fp = frame->f_regs[A6];	kfp->sf_sc.sc_ap = (int)&fp->sf_state;	kfp->sf_sc.sc_pc = frame->f_pc;	kfp->sf_sc.sc_ps = frame->f_sr;	(void) copyout((caddr_t)kfp, (caddr_t)fp, fsize);	frame->f_regs[SP] = (int)fp;#ifdef DEBUG	if (sigdebug & SDB_FOLLOW)		printf("sendsig(%d): sig %d scp %x fp %x sc_sp %x sc_ap %x\n",		       p->p_pid, sig, kfp->sf_scp, fp,		       kfp->sf_sc.sc_sp, kfp->sf_sc.sc_ap);#endif	/*	 * Signal trampoline code is at base of user stack.	 */	frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode);#ifdef DEBUG	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)		printf("sendsig(%d): sig %d returns\n",		       p->p_pid, sig);#endif	free((caddr_t)kfp, M_TEMP);}/* * 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;};/* ARGSUSED */sigreturn(p, uap, retval)	struct proc *p;	struct sigreturn_args *uap;	int *retval;{	register struct sigcontext *scp;	register struct frame *frame;	register int rf;	struct sigcontext tsigc;	struct sigstate tstate;	int flags;	scp = uap->sigcntxp;#ifdef DEBUG	if (sigdebug & SDB_FOLLOW)		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);#endif	if ((int)scp & 1)		return (EINVAL);	/*	 * Test and fetch the context structure.	 * We grab it all at once for speed.	 */	if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||	    copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))		return (EINVAL);	scp = &tsigc;	if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)		return (EINVAL);	/*	 * Restore the user supplied information	 */	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 &~ sigcantmask;	frame = (struct frame *) p->p_md.md_regs;	frame->f_regs[SP] = scp->sc_sp;	frame->f_regs[A6] = scp->sc_fp;	frame->f_pc = scp->sc_pc;	frame->f_sr = scp->sc_ps;	/*	 * Grab pointer to hardware state information.	 * If zero, the user is probably doing a longjmp.	 */	if ((rf = scp->sc_ap) == 0)		return (EJUSTRETURN);	/*	 * See if there is anything to do before we go to the	 * expense of copying in close to 1/2K of data	 */	flags = fuword((caddr_t)rf);#ifdef DEBUG	if (sigdebug & SDB_FOLLOW)		printf("sigreturn(%d): sc_ap %x flags %x\n",		       p->p_pid, rf, flags);#endif

⌨️ 快捷键说明

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