V10/lsys/md/mchknaut.c

Compare this file to the similar file:
Show the results in this format:

/*
 * nautilus-specific traps
 */

#include "sys/param.h"
#include "sys/mtpr.h"
#include "sys/psl.h"
#include "sys/systm.h"
#include "sys/user.h"

extern long *mcrcsr;		/* must read mem csr to clear NMI faults! */

/*
 * nautilus-specific registers and bits
 */

#define	MCSTS	0x26	/* machine check status */
#define	NMIFSR	0x82	/* NMI fault status */
#define	NMIEAR	0x84	/* error address */
#define	CLRTOS	0x88	/* clear timeout sts */
#define	COR	0x85	/* cache on */

/*
 * nmi fault
 */

nmiflt()
{
	register long fsr, addr;
	register junk;

	fsr = mfpr(NMIFSR);
	addr = mfpr(NMIEAR);
	junk = mcrcsr[5];	/* sigh */
	printf("nmi fault %x addr %x\n", fsr, addr);
}

/*
 * machine check things
 */
struct mck {
	int count;
	int mcsts;
	int upc;
	int va;
	int iber;
	int cber;
	int eber;
	int nmifsr;
	int nmiear;
	int pc;
	int ps;
};


#define	MCABORT	0x1		/* mcsts: can't possibly restart */

#define	FSRBCOD	0x0c000000	/* nmifsr: timeout buffer code */
#define	RTO	0x08000000	/* read timeout */
#define	WTO	0x04000000	/* write timeout */

#define	CBCERR	0x00303f00	/* cber: cache error */
#define	CBTERR	0x00070010	/* cber: trans buf error */
#define	CBRDS	0x00000006	/* cber: probably memory RDS */
#define	CBOXBAD	0x00000008	/* cber: various fatal errors */

#define	IBOXBAD	0x000007ff	/* iber: various fatal errors */

#define	EBBERR	0x80		/* eber (each byte): b-side error */
#define	EBAERR	0x40		/* eber: a-side error */
#define	EBBSRC	0x38		/* eber: b-side source */
#define	EBASRC	0x03		/* eber: a-side source */

static time_t lastcache;
static int cacheon;
/*
 * machine check
 * if we get here, there's no desire to trap it with nofault
 */
machinecheck(ps, f)
long ps;
struct mck *f;
{
	register ok;

	cacheon = mfpr(COR);
	mtpr(COR, 0);		/* in case that's what's broken */
	/*
	 * always print for now
	 * delays prevent console congestion
	 */
	printf("machine check:\n");
	DELAY(100000);
	printf("mcsts %x upc %x va %x\n", f->mcsts, f->upc, f->va);
	DELAY(100000);
	printf("iber %x cber %x eber %x\n", f->iber, f->cber, f->eber);
	DELAY(100000);
	printf("nmifsr %x nmiear %x\n", f->nmifsr, f->nmiear);
	printf("pc %x ps %x\n", f->pc, f->ps);
	DELAY(100000);
	ok = mckrec(f);
	machreset();
	if (ok)
		return;
	if (USERMODE(ps)) {
		/*
		 * code stolen from setrun
		 */
		runrun++;
		aston();
		psignal(u.u_procp, SIGBUS);
		return;
	}
	panic("mchk");
}

/*
 * decide if the machine check is recoverable
 * logic inspired by VAX/VMS
 * roughly, if the microcode said it wasn't restartable (MCABORT)
 * or if it seems a sufficiently nasty error (bus timeout, most ibox errors),
 * say no.
 */

mckrec(f)
struct mck *f;
{
	register int i, x;

	switch (f->nmifsr & FSRBCOD) {
	case RTO:
		printf("read timeout\n");
		break;

	case WTO:
		printf("write timeout\n");
		break;
	}
	if (f->cber & CBCERR) {
		printf("cache\n");
		if (time < lastcache + 5) {
			cacheon = 0;
			printf("turned off\n");
		}
		lastcache = time;
	}
	if (f->cber & CBTERR)
		printf("tbuf\n");
	if (f->cber & CBRDS)
		printf("mchk hard mem err\n");
	/* call mem err intr? */
	mtpr(COR, cacheon);
	if (f->mcsts & MCABORT)
		return (0);
	if (f->iber & IBOXBAD
	||  f->cber & CBOXBAD)
		return (0);
	if ((f->nmifsr & FSRBCOD) != 0)
		return (0);
	for (x = f->eber, i = 0; i < 4; x >>= 8, i++) {
		if (x & EBAERR)
			switch (x & EBASRC) {
			case 0:
			case 4:
				return (0);
			}
		if (x & EBBERR)
			switch (x & EBBSRC) {
			case 4:
				return (0);
			}
	}
	return (1);
}

/*
 * reset things after a machine check
 */

machreset()
{
	register junk;

	mtpr(MCSTS, mfpr(MCSTS));
	if (mcrcsr)
		junk = mcrcsr[5];
	mtpr(CLRTOS, 0);
}