|
|
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 "io.h"
8: #include "../port/error.h"
9:
10: void noted(Ureg*, ulong);
11: void rfnote(Ureg*);
12:
13: char *regname[]={
14: "R0",
15: "R1",
16: "R2",
17: "R3",
18: "R4",
19: "R5",
20: "R6",
21: "R7",
22: "A0",
23: "A1",
24: "A2",
25: "A3",
26: "A4",
27: "A5",
28: "A6",
29: "A7",
30: };
31:
32: long ticks;
33:
34: char *trapname[]={
35: "reset isp",
36: "reset ipc",
37: "bus error",
38: "address error",
39: "illegal instruction",
40: "zero divide",
41: "chk, chk2 instruction",
42: "trapcc instruction",
43: "privilege violation",
44: "trace",
45: "line 1010 emulator",
46: "line 1111 emulator",
47: "reserved",
48: "coprocessor protocol violation",
49: "format error",
50: "uninitialized interrupt",
51: "unassigned 0x40",
52: "unassigned 0x44",
53: "unassigned 0x48",
54: "unassigned 0x4C",
55: "unassigned 0x50",
56: "unassigned 0x54",
57: "unassigned 0x58",
58: "unassigned 0x5C",
59: "spurious interrupt",
60: "level 1 autovector (tac)",
61: "level 2 autovector (port)",
62: "level 3 autovector (incon)",
63: "level 4 autovector (mouse)",
64: "level 5 autovector (uart)",
65: "level 6 autovector (sync)",
66: "level 7 autovector",
67: };
68:
69: char *fptrapname[]={
70: [49-49] "inexact result",
71: [50-49] "divide by zero",
72: [51-49] "underflow",
73: [52-49] "operand error",
74: [53-49] "overflow",
75: [54-49] "signaling NaN",
76: };
77:
78: char*
79: excname(unsigned vo, ulong pc)
80: {
81: static char buf[32]; /* BUG: not reentrant! */
82: ulong fppc;
83:
84: vo &= 0x0FFF;
85: vo >>= 2;
86: if(vo < sizeof trapname/sizeof(char*)){
87: /* special case, and pc will be o.k. */
88: if(vo==4 && *(ushort*)pc==0x4848)
89: return "breakpoint";
90: sprint(buf, "trap: %s", trapname[vo]);
91: return buf;
92: }
93: if(49<=vo && vo<=54){
94: fppc = 0;
95: if(u)
96: fppc = *(ulong*)(u->fpsave.reg+8);
97: sprint(buf, "fp: %s fppc=0x%lux", fptrapname[vo-49], fppc);
98: return buf;
99: }
100: sprint(buf, "offset 0x%ux", vo<<2);
101: return buf;
102: }
103:
104: void
105: trap(Ureg *ur)
106: {
107: int user;
108: char buf[64];
109:
110: user = !(ur->sr&SUPER);
111:
112: if(u)
113: u->dbgreg = ur;
114:
115: if(user){
116: splhi();
117: procsave(u->p);
118: spllo();
119: sprint(buf, "sys: %s", excname(ur->vo, ur->pc));
120: postnote(u->p, 1, buf, NDebug);
121: }else{
122: print("kernel trap %s pc=0x%lux\n", excname(ur->vo, ur->pc), ur->pc);
123: dumpregs(ur);
124: exit(1);
125: }
126:
127: if(user)
128: notify(ur);
129: }
130:
131: void
132: dumpstack(void)
133: {
134: ulong l, v, i;
135: extern ulong etext;
136:
137: if(u==0)
138: return;
139:
140: i = 0;
141: for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
142: v = *(ulong*)l;
143: if(KTZERO < v && v < (ulong)&etext){
144: print("%lux\t", v);
145: if(++i == 4){
146: i = 0;
147: print("\n");
148: }
149: }
150: }
151: print("\n");
152: }
153:
154: void
155: dumpregs(Ureg *ur)
156: {
157: int i;
158: ulong *l;
159:
160: if(u)
161: print("registers for %s %d\n", u->p->text, u->p->pid);
162: else
163: print("registers for kernel\n");
164: print("SR=%ux PC=%lux VO=%lux, USP=%lux\n", ur->sr, ur->pc, ur->vo, ur->usp);
165: l = &ur->r0;
166: for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
167: print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
168: }
169:
170: /*
171: * Call user, if necessary, with note
172: */
173: int
174: notify(Ureg *ur)
175: {
176: int l;
177: ulong s, sp;
178: Note *n;
179:
180: if(u->p->procctl)
181: procctl(u->p);
182: if(u->nnote == 0)
183: return 0;
184:
185: s = spllo();
186: qlock(&u->p->debug);
187: u->p->notepending = 0;
188: n = &u->note[0];
189: if(strncmp(n->msg, "sys:", 4) == 0){
190: l = strlen(n->msg);
191: if(l > ERRLEN-15) /* " pc=0x12345678\0" */
192: l = ERRLEN-15;
193: sprint(n->msg+l, " pc=0x%lux", ur->pc);
194: }
195: if(n->flag!=NUser && (u->notified || u->notify==0)){
196: if(n->flag == NDebug){
197: qunlock(&u->p->debug);
198: pprint("suicide: %s\n", n->msg);
199: }else
200: qunlock(&u->p->debug);
201: pexit(n->msg, n->flag!=NDebug);
202: }
203:
204: if(u->notified){
205: qunlock(&u->p->debug);
206: splx(s);
207: return 0;
208: }
209:
210: if(!u->notify){
211: qunlock(&u->p->debug);
212: pexit(n->msg, n->flag!=NDebug);
213: }
214:
215: sp = ur->usp - sizeof(Ureg);
216:
217: if(!okaddr((ulong)u->notify, BY2WD, 0)
218: || !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){
219: qunlock(&u->p->debug);
220: pprint("suicide: bad address in notify\n");
221: pexit("Suicide", 0);
222: }
223:
224: memmove((Ureg*)sp, ur, sizeof(Ureg));
225: *(Ureg**)(sp-BY2WD) = u->ureg; /* word under Ureg is old u->ureg */
226: u->ureg = (void*)sp;
227: sp -= BY2WD+ERRLEN;
228: memmove((char*)sp, u->note[0].msg, ERRLEN);
229: sp -= 3*BY2WD;
230: *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
231: *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */
232: *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
233: ur->usp = sp;
234: ur->pc = (ulong)u->notify;
235: ur->vo = 0x0080; /* pretend we're returning from syscall */
236: u->notified = 1;
237: u->nnote--;
238: memmove(&u->lastnote, &u->note[0], sizeof(Note));
239: memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note));
240: qunlock(&u->p->debug);
241: splx(s);
242: return 1;
243: }
244:
245: /*
246: * Check that sr and vo are OK to return from note.
247: */
248: int
249: validstatus(ushort usr, ushort uvo)
250: {
251: ushort fmt, vector;
252: static char okfmt[] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 };
253:
254: fmt = uvo>>12;
255: if(!okfmt[fmt])
256: return 0;
257: if(uvo & 3) /* offset must be even */
258: return 0;
259: vector = (uvo & 0xFFF) >> 2;
260: if(vector<2 || vector >58) /* <2 is reset; greater than 58 is undefined */
261: return 0;
262: if(usr & 0xFF00) /* system byte must be clear */
263: return 0;
264: return 1;
265: }
266:
267: /*
268: * Return user to state before notify()
269: */
270: void
271: noted(Ureg *ur, ulong arg0)
272: {
273: Ureg *nur;
274: ulong oureg, sp;
275:
276: qlock(&u->p->debug);
277: if(arg0!=NRSTR && !u->notified){
278: qunlock(&u->p->debug);
279: pprint("call to noted() when not notified\n");
280: pexit("Suicide", 0);
281: }
282: u->notified = 0;
283:
284: nur = u->ureg;
285:
286: oureg = (ulong)nur;
287: if((oureg & (BY2WD-1))
288: || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
289: qunlock(&u->p->debug);
290: pprint("bad ureg in noted or call to noted() when not notified\n");
291: pexit("Suicide", 0);
292: }
293:
294: if(!validstatus(nur->sr, nur->vo)){
295: qunlock(&u->p->debug);
296: pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo);
297: pexit("Suicide", 0);
298: }
299:
300: memmove(ur, u->ureg, sizeof(Ureg));
301: switch(arg0){
302: case NCONT:
303: case NRSTR:
304: if(!okaddr(nur->pc, 2, 0) || !okaddr(nur->usp, BY2WD, 0)){
305: qunlock(&u->p->debug);
306: pprint("suicide: trap in noted\n");
307: pexit("Suicide", 0);
308: }
309: u->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
310: qunlock(&u->p->debug);
311: splhi();
312: rfnote(ur);
313: break;
314: /* never returns */
315:
316: case NSAVE:
317: if(!okaddr(nur->pc, 2, 0) || !okaddr(nur->usp, BY2WD, 0)){
318: qunlock(&u->p->debug);
319: pprint("suicide: trap in noted\n");
320: pexit("Suicide", 0);
321: }
322: qunlock(&u->p->debug);
323: sp = oureg-4*BY2WD-ERRLEN;
324: splhi();
325: ur->vo = 0x0080; /* we're returning from syscall */
326: ur->usp = sp;
327: ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
328: ((ulong*)sp)[0] = 0; /* arg 0 is pc */
329: rfnote(ur);
330: break;
331:
332: default:
333: u->lastnote.flag = NDebug;
334: qunlock(&u->p->debug);
335: pprint("unknown noted arg 0x%lux\n", arg0);
336: pprint("suicide: %s\n", u->lastnote.msg);
337: pexit(u->lastnote.msg, 0);
338:
339: case NDFLT:
340: if(u->lastnote.flag == NDebug){
341: qunlock(&u->p->debug);
342: pprint("suicide: %s\n", u->lastnote.msg);
343: }else
344: qunlock(&u->p->debug);
345: pexit(u->lastnote.msg, u->lastnote.flag!=NDebug);
346: }
347: }
348:
349: #include "../port/systab.h"
350:
351: long
352: syscall(Ureg *aur)
353: {
354: long ret;
355: ulong sp;
356: Ureg *ur;
357:
358: u->p->insyscall = 1;
359: ur = aur;
360: u->dbgreg = aur;
361: u->p->pc = ur->pc;
362: if(ur->sr & SUPER)
363: panic("recursive system call");
364:
365: /* must save FP registers before fork */
366: if(u->p->fpstate==FPactive && ur->r0==RFORK){
367: splhi();
368: procsave(u->p);
369: spllo();
370: }
371:
372: if(u->p->procctl)
373: procctl(u->p);
374:
375: u->scallnr = ur->r0;
376: sp = ur->usp;
377:
378: u->nerrlab = 0;
379: ret = -1;
380: if(!waserror()){
381: if(u->scallnr >= sizeof systab/sizeof systab[0]){
382: pprint("bad sys call number %d pc %lux\n", u->scallnr, ur->pc);
383: postnote(u->p, 1, "sys: bad sys call", NDebug);
384: error(Ebadarg);
385: }
386:
387: if(sp & (BY2WD-1)){
388: pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp);
389: postnote(u->p, 1, "sys: odd stack", NDebug);
390: error(Ebadarg);
391: }
392:
393: if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
394: validaddr(sp, sizeof(Sargs), 0);
395:
396: u->s = *((Sargs*)(sp+1*BY2WD));
397: u->p->psstate = sysctab[u->scallnr];
398:
399: ret = (*systab[u->scallnr])(u->s.args);
400: poperror();
401: }
402:
403: u->nerrlab = 0;
404: u->p->insyscall = 0;
405: u->p->psstate = 0;
406:
407: if(u->scallnr == NOTED) /* ugly hack */
408: noted(aur, *(ulong*)(sp+BY2WD)); /* doesn't return */
409: splhi();
410: if(u->scallnr!=RFORK && (u->p->procctl || u->nnote)){
411: ur->r0 = ret;
412: notify(ur);
413: }
414: return ret;
415: }
416:
417: long
418: execregs(ulong entry, ulong ssize, ulong nargs)
419: {
420: ulong *sp;
421:
422: sp = (ulong*)(USTKTOP - ssize);
423: *--sp = nargs;
424: ((Ureg*)UREGADDR)->usp = (ulong)sp;
425: ((Ureg*)UREGADDR)->pc = entry;
426: return USTKTOP-BY2WD; /* address of user-level clock */
427: }
428:
429: ulong
430: userpc(void)
431: {
432: return ((Ureg*)UREGADDR)->pc;
433: }
434:
435: /* This routine must save the values of registers the user is not permitted to write
436: * from devproc and the restore the saved values before returning
437: */
438: void
439: setregisters(Ureg *xp, char *pureg, char *uva, int n)
440: {
441: ushort sr;
442: ulong magic;
443: ushort vo;
444: char microstate[UREGVARSZ];
445:
446: sr = xp->sr;
447: vo = xp->vo;
448: magic = xp->magic;
449: memmove(microstate, xp->microstate, UREGVARSZ);
450:
451: memmove(pureg, uva, n);
452:
453: xp->sr = (sr&0xff00) |(xp->sr&0xff);
454: xp->vo = vo;
455: xp->magic = magic;
456: memmove(xp->microstate, microstate, UREGVARSZ);
457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.