Commit | Line | Data |
---|---|---|
45c48dda | 1 | /* trap.c 4.17 82/09/12 */ |
ee1451be BJ |
2 | |
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
f2b0161f | 7 | #include "assym.s" |
ee1451be BJ |
8 | #include "../h/proc.h" |
9 | #include "../h/reg.h" | |
10 | #include "../h/seg.h" | |
11 | #include "../h/trap.h" | |
12 | #include "../h/psl.h" | |
13 | #include "../h/pte.h" | |
73cde86e | 14 | #include "../h/inline.h" |
cb5eab56 | 15 | #include "../h/mtpr.h" |
683ddffc | 16 | #include "../h/acct.h" |
ee1451be BJ |
17 | |
18 | #define USER 040 /* user-mode flag added to type */ | |
19 | ||
49ed6685 BJ |
20 | struct sysent sysent[]; |
21 | int nsysent; | |
ee1451be | 22 | |
683ddffc RE |
23 | char *trap_type[] = { |
24 | "Reserved addressing mode", | |
25 | "Privileged instruction", | |
26 | "Reserved operand", | |
27 | "Breakpoint", | |
28 | "Xfc trap", | |
29 | "Syscall trap", | |
30 | "Arithmetic fault", | |
31 | "Ast trap", | |
32 | "Segmentation fault", | |
33 | "Protection fault", | |
34 | "Trace trap", | |
35 | "Compatibility mode trap", | |
36 | /** these never get to "default" case | |
37 | "Page fault", | |
38 | "Page table fault", | |
39 | **/ | |
40 | }; | |
41 | #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0]) | |
42 | ||
ee1451be BJ |
43 | /* |
44 | * Called from the trap handler when a processor trap occurs. | |
45 | */ | |
46 | /*ARGSUSED*/ | |
47 | trap(sp, type, code, pc, psl) | |
48 | unsigned code; | |
49 | { | |
50 | register int *locr0 = ((int *)&psl)-PS; | |
51 | register int i; | |
52 | register struct proc *p; | |
ee1451be | 53 | |
ee1451be BJ |
54 | if (USERMODE(locr0[PS])) { |
55 | type |= USER; | |
56 | u.u_ar0 = locr0; | |
57 | } | |
58 | switch (type) { | |
59 | ||
60 | default: | |
48575cec | 61 | printf("trap type %d, code = %x, pc = %x\n", type, code, pc); |
683ddffc RE |
62 | type &= ~USER; |
63 | if ((unsigned)type < TRAP_TYPES) | |
64 | panic(trap_type[type]); | |
ee1451be BJ |
65 | panic("trap"); |
66 | ||
67 | case PROTFLT + USER: /* protection fault */ | |
68 | i = SIGBUS; | |
69 | break; | |
70 | ||
71 | case PRIVINFLT + USER: /* privileged instruction fault */ | |
72 | case RESADFLT + USER: /* reserved addressing fault */ | |
73 | case RESOPFLT + USER: /* resereved operand fault */ | |
0d83d9c2 | 74 | u.u_code = type &~ USER; |
73cde86e | 75 | i = SIGILL; |
ee1451be BJ |
76 | break; |
77 | ||
4602969d | 78 | case ASTFLT + USER: |
cb5eab56 | 79 | astoff(); |
ee1451be BJ |
80 | goto out; |
81 | ||
ee1451be | 82 | case ARITHTRAP + USER: |
afb8c59e | 83 | u.u_code = code; |
73cde86e | 84 | i = SIGFPE; |
ee1451be BJ |
85 | break; |
86 | ||
87 | /* | |
88 | * If the user SP is above the stack segment, | |
89 | * grow the stack automatically. | |
90 | */ | |
afb8c59e BJ |
91 | case SEGFLT + USER: |
92 | if (grow((unsigned)locr0[SP]) || grow(code)) | |
ee1451be | 93 | goto out; |
73cde86e | 94 | i = SIGSEGV; |
ee1451be BJ |
95 | break; |
96 | ||
97 | case TABLEFLT: /* allow page table faults in kernel mode */ | |
98 | case TABLEFLT + USER: /* page table fault */ | |
afb8c59e | 99 | panic("ptable fault"); |
ee1451be BJ |
100 | |
101 | case PAGEFLT: /* allow page faults in kernel mode */ | |
102 | case PAGEFLT + USER: /* page fault */ | |
103 | i = u.u_error; | |
afb8c59e | 104 | pagein(code); |
ee1451be | 105 | u.u_error = i; |
ee1451be | 106 | if (type == PAGEFLT) |
ee1451be | 107 | return; |
ee1451be | 108 | goto out; |
ee1451be BJ |
109 | |
110 | case BPTFLT + USER: /* bpt instruction fault */ | |
111 | case TRCTRAP + USER: /* trace trap */ | |
afb8c59e | 112 | locr0[PS] &= ~PSL_T; |
73cde86e | 113 | i = SIGTRAP; |
ee1451be BJ |
114 | break; |
115 | ||
116 | case XFCFLT + USER: /* xfc instruction fault */ | |
117 | i = SIGEMT; | |
118 | break; | |
119 | ||
120 | case COMPATFLT + USER: /* compatibility mode fault */ | |
683ddffc | 121 | u.u_acflag |= ACOMPAT; |
afb8c59e | 122 | u.u_code = code; |
73cde86e | 123 | i = SIGILL; |
ee1451be BJ |
124 | break; |
125 | } | |
126 | psignal(u.u_procp, i); | |
127 | out: | |
128 | p = u.u_procp; | |
73cde86e | 129 | if (p->p_cursig || ISSIG(p)) |
ee1451be BJ |
130 | psig(); |
131 | p->p_pri = p->p_usrpri; | |
132 | if (runrun) { | |
133 | /* | |
134 | * Since we are u.u_procp, clock will normally just change | |
135 | * our priority without moving us from one queue to another | |
136 | * (since the running process is not on a queue.) | |
137 | * If that happened after we setrq ourselves but before we | |
138 | * swtch()'ed, we might not be on the queue indicated by | |
139 | * our priority. | |
140 | */ | |
934e4ecf | 141 | (void) spl6(); |
ee1451be | 142 | setrq(p); |
4602969d | 143 | u.u_ru.ru_nivcsw++; |
ee1451be BJ |
144 | swtch(); |
145 | } | |
ee1451be BJ |
146 | curpri = p->p_pri; |
147 | } | |
148 | ||
ee1451be BJ |
149 | /* |
150 | * Called from the trap handler when a system call occurs | |
151 | */ | |
152 | /*ARGSUSED*/ | |
153 | syscall(sp, type, code, pc, psl) | |
49ed6685 | 154 | unsigned code; |
ee1451be BJ |
155 | { |
156 | register int *locr0 = ((int *)&psl)-PS; | |
157 | register caddr_t params; /* known to be r10 below */ | |
158 | register int i; /* known to be r9 below */ | |
159 | register struct sysent *callp; | |
160 | register struct proc *p; | |
73cde86e | 161 | int opc; |
ee1451be | 162 | |
ee1451be BJ |
163 | if (!USERMODE(locr0[PS])) |
164 | panic("syscall"); | |
165 | u.u_ar0 = locr0; | |
166 | params = (caddr_t)locr0[AP] + NBPW; | |
167 | u.u_error = 0; | |
6fdc0335 | 168 | opc = pc - 2; |
73cde86e BJ |
169 | if (code > 63) |
170 | opc -= 2; | |
49ed6685 | 171 | callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; |
ee1451be BJ |
172 | if (callp == sysent) { |
173 | i = fuword(params); | |
174 | params += NBPW; | |
49ed6685 | 175 | callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; |
ee1451be BJ |
176 | } |
177 | if (i = callp->sy_narg * sizeof (int)) { | |
73cde86e BJ |
178 | asm("prober $3,r9,(r10)"); /* GROT */ |
179 | asm("bnequ ok"); /* GROT */ | |
180 | u.u_error = EFAULT; /* GROT */ | |
181 | goto bad; /* GROT */ | |
182 | asm("ok:"); /* GROT */ | |
183 | asm("movc3 r9,(r10),_u+U_ARG"); /* GROT */ | |
ee1451be BJ |
184 | } |
185 | u.u_ap = u.u_arg; | |
ee1451be BJ |
186 | u.u_dirp = (caddr_t)u.u_arg[0]; |
187 | u.u_r.r_val1 = 0; | |
188 | u.u_r.r_val2 = locr0[R1]; | |
45c48dda | 189 | if (setjmp(&u.u_qsave)) { |
73cde86e BJ |
190 | if (u.u_error == 0 && u.u_eosys == JUSTRETURN) |
191 | u.u_error = EINTR; | |
192 | } else { | |
193 | u.u_eosys = JUSTRETURN; | |
194 | (*(callp->sy_call))(); | |
195 | } | |
196 | locr0[PS] &= ~PSL_C; | |
197 | if (u.u_eosys == RESTARTSYS) | |
198 | pc = opc; | |
199 | else if (u.u_eosys == SIMULATERTI) | |
200 | dorti(); | |
201 | else if (u.u_error) { | |
ee1451be BJ |
202 | bad: |
203 | locr0[R0] = u.u_error; | |
204 | locr0[PS] |= PSL_C; /* carry bit */ | |
205 | } else { | |
206 | locr0[R0] = u.u_r.r_val1; | |
207 | locr0[R1] = u.u_r.r_val2; | |
208 | } | |
209 | p = u.u_procp; | |
73cde86e | 210 | if (p->p_cursig || ISSIG(p)) |
ee1451be BJ |
211 | psig(); |
212 | p->p_pri = p->p_usrpri; | |
213 | if (runrun) { | |
214 | /* | |
215 | * Since we are u.u_procp, clock will normally just change | |
216 | * our priority without moving us from one queue to another | |
217 | * (since the running process is not on a queue.) | |
218 | * If that happened after we setrq ourselves but before we | |
219 | * swtch()'ed, we might not be on the queue indicated by | |
220 | * our priority. | |
221 | */ | |
934e4ecf | 222 | (void) spl6(); |
ee1451be | 223 | setrq(p); |
4602969d | 224 | u.u_ru.ru_nivcsw++; |
ee1451be BJ |
225 | swtch(); |
226 | } | |
ee1451be BJ |
227 | curpri = p->p_pri; |
228 | } | |
229 | ||
230 | /* | |
683ddffc RE |
231 | * nonexistent system call-- signal process (may want to handle it) |
232 | * flag error if process won't see signal immediately | |
233 | * Q: should we do that all the time ?? | |
ee1451be BJ |
234 | */ |
235 | nosys() | |
236 | { | |
683ddffc RE |
237 | if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) |
238 | u.u_error = EINVAL; | |
239 | psignal(u.u_procp, SIGSYS); | |
ee1451be | 240 | } |