|
|
1.1 root 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 "../port/error.h"
8:
9: #define FORMAT(ur) ((((ur)->vo)>>12)&0xF)
10: #define OFFSET(ur) (((ur)->vo)&0xFFF)
11:
12: struct FFrame
13: {
14: ulong ea; /* effective address */
15: ushort ssw; /* special status word */
16: ushort wb3s; /* write back 3 status */
17: ushort wb2s; /* write back 2 status */
18: ushort wb1s; /* write back 1 status */
19: ulong fa; /* fault address */
20: ulong wb3a; /* write back 3 address */
21: ulong wb3d; /* write back 3 data */
22: ulong wb2a; /* write back 2 address */
23: ulong wb2d; /* write back 2 data */
24: ulong wb1a; /* write back 1 address */
25: ulong wb1d; /* write back 3 data */
26: ulong pd1; /* push data lw1 */
27: ulong pd2; /* push data lw2 */
28: ulong pd3; /* push data lw3 */
29: };
30:
31: static uchar tsz[4] = { 4, 1, 2, 0 };
32:
33: /*
34: * SSW bits
35: */
36: #define READ 0x0100
37: #define TM 0x0007
38:
39: /*
40: * Writeback bits
41: */
42: #define WBVALID (1<<7)
43: #define WBSIZE (3<<5)
44: #define WBSZSH 5
45: #define WBTT (3<<3)
46: #define WBTM (7<<0)
47:
48: int wbfault(ulong, int, ushort, int, ulong);
49: ulong normalize(ulong, ulong, ulong);
50:
51: extern struct{
52: ulong addr;
53: ulong baddr;
54: Lock;
55: }kmapalloc;
56:
57: void
58: fault68040(Ureg *ur, FFrame *f)
59: {
60: ulong addr, badvaddr;
61: int user, read, insyscall;
62: char buf[ERRLEN];
63: flushatc();
64: if(u == 0){
65: dumpregs(ur);
66: print("ssw=%ux ea=%lux fa=%lux\n", f->ssw, f->ea, f->fa);
67: panic("fault u==0 pc=%lux fa=%lux ssw=%lux", ur->pc, f->fa, f->ssw);
68: }
69:
70: insyscall = u->p->insyscall;
71: u->p->insyscall = 1;
72: addr = f->fa;
73: addr &= VAMASK;
74: badvaddr = addr;
75: addr &= ~(BY2PG-1);
76: read = 0;
77: if(f->ssw & READ)
78: read = 1;
79: user = !(ur->sr&SUPER);
80: if(user)
81: u->dbgreg = ur;
82: if((f->ssw&TM) == 0)
83: panic("cache push pc %lux addr %lux ssw %lux\n", ur->pc, f->fa, f->ssw);
84: /* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/
85:
86: /*
87: * original fault plus 3 writeback buffers
88: */
89: if(fault(addr, read) < 0
90: || wbfault(f->wb1a, user, f->wb1s, 1, normalize(f->wb1s, f->wb1a, f->wb1d)) < 0
91: || wbfault(f->wb2a, user, f->wb2s, 2, f->wb2d) < 0
92: || wbfault(f->wb3a, user, f->wb3s, 3, f->wb3d) < 0){
93: if(user){
94: sprint(buf, "sys: trap: fault %s addr=0x%lux",
95: read? "read" : "write", badvaddr);
96: postnote(u->p, 1, buf, NDebug);
97: notify(ur);
98: return;
99: }
100: dumpregs(ur);
101: print("wb1a %lux wb1s %lux wb1d %lux\n", f->wb1a, f->wb1s, f->wb1d);
102: print("wb2a %lux wb2s %lux wb2d %lux\n", f->wb2a, f->wb2s, f->wb2d);
103: print("wb3a %lux wb3s %lux wb3d %lux\n", f->wb3a, f->wb3s, f->wb3d);
104: panic("fault: 0x%lux 0x%lux", badvaddr, addr);
105: }
106: u->p->insyscall = insyscall;
107: if(user)
108: notify(ur);
109: }
110:
111: /*
112: * get relevant data into the right hand side of the long
113: */
114: ulong
115: normalize(ulong stat, ulong addr, ulong val)
116: {
117: int thecase, size;
118:
119: size = (stat&WBSIZE) >> WBSZSH;
120: thecase = (size<<2) | (addr&3);
121: switch(thecase){
122: /* long write */
123: case 0: return val;
124: case 1: return (val<<8) | ((val>>24)&0xff);
125: case 2: return (val<<16) | ((val>>16)&0xffff);
126: case 3: return (val<<24) | ((val>>8)&0xffffff);
127: /* byte write */
128: case 4: return val>>24;
129: case 5: return val>>16;
130: case 6: return val>>8;
131: case 7: return val;
132: /* short write */
133: case 8: return val>>16;
134: case 9: return val>>8;
135: case 10: return val;
136: case 11: return (val<<8) | ((val>>24)&0xff);
137: }
138: }
139:
140: /*
141: * Check fault status before doing writeback
142: */
143: int
144: wbfault(ulong fa, int user, ushort wbs, int wbn, ulong d)
145: {
146: int s;
147: ulong addr;
148:
149: if(!(wbs & WBVALID))
150: return 0;
151: if(wbs & WBTT)
152: panic("writeback%d status %ux", wbn, wbs);
153: addr = fa & ~(BY2PG-1);
154: s = tsz[(wbs&WBSIZE) >> WBSZSH];
155: if(user || !kernaddr(addr)){
156: if(fault(fa, 0) < 0){
157: print("wbfault: %lux, 0\n", fa);
158: return -1;
159: }
160: if(addr != ((fa+s-1)&~(BY2PG-1)))
161: if(fault(fa+s-1, 0) < 0){
162: print("wbfault: %lux, %lux\n", fa, fa+s-1);
163: return -1;
164: }
165: }
166:
167: switch(s){
168: case 4:
169: *(ulong*)fa = d;
170: break;
171: case 1:
172: *(uchar*)fa = d;
173: break;
174: case 2:
175: *(ushort*)fa = d;
176: break;
177: default:
178: panic("writeback%d %d\n", wbn, s);
179: }
180: return 0;
181: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.