Commit | Line | Data |
---|---|---|
bb155176 KT |
1 | # |
2 | #include "../param.h" | |
3 | #include "../systm.h" | |
4 | #include "../user.h" | |
5 | #include "../proc.h" | |
6 | #include "../reg.h" | |
7 | #include "../seg.h" | |
8 | ||
9 | #define EBIT 1 /* user error bit in PS: C-bit */ | |
10 | #define UMODE 0170000 /* user-mode bits in PS word */ | |
11 | #define SETD 0170011 /* SETD instruction */ | |
12 | #define SYS 0104400 /* sys (trap) instruction */ | |
13 | #define USER 020 /* user-mode flag added to dev */ | |
14 | ||
15 | /* | |
16 | * structure of the system entry table (sysent.c) | |
17 | */ | |
18 | struct sysent { | |
19 | int count; /* argument count */ | |
20 | int (*call)(); /* name of handler */ | |
21 | } sysent[64]; | |
22 | ||
23 | /* | |
24 | * Offsets of the user's registers relative to | |
25 | * the saved r0. See reg.h | |
26 | */ | |
27 | char regloc[9] | |
28 | { | |
29 | R0, R1, R2, R3, R4, R5, R6, R7, RPS | |
30 | }; | |
31 | ||
32 | /* | |
33 | * Called from l40.s or l45.s when a processor trap occurs. | |
34 | * The arguments are the words saved on the system stack | |
35 | * by the hardware and software during the trap processing. | |
36 | * Their order is dictated by the hardware and the details | |
37 | * of C's calling sequence. They are peculiar in that | |
38 | * this call is not 'by value' and changed user registers | |
39 | * get copied back on return. | |
40 | * dev is the kind of trap that occurred. | |
41 | */ | |
42 | trap(dev, sp, r1, nps, r0, pc, ps) | |
43 | { | |
44 | register i, a; | |
45 | register struct sysent *callp; | |
46 | ||
47 | savfp(); | |
48 | if ((ps&UMODE) == UMODE) | |
49 | dev =| USER; | |
50 | u.u_ar0 = &r0; | |
51 | switch(dev) { | |
52 | ||
53 | /* | |
54 | * Trap not expected. | |
55 | * Usually a kernel mode bus error. | |
56 | * The numbers printed are used to | |
57 | * find the hardware PS/PC as follows. | |
58 | * (all numbers in octal 18 bits) | |
59 | * address_of_saved_ps = | |
60 | * (ka6*0100) + aps - 0140000; | |
61 | * address_of_saved_pc = | |
62 | * address_of_saved_ps - 2; | |
63 | */ | |
64 | default: | |
65 | printf("ka6 = %o\n", *ka6); | |
66 | printf("aps = %o\n", &ps); | |
67 | printf("trap type %o\n", dev); | |
68 | panic("trap"); | |
69 | ||
70 | case 0+USER: /* bus error */ | |
71 | i = SIGBUS; | |
72 | break; | |
73 | ||
74 | /* | |
75 | * If illegal instructions are not | |
76 | * being caught and the offending instruction | |
77 | * is a SETD, the trap is ignored. | |
78 | * This is because C produces a SETD at | |
79 | * the beginning of every program which | |
80 | * will trap on CPUs without 11/45 FPU. | |
81 | */ | |
82 | case 1+USER: /* illegal instruction */ | |
83 | if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0) | |
84 | goto out; | |
85 | i = SIGINS; | |
86 | break; | |
87 | ||
88 | case 2+USER: /* bpt or trace */ | |
89 | i = SIGTRC; | |
90 | break; | |
91 | ||
92 | case 3+USER: /* iot */ | |
93 | i = SIGIOT; | |
94 | break; | |
95 | ||
96 | case 5+USER: /* emt */ | |
97 | i = SIGEMT; | |
98 | break; | |
99 | ||
100 | case 6+USER: /* sys call */ | |
101 | u.u_error = 0; | |
102 | ps =& ~EBIT; | |
103 | callp = &sysent[fuiword(pc-2)&077]; | |
104 | if (callp == sysent) { /* indirect */ | |
105 | a = fuiword(pc); | |
106 | pc =+ 2; | |
107 | i = fuword(a); | |
108 | if ((i & ~077) != SYS) | |
109 | i = 077; /* illegal */ | |
110 | callp = &sysent[i&077]; | |
111 | for(i=0; i<callp->count; i++) | |
112 | u.u_arg[i] = fuword(a =+ 2); | |
113 | } else { | |
114 | for(i=0; i<callp->count; i++) { | |
115 | u.u_arg[i] = fuiword(pc); | |
116 | pc =+ 2; | |
117 | } | |
118 | } | |
119 | u.u_dirp = u.u_arg[0]; | |
120 | trap1(callp->call); | |
121 | if(u.u_intflg) | |
122 | u.u_error = EINTR; | |
123 | if(u.u_error < 100) { | |
124 | if(u.u_error) { | |
125 | ps =| EBIT; | |
126 | r0 = u.u_error; | |
127 | } | |
128 | goto out; | |
129 | } | |
130 | i = SIGSYS; | |
131 | break; | |
132 | ||
133 | /* | |
134 | * Since the floating exception is an | |
135 | * imprecise trap, a user generated | |
136 | * trap may actually come from kernel | |
137 | * mode. In this case, a signal is sent | |
138 | * to the current process to be picked | |
139 | * up later. | |
140 | */ | |
141 | case 8: /* floating exception */ | |
142 | psignal(u.u_procp, SIGFPT); | |
143 | return; | |
144 | ||
145 | case 8+USER: | |
146 | i = SIGFPT; | |
147 | break; | |
148 | ||
149 | /* | |
150 | * If the user SP is below the stack segment, | |
151 | * grow the stack automatically. | |
152 | * This relies on the ability of the hardware | |
153 | * to restart a half executed instruction. | |
154 | * On the 11/40 this is not the case and | |
155 | * the routine backup/l40.s may fail. | |
156 | * The classic example is on the instruction | |
157 | * cmp -(sp),-(sp) | |
158 | */ | |
159 | case 9+USER: /* segmentation exception */ | |
160 | a = sp; | |
161 | if(backup(u.u_ar0) == 0) | |
162 | if(grow(a)) | |
163 | goto out; | |
164 | i = SIGSEG; | |
165 | break; | |
166 | } | |
167 | psignal(u.u_procp, i); | |
168 | ||
169 | out: | |
170 | if(issig()) | |
171 | psig(); | |
172 | setpri(u.u_procp); | |
173 | } | |
174 | ||
175 | /* | |
176 | * Call the system-entry routine f (out of the | |
177 | * sysent table). This is a subroutine for trap, and | |
178 | * not in-line, because if a signal occurs | |
179 | * during processing, an (abnormal) return is simulated from | |
180 | * the last caller to savu(qsav); if this took place | |
181 | * inside of trap, it wouldn't have a chance to clean up. | |
182 | * | |
183 | * If this occurs, the return takes place without | |
184 | * clearing u_intflg; if it's still set, trap | |
185 | * marks an error which means that a system | |
186 | * call (like read on a typewriter) got interrupted | |
187 | * by a signal. | |
188 | */ | |
189 | trap1(f) | |
190 | int (*f)(); | |
191 | { | |
192 | ||
193 | u.u_intflg = 1; | |
194 | savu(u.u_qsav); | |
195 | (*f)(); | |
196 | u.u_intflg = 0; | |
197 | } | |
198 | ||
199 | /* | |
200 | * nonexistent system call-- set fatal error code. | |
201 | */ | |
202 | nosys() | |
203 | { | |
204 | u.u_error = 100; | |
205 | } | |
206 | ||
207 | /* | |
208 | * Ignored system call | |
209 | */ | |
210 | nullsys() | |
211 | { | |
212 | } |