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

📄 memtest.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/* memtest.c *//* * This is a loadable driver (oh boy!) that allows you to check the * functioning of the parity and memory error handling code in the kernel. * * Mmap'ing it gives non-existent storage (references will cause * timeouts). * * The following ioctls are understood: * MEMTESTBADPAR	rewrites the byte at (user) addr with bad parity: * MEMTESTBADPAREXP	same as MEMTESTBADPAR but does it in expansion memory:	 * MEMTESTBADFETCH	does a kernel-mode ifetch of a bad-parity word: * MEMTESTBADLOAD	does a kernel-mode load of a bad-parity word: * MEMTESTBADSTORE	does a kernel-mode store to user address* * MEMTESTBADLOADT	does a kernel-mode load of a user address* * MEMTESTBADFETCHT	does a kernel-mode ifetch of a user address* * MEMTESTPEEKPOKE	does kernel-mode peeks and pokes of a user address* *	*preferably one that has been mmap'd to non-existent memory; * Usage: * int fd = open("/dev/memtest", O_RDWR); * caddr_t paddr = mmap(addr, len, prot, flags, fd, off); * typically, * caddr_t paddr = mmap(0, getpagesize(), PROT_ALL, MAP_SHARED, fd, 0); *	*paddr = 0; 	/* cause a memory timeout */ /* * * char *addr = 0; * ioctl(fd, MEMTESTBADPAR, addr); * int c = *addr;	/* cause a user parity fault */ /* * * ioctl(fd, MEMTESTBADFETCH, 0);	/* should panic kernel */ /* * ioctl(fd, MEMTESTBADLOAD, 0);	/* should panic kernel */ /* * ioctl(fd, MEMTESTBADSTORE, paddr);	/* should panic kernel */ /* * ioctl(fd, MEMTESTBADLOADT, paddr);	/* should panic kernel */ /* * ioctl(fd, MEMTESTBADFETCHT, paddr);	/* should panic kernel */ /* * * struct memtest_peekpoke peekpoke; * peekpoke.paddr = paddr; * ioctl(fd, MEMTESTPEEKPOKE, &peekpoke);/* should return 6 -1's /* */#include <sun/vddrv.h>#include <memtestio.h>#include <sys/param.h>#include <sys/conf.h>#include <sys/errno.h>#include <sundev/mbvar.h>#include <vm/seg.h>#include <machine/pte.h>#include <machine/memerr.h>#include <mon/sunromvec.h>#include <machine/cpu.h>#include <machine/enable.h>struct dev_ops	memtestops;struct cdevsw	memtestcdevsw;struct vdldrv	memtestdrv = {	VDMAGIC_PSEUDO,	"memtest pseudo-device",	&memtestops,	NULL,			/* bdevsw */	&memtestcdevsw,};struct dev_ops	memtestops = {	1,			/* rev */};int memtest_open(), memtest_close(), memtest_ioctl(), memtest_mmap();extern int nodev(), nulldev(), seltrue();struct cdevsw	memtestcdevsw = {	memtest_open,	nulldev,		/* close */	nodev,			/* read */	nodev,			/* write */	memtest_ioctl,	nodev,			/* reset */	seltrue,	memtest_mmap,	0,			/* str */};memtest_init(fcn, vdp, vdi, vds)	int			fcn;	register struct vddrv	*vdp;	caddr_t			vdi;	struct vdstat		*vds;	/* only meaningful for VDSTAT */{	int	status = 0;	switch (fcn) {	case VDLOAD:		vdp->vdd_vdtab = (struct vdlinkage *)&memtestdrv;		break;	case VDUNLOAD:		break;	case VDSTAT:		break;	default:		printf("memtest_init: unknown function 0x%x\n", fcn);		status = EINVAL;	}	return status;}memtest_open(dev)	dev_t	dev;{	if (minor(dev) != 0)		return (ENXIO);	return 0;}intmemtest_ioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	caddr_t uaddr = *(caddr_t *)data;	switch (cmd) {	case MEMTESTBADPAR:		return memtest_badpar_u(uaddr, 0);	case MEMTESTBADPAREXP:		return memtest_badpar_u(uaddr, 1);	case MEMTESTBADFETCH:		return memtest_badfetch();	case MEMTESTBADLOAD:		return memtest_badload();	case MEMTESTBADSTORE:		return memtest_badstore(uaddr);	case MEMTESTBADLOADT:		return memtest_badloadt(uaddr);	case MEMTESTBADFETCHT:		return memtest_badfetcht(uaddr);	case  MEMTESTPEEKPOKE:		return memtest_peekpoke((struct memtest_peekpoke *) data);	default:		return (EINVAL);	}}/*ARGSUSED*/memtest_mmap(dev, off, prot)	dev_t dev;	off_t off;{	struct pte	pte;	extern int	physpages;	*(unsigned int *)&pte = 0;	pte.pg_type = PGT_OBMEM;	pte.pg_pfnum = ~0;	return (*(unsigned int *)&pte);}/* * make sure uaddr is valid. * fault it in, if necessary. */intmemtest_badpar_u(uaddr, exp_flag)	caddr_t	uaddr;	int	exp_flag;	/* if exp_flag=1 use expansion parity reg */{	register int	c;	if ((c = fubyte_nc(uaddr)) == -1)	/* Is page accessable? */		return (EFAULT);	/* (this also faults it in) */	return (memtest_badpar(uaddr, c, exp_flag));}/* * fetch a byte from user space with the cache off */intfubyte_nc(addr)	caddr_t addr;{	int	oldvac = vac;	int	s, x;	struct pte	pte;	mmu_getpte(addr, &pte);	if (pte_valid(&pte)) {		if (oldvac) {			s = spl8();			off_enablereg(ENA_CACHE);			vac = 0;			splx(s);		}		x = fubyte(addr);		if (oldvac) {			s = spl8();			vac_flushall();	/* clear the cache */			on_enablereg(ENA_CACHE);			vac = 1;			splx(s);		}	} else		x = fubyte(addr);	return (x);}/* static data used by memtest_badload() */int	memtest_data = 0;intmemtest_badload(){	register int	c, d;	caddr_t addr;	int exp_flag=0;	c = memtest_data;	addr = (caddr_t)&memtest_data;	memtest_badpar(addr, c, exp_flag);	memtest_badpar(addr+2, c, exp_flag);	printf("memtest: wrote bad parity to 0x%x and 0x%x\n", addr, addr+2);	printf("memtest: about to load from 0x%x\n", &memtest_data);	d = memtest_data;		/* should panic here */	return (c ^ d);}/* function used by memtest_badfetch */extern int memtest_retl();intmemtest_badfetch(){	register int	c, d;	int	exp_flag=0;	c = *(u_char *)memtest_retl;	memtest_badpar(memtest_retl, c, exp_flag);	printf("memtest: about to fetch from 0x%x\n", memtest_retl);	d = memtest_retl(c);		/* should panic here */	*(char *)memtest_retl = c;	return (d ^ c);}intmemtest_badstore(uaddr)	caddr_t uaddr;{	printf("memtest: about to store to 0x%x\n", uaddr);	if (subyte(uaddr, 0) == -1)		return (EFAULT);		return 0;}intmemtest_badloadt(uaddr)	caddr_t uaddr;{	printf("memtest: about to load from 0x%x\n", uaddr);	if (fubyte(uaddr) == -1)		return (EFAULT);		return 0;}intmemtest_badfetcht(uaddr)	caddr_t uaddr;{	/*	 * Make sure we have a mapping; can't use on_fault() becuase	 * that only works for kernel data faults, not kernel text faults.	 */	if (pagefault(uaddr, F_INVAL, S_READ, 0) != 0)		return (EFAULT);	printf("memtest: about to fetch from 0x%x\n", uaddr);	((int (*)())uaddr)();	return 0;}extern int peek(), peekc(), peekl(), poke(), pokec(), pokel();/* * Invoke peek* and poke* routines with the user's bad-map address. */intmemtest_peekpoke(ppp)	struct memtest_peekpoke *ppp;{	caddr_t uaddr = ppp->paddr;	long dummy;	/*	 * Make sure we have a mapping; peek and poke use nofault, not	 * lofault.	 */	if (pagefault(uaddr, F_INVAL, S_WRITE, 0) != 0)		return (EFAULT);	printf("memtest: testing peeks from 0x%x\n", uaddr);	ppp->error[0] = peekc(uaddr);	ppp->error[1] = peek(uaddr);	ppp->error[2] = peekl(uaddr, &dummy);	printf("memtest: testing pokes to 0x%x\n", uaddr);	ppp->error[3] = pokec(uaddr, (char) 0);	ppp->error[4] = poke(uaddr, (short) 0);	ppp->error[5] = pokel(uaddr, (long) 0);	return 0;}/* * Write a byte with bad parity to an address. * This even works if the page isn't writeable, as we modify the pte. * (We modify the pte because we want the write to be transparent; we * want to be able to generate parity errors without otherwise setting * the modify bit, so we can test parity recovery.) */intmemtest_badpar(addr, c, exp_flag)	caddr_t	addr;	register int	c;	int 	exp_flag;	/* if exp_flag=1 use expansion par reg */{	int	s;	register u_int	saveper;	struct pte	pte;	register int	err = 0;	printf("memtest: about to store 0x%x with bad parity to 0x%x\n",		c, addr);	s = spl8();	mmu_getpte(addr, &pte);		/* Save pte */	if (pte.pg_v) {		struct pte	 tpte;		tpte = pte;		tpte.pg_prot = KW;		mmu_setpte(addr, tpte);		/* Writeable for us */		vac_pageflush(addr);		/* keep cache consistent */		if (exp_flag == 0) 			saveper = MEMERR->me_per;		else 			saveper = MEMERR2->me_per;		disable_dvma();		/* Don't want dvma w/ bad parity! */		if (exp_flag == 0) 			MEMERR->me_per = PER_TEST;		else 			MEMERR2->me_per = PER_TEST;		*(addr) = c;			/* write bad parity */		if (exp_flag == 0) 			MEMERR->me_per = saveper;		else 			MEMERR2->me_per = saveper;		enable_dvma();		/* Safe to turn dvma back on */		mmu_setpte(addr, pte);		vac_pageflush(addr);		/* keep cache consistent */	} else		err = EFAULT;	splx(s);	vac_flush(addr, 1);		/* flush it from the cache */	return err;}/* * Note: loadable device drivers are type 407; the text is read-write. * Otherwise, we would have had to place this in a separate assembler * file. */intmemtest_retl(c)	int	c;{	return c;}

⌨️ 快捷键说明

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