|
|
researchv10 Norman
/*
* routines that deal closely with
* machine checks and the like
* VAX-11/780 version
*/
#include "sys/param.h"
#include "sys/systm.h"
#include "sys/psl.h"
#include "sys/mtpr.h"
#include "sys/user.h"
/*
* SBI-related registers
*/
#define SBIFS 48 /* SBI fault and status */
#define SBIMT 51 /* SBI and cache maint */
#define SBIER 52 /* SBI error */
#define SBITA 53 /* SBI timeout address */
#define FSNEF 0x2000000 /* nested error flag in fault status */
#define FSIE 0x40000 /* interrupt enable for sbi faults */
#define ERCLR 0x70c0 /* latches in error register: */
/* ib timeout, ib rds, cp timeout, rds, crd */
#define TAMODE 0xc0000000 /* mode of failure for wtmo, 3 == user */
#define TAPROT 0x20000000 /* protection checked reference; off -> pt */
struct mframe {
long count;
long type;
long ces;
long upc;
long vaddr;
long dr;
long tb0;
long tb1;
long paddr;
long par;
long sbi;
long pc;
long psl;
};
#define NMCK 16 /* number of possible type codes */
static char *macher[NMCK] = {
"read timeout",
"control store parity",
"trans buffer parity",
"cache parity",
"-",
"read data substitute",
"microcode lost",
"-",
"-",
"-",
"ib trans buffer parity",
"-",
"ib read data substitute",
"ib read timeout",
"-",
"ib cache parity",
};
int mchkcnt[NMCK]; /* number of mchecks of each type */
int mchktime[NMCK]; /* time of last mcheck */
/*
* table of resumable instructions
* a table of bits, indexed by opcode
* this is taken straight from vms;
* don't ask me to justify choices
*/
static char mrestab[256/8] = {
0x3b, /* rei ldpctx svpctx */
0x3c, /* insque remque cvtps cvtsp */
0xff,
0xff,
0x0, /* packed decimal stuff */
0xff,
0xff,
0xfe, /* editpc */
0xff,
0xff,
0x2f, /* emodf cvtfd adawi */
0x0, /* more interlocked instructions */
0x0, /* double precision floating point */
0x0f, /* more double stuff */
0x4a, /* more double/quad */
0xc1, /* .. */
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xf3, /* pushr popr */
0xff,
0xff,
0xff,
0xf4, /* adwc sbwc mfpr */
0x3f, /* bbssi bbcci */
0xff,
0xff,
0x0, /* ashp cvtlp callg calls xfc reserved */
};
/*
* bits in machine check type code
*/
#define TYPE 0xf /* the real type code */
#define IB 0x8 /* set if detected by instruction prefetch */
#define ABORT 0xf0 /* this was an abort */
#define TIMEOUT 0x100 /* timeout pending */
/*
* types
*/
#define CPTIMEOUT 0 /* read timeout */
#define CSPAR 1 /* control store parity */
#define TBUFPAR 2 /* translation buffer parity */
#define CACHEPAR 3 /* cache parity */
#define RDSUBST 5 /* read data substitute */
#define IBROMCHK 6 /* confused microcode */
#define IBTBUF 10 /* ib-detected translation buffer parity */
#define IBRDSUB 12 /* ib-detected read substitute */
#define IBTIMEOUT 13 /* ib-detected read timeout */
#define IBCACHE 15 /* ib-detected cache parity */
/*
* bits in cache error register
*/
#define G0OK 0x3f8 /* `ok' bits for group 0 */
/*
* bits in sbi maint register
*/
#define G1REPL 0x2000 /* force replace in group 1 */
#define G0REPL 0x4000 /* force replace in group 0 */
#define G1MISS 0x8000 /* force miss in group 1 */
#define G0MISS 0x10000 /* force miss in group 0 */
#define SBIINV 0x200000 /* enable sbi invalidate */
#define CACHEOFF (G0REPL|G1MISS|G0MISS|SBIINV)
static int mchkkill; /* number of times we've recovered by killing */
static int mchklock; /* reentrancy lock */
static int mchkcache = SBIINV; /* current state of cache disable bits */
/*
* sbi fault
* yell and hope for the best
*/
sbifault()
{
register int fs, er;
fs = mfpr(SBIFS);
er = mfpr(SBIER);
machreset();
printf("sbi fault: fs %x er %x\n", fs, er);
}
/*
* SBI write timeout
* no recovery;
* panic if kernel or if updating page table
* else just signal
*/
machwtmo()
{
register int fs, er, ta;
fs = mfpr(SBIFS);
er = mfpr(SBIER);
ta = mfpr(SBITA);
machreset();
printf("sbi write timeout: fs %x er %x ta %x\n", fs, er, ta);
if ((ta & (TAMODE | TAPROT)) != (TAMODE | TAPROT))
panic("wtmo");
runrun++;
aston();
psignal(u.u_procp, SIGBUS);
}
/*
* clear latches in sbi error registers
*/
machreset()
{
mtpr(SBIFS, (mfpr(SBIFS) &~ FSNEF)|FSIE);
mtpr(SBIER, mfpr(SBIER) | ERCLR);
}
/*
* Machine check.
* If possible, recover and return;
* if not but in user mode, send a signal;
* if not and in kernel mode, panic.
*/
machinecheck(ps, f)
long ps;
struct mframe *f;
{
int ok;
ok = mckrec(f);
machreset();
printf("\nMachine check, type %x\n", f->type);
if ((f->type & ABORT) == 0)
printf("%s fault\n", macher[f->type & TYPE]);
else
printf("%s abort\n", macher[f->type & TYPE]);
printf("pc %x psl %x\n", f->pc, f->psl);
printf("v/p addr %x/%x\n", f->vaddr, f->paddr<<2);
printf("ces %x sbi %x\n", f->ces, f->sbi);
if (ok)
return;
if (USERMODE(ps)) {
/*
* code stolen from setrun
*/
runrun++;
aston();
psignal(u.u_procp, SIGBUS);
return;
}
panic("mchk");
}
/*
* here to look at machine check type
* and arrange for recovery if possible
* cache is still turned off when we start
* return nonzero if we recovered
*/
int
mckrec(f)
register struct mframe *f;
{
register int x;
mchkcnt[f->type & TYPE]++;
switch (f->type & TYPE) {
case TBUFPAR: /* trans buffer parity */
case IBTBUF:
mtpr(TBIA, 0); /* clear the buffer */
mtpr(SBIMT, mchkcache);
break;
case IBROMCHK: /* unexpected microcode confusion */
case CSPAR: /* control store parity */
mtpr(SBIMT, mchkcache);
return (0); /* can never recover */
case CACHEPAR: /* cache parity error */
case IBCACHE:
/*
* force bad stuff to be replaced
* in both cache groups
*/
x = *(char *)f->vaddr;
mtpr(SBIMT, CACHEOFF);
x = 0; /* defeat optimizer */
x = *(char *)f->vaddr;
if ((f->par & G0OK) != G0OK) {
printf("group 0 off\n");
mchkcache |= G0MISS | G0REPL;
mchkcache &=~ G1REPL; /* don't replace both groups */
}
else {
printf("group 1 off\n");
mchkcache |= G1MISS | G1REPL;
mchkcache &=~ G0REPL;
}
mtpr(SBIMT, mchkcache);
break;
case CPTIMEOUT:
case IBTIMEOUT:
mtpr(SBIMT, mchkcache);
break;
case RDSUBST: /* read data substitute == hard mem err */
case IBRDSUB:
mtpr(SBIMT, mchkcache);
memerr();
return (0);
default:
mtpr(SBIMT, mchkcache);
panic("weird mcheck");
}
/*
* if we get here, it's potentially recoverable
* may recover if:
* haven't had one in the last second
* not an abort or timeout
* detected by lookahead, or resumable instruction
*/
if (mchktime[f->type & TYPE] == time)
return (0);
mchktime[f->type & TYPE] = time;
if (f->type & (ABORT | TIMEOUT))
return (0);
if (f->type & IB)
return (1);
x = *(char *)f->pc & 0377;
if (mrestab[x >> 3] & (1 << (x & 07)))
return (1);
return (0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.