xref: /inferno-os/os/mpc/faultpower.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"ureg.h"
7 #include	"io.h"
8 
9 enum
10 {
11 	MC_IFETCH	= (1<<30),
12 	MC_STORE	= (1<<11),	/* bit 23 if X-form, bit 3 if D-form => write */
13 	DSI_STORE	= (1<<25),
14 	DSI_PROT		= (1<<27),
15 };
16 
17 void
18 faultpower(Ureg *ur)
19 {
20 	ulong addr;
21 	char buf[ERRMAX];
22 	int read, i;
23 
24 	addr = ur->pc;			/* assume instr. exception */
25 	read = 1;
26 	i = ur->cause >> 8;
27 	if(i == CDSI || i == CDTLBE || i == CMCHECK && (ur->status&MC_IFETCH) == 0) {	/* data access error including machine check load/store */
28 		addr = getdar();
29 		if(getdsisr() & (DSI_STORE|MC_STORE))
30 			read = 0;
31 	} else if(i == CDMISS)	/* DTLB miss */
32 		addr = getdepn() & ~0x3FF;	/* can't distinguish read/write, but Inferno doesn't care */
33 /*
34 print("fault %lux %lux %lux %d\n", ur->pc, ur->cause, addr, read);
35 print("imiss %lux dmiss %lux hash1 %lux dcmp %lux hash2 %lux\n",
36 	getimiss(), getdmiss(), gethash1(), getdcmp(), gethash2());
37 print("up %lux %lux %lux\n", m->upage, m->upage->virt, m->upage->phys);
38 */
39 
40 	up->dbgreg = ur;		/* For remote ACID */
41 
42 	spllo();
43 	sprint(buf, "trap: fault %s pc=0x%lux addr=0x%lux",
44 			read ? "read" : "write", ur->pc, addr);
45 	if(up->type == Interp)
46 		disfault(ur, buf);
47 	dumpregs(ur);
48 	panic("fault: %s\n", buf);
49 }
50