Deleted Added
full compact
subr_trap.c (351) subr_trap.c (608)
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * the University of Utah, and William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * the University of Utah, and William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)trap.c 7.4 (Berkeley) 5/13/91
37 *
38 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
39 * -------------------- ----- ----------------------
40 * CURRENT PATCH LEVEL: 1 00137
41 * -------------------- ----- ----------------------
42 *
43 * 08 Apr 93 Bruce Evans Several VM system fixes
44 * Paul Kranenburg Add counter for vmstat
36 * from: @(#)trap.c 7.4 (Berkeley) 5/13/91
37 * $Id$
45 */
38 */
46static char rcsid[] = "$Header: /a/cvs/386BSD/src/sys/i386/i386/trap.c,v 1.2 1993/07/27 10:52:20 davidg Exp $";
47
48/*
49 * 386 Trap and System call handleing
50 */
51
39
40/*
41 * 386 Trap and System call handleing
42 */
43
44#include "npx.h"
52#include "machine/cpu.h"
53#include "machine/psl.h"
54#include "machine/reg.h"
55
56#include "param.h"
57#include "systm.h"
58#include "proc.h"
59#include "user.h"
60#include "acct.h"
61#include "kernel.h"
62#ifdef KTRACE
63#include "ktrace.h"
64#endif
65
66#include "vm/vm_param.h"
67#include "vm/pmap.h"
68#include "vm/vm_map.h"
69#include "sys/vmmeter.h"
70
71#include "machine/trap.h"
72
73#ifdef __GNUC__
74
75/*
76 * The "r" contraint could be "rm" except for fatal bugs in gas. As usual,
77 * we omit the size from the mov instruction to avoid nonfatal bugs in gas.
78 */
79#define read_gs() ({ u_short gs; __asm("mov %%gs,%0" : "=r" (gs)); gs; })
80#define write_gs(gs) __asm("mov %0,%%gs" : : "r" ((u_short) gs))
81
82#else /* not __GNUC__ */
83
84u_short read_gs __P((void));
85void write_gs __P((/* promoted u_short */ int gs));
86
87#endif /* __GNUC__ */
88
89struct sysent sysent[];
90int nsysent;
91int dostacklimits;
92unsigned rcr2();
93extern short cpl;
94
95
96/*
97 * trap(frame):
98 * Exception, fault, and trap interface to BSD kernel. This
99 * common code is called from assembly language IDT gate entry
100 * routines that prepare a suitable stack frame, and restore this
101 * frame after the exception has been processed. Note that the
102 * effect is as if the arguments were passed call by reference.
103 */
104
105/*ARGSUSED*/
106trap(frame)
107 struct trapframe frame;
108{
109 register int i;
110 register struct proc *p = curproc;
111 struct timeval syst;
112 int ucode, type, code, eva;
113
114 frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
115 type = frame.tf_trapno;
116#include "ddb.h"
117#if NDDB > 0
118 if (curpcb && curpcb->pcb_onfault) {
119 if (frame.tf_trapno == T_BPTFLT
120 || frame.tf_trapno == T_TRCTRAP)
121 if (kdb_trap (type, 0, &frame))
122 return;
123 }
124#endif
125
126/*pg("trap type %d code = %x eip = %x cs = %x eva = %x esp %x",
127 frame.tf_trapno, frame.tf_err, frame.tf_eip,
128 frame.tf_cs, rcr2(), frame.tf_esp);*/
129if(curpcb == 0 || curproc == 0) goto we_re_toast;
130 if (curpcb->pcb_onfault && frame.tf_trapno != T_PAGEFLT) {
131 extern int _udatasel;
132
133 if (read_gs() != (u_short) _udatasel)
134 /*
135 * Some user has corrupted %gs but we depend on it in
136 * copyout() etc. Fix it up and retry.
137 *
138 * (We don't preserve %fs or %gs, so users can change
139 * them to either _ucodesel, _udatasel or a not-present
140 * selector, possibly ORed with 0 to 3, making them
141 * volatile for other users. Not preserving them saves
142 * time and doesn't lose functionality or open security
143 * holes.)
144 */
145 write_gs(_udatasel);
146 else
147copyfault:
148 frame.tf_eip = (int)curpcb->pcb_onfault;
149 return;
150 }
151
152 syst = p->p_stime;
153 if (ISPL(frame.tf_cs) == SEL_UPL) {
154 type |= T_USER;
155 p->p_regs = (int *)&frame;
156 curpcb->pcb_flags |= FM_TRAP; /* used by sendsig */
157 }
158
159 ucode=0;
160 eva = rcr2();
161 code = frame.tf_err;
162 switch (type) {
163
164 default:
165 we_re_toast:
166#ifdef KDB
167 if (kdb_trap(&psl))
168 return;
169#endif
170#if NDDB > 0
171 if (kdb_trap (type, 0, &frame))
172 return;
173#endif
174
175 printf("trap type %d code = %x eip = %x cs = %x eflags = %x ",
176 frame.tf_trapno, frame.tf_err, frame.tf_eip,
177 frame.tf_cs, frame.tf_eflags);
178 eva = rcr2();
179 printf("cr2 %x cpl %x\n", eva, cpl);
180 /* type &= ~T_USER; */ /* XXX what the hell is this */
181 panic("trap");
182 /*NOTREACHED*/
183
184 case T_SEGNPFLT|T_USER:
185 case T_STKFLT|T_USER:
186 case T_PROTFLT|T_USER: /* protection fault */
187 ucode = code + BUS_SEGM_FAULT ;
188 i = SIGBUS;
189 break;
190
191 case T_PRIVINFLT|T_USER: /* privileged instruction fault */
192 case T_RESADFLT|T_USER: /* reserved addressing fault */
193 case T_RESOPFLT|T_USER: /* reserved operand fault */
194 case T_FPOPFLT|T_USER: /* coprocessor operand fault */
195 ucode = type &~ T_USER;
196 i = SIGILL;
197 break;
198
199 case T_ASTFLT|T_USER: /* Allow process switch */
200 astoff();
201 cnt.v_soft++;
202 if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
203 addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
204 p->p_flag &= ~SOWEUPC;
205 }
206 goto out;
207
208 case T_DNA|T_USER:
45#include "machine/cpu.h"
46#include "machine/psl.h"
47#include "machine/reg.h"
48
49#include "param.h"
50#include "systm.h"
51#include "proc.h"
52#include "user.h"
53#include "acct.h"
54#include "kernel.h"
55#ifdef KTRACE
56#include "ktrace.h"
57#endif
58
59#include "vm/vm_param.h"
60#include "vm/pmap.h"
61#include "vm/vm_map.h"
62#include "sys/vmmeter.h"
63
64#include "machine/trap.h"
65
66#ifdef __GNUC__
67
68/*
69 * The "r" contraint could be "rm" except for fatal bugs in gas. As usual,
70 * we omit the size from the mov instruction to avoid nonfatal bugs in gas.
71 */
72#define read_gs() ({ u_short gs; __asm("mov %%gs,%0" : "=r" (gs)); gs; })
73#define write_gs(gs) __asm("mov %0,%%gs" : : "r" ((u_short) gs))
74
75#else /* not __GNUC__ */
76
77u_short read_gs __P((void));
78void write_gs __P((/* promoted u_short */ int gs));
79
80#endif /* __GNUC__ */
81
82struct sysent sysent[];
83int nsysent;
84int dostacklimits;
85unsigned rcr2();
86extern short cpl;
87
88
89/*
90 * trap(frame):
91 * Exception, fault, and trap interface to BSD kernel. This
92 * common code is called from assembly language IDT gate entry
93 * routines that prepare a suitable stack frame, and restore this
94 * frame after the exception has been processed. Note that the
95 * effect is as if the arguments were passed call by reference.
96 */
97
98/*ARGSUSED*/
99trap(frame)
100 struct trapframe frame;
101{
102 register int i;
103 register struct proc *p = curproc;
104 struct timeval syst;
105 int ucode, type, code, eva;
106
107 frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
108 type = frame.tf_trapno;
109#include "ddb.h"
110#if NDDB > 0
111 if (curpcb && curpcb->pcb_onfault) {
112 if (frame.tf_trapno == T_BPTFLT
113 || frame.tf_trapno == T_TRCTRAP)
114 if (kdb_trap (type, 0, &frame))
115 return;
116 }
117#endif
118
119/*pg("trap type %d code = %x eip = %x cs = %x eva = %x esp %x",
120 frame.tf_trapno, frame.tf_err, frame.tf_eip,
121 frame.tf_cs, rcr2(), frame.tf_esp);*/
122if(curpcb == 0 || curproc == 0) goto we_re_toast;
123 if (curpcb->pcb_onfault && frame.tf_trapno != T_PAGEFLT) {
124 extern int _udatasel;
125
126 if (read_gs() != (u_short) _udatasel)
127 /*
128 * Some user has corrupted %gs but we depend on it in
129 * copyout() etc. Fix it up and retry.
130 *
131 * (We don't preserve %fs or %gs, so users can change
132 * them to either _ucodesel, _udatasel or a not-present
133 * selector, possibly ORed with 0 to 3, making them
134 * volatile for other users. Not preserving them saves
135 * time and doesn't lose functionality or open security
136 * holes.)
137 */
138 write_gs(_udatasel);
139 else
140copyfault:
141 frame.tf_eip = (int)curpcb->pcb_onfault;
142 return;
143 }
144
145 syst = p->p_stime;
146 if (ISPL(frame.tf_cs) == SEL_UPL) {
147 type |= T_USER;
148 p->p_regs = (int *)&frame;
149 curpcb->pcb_flags |= FM_TRAP; /* used by sendsig */
150 }
151
152 ucode=0;
153 eva = rcr2();
154 code = frame.tf_err;
155 switch (type) {
156
157 default:
158 we_re_toast:
159#ifdef KDB
160 if (kdb_trap(&psl))
161 return;
162#endif
163#if NDDB > 0
164 if (kdb_trap (type, 0, &frame))
165 return;
166#endif
167
168 printf("trap type %d code = %x eip = %x cs = %x eflags = %x ",
169 frame.tf_trapno, frame.tf_err, frame.tf_eip,
170 frame.tf_cs, frame.tf_eflags);
171 eva = rcr2();
172 printf("cr2 %x cpl %x\n", eva, cpl);
173 /* type &= ~T_USER; */ /* XXX what the hell is this */
174 panic("trap");
175 /*NOTREACHED*/
176
177 case T_SEGNPFLT|T_USER:
178 case T_STKFLT|T_USER:
179 case T_PROTFLT|T_USER: /* protection fault */
180 ucode = code + BUS_SEGM_FAULT ;
181 i = SIGBUS;
182 break;
183
184 case T_PRIVINFLT|T_USER: /* privileged instruction fault */
185 case T_RESADFLT|T_USER: /* reserved addressing fault */
186 case T_RESOPFLT|T_USER: /* reserved operand fault */
187 case T_FPOPFLT|T_USER: /* coprocessor operand fault */
188 ucode = type &~ T_USER;
189 i = SIGILL;
190 break;
191
192 case T_ASTFLT|T_USER: /* Allow process switch */
193 astoff();
194 cnt.v_soft++;
195 if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
196 addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
197 p->p_flag &= ~SOWEUPC;
198 }
199 goto out;
200
201 case T_DNA|T_USER:
209#ifdef NPX
202#if NNPX > 0
210 /* if a transparent fault (due to context switch "late") */
211 if (npxdna()) return;
203 /* if a transparent fault (due to context switch "late") */
204 if (npxdna()) return;
212#endif
205#endif /* NNPX > 0 */
213#ifdef MATH_EMULATE
214 i = math_emulate(&frame);
215 if (i == 0) return;
216#else /* MATH_EMULTATE */
217 panic("trap: math emulation necessary!");
218#endif /* MATH_EMULTATE */
219 ucode = FPE_FPU_NP_TRAP;
220 break;
221
222 case T_BOUND|T_USER:
223 ucode = FPE_SUBRNG_TRAP;
224 i = SIGFPE;
225 break;
226
227 case T_OFLOW|T_USER:
228 ucode = FPE_INTOVF_TRAP;
229 i = SIGFPE;
230 break;
231
232 case T_DIVIDE|T_USER:
233 ucode = FPE_INTDIV_TRAP;
234 i = SIGFPE;
235 break;
236
237 case T_ARITHTRAP|T_USER:
238 ucode = code;
239 i = SIGFPE;
240 break;
241
242 case T_PAGEFLT: /* allow page faults in kernel mode */
243#if 0
244 /* XXX - check only applies to 386's and 486's with WP off */
245 if (code & PGEX_P) goto we_re_toast;
246#endif
247
248 /* fall into */
249 case T_PAGEFLT|T_USER: /* page fault */
250 {
251 register vm_offset_t va;
252 register struct vmspace *vm = p->p_vmspace;
253 register vm_map_t map;
254 int rv;
255 vm_prot_t ftype;
256 extern vm_map_t kernel_map;
257 unsigned nss,v;
258
259 va = trunc_page((vm_offset_t)eva);
260 /*
206#ifdef MATH_EMULATE
207 i = math_emulate(&frame);
208 if (i == 0) return;
209#else /* MATH_EMULTATE */
210 panic("trap: math emulation necessary!");
211#endif /* MATH_EMULTATE */
212 ucode = FPE_FPU_NP_TRAP;
213 break;
214
215 case T_BOUND|T_USER:
216 ucode = FPE_SUBRNG_TRAP;
217 i = SIGFPE;
218 break;
219
220 case T_OFLOW|T_USER:
221 ucode = FPE_INTOVF_TRAP;
222 i = SIGFPE;
223 break;
224
225 case T_DIVIDE|T_USER:
226 ucode = FPE_INTDIV_TRAP;
227 i = SIGFPE;
228 break;
229
230 case T_ARITHTRAP|T_USER:
231 ucode = code;
232 i = SIGFPE;
233 break;
234
235 case T_PAGEFLT: /* allow page faults in kernel mode */
236#if 0
237 /* XXX - check only applies to 386's and 486's with WP off */
238 if (code & PGEX_P) goto we_re_toast;
239#endif
240
241 /* fall into */
242 case T_PAGEFLT|T_USER: /* page fault */
243 {
244 register vm_offset_t va;
245 register struct vmspace *vm = p->p_vmspace;
246 register vm_map_t map;
247 int rv;
248 vm_prot_t ftype;
249 extern vm_map_t kernel_map;
250 unsigned nss,v;
251
252 va = trunc_page((vm_offset_t)eva);
253 /*
261 * Avoid even looking at pde_v(va) for high va's. va's
262 * above VM_MAX_KERNEL_ADDRESS don't correspond to normal
263 * PDE's (half of them correspond to APDEpde and half to
264 * an unmapped kernel PDE). va's betweeen 0xFEC00000 and
265 * VM_MAX_KERNEL_ADDRESS correspond to unmapped kernel PDE's
266 * (XXX - why are only 3 initialized when 6 are required to
267 * reach VM_MAX_KERNEL_ADDRESS?). Faulting in an unmapped
268 * kernel page table would give inconsistent PTD's.
269 *
270 * XXX - faulting in unmapped page tables wastes a page if
271 * va turns out to be invalid.
272 *
273 * XXX - should "kernel address space" cover the kernel page
274 * tables? Might have same problem with PDEpde as with
275 * APDEpde (or there may be no problem with APDEpde).
276 */
277 if (va > 0xFEBFF000) {
278 rv = KERN_FAILURE; /* becomes SIGBUS */
279 goto nogo;
280 }
281 /*
282 * It is only a kernel address space fault iff:
283 * 1. (type & T_USER) == 0 and
284 * 2. pcb_onfault not set or
285 * 3. pcb_onfault set but supervisor space fault
286 * The last can occur during an exec() copyin where the
287 * argument space is lazy-allocated.
288 */
289 if (type == T_PAGEFLT && va >= KERNBASE)
290 map = kernel_map;
291 else
292 map = &vm->vm_map;
293 if (code & PGEX_W)
294 ftype = VM_PROT_READ | VM_PROT_WRITE;
295 else
296 ftype = VM_PROT_READ;
297
298#ifdef DEBUG
299 if (map == kernel_map && va == 0) {
300 printf("trap: bad kernel access at %x\n", va);
301 goto we_re_toast;
302 }
303#endif
304
305 /*
306 * XXX: rude hack to make stack limits "work"
307 */
308 nss = 0;
309 if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map
310 && dostacklimits) {
311 nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
312 + MAXSSIZ - (unsigned)va));
313 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
314/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
315 rv = KERN_FAILURE;
316 goto nogo;
317 }
318 }
319
320 /* check if page table is mapped, if not, fault it first */
321#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
322 if (!pde_v(va)) {
323 v = trunc_page(vtopte(va));
324 rv = vm_fault(map, v, ftype, FALSE);
325 if (rv != KERN_SUCCESS) goto nogo;
326 /* check if page table fault, increment wiring */
327 vm_map_pageable(map, v, round_page(v+1), FALSE);
328 } else v=0;
329 rv = vm_fault(map, va, ftype, FALSE);
330 if (rv == KERN_SUCCESS) {
331 /*
332 * XXX: continuation of rude stack hack
333 */
334 if (nss > vm->vm_ssize)
335 vm->vm_ssize = nss;
336 va = trunc_page(vtopte(va));
337 /* for page table, increment wiring
338 as long as not a page table fault as well */
339 if (!v && type != T_PAGEFLT)
340 vm_map_pageable(map, va, round_page(va+1), FALSE);
341 if (type == T_PAGEFLT)
342 return;
343 goto out;
344 }
345nogo:
346 if (type == T_PAGEFLT) {
347 if (curpcb->pcb_onfault)
348 goto copyfault;
349 printf("vm_fault(%x, %x, %x, 0) -> %x\n",
350 map, va, ftype, rv);
351 printf(" type %x, code %x\n",
352 type, code);
353 goto we_re_toast;
354 }
355 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
356 break;
357 }
358
359#if NDDB == 0
360 case T_TRCTRAP: /* trace trap -- someone single stepping lcall's */
361 frame.tf_eflags &= ~PSL_T;
362
363 /* Q: how do we turn it on again? */
364 return;
365#endif
366
367 case T_BPTFLT|T_USER: /* bpt instruction fault */
368 case T_TRCTRAP|T_USER: /* trace trap */
369 frame.tf_eflags &= ~PSL_T;
370 i = SIGTRAP;
371 break;
372
373#include "isa.h"
374#if NISA > 0
375 case T_NMI:
376 case T_NMI|T_USER:
377#if NDDB > 0
378 /* NMI can be hooked up to a pushbutton for debugging */
379 printf ("NMI ... going to debugger\n");
380 if (kdb_trap (type, 0, &frame))
381 return;
382#endif
383 /* machine/parity/power fail/"kitchen sink" faults */
384 if(isa_nmi(code) == 0) return;
385 else goto we_re_toast;
386#endif
387 }
388
389 trapsignal(p, i, ucode);
390 if ((type & T_USER) == 0)
391 return;
392out:
393 while (i = CURSIG(p))
394 psig(i);
395 p->p_pri = p->p_usrpri;
396 if (want_resched) {
397 /*
398 * Since we are curproc, clock will normally just change
399 * our priority without moving us from one queue to another
400 * (since the running process is not on a queue.)
401 * If that happened after we setrq ourselves but before we
402 * swtch()'ed, we might not be on the queue indicated by
403 * our priority.
404 */
405 (void) splclock();
406 setrq(p);
407 p->p_stats->p_ru.ru_nivcsw++;
408 swtch();
409 (void) splnone();
410 while (i = CURSIG(p))
411 psig(i);
412 }
413 if (p->p_stats->p_prof.pr_scale) {
414 int ticks;
415 struct timeval *tv = &p->p_stime;
416
417 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
418 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
419 if (ticks) {
420#ifdef PROFTIMER
421 extern int profscale;
422 addupc(frame.tf_eip, &p->p_stats->p_prof,
423 ticks * profscale);
424#else
425 addupc(frame.tf_eip, &p->p_stats->p_prof, ticks);
426#endif
427 }
428 }
429 curpri = p->p_pri;
430 curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
431}
432
433/*
434 * Compensate for 386 brain damage (missing URKR).
435 * This is a little simpler than the pagefault handler in trap() because
436 * it the page tables have already been faulted in and high addresses
437 * are thrown out early for other reasons.
438 */
439int trapwrite(addr)
440 unsigned addr;
441{
442 unsigned nss;
443 struct proc *p;
444 vm_offset_t va;
445 struct vmspace *vm;
446
447 va = trunc_page((vm_offset_t)addr);
448 /*
449 * XXX - MAX is END. Changed > to >= for temp. fix.
450 */
451 if (va >= VM_MAXUSER_ADDRESS)
452 return (1);
453 /*
454 * XXX: rude stack hack adapted from trap().
455 */
456 nss = 0;
457 p = curproc;
458 vm = p->p_vmspace;
459 if ((caddr_t)va >= vm->vm_maxsaddr && dostacklimits) {
460 nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
461 - (unsigned)va));
462 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
463 return (1);
464 }
465
466 if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
467 != KERN_SUCCESS)
468 return (1);
469
470 /*
471 * XXX: continuation of rude stack hack
472 */
473 if (nss > vm->vm_ssize)
474 vm->vm_ssize = nss;
475
476 return (0);
477}
478
479/*
480 * syscall(frame):
481 * System call request from POSIX system call gate interface to kernel.
482 * Like trap(), argument is call by reference.
483 */
484/*ARGSUSED*/
485syscall(frame)
486 volatile struct syscframe frame;
487{
488 register int *locr0 = ((int *)&frame);
489 register caddr_t params;
490 register int i;
491 register struct sysent *callp;
492 register struct proc *p = curproc;
493 struct timeval syst;
494 int error, opc;
495 int args[8], rval[2];
496 int code;
497
498#ifdef lint
499 r0 = 0; r0 = r0; r1 = 0; r1 = r1;
500#endif
501 syst = p->p_stime;
502 if (ISPL(frame.sf_cs) != SEL_UPL)
503 panic("syscall");
504
505 code = frame.sf_eax;
506 curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
507 p->p_regs = (int *)&frame;
508 params = (caddr_t)frame.sf_esp + sizeof (int) ;
509
510 /*
511 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
512 */
513 opc = frame.sf_eip - 7;
514 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
515 if (callp == sysent) {
516 i = fuword(params);
517 params += sizeof (int);
518 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
519 }
520
521 if ((i = callp->sy_narg * sizeof (int)) &&
522 (error = copyin(params, (caddr_t)args, (u_int)i))) {
523 frame.sf_eax = error;
524 frame.sf_eflags |= PSL_C; /* carry bit */
525#ifdef KTRACE
526 if (KTRPOINT(p, KTR_SYSCALL))
527 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
528#endif
529 goto done;
530 }
531#ifdef KTRACE
532 if (KTRPOINT(p, KTR_SYSCALL))
533 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
534#endif
535 rval[0] = 0;
536 rval[1] = frame.sf_edx;
537/*pg("%d. s %d\n", p->p_pid, code);*/
538 error = (*callp->sy_call)(p, args, rval);
539 if (error == ERESTART)
540 frame.sf_eip = opc;
541 else if (error != EJUSTRETURN) {
542 if (error) {
543/*pg("error %d", error);*/
544 frame.sf_eax = error;
545 frame.sf_eflags |= PSL_C; /* carry bit */
546 } else {
547 frame.sf_eax = rval[0];
548 frame.sf_edx = rval[1];
549 frame.sf_eflags &= ~PSL_C; /* carry bit */
550 }
551 }
552 /* else if (error == EJUSTRETURN) */
553 /* nothing to do */
554done:
555 /*
556 * Reinitialize proc pointer `p' as it may be different
557 * if this is a child returning from fork syscall.
558 */
559 p = curproc;
560 while (i = CURSIG(p))
561 psig(i);
562 p->p_pri = p->p_usrpri;
563 if (want_resched) {
564 /*
565 * Since we are curproc, clock will normally just change
566 * our priority without moving us from one queue to another
567 * (since the running process is not on a queue.)
568 * If that happened after we setrq ourselves but before we
569 * swtch()'ed, we might not be on the queue indicated by
570 * our priority.
571 */
572 (void) splclock();
573 setrq(p);
574 p->p_stats->p_ru.ru_nivcsw++;
575 swtch();
576 (void) splnone();
577 while (i = CURSIG(p))
578 psig(i);
579 }
580 if (p->p_stats->p_prof.pr_scale) {
581 int ticks;
582 struct timeval *tv = &p->p_stime;
583
584 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
585 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
586 if (ticks) {
587#ifdef PROFTIMER
588 extern int profscale;
589 addupc(frame.sf_eip, &p->p_stats->p_prof,
590 ticks * profscale);
591#else
592 addupc(frame.sf_eip, &p->p_stats->p_prof, ticks);
593#endif
594 }
595 }
596 curpri = p->p_pri;
597#ifdef KTRACE
598 if (KTRPOINT(p, KTR_SYSRET))
599 ktrsysret(p->p_tracep, code, error, rval[0]);
600#endif
601#ifdef DIAGNOSTICx
602{ extern int _udatasel, _ucodesel;
603 if (frame.sf_ss != _udatasel)
604 printf("ss %x call %d\n", frame.sf_ss, code);
605 if ((frame.sf_cs&0xffff) != _ucodesel)
606 printf("cs %x call %d\n", frame.sf_cs, code);
607 if (frame.sf_eip > VM_MAXUSER_ADDRESS) {
608 printf("eip %x call %d\n", frame.sf_eip, code);
609 frame.sf_eip = 0;
610 }
611}
612#endif
613}
254 * It is only a kernel address space fault iff:
255 * 1. (type & T_USER) == 0 and
256 * 2. pcb_onfault not set or
257 * 3. pcb_onfault set but supervisor space fault
258 * The last can occur during an exec() copyin where the
259 * argument space is lazy-allocated.
260 */
261 if (type == T_PAGEFLT && va >= KERNBASE)
262 map = kernel_map;
263 else
264 map = &vm->vm_map;
265 if (code & PGEX_W)
266 ftype = VM_PROT_READ | VM_PROT_WRITE;
267 else
268 ftype = VM_PROT_READ;
269
270#ifdef DEBUG
271 if (map == kernel_map && va == 0) {
272 printf("trap: bad kernel access at %x\n", va);
273 goto we_re_toast;
274 }
275#endif
276
277 /*
278 * XXX: rude hack to make stack limits "work"
279 */
280 nss = 0;
281 if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map
282 && dostacklimits) {
283 nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
284 + MAXSSIZ - (unsigned)va));
285 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
286/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
287 rv = KERN_FAILURE;
288 goto nogo;
289 }
290 }
291
292 /* check if page table is mapped, if not, fault it first */
293#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
294 if (!pde_v(va)) {
295 v = trunc_page(vtopte(va));
296 rv = vm_fault(map, v, ftype, FALSE);
297 if (rv != KERN_SUCCESS) goto nogo;
298 /* check if page table fault, increment wiring */
299 vm_map_pageable(map, v, round_page(v+1), FALSE);
300 } else v=0;
301 rv = vm_fault(map, va, ftype, FALSE);
302 if (rv == KERN_SUCCESS) {
303 /*
304 * XXX: continuation of rude stack hack
305 */
306 if (nss > vm->vm_ssize)
307 vm->vm_ssize = nss;
308 va = trunc_page(vtopte(va));
309 /* for page table, increment wiring
310 as long as not a page table fault as well */
311 if (!v && type != T_PAGEFLT)
312 vm_map_pageable(map, va, round_page(va+1), FALSE);
313 if (type == T_PAGEFLT)
314 return;
315 goto out;
316 }
317nogo:
318 if (type == T_PAGEFLT) {
319 if (curpcb->pcb_onfault)
320 goto copyfault;
321 printf("vm_fault(%x, %x, %x, 0) -> %x\n",
322 map, va, ftype, rv);
323 printf(" type %x, code %x\n",
324 type, code);
325 goto we_re_toast;
326 }
327 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
328 break;
329 }
330
331#if NDDB == 0
332 case T_TRCTRAP: /* trace trap -- someone single stepping lcall's */
333 frame.tf_eflags &= ~PSL_T;
334
335 /* Q: how do we turn it on again? */
336 return;
337#endif
338
339 case T_BPTFLT|T_USER: /* bpt instruction fault */
340 case T_TRCTRAP|T_USER: /* trace trap */
341 frame.tf_eflags &= ~PSL_T;
342 i = SIGTRAP;
343 break;
344
345#include "isa.h"
346#if NISA > 0
347 case T_NMI:
348 case T_NMI|T_USER:
349#if NDDB > 0
350 /* NMI can be hooked up to a pushbutton for debugging */
351 printf ("NMI ... going to debugger\n");
352 if (kdb_trap (type, 0, &frame))
353 return;
354#endif
355 /* machine/parity/power fail/"kitchen sink" faults */
356 if(isa_nmi(code) == 0) return;
357 else goto we_re_toast;
358#endif
359 }
360
361 trapsignal(p, i, ucode);
362 if ((type & T_USER) == 0)
363 return;
364out:
365 while (i = CURSIG(p))
366 psig(i);
367 p->p_pri = p->p_usrpri;
368 if (want_resched) {
369 /*
370 * Since we are curproc, clock will normally just change
371 * our priority without moving us from one queue to another
372 * (since the running process is not on a queue.)
373 * If that happened after we setrq ourselves but before we
374 * swtch()'ed, we might not be on the queue indicated by
375 * our priority.
376 */
377 (void) splclock();
378 setrq(p);
379 p->p_stats->p_ru.ru_nivcsw++;
380 swtch();
381 (void) splnone();
382 while (i = CURSIG(p))
383 psig(i);
384 }
385 if (p->p_stats->p_prof.pr_scale) {
386 int ticks;
387 struct timeval *tv = &p->p_stime;
388
389 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
390 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
391 if (ticks) {
392#ifdef PROFTIMER
393 extern int profscale;
394 addupc(frame.tf_eip, &p->p_stats->p_prof,
395 ticks * profscale);
396#else
397 addupc(frame.tf_eip, &p->p_stats->p_prof, ticks);
398#endif
399 }
400 }
401 curpri = p->p_pri;
402 curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
403}
404
405/*
406 * Compensate for 386 brain damage (missing URKR).
407 * This is a little simpler than the pagefault handler in trap() because
408 * it the page tables have already been faulted in and high addresses
409 * are thrown out early for other reasons.
410 */
411int trapwrite(addr)
412 unsigned addr;
413{
414 unsigned nss;
415 struct proc *p;
416 vm_offset_t va;
417 struct vmspace *vm;
418
419 va = trunc_page((vm_offset_t)addr);
420 /*
421 * XXX - MAX is END. Changed > to >= for temp. fix.
422 */
423 if (va >= VM_MAXUSER_ADDRESS)
424 return (1);
425 /*
426 * XXX: rude stack hack adapted from trap().
427 */
428 nss = 0;
429 p = curproc;
430 vm = p->p_vmspace;
431 if ((caddr_t)va >= vm->vm_maxsaddr && dostacklimits) {
432 nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
433 - (unsigned)va));
434 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
435 return (1);
436 }
437
438 if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
439 != KERN_SUCCESS)
440 return (1);
441
442 /*
443 * XXX: continuation of rude stack hack
444 */
445 if (nss > vm->vm_ssize)
446 vm->vm_ssize = nss;
447
448 return (0);
449}
450
451/*
452 * syscall(frame):
453 * System call request from POSIX system call gate interface to kernel.
454 * Like trap(), argument is call by reference.
455 */
456/*ARGSUSED*/
457syscall(frame)
458 volatile struct syscframe frame;
459{
460 register int *locr0 = ((int *)&frame);
461 register caddr_t params;
462 register int i;
463 register struct sysent *callp;
464 register struct proc *p = curproc;
465 struct timeval syst;
466 int error, opc;
467 int args[8], rval[2];
468 int code;
469
470#ifdef lint
471 r0 = 0; r0 = r0; r1 = 0; r1 = r1;
472#endif
473 syst = p->p_stime;
474 if (ISPL(frame.sf_cs) != SEL_UPL)
475 panic("syscall");
476
477 code = frame.sf_eax;
478 curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
479 p->p_regs = (int *)&frame;
480 params = (caddr_t)frame.sf_esp + sizeof (int) ;
481
482 /*
483 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
484 */
485 opc = frame.sf_eip - 7;
486 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
487 if (callp == sysent) {
488 i = fuword(params);
489 params += sizeof (int);
490 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
491 }
492
493 if ((i = callp->sy_narg * sizeof (int)) &&
494 (error = copyin(params, (caddr_t)args, (u_int)i))) {
495 frame.sf_eax = error;
496 frame.sf_eflags |= PSL_C; /* carry bit */
497#ifdef KTRACE
498 if (KTRPOINT(p, KTR_SYSCALL))
499 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
500#endif
501 goto done;
502 }
503#ifdef KTRACE
504 if (KTRPOINT(p, KTR_SYSCALL))
505 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
506#endif
507 rval[0] = 0;
508 rval[1] = frame.sf_edx;
509/*pg("%d. s %d\n", p->p_pid, code);*/
510 error = (*callp->sy_call)(p, args, rval);
511 if (error == ERESTART)
512 frame.sf_eip = opc;
513 else if (error != EJUSTRETURN) {
514 if (error) {
515/*pg("error %d", error);*/
516 frame.sf_eax = error;
517 frame.sf_eflags |= PSL_C; /* carry bit */
518 } else {
519 frame.sf_eax = rval[0];
520 frame.sf_edx = rval[1];
521 frame.sf_eflags &= ~PSL_C; /* carry bit */
522 }
523 }
524 /* else if (error == EJUSTRETURN) */
525 /* nothing to do */
526done:
527 /*
528 * Reinitialize proc pointer `p' as it may be different
529 * if this is a child returning from fork syscall.
530 */
531 p = curproc;
532 while (i = CURSIG(p))
533 psig(i);
534 p->p_pri = p->p_usrpri;
535 if (want_resched) {
536 /*
537 * Since we are curproc, clock will normally just change
538 * our priority without moving us from one queue to another
539 * (since the running process is not on a queue.)
540 * If that happened after we setrq ourselves but before we
541 * swtch()'ed, we might not be on the queue indicated by
542 * our priority.
543 */
544 (void) splclock();
545 setrq(p);
546 p->p_stats->p_ru.ru_nivcsw++;
547 swtch();
548 (void) splnone();
549 while (i = CURSIG(p))
550 psig(i);
551 }
552 if (p->p_stats->p_prof.pr_scale) {
553 int ticks;
554 struct timeval *tv = &p->p_stime;
555
556 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
557 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
558 if (ticks) {
559#ifdef PROFTIMER
560 extern int profscale;
561 addupc(frame.sf_eip, &p->p_stats->p_prof,
562 ticks * profscale);
563#else
564 addupc(frame.sf_eip, &p->p_stats->p_prof, ticks);
565#endif
566 }
567 }
568 curpri = p->p_pri;
569#ifdef KTRACE
570 if (KTRPOINT(p, KTR_SYSRET))
571 ktrsysret(p->p_tracep, code, error, rval[0]);
572#endif
573#ifdef DIAGNOSTICx
574{ extern int _udatasel, _ucodesel;
575 if (frame.sf_ss != _udatasel)
576 printf("ss %x call %d\n", frame.sf_ss, code);
577 if ((frame.sf_cs&0xffff) != _ucodesel)
578 printf("cs %x call %d\n", frame.sf_cs, code);
579 if (frame.sf_eip > VM_MAXUSER_ADDRESS) {
580 printf("eip %x call %d\n", frame.sf_eip, code);
581 frame.sf_eip = 0;
582 }
583}
584#endif
585}