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

📄 machdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * Be careful to save and restore the original contents for msgbuf.	 */	physmem = btoc(v - KERNBASE);	cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);	while (cp < (char *)MACH_MAX_MEM_ADDR) {		if (badaddr(cp, 4))			break;		i = *(int *)cp;		*(int *)cp = 0xa5a5a5a5;		/*		 * Data will persist on the bus if we read it right away.		 * Have to be tricky here.		 */		((int *)cp)[4] = 0x5a5a5a5a;		MachEmptyWriteBuffer();		if (*(int *)cp != 0xa5a5a5a5)			break;		*(int *)cp = i;		cp += NBPG;		physmem++;	}	maxmem = physmem;#if NLE > 0	/*	 * Grab 128K at the top of physical memory for the lance chip	 * on machines where it does dma through the I/O ASIC.	 * It must be physically contiguous and aligned on a 128K boundary.	 */	if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||		pmax_boardtype == DS_3MAXPLUS) {		maxmem -= btoc(128 * 1024);		le_iomem = (maxmem << PGSHIFT);	}#endif /* NLE */#if NASC > 0	/*	 * Ditto for the scsi chip. There is probably a way to make asc.c	 * do dma without these buffers, but it would require major	 * re-engineering of the asc driver.	 * They must be 8K in size and page aligned.	 */	if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||		pmax_boardtype == DS_3MAXPLUS) {		maxmem -= btoc(ASC_NCMD * 8192);		asc_iomem = (maxmem << PGSHIFT);	}#endif /* NASC */	/*	 * Initialize error message buffer (at end of core).	 */	maxmem -= btoc(sizeof (struct msgbuf));	msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT));	msgbufmapped = 1;	/*	 * Allocate space for system data structures.	 * The first available kernel virtual address is in "v".	 * As pages of kernel virtual memory are allocated, "v" is incremented.	 *	 * These data structures are allocated here instead of cpu_startup()	 * because physical memory is directly addressable. We don't have	 * to map these into virtual address space.	 */	start = v;#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.	 * We allocate more buffer space than the BSD standard of	 * using 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);	/*	 * Clear allocated memory.	 */	bzero(start, v - start);	/*	 * Initialize the virtual memory system.	 */	pmap_bootstrap((vm_offset_t)v);}/* * Console initialization: called early on from main, * before vm init or startup.  Do enough configuration * to choose and initialize a console. */consinit(){	register int kbd, crt;	register char *oscon;	/*	 * First get the "osconsole" environment variable.	 */	oscon = (*callv->getenv)("osconsole");	crt = kbd = -1;	if (oscon && *oscon >= '0' && *oscon <= '9') {		kbd = *oscon - '0';		cn_tab.cn_screen = 0;		while (*++oscon) {			if (*oscon == ',')				cn_tab.cn_screen = 1;			else if (cn_tab.cn_screen &&			    *oscon >= '0' && *oscon <= '9') {				crt = kbd;				kbd = *oscon - '0';				break;			}		}	}	if (pmax_boardtype == DS_PMAX && kbd == 1)		cn_tab.cn_screen = 1;	/*	 * The boot program uses PMAX ROM entrypoints so the ROM sets	 * osconsole to '1' like the PMAX.	 */	if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) {		cn_tab.cn_screen = 1;		crt = 0;		kbd = 7;	}	/*	 * First try the keyboard/crt cases then fall through to the	 * remote serial lines.	 */	if (cn_tab.cn_screen) {	    switch (pmax_boardtype) {	    case DS_PMAX:#if NDC > 0 && NPM > 0		if (pminit()) {			cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);			cn_tab.cn_getc = KBDGetc;			cn_tab.cn_kbdgetc = dcGetc;			cn_tab.cn_putc = fbPutc;			cn_tab.cn_disabled = 0;			return;		}#endif /* NDC and NPM */		goto remcons;	    case DS_MAXINE:#if NDTOP > 0		if (kbd == 3) {			cn_tab.cn_dev = makedev(DTOPDEV, 0);			cn_tab.cn_getc = dtopKBDGetc;			cn_tab.cn_putc = fbPutc;		} else#endif /* NDTOP */			goto remcons;#if NXCFB > 0		if (crt == 3 && xcfbinit()) {			cn_tab.cn_disabled = 0;			return;		}#endif /* XCFB */		break;	    case DS_3MAX:#if NDC > 0		if (kbd == 7) {			cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);			cn_tab.cn_getc = KBDGetc;			cn_tab.cn_kbdgetc = dcGetc;			cn_tab.cn_putc = fbPutc;		} else#endif /* NDC */			goto remcons;		break;	    case DS_3MIN:	    case DS_3MAXPLUS:#if NSCC > 0		if (kbd == 3) {			cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT);			cn_tab.cn_getc = KBDGetc;			cn_tab.cn_kbdgetc = sccGetc;			cn_tab.cn_putc = fbPutc;		} else#endif /* NSCC */			goto remcons;		break;	    default:		goto remcons;	    };	    /*	     * Check for a suitable turbochannel frame buffer.	     */	    if (tc_slot_info[crt].driver_name) {#if NMFB > 0		if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&		    mfbinit(tc_slot_info[crt].k1seg_address)) {			cn_tab.cn_disabled = 0;			return;		}#endif /* NMFB */#if NCFB > 0		if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&		    cfbinit(tc_slot_info[crt].k1seg_address)) {			cn_tab.cn_disabled = 0;			return;		}#endif /* NCFB */		printf("crt: %s not supported as console device\n",			tc_slot_info[crt].driver_name);	    } else		printf("No crt console device in slot %d\n", crt);	}remcons:	/*	 * Configure a serial port as a remote console.	 */	cn_tab.cn_screen = 0;	switch (pmax_boardtype) {	case DS_PMAX:#if NDC > 0		if (kbd == 4)			cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT);		else			cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);		cn_tab.cn_getc = dcGetc;		cn_tab.cn_putc = dcPutc;#endif /* NDC */		break;	case DS_3MAX:#if NDC > 0		cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);		cn_tab.cn_getc = dcGetc;		cn_tab.cn_putc = dcPutc;#endif /* NDC */		break;	case DS_3MIN:	case DS_3MAXPLUS:#if NSCC > 0		cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT);		cn_tab.cn_getc = sccGetc;		cn_tab.cn_putc = sccPutc;#endif /* NSCC */		break;	case DS_MAXINE:#if NSCC > 0		cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT);		cn_tab.cn_getc = sccGetc;		cn_tab.cn_putc = sccPutc;#endif /* NSCC */		break;	};	if (cn_tab.cn_dev == NODEV)		printf("Can't configure console!\n");}/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */cpu_startup(){	register unsigned i;	register caddr_t v;	int base, residual;	vm_offset_t minaddr, maxaddr;	vm_size_t size;#ifdef DEBUG	extern int pmapdebug;	int opmapdebug = pmapdebug;	pmapdebug = 0;#endif	/*	 * Good {morning,afternoon,evening,night}.	 */	printf(version);	printf("real mem = %d\n", ctob(physmem));	/*	 * Allocate virtual address space for file I/O buffers.	 * Note they are different than the array of headers, 'buf',	 * and 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();}/* * machine dependent system variables. */cpu_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;{	/* all sysctl names at this level are terminal */	if (namelen != 1)		return (ENOTDIR);		/* overloaded */	switch (name[0]) {	case CPU_CONSDEV:		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab.cn_dev,		    sizeof cn_tab.cn_dev));	default:		return (EOPNOTSUPP);	}	/* NOTREACHED */}/* * Set registers on exec. * Clear all registers except sp, pc. */setregs(p, entry, retval)	register struct proc *p;	u_long entry;	int retval[2];{	int sp = p->p_md.md_regs[SP];	extern struct proc *machFPCurProcPtr;	bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));	p->p_md.md_regs[SP] = sp;	p->p_md.md_regs[PC] = entry & ~3;	p->p_md.md_regs[PS] = PSL_USERSET;	p->p_md.md_flags & ~MDP_FPUSED;	if (machFPCurProcPtr == p)		machFPCurProcPtr = (struct proc *)0;}/* * 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	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;	register int *regs;	register struct sigacts *psp = p->p_sigacts;	int oonstack, fsize;	struct sigcontext ksc;	extern char sigcode[], esigcode[];	regs = p->p_md.md_regs;	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;	/*	 * Allocate and validate space for the signal handler	 * context. Note that if the stack is in data space, the	 * call to grow() is a nop, and the copyout()	 * 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 *)(regs[SP] - fsize);	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 		(void)grow(p, (unsigned)fp);#ifdef DEBUG	if ((sigdebug & SDB_FOLLOW) ||	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",		       p->p_pid, sig, &oonstack, fp, &fp->sf_sc);#endif	/*	 * Build the signal context to be used by sigreturn.	 */	ksc.sc_onstack = oonstack;	ksc.sc_mask = mask;	ksc.sc_pc = regs[PC];	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],		sizeof(ksc.sc_regs) - sizeof(int));	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;	if (ksc.sc_fpused) {		extern struct proc *machFPCurProcPtr;		/* if FPU has current state, save it first */		if (p == machFPCurProcPtr)			MachSaveCurFPState(p);		bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,			sizeof(ksc.sc_fpregs));	}	if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {		/*		 * 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;

⌨️ 快捷键说明

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