|
|
Plan 9 NeXT
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "ureg.h"
#include "../port/error.h"
#define FORMAT(ur) ((((ur)->vo)>>12)&0xF)
#define OFFSET(ur) (((ur)->vo)&0xFFF)
struct FFrame
{
ushort ireg0; /* internal register */
ushort ssw; /* special status word */
ushort ipsc; /* instr. pipe stage c */
ushort ipsb; /* instr. pipe stage b */
ulong addr; /* data cycle fault address */
ushort ireg1; /* internal register */
ushort ireg2; /* internal register */
ulong dob; /* data output buffer */
ushort ireg3[4]; /* more stuff */
ulong baddr; /* stage b address */
ushort ireg4[26]; /* more more stuff */
};
/*
* SSW bits
*/
#define RW 0x0040 /* read/write for data cycle */
#define FC 0x8000 /* fault on stage C of instruction pipe */
#define FB 0x4000 /* fault on stage B of instruction pipe */
#define RC 0x2000 /* rerun flag for stage C of instruction pipe */
#define RB 0x1000 /* rerun flag for stage B of instruction pipe */
#define DF 0x0100 /* fault/rerun flag for data cycle */
#define RM 0x0080 /* read-modify-write on data cycle */
#define READ 0x0040
#define WRITE 0x0000
#define SIZ 0x0030 /* size code for data cycle */
#define FC2 0x0004 /* address space for data cycle */
#define FC1 0x0002
#define FC0 0x0001
void
fault68020(Ureg *ur, FFrame *f)
{
ulong addr, badvaddr;
int user, read, insyscall;
char buf[ERRLEN];
if(u == 0){
dumpregs(ur);
panic("fault u==0 pc=%lux", ur->pc);
}
insyscall = u->p->insyscall;
u->p->insyscall = 1;
addr = 0; /* set */
if(f->ssw & DF)
addr = f->addr;
else if(FORMAT(ur) == 0xA){
if(f->ssw & FC)
addr = ur->pc+2;
else if(f->ssw & FB)
addr = ur->pc+4;
else
panic("prefetch pagefault");
}else if(FORMAT(ur) == 0xB){
if(f->ssw & FC)
addr = f->baddr-2;
else if(f->ssw & FB)
addr = f->baddr;
else
panic("prefetch pagefault");
}else
panic("prefetch format");
addr &= VAMASK;
badvaddr = addr;
addr &= ~(BY2PG-1);
user = !(ur->sr&SUPER);
if(user)
u->dbgreg = ur;
if(f->ssw & DF)
read = (f->ssw&READ) && !(f->ssw&RM);
else
read = f->ssw&(FB|FC);
/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/
if(fault(addr, read) < 0){
if(user){
sprint(buf, "sys: trap: fault %s addr=0x%lux",
read? "read" : "write", badvaddr);
postnote(u->p, 1, buf, NDebug);
notify(ur);
return;
}
dumpregs(ur);
panic("fault: 0x%lux", badvaddr);
}
u->p->insyscall = insyscall;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.