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

📄 machdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||	    suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)) {		/*		 * Process has trashed its stack; give it an illegal		 * instruction to halt it in its tracks.		 */#ifdef DEBUG		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)			printf("sendsig: window save or copyout error\n");#endif		sigexit(p, SIGILL);		/* NOTREACHED */	}#ifdef DEBUG	if (sigdebug & SDB_FOLLOW)		printf("sendsig: %s[%d] sig %d scp %x\n",		       p->p_comm, p->p_pid, sig, &fp->sf_sc);#endif	/*	 * Arrange to continue execution at the code copied out in exec().	 * It needs the function to call in %g1, and a new stack pointer.	 */#ifdef COMPAT_SUNOS	if (psp->ps_usertramp & sigmask(sig)) {		addr = (int)catcher;	/* user does his own trampolining */	} else#endif	{		addr = USRSTACK - sizeof(struct ps_strings) - szsigcode;		tf->tf_global[1] = (int)catcher;	}	tf->tf_pc = addr;	tf->tf_npc = addr + 4;	tf->tf_out[6] = newsp;#ifdef DEBUG	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)		printf("sendsig: about to return to catcher\n");#endif}/* * System call to cleanup state after a signal * has been taken.  Reset signal mask and * stack state from context left by sendsig (above), * and return to the given trap frame (if there is one). * Check carefully to make sure that the user has not * modified the state to gain improper privileges or to cause * a machine fault. *//* ARGSUSED */struct sigreturn_args {	struct sigcontext *scp;};sigreturn(p, uap, retval)	register struct proc *p;	struct sigreturn_args *uap;	int *retval;{	register struct sigcontext *scp;	register struct trapframe *tf;	/* First ensure consistent stack state (see sendsig). */	write_user_windows();	if (rwindow_save(p))		sigexit(p, SIGILL);#ifdef DEBUG	if (sigdebug & SDB_FOLLOW)		printf("sigreturn: %s[%d], scp %x\n",		    p->p_comm, p->p_pid, uap->scp);#endif	scp = uap->scp;	if ((int)scp & 3 || useracc((caddr_t)scp, sizeof *scp, B_WRITE) == 0)		return (EINVAL);	tf = p->p_md.md_tf;	/*	 * Only the icc bits in the psr are used, so it need not be	 * verified.  pc and npc must be multiples of 4.  This is all	 * that is required; if it holds, just do it.	 */	if (((scp->sc_pc | scp->sc_npc) & 3) != 0)		return (EINVAL);	/* take only psr ICC field */	tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (scp->sc_psr & PSR_ICC);	tf->tf_pc = scp->sc_pc;	tf->tf_npc = scp->sc_npc;	tf->tf_global[1] = scp->sc_g1;	tf->tf_out[0] = scp->sc_o0;	tf->tf_out[6] = scp->sc_sp;	if (scp->sc_onstack & 1)		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;	return (EJUSTRETURN);}int	waittime = -1;boot(howto)	register int howto;{	int i;	static char str[4];	/* room for "-sd\0" */	extern volatile void romhalt(void);	extern volatile void romboot(char *);	fb_unblank();	boothowto = howto;	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {		register struct buf *bp;		int iter, nbusy;#if 1		extern struct proc proc0;		/* protect against curproc->p_stats.foo refs in sync()   XXX */		if (curproc == NULL)			curproc = &proc0;#endif		waittime = 0;		(void) spl0();		printf("syncing disks... ");		/*		 * Release vnodes held by texts before sync.		 */		if (panicstr == 0)			vnode_pager_umount((struct mount *)NULL);		sync(&proc0, (void *)NULL, (int *)NULL);		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");		/*		 * If we've been adjusting the clock, the todr		 * will be out of synch; adjust it now.		 */		resettodr();	}	(void) splhigh();		/* ??? */	if (howto & RB_HALT) {		printf("halted\n\n");		romhalt();	}	if (howto & RB_DUMP)		dumpsys();	printf("rebooting\n\n");	i = 1;	if (howto & RB_SINGLE)		str[i++] = 's';	if (howto & RB_KDB)		str[i++] = 'd';	if (i > 1) {		str[0] = '-';		str[i] = 0;	} else		str[0] = 0;	romboot(str);	/*NOTREACHED*/}int	dumpmag = 0x8fca0101;	/* magic number for savecore */int	dumpsize = 0;		/* also for savecore */long	dumplo = 0;dumpconf(){	int nblks;	dumpsize = physmem;#define DUMPMMU#ifdef DUMPMMU#define NPMEG 128	/*	 * savecore views the image in units of pages (i.e., dumpsize is in	 * pages) so we round the two mmu entities into page-sized chunks.	 * The PMEGs (32kB) and the segment table (512 bytes plus padding)	 * are appending to the end of the crash dump.	 */	dumpsize += btoc(sizeof(((struct kpmap *)0)->pm_rsegmap)) +		btoc(NPMEG * NPTESG * sizeof(int));#endif	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);		/*		 * Don't dump on the first CLBYTES (why CLBYTES?)		 * in case the dump device includes a disk label.		 */		if (dumplo < btodb(CLBYTES))			dumplo = btodb(CLBYTES);		/*		 * If dumpsize is too big for the partition, truncate it.		 * Otherwise, put the dump at the end of the partition		 * by making dumplo as large as possible.		 */		if (dumpsize > btoc(dbtob(nblks - dumplo)))			dumpsize = btoc(dbtob(nblks - dumplo));		else if (dumplo + ctod(dumpsize) > nblks)			dumplo = nblks - ctod(dumpsize);	}}#ifdef DUMPMMU/* XXX */#include <machine/ctlreg.h>#define	getpte(va)		lda(va, ASI_PTE)#define	setsegmap(va, pmeg)	stba(va, ASI_SEGMAP, pmeg)/* * Write the mmu contents to the dump device. * This gets appended to the end of a crash dump since * there is no in-core copy of kernel memory mappings. */intdumpmmu(blkno)	register daddr_t blkno;{	register int (*dump)(/*dev_t, daddr_t, caddr_t, int*/);	register int pmeg;	register int addr;	/* unused kernel virtual address */	register int i;	register int *pte, *ptend;	register int error;	register struct kpmap *kpmap = &kernel_pmap_store;	int buffer[dbtob(1) / sizeof(int)];	extern int seginval;	/* from pmap.c */		dump = bdevsw[major(dumpdev)].d_dump;	/*	 * dump page table entries	 *	 * We dump each pmeg in order (by segment number).  Since the MMU	 * automatically maps the given virtual segment to a pmeg we must	 * iterate over the segments by incrementing an unused segment slot	 * in the MMU.  This fixed segment number is used in the virtual	 * address argument to getpte().	 */	/* First find an unused virtual segment. */	i = NKSEG;	while (kpmap->pm_rsegmap[--i] != seginval)		if (i <= 0)			return (-1);	/*	 * Compute the base address corresponding to the unused segment.	 * Note that the kernel segments start after all the user segments	 * so we must account for this offset.	 */	addr = VSTOVA(i + NUSEG);	/*	 * Go through the pmegs and dump each one.	 */	pte = buffer;	ptend = &buffer[sizeof(buffer) / sizeof(buffer[0])];	for (pmeg = 0; pmeg < NPMEG; ++pmeg) {		register int va = addr;		setsegmap(addr, pmeg);		i = NPTESG;		do {			*pte++ = getpte(va);			if (pte >= ptend) {				/*				 * Note that we'll dump the last block				 * the last time through the loops because				 * all the PMEGs occupy 32KB which is 				 * a multiple of the block size.				 */				error = (*dump)(dumpdev, blkno,						(caddr_t)buffer,						dbtob(1));				if (error != 0)					return (error);				++blkno;				pte = buffer;			}			va += NBPG;		} while (--i > 0);	}	setsegmap(addr, seginval);	/*	 * dump (512 byte) segment map 	 * XXX assume it's a multiple of the block size	 */	error = (*dump)(dumpdev, blkno, (caddr_t)kpmap->pm_rsegmap,			sizeof(kpmap->pm_rsegmap));	return (error);}#endif#define	BYTES_PER_DUMP	(32 * 1024)	/* must be a multiple of pagesize */static vm_offset_t dumpspace;caddr_treserve_dumppages(p)	caddr_t p;{	dumpspace = (vm_offset_t)p;	return (p + BYTES_PER_DUMP);}/* * Write a crash dump. */dumpsys(){	register unsigned bytes, i, n;	register int maddr, psize;	register daddr_t blkno;	register int (*dump)(/*dev_t, daddr_t, caddr_t, int, int*/);	int error = 0;	if (dumpdev == NODEV)		return;	/* copy registers to memory */	snapshot(cpcb);	/*	 * For dumps during autoconfiguration,	 * if dump device has already configured...	 */	if (dumpsize == 0)		dumpconf();	if (dumplo < 0)		return;	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);	printf("dump ");	if (psize == -1) {		printf("area unavailable\n");		return;	}	bytes = physmem << PGSHIFT;	maddr = 0;	blkno = dumplo;	dump = bdevsw[major(dumpdev)].d_dump;	for (i = 0; i < bytes; i += n) {		n = bytes - i;		if (n > BYTES_PER_DUMP)			 n = BYTES_PER_DUMP;#ifdef DEBUG		/* print out how many MBs we have dumped */		if (i && (i % (1024*1024)) == 0)			printf("%d ", i / (1024*1024));#endif		(void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);		error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, (int)n);		if (error)			break;		maddr += n;		blkno += btodb(n);	}#ifdef DUMPMMU	if (!error)		error = dumpmmu(blkno);#endif	switch (error) {	case ENXIO:		printf("device bad\n");		break;	case EFAULT:		printf("device not ready\n");		break;	case EINVAL:		printf("area improper\n");		break;	case EIO:		printf("i/o error\n");		break;	case 0:		printf("succeeded\n");		break;	default:		printf("error %d\n", error);		break;	}}/* * Map an I/O device given physical address and size in bytes, e.g., * *	mydev = (struct mydev *)mapdev(myioaddr, 0, sizeof(struct mydev)); * * See also machine/autoconf.h. */void *mapdev(phys, virt, size)	register void *phys;	register int virt, size;{	register vm_offset_t v;	register void *ret;	static vm_offset_t iobase = IODEV_BASE;	size = round_page(size);	if (virt)		v = trunc_page(virt);	else {		v = iobase;		iobase += size;		if (iobase > IODEV_END)	/* unlikely */			panic("mapiodev");	}	ret = (void *)v;	phys = (void *)trunc_page(phys);	do {		pmap_enter(kernel_pmap, v,		    (vm_offset_t)phys | PMAP_OBIO | PMAP_NC,		    VM_PROT_READ | VM_PROT_WRITE, 1);		v += PAGE_SIZE;		phys += PAGE_SIZE;	} while ((size -= PAGE_SIZE) > 0);	return (ret);}

⌨️ 快捷键说明

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