xref: /csrg-svn/sys/tahoe/tahoe/trap.c (revision 25678)
1*25678Ssam /*	trap.c	1.2	86/01/05	*/
224012Ssam 
3*25678Ssam #include "../tahoe/psl.h"
4*25678Ssam #include "../tahoe/reg.h"
5*25678Ssam #include "../tahoe/pte.h"
6*25678Ssam #include "../tahoe/mtpr.h"
724012Ssam 
8*25678Ssam #include "param.h"
9*25678Ssam #include "systm.h"
10*25678Ssam #include "dir.h"
11*25678Ssam #include "user.h"
12*25678Ssam #include "proc.h"
13*25678Ssam #include "seg.h"
14*25678Ssam #include "acct.h"
15*25678Ssam #include "kernel.h"
16*25678Ssam #define	SYSCALLTRACE
1724012Ssam #ifdef SYSCALLTRACE
1824012Ssam #include "../sys/syscalls.c"
1924012Ssam #endif
2024012Ssam 
21*25678Ssam #include "../tahoe/trap.h"
22*25678Ssam 
2324012Ssam #define	USER	040		/* user-mode flag added to type */
2424012Ssam 
25*25678Ssam struct	sysent sysent[];
26*25678Ssam int	nsysent;
2724012Ssam 
28*25678Ssam char	*trap_type[] = {
29*25678Ssam 	"Reserved addressing mode",		/* T_RESADFLT */
30*25678Ssam 	"Privileged instruction",		/* T_PRIVINFLT */
31*25678Ssam 	"Reserved operand",			/* T_RESOPFLT */
32*25678Ssam 	"Breakpoint",				/* T_BPTFLT */
33*25678Ssam 	0,
34*25678Ssam 	"Kernel call",				/* T_SYSCALL */
35*25678Ssam 	"Arithmetic trap",			/* T_ARITHTRAP */
36*25678Ssam 	"System forced exception",		/* T_ASTFLT */
37*25678Ssam 	"Segmentation fault",			/* T_SEGFLT */
38*25678Ssam 	"Protection fault",			/* T_PROTFLT */
39*25678Ssam 	"Trace trap",				/* T_TRCTRAP */
40*25678Ssam 	0,
41*25678Ssam 	"Page fault",				/* T_PAGEFLT */
42*25678Ssam 	"Page table fault",			/* T_TABLEFLT */
43*25678Ssam 	"Alignment fault",			/* T_ALIGNFLT */
44*25678Ssam 	"Kernel stack not valid",		/* T_KSPNOTVAL */
45*25678Ssam 	"Bus error",				/* T_BUSERR */
46*25678Ssam };
47*25678Ssam #define	TRAP_TYPES	(sizeof (trap_type) / sizeof (trap_type[0]))
48*25678Ssam 
4924012Ssam /*
5024012Ssam  * Called from the trap handler when a processor trap occurs.
5124012Ssam  */
52*25678Ssam /*ARGSUSED*/
5324012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
54*25678Ssam 	unsigned type, code;
5524012Ssam {
56*25678Ssam 	int r0, r1;		/* must reserve space */
5724012Ssam 	register int *locr0 = ((int *)&psl)-PS;
5824012Ssam 	register int i;
5924012Ssam 	register struct proc *p;
6024012Ssam 	struct timeval syst;
6124012Ssam 
62*25678Ssam #ifdef lint
63*25678Ssam 	r0 = 0; r0 = r0; r1 = 0; r1 = r1;
64*25678Ssam #endif
6524012Ssam 	syst = u.u_ru.ru_stime;
6624012Ssam 	if (USERMODE(locr0[PS])) {
6724012Ssam 		type |= USER;
6824012Ssam 		u.u_ar0 = locr0;
6924012Ssam 	}
7024012Ssam 	switch (type) {
7124012Ssam 
72*25678Ssam 	default:
73*25678Ssam 		printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
74*25678Ssam 		type &= ~USER;
75*25678Ssam 		if (type < TRAP_TYPES && trap_type[type])
76*25678Ssam 			panic(trap_type[type]);
77*25678Ssam 		else
78*25678Ssam 			panic("trap");
79*25678Ssam 		/*NOTREACHED*/
8024012Ssam 
81*25678Ssam 	case T_PROTFLT + USER:		/* protection fault */
8224012Ssam 		i = SIGBUS;
8324012Ssam 		break;
8424012Ssam 
8524012Ssam 	case T_PRIVINFLT + USER:	/* privileged instruction fault */
86*25678Ssam 	case T_RESADFLT + USER:		/* reserved addressing fault */
87*25678Ssam 	case T_RESOPFLT + USER:		/* resereved operand fault */
88*25678Ssam 	case T_ALIGNFLT + USER:		/* unaligned data fault */
8924012Ssam 		u.u_code = type &~ USER;
9024012Ssam 		i = SIGILL;
9124012Ssam 		break;
9224012Ssam 
93*25678Ssam 	case T_ASTFLT + USER:		/* Allow process switch */
9424012Ssam 	case T_ASTFLT:
9524012Ssam 		astoff();
9624012Ssam 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
9724012Ssam 			addupc(pc, &u.u_prof, 1);
9824012Ssam 			u.u_procp->p_flag &= ~SOWEUPC;
9924012Ssam 		}
10024012Ssam 		goto out;
10124012Ssam 
10224012Ssam 	case T_ARITHTRAP + USER:
10324012Ssam 		u.u_code = code;
10424012Ssam 		i = SIGFPE;
10524012Ssam 		break;
10624012Ssam 
10724012Ssam 	/*
10824012Ssam 	 * If the user SP is above the stack segment,
10924012Ssam 	 * grow the stack automatically.
11024012Ssam 	 */
11124012Ssam 	case T_SEGFLT + USER:
11224012Ssam 		if (grow((unsigned)locr0[SP]) || grow(code))
11324012Ssam 			goto out;
11424012Ssam 		i = SIGSEGV;
11524012Ssam 		break;
11624012Ssam 
117*25678Ssam 	case T_TABLEFLT:		/* allow page table faults in kernel */
118*25678Ssam 	case T_TABLEFLT + USER:		/* page table fault */
11924012Ssam 		panic("ptable fault");
12024012Ssam 
121*25678Ssam 	case T_PAGEFLT:			/* allow page faults in kernel mode */
122*25678Ssam 	case T_PAGEFLT + USER:		/* page fault */
12324012Ssam 		i = u.u_error;
124*25678Ssam 		pagein(code, 0);
12524012Ssam 		u.u_error = i;
12624012Ssam 		if (type == T_PAGEFLT)
12724012Ssam 			return;
12824012Ssam 		goto out;
12924012Ssam 
130*25678Ssam 	case T_BPTFLT + USER:		/* bpt instruction fault */
131*25678Ssam 	case T_TRCTRAP + USER:		/* trace trap */
13224012Ssam 		locr0[PS] &= ~PSL_T;
13324012Ssam 		i = SIGTRAP;
13424012Ssam 		break;
135*25678Ssam 
13624012Ssam 	case T_KSPNOTVAL:
13724012Ssam 	case T_KSPNOTVAL + USER:
13824012Ssam 		i = SIGKILL;	/* There is nothing to do but to kill the
13924012Ssam 				 * process.. */
14024012Ssam 		printf("KSP NOT VALID.\n");
14124012Ssam 		break;
14224012Ssam 
143*25678Ssam 	case T_BUSERR + USER:
144*25678Ssam 		i = SIGBUS;
145*25678Ssam 		u.u_code = code;
146*25678Ssam 		break;
14724012Ssam 	}
14824012Ssam 	psignal(u.u_procp, i);
14924012Ssam out:
15024012Ssam 	p = u.u_procp;
15124012Ssam 	if (p->p_cursig || ISSIG(p))
15224012Ssam 		psig();
15324012Ssam 	p->p_pri = p->p_usrpri;
15424012Ssam 	if (runrun) {
15524012Ssam 		/*
15624012Ssam 		 * Since we are u.u_procp, clock will normally just change
15724012Ssam 		 * our priority without moving us from one queue to another
15824012Ssam 		 * (since the running process is not on a queue.)
15924012Ssam 		 * If that happened after we setrq ourselves but before we
16024012Ssam 		 * swtch()'ed, we might not be on the queue indicated by
16124012Ssam 		 * our priority.
16224012Ssam 		 */
16324012Ssam 		(void) spl8();
16424012Ssam 		setrq(p);
16524012Ssam 		u.u_ru.ru_nivcsw++;
16624012Ssam 		swtch();
16724012Ssam 	}
16824012Ssam 	if (u.u_prof.pr_scale) {
16924012Ssam 		int ticks;
17024012Ssam 		struct timeval *tv = &u.u_ru.ru_stime;
17124012Ssam 
17224012Ssam 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
17324012Ssam 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
17424012Ssam 		if (ticks)
17524012Ssam 			addupc(locr0[PC], &u.u_prof, ticks);
17624012Ssam 	}
17724012Ssam 	curpri = p->p_pri;
17824012Ssam }
17924012Ssam 
18024012Ssam #ifdef SYSCALLTRACE
181*25678Ssam int	syscalltrace = 0;
18224012Ssam #endif
18324012Ssam 
18424012Ssam /*
185*25678Ssam  * Called from locore when a system call occurs
18624012Ssam  */
187*25678Ssam /*ARGSUSED*/
18824012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
189*25678Ssam 	unsigned code;
19024012Ssam {
191*25678Ssam 	int r0, r1;			/* must reserve space */
19224012Ssam 	register int *locr0 = ((int *)&psl)-PS;
193*25678Ssam 	register caddr_t params;
194*25678Ssam 	register int i;
19524012Ssam 	register struct sysent *callp;
19624012Ssam 	register struct proc *p;
197*25678Ssam 	struct timeval syst;
19824012Ssam 	int opc;
19924012Ssam 
200*25678Ssam #ifdef lint
201*25678Ssam 	r0 = 0; r0 = r0; r1 = 0; r1 = r1;
202*25678Ssam #endif
20324012Ssam 	syst = u.u_ru.ru_stime;
20424012Ssam 	if (!USERMODE(locr0[PS]))
20524012Ssam 		panic("syscall");
20624012Ssam 	u.u_ar0 = locr0;
207*25678Ssam 	if (code == 139) {			/* 4.2 COMPATIBILTY XXX */
208*25678Ssam 		osigcleanup();			/* 4.2 COMPATIBILTY XXX */
209*25678Ssam 		goto done;			/* 4.2 COMPATIBILTY XXX */
21024012Ssam 	}
21124012Ssam 	params = (caddr_t)locr0[FP] + NBPW;
21224012Ssam 	u.u_error = 0;
213*25678Ssam /* BEGIN GROT */
214*25678Ssam 	/*
215*25678Ssam 	 * Try to reconstruct pc, assuming code
216*25678Ssam 	 * is an immediate constant
217*25678Ssam 	 */
21824012Ssam 	opc = pc - 2;		/* short literal */
21924012Ssam 	if (code > 0x3f) {
220*25678Ssam 		opc--;				/* byte immediate */
22124012Ssam 		if (code > 0x7f) {
222*25678Ssam 			opc--;			/* word immediate */
22324012Ssam 			if (code > 0x7fff)
22424012Ssam 				opc -= 2;	/* long immediate */
22524012Ssam 		}
22624012Ssam 	}
227*25678Ssam /* END GROT */
22824012Ssam 	callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
22924012Ssam 	if (callp == sysent) {
23024012Ssam 		i = fuword(params);
23124012Ssam 		params += NBPW;
232*25678Ssam 		callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
23324012Ssam 	}
234*25678Ssam 	if ((i = callp->sy_narg * sizeof (int)) &&
235*25678Ssam 	    (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
236*25678Ssam 		locr0[R0] = u.u_error;
237*25678Ssam 		locr0[PS] |= PSL_C;	/* carry bit */
238*25678Ssam 		goto done;
23924012Ssam 	}
24024012Ssam 	u.u_r.r_val1 = 0;
241*25678Ssam 	u.u_r.r_val2 = locr0[R1];
24224012Ssam 	if (setjmp(&u.u_qsave)) {
243*25678Ssam 		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
24424012Ssam 			u.u_error = EINTR;
24524012Ssam 	} else {
246*25678Ssam 		u.u_eosys = NORMALRETURN;
24724012Ssam #ifdef SYSCALLTRACE
24824012Ssam 		if (syscalltrace) {
24924012Ssam 			register int i;
25024012Ssam 			char *cp;
25124012Ssam 
25224012Ssam 			if (code >= nsysent)
25324012Ssam 				printf("0x%x", code);
25424012Ssam 			else
25524012Ssam 				printf("%s", syscallnames[code]);
25624012Ssam 			cp = "(";
25724012Ssam 			for (i= 0; i < callp->sy_narg; i++) {
25824012Ssam 				printf("%s%x", cp, u.u_arg[i]);
25924012Ssam 				cp = ", ";
26024012Ssam 			}
26124012Ssam 			if (i)
26224012Ssam 				putchar(')', 0);
26324012Ssam 			putchar('\n', 0);
26424012Ssam 		}
26524012Ssam #endif
266*25678Ssam 		(*callp->sy_call)();
26724012Ssam 	}
268*25678Ssam 	if (u.u_eosys == NORMALRETURN) {
269*25678Ssam 		if (u.u_error) {
270*25678Ssam 			locr0[R0] = u.u_error;
271*25678Ssam 			locr0[PS] |= PSL_C;	/* carry bit */
272*25678Ssam 		} else {
273*25678Ssam 			locr0[PS] &= ~PSL_C;	/* clear carry bit */
274*25678Ssam 			locr0[R0] = u.u_r.r_val1;
275*25678Ssam 			locr0[R1] = u.u_r.r_val2;
276*25678Ssam 		}
277*25678Ssam 	} else if (u.u_eosys == RESTARTSYS)
27824012Ssam 		pc = opc;
279*25678Ssam 	/* else if (u.u_eosys == JUSTRETURN) */
280*25678Ssam 		/* nothing to do */
28124012Ssam done:
28224012Ssam 	p = u.u_procp;
28324012Ssam 	if (p->p_cursig || ISSIG(p))
28424012Ssam 		psig();
28524012Ssam 	p->p_pri = p->p_usrpri;
28624012Ssam 	if (runrun) {
28724012Ssam 		/*
28824012Ssam 		 * Since we are u.u_procp, clock will normally just change
28924012Ssam 		 * our priority without moving us from one queue to another
29024012Ssam 		 * (since the running process is not on a queue.)
29124012Ssam 		 * If that happened after we setrq ourselves but before we
29224012Ssam 		 * swtch()'ed, we might not be on the queue indicated by
29324012Ssam 		 * our priority.
29424012Ssam 		 */
29524012Ssam 		(void) spl8();
29624012Ssam 		setrq(p);
29724012Ssam 		u.u_ru.ru_nivcsw++;
29824012Ssam 		swtch();
29924012Ssam 	}
30024012Ssam 	if (u.u_prof.pr_scale) {
30124012Ssam 		int ticks;
30224012Ssam 		struct timeval *tv = &u.u_ru.ru_stime;
30324012Ssam 
30424012Ssam 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
30524012Ssam 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
30624012Ssam 		if (ticks)
30724012Ssam 			addupc(locr0[PC], &u.u_prof, ticks);
30824012Ssam 	}
30924012Ssam 	curpri = p->p_pri;
31024012Ssam }
31124012Ssam 
31224012Ssam /*
31324012Ssam  * nonexistent system call-- signal process (may want to handle it)
31424012Ssam  * flag error if process won't see signal immediately
31524012Ssam  * Q: should we do that all the time ??
31624012Ssam  */
31724012Ssam nosys()
31824012Ssam {
319*25678Ssam 
32024012Ssam 	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
32124012Ssam 		u.u_error = EINVAL;
32224012Ssam 	psignal(u.u_procp, SIGSYS);
32324012Ssam }
32424012Ssam 
325*25678Ssam #ifdef notdef
32624012Ssam /*
32724012Ssam  * Ignored system call
32824012Ssam  */
32924012Ssam nullsys()
33024012Ssam {
33124012Ssam 
33224012Ssam }
333*25678Ssam #endif
334