|
|
1.1 root 1: /* trap.c 4.10 84/02/09 */
2:
3: #include "../machine/psl.h"
4: #include "../machine/reg.h"
5: #include "../machine/pte.h"
6:
7: #include "../h/param.h"
8: #include "../h/systm.h"
9: #include "../h/dir.h"
10: #include "../h/user.h"
11: #include "../h/proc.h"
12: #include "../h/seg.h"
13: #include "../machine/trap.h"
14: #include "../h/acct.h"
15: #include "../h/kernel.h"
16: #include "../machine/mtpr.h"
1.1.1.2 ! root 17: #include "../machine/alignment.h"
1.1 root 18: #ifdef SYSCALLTRACE
19: #include "../sys/syscalls.c"
20: #endif
21: #include "../machine/fp_in_krnl.h"
22:
23: #define USER 040 /* user-mode flag added to type */
1.1.1.2 ! root 24: #define SYSTEM 0xc0000000 /* system space */
1.1 root 25:
26: struct sysent sysent[];
27: int nsysent;
28:
29: /*
30: * Called from the trap handler when a processor trap occurs.
31: */
1.1.1.2 ! root 32: trap(sP, type, hfs, accmst, acclst, dbl, code, pC, psL)
1.1 root 33: unsigned code;
34: {
35: /* Next 2 dummy variables MUST BE the first local */
36: /* variables; leaving place for registers 0 and 1 */
37: /* which are not preserved by the 'cct' */
38:
39: int dumm1; /* register 1 */
40: int dumm0; /* register 0 */
41: register dumm3; /* register 12 is the 1'st register variable */
42: /* in TAHOE (register 11 in VAX) */
43:
1.1.1.2 ! root 44: register int *locr0 = ((int *)&psL)-PS;
1.1 root 45: register int i;
46: register struct proc *p;
47: struct timeval syst;
48: char *typename;
1.1.1.2 ! root 49: process_info *infop;
1.1 root 50:
51: syst = u.u_ru.ru_stime;
52: if (USERMODE(locr0[PS])) {
53: type |= USER;
54: u.u_ar0 = locr0;
1.1.1.2 ! root 55: } else if (u.u_eosys & EMULATEALIGN) {
! 56: type |= USER;
! 57: u.u_ar0 = locr0;
! 58: locr0[PS] |= PSL_USERSET;
1.1 root 59: }
1.1.1.2 ! root 60:
1.1 root 61: switch (type) {
62:
63: default: switch (type) {
64: case T_RESADFLT:
65: typename = "reserved addressing mode";break;
66: case T_PRIVINFLT:
67: typename = "illegal opcode";break;
68: case T_RESOPFLT:
69: typename = "reserved operand";break;
70: case T_BPTFLT:
71: typename = "breakpoint";break;
72: case T_SYSCALL:
73: typename = "kernel call";break;
74: case T_ARITHTRAP:
75: typename = "arithmetic exception";break;
76: case T_ASTFLT:
77: typename = "system forced exception";break;
78: case T_SEGFLT:
79: typename = "limit fault";break;
80: case T_PROTFLT:
81: typename = "illegal access type";break;
82: case T_TRCTRAP:
83: typename = "trace trap";break;
84: case T_PAGEFLT:
85: typename = "page fault";break;
86: case T_TABLEFLT:
87: typename = "page table fault";break;
88: case T_ALIGNFLT:
89: typename = "alignment fault";break;
90: case T_KSPNOTVAL:
91: typename = "kernel stack not valid";break;
92: }
93: printf("System trap (%s), code = %x, pc = %x\n",
1.1.1.2 ! root 94: typename, code, pC);
1.1 root 95: panic("trap");
96:
97: case T_PROTFLT + USER: /* protection fault */
1.1.1.2 ! root 98: if (u.u_eosys & EMULATEALIGN) {
! 99: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 100: locr0[PC] = saved_pc;
! 101: }
1.1 root 102: i = SIGBUS;
103: break;
104:
105: case T_PRIVINFLT + USER: /* privileged instruction fault */
106: case T_RESADFLT + USER: /* reserved addressing fault */
107: case T_RESOPFLT + USER: /* resereved operand fault */
108: case T_ALIGNFLT + USER: /* unaligned data fault */
1.1.1.2 ! root 109: if (u.u_eosys & EMULATEALIGN) {
! 110: typename="miscellaneous illegal user instruction";
! 111: printf("In this System trap (%s), code = %x, pc = %x\n",
! 112: typename, code, pC);
! 113: panic("trap");
! 114: }
1.1 root 115: u.u_code = type &~ USER;
116: i = SIGILL;
117: break;
118:
119: case T_ASTFLT + USER: /* Allow process switch */
120: case T_ASTFLT:
121: astoff();
122: if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
1.1.1.2 ! root 123: addupc(pC, &u.u_prof, 1);
1.1 root 124: u.u_procp->p_flag &= ~SOWEUPC;
125: }
1.1.1.2 ! root 126: if (u.u_eosys & EMULATEALIGN) {
! 127: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 128: locr0[PC] = saved_pc;
! 129: locr0[PS] &= ~PSL_USERSET;
! 130: }
1.1 root 131: goto out;
132:
133: case T_ARITHTRAP + USER:
1.1.1.2 ! root 134: if (u.u_eosys & EMULATEALIGN) {
! 135: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 136: locr0[PC] = saved_pc;
! 137: printf("in arithtrap with emulation,locr0[PC] = 0x%x, locr0[PS] = 0x%x \n",locr0[PC],locr0[PS]);
! 138: }
1.1 root 139: u.u_code = code;
140: i = SIGFPE;
141: break;
142:
143: /*
144: * If the user SP is above the stack segment,
145: * grow the stack automatically.
146: */
147: case T_SEGFLT + USER:
1.1.1.2 ! root 148: if (grow((unsigned)locr0[SP]) || grow(code)) {
! 149: if (u.u_eosys & EMULATEALIGN)
! 150: locr0[PS] &= ~PSL_USERSET;
1.1 root 151: goto out;
1.1.1.2 ! root 152: }
! 153: if (u.u_eosys & EMULATEALIGN) {
! 154: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 155: locr0[PC] = saved_pc;
! 156: }
1.1 root 157: i = SIGSEGV;
158: break;
159:
160: case T_TABLEFLT: /* allow page table faults in kernel mode */
161: case T_TABLEFLT + USER: /* page table fault */
162: panic("ptable fault");
163:
164: case T_PAGEFLT: /* allow page faults in kernel mode */
165: case T_PAGEFLT + USER: /* page fault */
166: i = u.u_error;
167: pagein(code, 0);
168: u.u_error = i;
1.1.1.2 ! root 169: if (u.u_eosys & EMULATEALIGN) {
! 170: locr0[PS] &= ~PSL_USERSET;
! 171: return;
! 172: }
1.1 root 173: if (type == T_PAGEFLT)
174: return;
175: goto out;
176:
177: case T_BPTFLT + USER: /* bpt instruction fault */
178: case T_TRCTRAP + USER: /* trace trap */
1.1.1.2 ! root 179: if (u.u_eosys & EMULATEALIGN) {
! 180: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 181: locr0[PC] = saved_pc;
! 182: }
1.1 root 183: locr0[PS] &= ~PSL_T;
184: i = SIGTRAP;
185: break;
186: case T_KSPNOTVAL:
187: case T_KSPNOTVAL + USER:
1.1.1.2 ! root 188: if (u.u_eosys & EMULATEALIGN) {
! 189: infop = (process_info *)(SYSTEM - sizeof(process_info));
! 190: locr0[PC] = saved_pc;
! 191: }
1.1 root 192: i = SIGKILL; /* There is nothing to do but to kill the
193: * process.. */
194: printf("KSP NOT VALID.\n");
195: break;
196:
197: }
198: psignal(u.u_procp, i);
199: out:
200: p = u.u_procp;
201: if (p->p_cursig || ISSIG(p))
202: psig();
203: p->p_pri = p->p_usrpri;
204: if (runrun) {
205: /*
206: * Since we are u.u_procp, clock will normally just change
207: * our priority without moving us from one queue to another
208: * (since the running process is not on a queue.)
209: * If that happened after we setrq ourselves but before we
210: * swtch()'ed, we might not be on the queue indicated by
211: * our priority.
212: */
213: (void) spl8();
214: setrq(p);
215: u.u_ru.ru_nivcsw++;
216: swtch();
217: }
218: if (u.u_prof.pr_scale) {
219: int ticks;
220: struct timeval *tv = &u.u_ru.ru_stime;
221:
222: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
223: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
224: if (ticks)
225: addupc(locr0[PC], &u.u_prof, ticks);
226: }
227: curpri = p->p_pri;
228: }
229:
230: #ifdef SYSCALLTRACE
231: int syscalltrace = 0;
232: #endif
233:
234: /*
235: * Called from the trap handler when a system call occurs
236: */
1.1.1.2 ! root 237: syscall(Sp, type, hfs, accmst, acclst, dbl, code, pC, psL)
1.1 root 238: unsigned code;
239: {
240: /* Next 2 dummy variables MUST BE the first local */
241: /* variables; leaving place for registers 0 and 1 */
242: /* which are not preserved by the 'cct' */
243:
244: int dumm1; /* register 1 */
245: int dumm0; /* register 0 */
246: register dumm3; /* register 12 is the 1'st register variable */
247: /* in TAHOE (register 11 in VAX) */
248:
1.1.1.2 ! root 249: register int *locr0 = ((int *)&psL)-PS;
1.1 root 250: register caddr_t params; /* known to be r10 below */
251: register int i; /* known to be r9 below */
252: register struct sysent *callp;
253: register struct proc *p;
254: struct timeval syst;
255: int opc;
256:
257: syst = u.u_ru.ru_stime;
258: if (!USERMODE(locr0[PS]))
259: panic("syscall");
260: u.u_ar0 = locr0;
261: if (code == 139) { /* XXX */
262: sigcleanup(); /* XXX */
263: goto done; /* XXX */
264: }
265: params = (caddr_t)locr0[FP] + NBPW;
266: u.u_error = 0;
267: /*------ DIRTY CODE !!!!!!!!!---------*/
268: /* try to reconstruct pc, assuming code is an immediate constant */
1.1.1.2 ! root 269: opc = pC - 2; /* short literal */
1.1 root 270: if (code > 0x3f) {
271: opc--; /* byte immediate */
272: if (code > 0x7f) {
273: opc--; /* word immediate */
274: if (code > 0x7fff)
275: opc -= 2; /* long immediate */
276: }
277: }
278: /*------------------------------------*/
279: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
280: if (callp == sysent) {
281: i = fuword(params);
282: params += NBPW;
1.1.1.2 ! root 283: callp = ((unsigned)i >= nsysent) ? &sysent[63] : &sysent[i];
1.1 root 284: }
285: if (i = callp->sy_narg * sizeof (int)) {
1.1.1.2 ! root 286: register int xxx; /* r6 */
! 287:
! 288: asm("prober $1,(r10),$1"); /* GROT */
! 289: asm("bnequ ok"); /* GROT */
! 290: asm("addl3 r9,r10,r6"); /* get last byte */
! 291: asm("decl r6");
! 292: asm("prober $1,(r6),$1"); /* GROT */
1.1 root 293: asm("bnequ ok"); /* GROT */
294: u.u_error = EFAULT; /* GROT */
295: goto bad; /* GROT */
296: asm("ok:"); /* GROT */
297: bcopy(params,u.u_arg,i);
298: }
299: u.u_ap = u.u_arg;
300: u.u_dirp = (caddr_t)u.u_arg[0];
301: u.u_r.r_val1 = 0;
302: u.u_r.r_val2 = locr0[R1]; /*------------ CHECK again */
303: if (setjmp(&u.u_qsave)) {
304: if (u.u_error == 0 && u.u_eosys == JUSTRETURN)
305: u.u_error = EINTR;
306: } else {
307: u.u_eosys = JUSTRETURN;
308: #ifdef SYSCALLTRACE
309: if (syscalltrace) {
310: register int i;
311: char *cp;
312:
313: if (code >= nsysent)
314: printf("0x%x", code);
315: else
316: printf("%s", syscallnames[code]);
317: cp = "(";
318: for (i= 0; i < callp->sy_narg; i++) {
319: printf("%s%x", cp, u.u_arg[i]);
320: cp = ", ";
321: }
322: if (i)
323: putchar(')', 0);
324: putchar('\n', 0);
325: }
326: #endif
327:
328: (*(callp->sy_call))();
329: }
330: if (u.u_eosys == RESTARTSYS)
1.1.1.2 ! root 331: pC = opc;
1.1 root 332: else if (u.u_error) {
333: bad:
334: locr0[R0] = u.u_error;
335: locr0[PS] |= PSL_C; /* carry bit */
336: } else {
337: locr0[PS] &= ~PSL_C; /* clear carry bit */
338: locr0[R0] = u.u_r.r_val1;
339: locr0[R1] = u.u_r.r_val2;
340: }
341: done:
342: p = u.u_procp;
343: if (p->p_cursig || ISSIG(p))
344: psig();
345: p->p_pri = p->p_usrpri;
346: if (runrun) {
347: /*
348: * Since we are u.u_procp, clock will normally just change
349: * our priority without moving us from one queue to another
350: * (since the running process is not on a queue.)
351: * If that happened after we setrq ourselves but before we
352: * swtch()'ed, we might not be on the queue indicated by
353: * our priority.
354: */
355: (void) spl8();
356: setrq(p);
357: u.u_ru.ru_nivcsw++;
358: swtch();
359: }
360: if (u.u_prof.pr_scale) {
361: int ticks;
362: struct timeval *tv = &u.u_ru.ru_stime;
363:
364: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
365: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
366: if (ticks)
367: addupc(locr0[PC], &u.u_prof, ticks);
368: }
369: curpri = p->p_pri;
370: }
371:
372: /*
373: * nonexistent system call-- signal process (may want to handle it)
374: * flag error if process won't see signal immediately
375: * Q: should we do that all the time ??
376: */
377: nosys()
378: {
379: if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
380: u.u_error = EINVAL;
381: psignal(u.u_procp, SIGSYS);
382: }
383:
384: /*
385: * Ignored system call
386: */
387: nullsys()
388: {
389:
390: }
391:
1.1.1.2 ! root 392: fpemulate(hfsreg,acc_most,acc_least,dbl,op_most,op_least,opcode,pC,psL)
1.1 root 393: {
394: /*
395: * Emulate the F.P. 'opcode'. Update psl flags as necessary.
396: * If all OK, set 'opcode' to 0, else to the F.P. exception #.
397: * Not all parameter longwords are relevant - depends on opcode.
398: *
399: * The entry mask is set so ALL registers are saved - courtesy of
400: * locore.s. This enables F.P. opcodes to change 'user' registers
401: * before return.
402: */
403:
404: /* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS. */
405:
406: /* Next 2 dummy variables MUST BE the first local */
407: /* variables; leaving place for registers 0 and 1 */
408: /* which are not preserved by the 'cct' */
409:
410: int dumm1; /* register 1 */
411: int dumm0; /* register 0 */
412: register dumm3; /* register 12 is the 1'st register variable */
413: /* in TAHOE (register 11 in VAX) */
414:
1.1.1.2 ! root 415: register int *locr0 = ((int *)&psL)-PS; /* R11 */
1.1 root 416: int hfs = 0; /* returned data about exceptions */
417: float (*f_proc)(); /* fp procedure to be called. */
418: double (*d_proc)(); /* fp procedure to be called. */
419: int dest_type; /* float or double. */
420: union{
421: float ff; /* float result. */
422: int fi;
423: }f_res;
424: union{
425: double dd; /* double result. */
426: int di[2] ;
427: }d_res;
428: extern float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf();
429: extern double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd();
430: extern float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf();
431:
432:
433:
434: switch(opcode & 0x0FF){
435:
436: case CVLF: f_proc = Kcvtlf; dest_type = FLOAT;
437: locr0[PS] &= ~PSL_DBL;
438: dbl &= ~1;break; /* clear double bit */
439: case CVLD: d_proc = Kcvtld; dest_type = DOUBLE;
440: locr0[PS] |= PSL_DBL;
441: dbl |= 1; break; /* turn on double bit */
442: case ADDF: f_proc = Kaddf; dest_type = FLOAT;
443: break;
444: case ADDD: d_proc = Kaddd; dest_type = DOUBLE;
445: break;
446: case SUBF: f_proc = Ksubf; dest_type = FLOAT;
447: break;
448: case SUBD: d_proc = Ksubd; dest_type = DOUBLE;
449: break;
450: case MULF: f_proc = Kmulf; dest_type = FLOAT;
451: break;
452: case MULD: d_proc = Kmuld; dest_type = DOUBLE;
453: break;
454: case DIVF: f_proc = Kdivf; dest_type = FLOAT;
455: break;
456: case DIVD: d_proc = Kdivd; dest_type = DOUBLE;
457: break;
458: case SINF: f_proc = Ksinf; dest_type = FLOAT;
459: break;
460: case COSF: f_proc = Kcosf; dest_type = FLOAT;
461: break;
462: case ATANF: f_proc = Katanf; dest_type = FLOAT;
463: break;
464: case LOGF: f_proc = Klogf; dest_type = FLOAT;
465: break;
466: case SQRTF: f_proc = Ksqrtf; dest_type = FLOAT;
467: break;
468: case EXPF: f_proc = Kexpf; dest_type = FLOAT;
469: break;
470: }
471:
472: switch(dest_type){
473:
474: case FLOAT:
475: f_res.ff = (*f_proc)(acc_most,acc_least,op_most,op_least,&hfs);
476:
477: if (f_res.fi == 0 ) locr0[PS] |= PSL_Z;
478: if (f_res.fi < 0 ) locr0[PS] |= PSL_N;
479: break;
480: case DOUBLE:
481: d_res.dd = (*d_proc)(acc_most,acc_least,op_most,op_least,&hfs);
482: if ((d_res.di[0] == 0) && (d_res.di[1] == 0))
483: locr0[PS] |= PSL_Z;
484: if (d_res.di[0] < 0 ) locr0[PS] |= PSL_N;
485: break;
486: }
487:
488: if (hfs & HFS_OVF){
489: locr0[PS] |= PSL_V; /* turn on overflow bit */
490: /* if (locr0[PS] & PSL_IV) { /* overflow elabled? */
491: opcode = OVF_EXC;
492: u.u_error = (hfs & HFS_DOM) ? EDOM : ERANGE;
493: return;
494: /*}*/
495: }
496: else if (hfs & HFS_UNDF){
497: if (locr0[PS] & PSL_FU){ /* underflow elabled? */
498: opcode = UNDF_EXC;
499: u.u_error = (hfs & HFS_DOM) ? EDOM : ERANGE;
500: return;
501: }
502: }
503: else if (hfs & HFS_DIVZ){
504: opcode = DIV0_EXC;
505: return;
506: }
507: else if (hfs & HFS_DOM)
508: u.u_error = EDOM;
509: else if (hfs & HFS_RANGE)
510: u.u_error = ERANGE;
511:
512: switch(dest_type){
513: case FLOAT:
514: if ((hfs & HFS_OVF) || (hfs & HFS_UNDF)) {
515: f_res.ff = 0.0;
516: locr0[PS] |= PSL_Z;
517: }
518: mvtofacc(f_res.ff, &acc_most);
519: break;
520: case DOUBLE:
521: if ((hfs & HFS_OVF) || (hfs & HFS_UNDF)) {
522: d_res.dd = 0.0;
523: locr0[PS] |= PSL_Z;
524: }
525: mvtodacc(d_res.di[0], d_res.di[1], &acc_most);
526: break;
527: }
528: opcode=0;
529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.