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

📄 kn230.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
					kn230_trans_errcnt.trans_last = 0;					currtime = 0;				}			        log_kn230mem(ep, EL_PRIHIGH, pa, memreg);				kn230_trans_errcnt.trans_prev = kn230_trans_errcnt.trans_last;				kn230_trans_errcnt.trans_last = currtime;			    }			    return(0);			}			pagetype = cmap[pgtocm(btop(pa))].c_type;			if (SHAREDPG(pagetype)) {				log_kn230mem(ep, EL_PRISEVERE, pa,memreg);				kn230consprint(MEMPKT, ep, pa);				panic("memory parity error in shared page");			} else {			        log_kn230mem(ep, EL_PRIHIGH, pa,memreg);		                printf("pid %d (%s) was killed on memory parity error\n",p->p_pid, u.u_comm);				uprintf("pid %d (%s) was killed on memory parity error\n",p->p_pid, u.u_comm);			}		} else {			uprintf("pid %d (%s) was killed on bus read error\n",				p->p_pid, u.u_comm);		}	} else {		/*		 * Kernel mode errors.		 * They all panic, its just a matter of what we log		 * and what panic message we issue.		 */		switch (code) {		case EXC_DBE:		case EXC_IBE:			/*			 * Figure out if its a memory parity error			 *     or a read bus timeout error			 */			pa = vatophys(ep[EF_BADVADDR]);			if ( (int)pa != -1 && (btop((int)pa) < kn230_physmem))			    {				/*				 * Note: must save anything "interesting"				 * from the exception frame, since                                  * kn230_isolatepar() may cause				 * additional bus errors which will				 * stomp on the exception frame in locore.				 */				vaddr = ep[EF_BADVADDR];				epc = ep[EF_EPC];				memreg = kn230_isolatepar(pa, vaddr); 				ep[EF_BADVADDR] = vaddr;				ep[EF_EPC] = epc;				log_kn230mem(ep, EL_PRISEVERE, pa,memreg); 				kn230consprint(MEMPKT, ep, pa);				panic("memory parity error in kernel mode");			} else {				log_kn230esr(ep, EL_PRISEVERE);				kn230consprint(ESRPKT, ep, 0);				panic("bus timeout");			}			break;		case EXC_CPU:			log_kn230esr(ep, EL_PRISEVERE);			kn230consprint(ESRPKT, ep, 0);			panic("coprocessor unusable");			break;		case EXC_RADE:		case EXC_WADE:			log_kn230esr(ep, EL_PRISEVERE);			kn230consprint(ESRPKT, ep, 0);			panic("unaligned access");			break;		default:			log_kn230esr(ep, EL_PRISEVERE);			kn230consprint(ESRPKT, ep, 0);			panic("trap");			break;		}	}	/*	 * Default user-mode action is to terminate the process	 */	*signo = SIGBUS;	return(0);}/*****************************************************************************  * * kn230_memintr: Entry for WMERR interupt -- write to a non-existent address * * This does not happen synchronously (buffered write), * therefore we are not in process context and cannot terminate * a user process.  We must crash the system. * *****************************************************************************/kn230_memintr(ep)	u_int *ep;		/* exception frame ptr */{	volatile unsigned int icsr;	/*	 * read icsr and clear error	 */	icsr = *(int *)ICSR_ADDR;	*(int *)ICSR_ADDR |= KN230_WMERR ;	/*	 * save the state of the system registers for 	 * error logging.	 *	 */	kn230_esr_icsr = icsr;	kn230_esr_leds = *(int *)LED_ADDR;	kn230_esr_wear = *(int *)WEAR_ADDR;	kn230_esr_oid  = *(int *)OID_ADDR;	if ( icsr & KN230_WMERR) {	  log_kn230esr(ep, EL_PRISEVERE);	  kn230consprint(ESRPKT, ep, 0); 	  panic("NXM - write to non-existant memory");	} 	else {	  log_kn230esr(ep, EL_PRISEVERE);	  kn230consprint(ESRPKT, ep, 0);  	  panic("stray memory error interrupt");	}	}/***************************************************************************** * * kn230consprint: print error information to console * *****************************************************************************/kn230consprint(packet_type, ep, pa)int packet_type;      /* ESR or MEM type error */register u_int *ep;   /* exception frame pointer */unsigned pa;          /* phys addr of MEM error */{  switch (packet_type) {  case ESRPKT:    cprintf("\nException condition\n");    break;  case MEMPKT:    cprintf("\nMemory Error\n");    break;  default:    cprintf("bad consprint - no packet_type given\n");    break;  }  cprintf("\tCause reg\t\t= 0x%x\n", ep[EF_CAUSE]);  cprintf("\tException PC\t\t= 0x%x\n", ep[EF_EPC]);  cprintf("\tStatus reg\t\t= 0x%x\n", ep[EF_SR]);  cprintf("\tBad virt addr\t\t= 0x%x\n", ep[EF_BADVADDR]);  cprintf("\tInterupt CSR reg\t= 0x%x\n", *(int *)ICSR_ADDR);  cprintf("\tWrite Error Add reg\t= 0x%x\n", *(int *)WEAR_ADDR);  cprintf("\tLED reg\t\t\t= 0x%x\n", *(int *)LED_ADDR);  cprintf("\tOption ID reg\t\t= 0x%x\n", *(int *)OID_ADDR);    if (pa)    cprintf("\tPhysical address of error: 0x%x\n",pa);}/***************************************************************************** * * log_kn230esr: Log Error & Status Registers to the error log buffer * *****************************************************************************/log_kn230esr(ep, priority)	register u_int *ep;	/* exception frame ptr */	int priority;		/* for pkt priority */{	struct el_rec *elrp;	elrp = ealloc(sizeof(struct el_esr5100), priority);	if (elrp != NULL) {	  LSUBID(elrp,ELCT_ESR,ELESR_5100,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF);	  elrp->el_body.elesr.elesr.el_esr5100.esr_cause = ep[EF_CAUSE];	  elrp->el_body.elesr.elesr.el_esr5100.esr_epc = ep[EF_EPC];	  elrp->el_body.elesr.elesr.el_esr5100.esr_status = ep[EF_SR];	  elrp->el_body.elesr.elesr.el_esr5100.esr_badva = ep[EF_BADVADDR];	  elrp->el_body.elesr.elesr.el_esr5100.esr_sp = ep[EF_SP];          elrp->el_body.elesr.elesr.el_esr5100.esr_icsr = kn230_esr_icsr;          elrp->el_body.elesr.elesr.el_esr5100.esr_leds = kn230_esr_leds;          elrp->el_body.elesr.elesr.el_esr5100.esr_wear = kn230_esr_wear;          elrp->el_body.elesr.elesr.el_esr5100.esr_oid = kn230_esr_oid;	  EVALID(elrp);	}}/***************************************************************************** * * log_kn230mem: Log a memory error packet, so uerf can find it as a *               main memory error. * *****************************************************************************/log_kn230mem(ep, priority, pa, memreg)	register u_int *ep;	/* exception frame ptr */	int priority;		/* pkt priority: panic: severe; else: high */	int pa;			/* physical addr where memory err occured */        unsigned memreg;        /* parity error information */{	struct el_rec *elrp;	register struct el_mem *mrp;	elrp = ealloc(EL_MEMSIZE, priority);	if (elrp != NULL) {	LSUBID(elrp,ELCT_MEM,EL_UNDEF,ELMCNTR_5100,EL_UNDEF,EL_UNDEF,EL_UNDEF);		mrp = &elrp->el_body.elmem;		mrp->elmem_cnt = 1;		mrp->elmemerr.cntl = 1;		mrp->elmemerr.type = ELMETYP_PAR;		mrp->elmemerr.numerr = 1;		mrp->elmemerr.regs[0] = memreg;		mrp->elmemerr.regs[1] = pa;		mrp->elmemerr.regs[2] = ep[EF_EPC];		mrp->elmemerr.regs[3] = ep[EF_BADVADDR];		EVALID(elrp);	}}/**************************************************************************** * * kn230_isolatepar: * * Overall goal here is to be able to recover a user process if the  * parity error was a soft error, and to log additional information. * * Isolate a memory parity error to which SIMM is in error. * This routine is machine specific, in that it "knows" how the memory * is laid out, i.e. how to convert a physical address to a module number. * * Block faults from occuring while we isolate the parity error by using * "nofault" facility thru the bbadaddr routine. * ****************************************************************************/unsigned kn230_isolatepar(pa, va)	register caddr_t pa;	/* the phys addr to convert to a SIMM */	caddr_t va;		/* the virtual addr of the error */	{	register int i;		/* loop index */		register char *addr;	/* increment thru the word w/ parity error */	register char *k1_addr;	/* kseg1 addr. for mem test writes */	unsigned memreg;	/* collection of memory error info */	int odd;		/* true if its the odd numbered SIMM */	int simm;		/* which simm had the error */	register int allzeros;	/* true if parity err occurs on all 0's write*/	register int allones;	/* true if parity err occurs on all 1's write*/	register int oneone;	/* true if parity err occurs on 1 1 write */	int dp;			/* 0 for data bit, 1 for parity bit */	int type;		/* error type: transient, soft, hard */	int byte;		/* 0 for low byte; 1 for high byte in word */	/*	 * Round address down to long word, & clear flags.	 */	addr = (char *)((int)va & (~0x3));	type = 0;	dp = 0;	/*	 * Do badaddr probe on addr (a few times),	 * to see if it was only a transient.	 */	kn230_parityerr = 0;	for (i = 0; i < 4; i++) {		if (bbadaddr(addr, 4)) {			kn230_parityerr = 1;			break;		}	}	if (!kn230_parityerr) {		type = TRANSPAR;		byte = 0;		odd = 1;		goto getsimm;	}	/*	 * Isolate the parity error to which SIMM is in error (which byte in	 * the word) and isolate the type of error: soft or hard, data bit	 * or parity bit.	 *	 * This is done by writing (& reading) each byte in the word first	 * with all 0's then with all 1's (0xff) then with one 1 (0x1).	 *	 * Use k1_addr in order not to get TLBMOD exception when writing	 * shared memory space	 *	 */	k1_addr = (char *)(PHYS_TO_K1(((int)pa  & (~0x3)))); /*lw addr*/		for (i = 0; i < 4; i++, addr += 1) {		allzeros = 0;		*k1_addr = 0x00;		if (bbadaddr(addr, 1))			allzeros = 1;		allones = 0;		*k1_addr = 0xff;		if (bbadaddr(addr, 1))			allones = 1;		oneone = 0;		*k1_addr = 0x1;		if (bbadaddr(addr, 1))			oneone = 1;		/*		 * If all 3 reads caused the error then this is the wrong		 * byte, go on to the next byte		 */		if (allzeros && allones && oneone)			continue;		/*		 * If only one of the allones/allzeros patterns caused a		 * parity error, then we have a hard data bit stuck to		 * zero or one.		 */		if ((allzeros && !allones && !oneone) ||		    (allones && !allzeros && !oneone)) {			type = HARDPAR;			break;		}		/*		 * If only the "oneone" (0x1) pattern caused a parity error,		 *   then we have a parity bit stuck to zero.		 * If only the "oneone" (0x1) pattern did NOT cause a parity		 *   error then we have a parity bit stuck to one.		 */		if ((oneone && !allzeros && !allones) ||		    (allzeros && allones && !oneone)) {			type = HARDPAR;			dp = 1;			break;		}		/*		 * If no parity error on all 3 patterns then we had a soft		 * parity error in one of the data bits or in the parity bit		 * of this byte.		 */		if (!allzeros && !allones && !oneone) {			type = SOFTPAR;			break;		}	}	/*	 * If i is 0 or 1, parity error is on the odd SIMM.	 * If i is 2 or 3, parity error is on the even SIMM.	 * Also record high or low byte position in half-word.	 */	switch (i) {	case 0:		byte = 0;		odd = 1;		break;	case 1:		byte = 1;		odd = 1;		break;	case 2:		byte = 0;		odd = 0;		break;	case 3:	default:		byte = 1;		odd = 0;		break;	}getsimm:	/*	 * Record which SIMM	 */	if ((int)pa < kn230_bank1*1024*1024)		if (odd)			simm = 1;		else			simm = 2;	else if ((int)pa < (kn230_bank1+kn230_bank2)*1024*1024)		if (odd)			simm = 3;		else			simm = 4;	else if ((int)pa < (kn230_bank1+kn230_bank2+kn230_bank3)*1024*1024)		if (odd)			simm = 5;		else			simm = 6;	else if ((int)pa < (kn230_bank1+kn230_bank2+kn230_bank3+kn230_bank4)*1024*1024)		if (odd)			simm = 7;		else			simm = 8;	/*	 * Increment error counts	 */	switch (type) {	case TRANSPAR:	default:		tcount[simm]++;		if (tcount[simm] > 255) {			mprintf("Transient parity error count on simm # %d reached 255, reset to zero.\n", simm);			tcount[simm] = 0;		}		break;	case SOFTPAR:		scount[simm]++;		break;	case HARDPAR:		hcount[simm]++;		break;	}	memreg = MEMREGFMT(simm, type, byte, dp, tcount[simm], scount[simm], hcount[simm]);	return(memreg);}/**************************************************************************** * * kn230_getSIMMsizes: Function is to identify the size of each of the *                     four banks of the kn230 SIMM memory. This info *                     is necessary for kn230_isolatepar, which uses it *                     to report which SIMM the parity error occured on.

⌨️ 快捷键说明

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