Annotation of sys/arch/solbourne/solbourne/trap.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: trap.c,v 1.9 2007/03/15 10:22:29 art Exp $ */
2: /* OpenBSD: trap.c,v 1.42 2004/12/06 20:12:25 miod Exp */
3:
4: /*
5: * Copyright (c) 1996
6: * The President and Fellows of Harvard College. All rights reserved.
7: * Copyright (c) 1992, 1993
8: * The Regents of the University of California. All rights reserved.
9: *
10: * This software was developed by the Computer Systems Engineering group
11: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
12: * contributed to Berkeley.
13: *
14: * All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Lawrence Berkeley Laboratory.
18: * This product includes software developed by Harvard University.
19: *
20: * Redistribution and use in source and binary forms, with or without
21: * modification, are permitted provided that the following conditions
22: * are met:
23: * 1. Redistributions of source code must retain the above copyright
24: * notice, this list of conditions and the following disclaimer.
25: * 2. Redistributions in binary form must reproduce the above copyright
26: * notice, this list of conditions and the following disclaimer in the
27: * documentation and/or other materials provided with the distribution.
28: * 3. All advertising materials mentioning features or use of this software
29: * must display the following acknowledgement:
30: * This product includes software developed by the University of
31: * California, Berkeley and its contributors.
32: * This product includes software developed by Harvard University.
33: * 4. Neither the name of the University nor the names of its contributors
34: * may be used to endorse or promote products derived from this software
35: * without specific prior written permission.
36: *
37: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47: * SUCH DAMAGE.
48: *
49: * @(#)trap.c 8.4 (Berkeley) 9/23/93
50: */
51:
52: #include <sys/param.h>
53: #include <sys/systm.h>
54: #include <sys/proc.h>
55: #include <sys/signalvar.h>
56: #include <sys/user.h>
57: #include <sys/kernel.h>
58: #include <sys/malloc.h>
59: #include <sys/resource.h>
60: #include <sys/signal.h>
61: #include <sys/wait.h>
62: #include <sys/syscall.h>
63: #include <sys/syslog.h>
64: #ifdef KTRACE
65: #include <sys/ktrace.h>
66: #endif
67:
68: #include "systrace.h"
69: #include <dev/systrace.h>
70:
71: #include <uvm/uvm_extern.h>
72:
73: #include <sparc/sparc/asm.h>
74: #include <machine/cpu.h>
75: #include <machine/ctlreg.h>
76: #include <machine/trap.h>
77: #include <machine/instr.h>
78: #include <machine/pmap.h>
79:
80: #include <machine/idt.h>
81: #include <machine/kap.h>
82:
83: #ifdef DDB
84: #include <machine/db_machdep.h>
85: #else
86: #include <machine/frame.h>
87: #endif
88: #ifdef COMPAT_SVR4
89: #include <machine/svr4_machdep.h>
90: #endif
91:
92: #include <sparc/fpu/fpu_extern.h>
93: #include <sparc/sparc/memreg.h>
94: #include <sparc/sparc/cpuvar.h>
95:
96: #ifdef DEBUG
97: int rwindow_debug = 0;
98: #endif
99:
100: /*
101: * Initial FPU state is all registers == all 1s, everything else == all 0s.
102: * This makes every floating point register a signalling NaN, with sign bit
103: * set, no matter how it is interpreted. Appendix N of the Sparc V8 document
104: * seems to imply that we should do this, and it does make sense.
105: */
106: struct fpstate initfpstate = {
107: { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
108: ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }
109: };
110:
111: /*
112: * There are more than 100 trap types, but most are unused.
113: *
114: * Trap type 0 is taken over as an `Asynchronous System Trap'.
115: * This is left-over Vax emulation crap that should be fixed.
116: *
117: * Note that some of the Sparc v8 traps are actually handled by
118: * the corresponding v7 routine, but listed here for completeness.
119: * The Fujitsu Turbo-Sparc Guide also alludes to several more
120: * unimplemented trap types, but doesn't give the nominal coding.
121: */
122: static const char T[] = "trap";
123: const char *trap_type[] = {
124: /* non-user vectors */
125: "ast", /* 0 */
126: "text fault", /* 1 */
127: "illegal instruction", /* 2 */
128: "privileged instruction",/*3 */
129: "fp disabled", /* 4 */
130: "window overflow", /* 5 */
131: "window underflow", /* 6 */
132: "alignment fault", /* 7 */
133: "fp exception", /* 8 */
134: "data fault", /* 9 */
135: "tag overflow", /* 0a */
136: "watchpoint", /* 0b */
137: T, T, T, T, T, /* 0c..10 */
138: "level 1 int", /* 11 */
139: "level 2 int", /* 12 */
140: "level 3 int", /* 13 */
141: "level 4 int", /* 14 */
142: "level 5 int", /* 15 */
143: "level 6 int", /* 16 */
144: "level 7 int", /* 17 */
145: "level 8 int", /* 18 */
146: "level 9 int", /* 19 */
147: "level 10 int", /* 1a */
148: "level 11 int", /* 1b */
149: "level 12 int", /* 1c */
150: "level 13 int", /* 1d */
151: "level 14 int", /* 1e */
152: "level 15 int", /* 1f */
153: "double trap", /* 20 */
154: "v8 text error", /* 21 */
155: T, T, /* 22..23 */
156: "v8 cp disabled", /* 24 */
157: "v8 unimp flush", /* 25 */
158: T, T, /* 26..27 */
159: "v8 cp exception", /* 28 */
160: "v8 data error", /* 29 */
161: "v8 idiv by zero", /* 2a */
162: "v8 store error", /* 2b */
163: "dtlb miss", /* 2c */
164: T, T, T, /* 2d..2f */
165: T, T, T, T, T, T, T, T, /* 30..37 */
166: T, T, T, T, /* 38..3b */
167: "itlb miss", /* 3c */
168: T, T, T, /* 3d..3f */
169: T, T, T, T, T, T, T, T, /* 40..48 */
170: T, T, T, T, T, T, T, T, /* 48..4f */
171: T, T, T, T, T, T, T, T, /* 50..57 */
172: T, T, T, T, T, T, T, T, /* 58..5f */
173: T, T, T, T, T, T, T, T, /* 60..67 */
174: T, T, T, T, T, T, T, T, /* 68..6f */
175: T, T, T, T, T, T, T, T, /* 70..77 */
176: T, T, T, T, T, T, T, T, /* 78..7f */
177:
178: /* user (software trap) vectors */
179: "syscall", /* 80 */
180: "breakpoint", /* 81 */
181: "zero divide", /* 82 */
182: "flush windows", /* 83 */
183: "clean windows", /* 84 */
184: "range check", /* 85 */
185: "fix align", /* 86 */
186: "integer overflow", /* 87 */
187: "svr4 syscall", /* 88 */
188: "4.4 syscall", /* 89 */
189: "kgdb exec", /* 8a */
190: T, T, T, T, T, /* 8b..8f */
191: T, T, T, T, T, T, T, T, /* 9a..97 */
192: T, T, T, T, T, T, T, T, /* 98..9f */
193: "svr4 getcc", /* a0 */
194: "svr4 setcc", /* a1 */
195: "svr4 getpsr", /* a2 */
196: "svr4 setpsr", /* a3 */
197: "svr4 gethrtime", /* a4 */
198: "svr4 gethrvtime", /* a5 */
199: T, /* a6 */
200: "svr4 gethrestime", /* a7 */
201: };
202:
203: #define N_TRAP_TYPES (sizeof trap_type / sizeof *trap_type)
204:
205: static __inline void userret(struct proc *);
206: void trap(unsigned, int, int, struct trapframe *);
207: static __inline void share_fpu(struct proc *, struct trapframe *);
208: void mem_access_fault(unsigned, int, u_int, int, int, struct trapframe *);
209: void ecc_fault(unsigned, int, u_int, int, int, struct trapframe *);
210: void syscall(register_t, struct trapframe *, register_t);
211:
212: int ignore_bogus_traps = 0;
213:
214: int want_ast = 0;
215: /*
216: * Define the code needed before returning to user mode, for
217: * trap, mem_access_fault, and syscall.
218: */
219: static __inline void
220: userret(struct proc *p)
221: {
222: int sig;
223:
224: /* take pending signals */
225: while ((sig = CURSIG(p)) != 0)
226: postsig(sig);
227:
228: curpriority = p->p_priority = p->p_usrpri;
229: }
230:
231: /*
232: * If someone stole the FPU while we were away, do not enable it
233: * on return. This is not done in userret() above as it must follow
234: * the ktrsysret() in syscall(). Actually, it is likely that the
235: * ktrsysret should occur before the call to userret.
236: */
237: static __inline void share_fpu(p, tf)
238: struct proc *p;
239: struct trapframe *tf;
240: {
241: if ((tf->tf_psr & PSR_EF) != 0 && cpuinfo.fpproc != p)
242: tf->tf_psr &= ~PSR_EF;
243: }
244:
245: /*
246: * Called from locore.s trap handling, for non-MMU-related traps.
247: * (MMU-related traps go through mem_access_fault, below.)
248: */
249: void
250: trap(type, psr, pc, tf)
251: unsigned type;
252: int psr, pc;
253: struct trapframe *tf;
254: {
255: struct proc *p;
256: struct pcb *pcb;
257: int n;
258: union sigval sv;
259:
260: sv.sival_int = pc; /* XXX fix for parm five of trapsignal() */
261:
262: /* This steps the PC over the trap. */
263: #define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
264:
265: uvmexp.traps++;
266: /*
267: * Generally, kernel traps cause a panic. Any exceptions are
268: * handled early here.
269: */
270: if (psr & PSR_PS) {
271: #ifdef DDB
272: if (type == T_BREAKPOINT) {
273: write_all_windows();
274: if (kdb_trap(type, tf)) {
275: return;
276: }
277: }
278: #endif
279: #ifdef DIAGNOSTIC
280: /*
281: * Currently, we allow DIAGNOSTIC kernel code to
282: * flush the windows to record stack traces.
283: */
284: if (type == T_FLUSHWIN) {
285: write_all_windows();
286: ADVANCE;
287: return;
288: }
289: #endif
290: /*
291: * Storing %fsr in cpu_attach will cause this trap
292: * even though the fpu has been enabled, if and only
293: * if there is no FPU.
294: */
295: if (type == T_FPDISABLED && cold) {
296: ADVANCE;
297: return;
298: }
299: dopanic:
300: printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n",
301: type, pc, tf->tf_npc, psr, PSR_BITS);
302: if (type == T_RREGERROR) /* 0x20 double fault */
303: printf("fcr %b fvar %08x fpar %08x fpsr %08x pdbr %08x\n",
304: lda(0, ASI_FCR), FCR_BITS, lda(0, ASI_FPAR),
305: lda(0, ASI_FPSR), lda(0, ASI_PDBR));
306: panic(type < N_TRAP_TYPES ? trap_type[type] : T);
307: /* NOTREACHED */
308: }
309: if ((p = curproc) == NULL)
310: p = &proc0;
311: pcb = &p->p_addr->u_pcb;
312: p->p_md.md_tf = tf; /* for ptrace/signals */
313:
314: switch (type) {
315:
316: default:
317: if (type < 0x80) {
318: if (!ignore_bogus_traps)
319: goto dopanic;
320: printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n",
321: type, pc, tf->tf_npc, psr, PSR_BITS);
322: trapsignal(p, SIGILL, type, ILL_ILLOPC, sv);
323: break;
324: }
325: #if defined(COMPAT_SVR4)
326: badtrap:
327: #endif
328: /* the following message is gratuitous */
329: /* ... but leave it in until we find anything */
330: printf("%s[%d]: unimplemented software trap 0x%x\n",
331: p->p_comm, p->p_pid, type);
332: trapsignal(p, SIGILL, type, ILL_ILLOPC, sv);
333: break;
334:
335: #ifdef COMPAT_SVR4
336: case T_SVR4_GETCC:
337: case T_SVR4_SETCC:
338: case T_SVR4_GETPSR:
339: case T_SVR4_SETPSR:
340: case T_SVR4_GETHRTIME:
341: case T_SVR4_GETHRVTIME:
342: case T_SVR4_GETHRESTIME:
343: if (!svr4_trap(type, p))
344: goto badtrap;
345: break;
346: #endif
347:
348: case T_AST:
349: want_ast = 0;
350: if (p->p_flag & P_OWEUPC) {
351: ADDUPROF(p);
352: }
353: if (want_resched)
354: preempt(NULL);
355: break;
356:
357: case T_ILLINST:
358: if ((n = emulinstr(pc, tf)) == 0) {
359: ADVANCE;
360: break;
361: }
362: trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
363: break;
364:
365: case T_PRIVINST:
366: trapsignal(p, SIGILL, 0, ILL_PRVOPC, sv);
367: break;
368:
369: case T_FPDISABLED: {
370: struct fpstate *fs = p->p_md.md_fpstate;
371:
372: if (fs == NULL) {
373: fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK);
374: *fs = initfpstate;
375: p->p_md.md_fpstate = fs;
376: }
377: /*
378: * If we have not found an FPU, we have to emulate it.
379: */
380: if (!foundfpu) {
381: #ifdef notyet
382: fpu_emulate(p, tf, fs);
383: break;
384: #else
385: trapsignal(p, SIGFPE, 0, FPE_FLTINV, sv);
386: break;
387: #endif
388: }
389: /*
390: * We may have more FPEs stored up and/or ops queued.
391: * If they exist, handle them and get out. Otherwise,
392: * resolve the FPU state, turn it on, and try again.
393: */
394: if (fs->fs_qsize) {
395: fpu_cleanup(p, fs);
396: break;
397: }
398: if (cpuinfo.fpproc != p) { /* we do not have it */
399: if (cpuinfo.fpproc != NULL) /* someone else had it */
400: savefpstate(cpuinfo.fpproc->p_md.md_fpstate);
401: loadfpstate(fs);
402: cpuinfo.fpproc = p; /* now we do have it */
403: uvmexp.fpswtch++;
404: }
405: tf->tf_psr |= PSR_EF;
406: break;
407: }
408:
409: case T_WINOF:
410: if (rwindow_save(p))
411: sigexit(p, SIGILL);
412: break;
413:
414: #define read_rw(src, dst) \
415: copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow))
416:
417: case T_RWRET:
418: /*
419: * T_RWRET is a window load needed in order to rett.
420: * It simply needs the window to which tf->tf_out[6]
421: * (%sp) points. There are no user or saved windows now.
422: * Copy the one from %sp into pcb->pcb_rw[0] and set
423: * nsaved to -1. If we decide to deliver a signal on
424: * our way out, we will clear nsaved.
425: */
426: if (pcb->pcb_uw || pcb->pcb_nsaved)
427: panic("trap T_RWRET 1");
428: #ifdef DEBUG
429: if (rwindow_debug)
430: printf("%s[%d]: rwindow: pcb<-stack: 0x%x\n",
431: p->p_comm, p->p_pid, tf->tf_out[6]);
432: #endif
433: if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
434: sigexit(p, SIGILL);
435: if (pcb->pcb_nsaved)
436: panic("trap T_RWRET 2");
437: pcb->pcb_nsaved = -1; /* mark success */
438: break;
439:
440: case T_WINUF:
441: /*
442: * T_WINUF is a real window underflow, from a restore
443: * instruction. It needs to have the contents of two
444: * windows---the one belonging to the restore instruction
445: * itself, which is at its %sp, and the one belonging to
446: * the window above, which is at its %fp or %i6---both
447: * in the pcb. The restore's window may still be in
448: * the cpu; we need to force it out to the stack.
449: */
450: #ifdef DEBUG
451: if (rwindow_debug)
452: printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: 0x%x\n",
453: p->p_comm, p->p_pid, tf->tf_out[6]);
454: #endif
455: write_user_windows();
456: if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
457: sigexit(p, SIGILL);
458: #ifdef DEBUG
459: if (rwindow_debug)
460: printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: 0x%x\n",
461: p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]);
462: #endif
463: if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1]))
464: sigexit(p, SIGILL);
465: if (pcb->pcb_nsaved)
466: panic("trap T_WINUF");
467: pcb->pcb_nsaved = -1; /* mark success */
468: break;
469:
470: case T_ALIGN:
471: if ((p->p_md.md_flags & MDP_FIXALIGN) != 0 &&
472: fixalign(p, tf) == 0) {
473: ADVANCE;
474: break;
475: }
476: trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv);
477: break;
478:
479: case T_FPE:
480: /*
481: * Clean up after a floating point exception.
482: * fpu_cleanup can (and usually does) modify the
483: * state we save here, so we must `give up' the FPU
484: * chip context. (The software and hardware states
485: * will not match once fpu_cleanup does its job, so
486: * we must not save again later.)
487: */
488: if (p != cpuinfo.fpproc)
489: panic("fpe without being the FP user");
490: savefpstate(p->p_md.md_fpstate);
491: cpuinfo.fpproc = NULL;
492: /* tf->tf_psr &= ~PSR_EF; */ /* share_fpu will do this */
493: fpu_cleanup(p, p->p_md.md_fpstate);
494: /* fpu_cleanup posts signals if needed */
495: #if 0 /* ??? really never??? */
496: ADVANCE;
497: #endif
498: break;
499:
500: case T_TAGOF:
501: trapsignal(p, SIGEMT, 0, EMT_TAGOVF, sv);
502: break;
503:
504: case T_CPDISABLED:
505: uprintf("coprocessor instruction\n"); /* XXX */
506: trapsignal(p, SIGILL, 0, ILL_COPROC, sv);
507: break;
508:
509: case T_BREAKPOINT:
510: trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv);
511: break;
512:
513: case T_DIV0:
514: case T_IDIV0:
515: ADVANCE;
516: trapsignal(p, SIGFPE, 0, FPE_INTDIV, sv);
517: break;
518:
519: case T_FLUSHWIN:
520: write_user_windows();
521: #ifdef probably_slower_since_this_is_usually_false
522: if (pcb->pcb_nsaved && rwindow_save(p))
523: sigexit(p, SIGILL);
524: #endif
525: ADVANCE;
526: break;
527:
528: case T_CLEANWIN:
529: uprintf("T_CLEANWIN\n"); /* XXX */
530: ADVANCE;
531: break;
532:
533: case T_RANGECHECK:
534: uprintf("T_RANGECHECK\n"); /* XXX */
535: ADVANCE;
536: trapsignal(p, SIGILL, 0, ILL_ILLOPN, sv);
537: break;
538:
539: case T_FIXALIGN:
540: #ifdef DEBUG_ALIGN
541: uprintf("T_FIXALIGN\n");
542: #endif
543: /* User wants us to fix alignment faults */
544: p->p_md.md_flags |= MDP_FIXALIGN;
545: ADVANCE;
546: break;
547:
548: case T_INTOF:
549: uprintf("T_INTOF\n"); /* XXX */
550: ADVANCE;
551: trapsignal(p, SIGFPE, FPE_INTOVF_TRAP, FPE_INTOVF, sv);
552: break;
553: }
554: userret(p);
555: share_fpu(p, tf);
556: #undef ADVANCE
557: }
558:
559: /*
560: * Save windows from PCB into user stack, and return 0. This is used on
561: * window overflow pseudo-traps (from locore.s, just before returning to
562: * user mode) and when ptrace or sendsig needs a consistent state.
563: * As a side effect, rwindow_save() always sets pcb_nsaved to 0,
564: * clobbering the `underflow restore' indicator if it was -1.
565: *
566: * If the windows cannot be saved, pcb_nsaved is restored and we return -1.
567: */
568: int
569: rwindow_save(p)
570: struct proc *p;
571: {
572: struct pcb *pcb = &p->p_addr->u_pcb;
573: struct rwindow *rw = &pcb->pcb_rw[0];
574: int i;
575:
576: i = pcb->pcb_nsaved;
577: if (i < 0) {
578: pcb->pcb_nsaved = 0;
579: return (0);
580: }
581: if (i == 0)
582: return (0);
583: #ifdef DEBUG
584: if (rwindow_debug)
585: printf("%s[%d]: rwindow: pcb->stack:", p->p_comm, p->p_pid);
586: #endif
587: do {
588: #ifdef DEBUG
589: if (rwindow_debug)
590: printf(" 0x%x", rw[1].rw_in[6]);
591: #endif
592: if (copyout((caddr_t)rw, (caddr_t)rw[1].rw_in[6],
593: sizeof *rw))
594: return (-1);
595: rw++;
596: } while (--i > 0);
597: #ifdef DEBUG
598: if (rwindow_debug)
599: printf("\n");
600: #endif
601: pcb->pcb_nsaved = 0;
602: return (0);
603: }
604:
605: /*
606: * Kill user windows (before exec) by writing back to stack or pcb
607: * and then erasing any pcb tracks. Otherwise we might try to write
608: * the registers into the new process after the exec.
609: */
610: void
611: pmap_unuse_final(p)
612: struct proc *p;
613: {
614:
615: write_user_windows();
616: p->p_addr->u_pcb.pcb_nsaved = 0;
617: }
618:
619: /*
620: * Called from locore.s trap handling, for synchronous memory faults.
621: *
622: * This duplicates a lot of logic in trap() and perhaps should be
623: * moved there; but the bus-error-register parameters are unique to
624: * this routine.
625: *
626: * Since synchronous errors accumulate during prefetch, we can have
627: * more than one `cause'. But we do not care what the cause, here;
628: * we just want to page in the page and try again.
629: */
630: void
631: mem_access_fault(type, ser, v, pc, psr, tf)
632: unsigned type;
633: int ser;
634: u_int v;
635: int pc, psr;
636: struct trapframe *tf;
637: {
638: struct proc *p;
639: struct vmspace *vm;
640: vaddr_t va;
641: int rv;
642: vm_prot_t ftype;
643: int onfault;
644: union sigval sv;
645: u_int isr;
646:
647: uvmexp.traps++;
648: if ((p = curproc) == NULL) /* safety check */
649: p = &proc0;
650:
651: if (type == T_DATAFAULT && (ser & FCR_EXTERNAL) != 0) {
652: /*
653: * For external faults, check the iCU status.
654: */
655:
656: isr = lda(ICU_ISR, ASI_PHYS_IO);
657:
658: /*
659: * Sometimes the interrupt register is empty... and I have
660: * no idea what we are supposed to do in such situations.
661: */
662: if (isr == 0) {
663: #ifdef DEBUG
664: printf("external data fault, fcr %b pc %08x fvar %08x fpar %08x fpsr %08x pdbr %08x\n",
665: ser, FCR_BITS, pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR), lda(0, ASI_PDBR));
666: #ifdef DDB
667: Debugger();
668: #endif
669: #endif
670: ser &= ~FCR_EXTERNAL;
671: if (ser == 0)
672: goto out;
673: } else {
674: /*
675: * This is either an unrecoverable DMA or ECC error,
676: * or a bus timeout.
677: * XXX should restart the operation if retry timeout.
678: */
679: panic("data fault: fcr %b isr %b pc %08x addr %08x fpar %08x fpsr %08x",
680: ser, FCR_BITS, isr, ISR_BITS,
681: pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR));
682: }
683: }
684:
685: /*
686: * Figure out what to pass the VM code, and ignore the sva register
687: * value in v on text faults (text faults are always at pc).
688: * Kernel faults are somewhat different: text faults are always
689: * illegal, and data faults are extra complex. User faults must
690: * set p->p_md.md_tf, in case we decide to deliver a signal. Check
691: * for illegal virtual addresses early since those can induce more
692: * faults.
693: */
694: if (type == T_TEXTFAULT)
695: v = pc;
696: ftype = ser & FCR_RO ? VM_PROT_WRITE : VM_PROT_READ;
697: va = trunc_page(v);
698: if (psr & PSR_PS) {
699: extern char Lfsbail[];
700: if (type == T_TEXTFAULT) {
701: /*
702: * If we are trying to figure on which processor mask
703: * we run, we might trigger a text fault with
704: * pcb_onfault set.
705: * This is normal; don't panic there.
706: */
707: if (cold && p->p_addr->u_pcb.pcb_onfault != NULL)
708: goto kfault;
709: (void) splhigh();
710: printf("text fault: pc=0x%x fcr=%b\n", pc,
711: ser, FCR_BITS);
712: panic("kernel fault");
713: /* NOTREACHED */
714: }
715: /*
716: * If this was an access that we shouldn't try to page in,
717: * resume at the fault handler without any action.
718: */
719: if (p->p_addr && p->p_addr->u_pcb.pcb_onfault == Lfsbail)
720: goto kfault;
721:
722: /*
723: * During autoconfiguration, faults are never OK unless
724: * pcb_onfault is set. Once running normally we must allow
725: * exec() to cause copy-on-write faults to kernel addresses.
726: */
727: if (cold)
728: goto kfault;
729: if (va >= VM_MIN_KERNEL_ADDRESS) {
730: if (uvm_fault(kernel_map, va, 0, ftype) == 0)
731: return;
732: goto kfault;
733: }
734: } else
735: p->p_md.md_tf = tf;
736:
737: vm = p->p_vmspace;
738: rv = uvm_fault(&vm->vm_map, (vaddr_t)va, 0, ftype);
739:
740: /*
741: * If this was a stack access we keep track of the maximum
742: * accessed stack size. Also, if vm_fault gets a protection
743: * failure it is due to accessing the stack region outside
744: * the current limit and we need to reflect that as an access
745: * error.
746: */
747: if ((caddr_t)va >= vm->vm_maxsaddr) {
748: if (rv == 0)
749: uvm_grow(p, va);
750: else if (rv == EACCES)
751: rv = EFAULT;
752: }
753: if (rv != 0) {
754: /*
755: * If doing copyin/out, return to onfault address. Any
756: * other page fault in kernel, die; if user fault, deliver
757: * SIGSEGV.
758: */
759: if (psr & PSR_PS) {
760: kfault:
761: onfault = p->p_addr ?
762: (int)p->p_addr->u_pcb.pcb_onfault : 0;
763: if (!onfault) {
764: (void) splhigh();
765: printf("data fault: pc=0x%x addr=0x%x fcr=%b\n",
766: pc, v, ser, FCR_BITS);
767: panic("kernel fault");
768: /* NOTREACHED */
769: }
770: tf->tf_pc = onfault;
771: tf->tf_npc = onfault + 4;
772: return;
773: }
774:
775: sv.sival_int = v;
776: trapsignal(p, SIGSEGV, (ser & FCR_RO) ? VM_PROT_WRITE :
777: VM_PROT_READ, SEGV_MAPERR, sv);
778: }
779: out:
780: if ((psr & PSR_PS) == 0) {
781: userret(p);
782: share_fpu(p, tf);
783: }
784: }
785:
786: void
787: ecc_fault(type, ser, v, pc, psr, tf)
788: unsigned type;
789: int ser;
790: u_int v;
791: int pc, psr;
792: struct trapframe *tf;
793: {
794: /* XXX */
795: panic("ecc_fault");
796: }
797:
798: /*
799: * System calls. `pc' is just a copy of tf->tf_pc.
800: *
801: * Note that the things labelled `out' registers in the trapframe were the
802: * `in' registers within the syscall trap code (because of the automatic
803: * `save' effect of each trap). They are, however, the %o registers of the
804: * thing that made the system call, and are named that way here.
805: */
806: void
807: syscall(code, tf, pc)
808: register_t code;
809: struct trapframe *tf;
810: register_t pc;
811: {
812: int i, nsys, *ap, nap;
813: struct sysent *callp;
814: struct proc *p;
815: int error, new;
816: struct args {
817: register_t i[8];
818: } args;
819: register_t rval[2];
820: #ifdef DIAGNOSTIC
821: extern struct pcb *cpcb;
822: #endif
823:
824: uvmexp.syscalls++;
825: p = curproc;
826: #ifdef DIAGNOSTIC
827: if (tf->tf_psr & PSR_PS)
828: panic("syscall");
829: if (cpcb != &p->p_addr->u_pcb)
830: panic("syscall cpcb/ppcb");
831: if (tf != (struct trapframe *)((caddr_t)cpcb + USPACE) - 1)
832: panic("syscall trapframe");
833: #endif
834: p->p_md.md_tf = tf;
835: new = code & (SYSCALL_G7RFLAG | SYSCALL_G2RFLAG);
836: code &= ~(SYSCALL_G7RFLAG | SYSCALL_G2RFLAG);
837:
838: callp = p->p_emul->e_sysent;
839: nsys = p->p_emul->e_nsysent;
840:
841: /*
842: * The first six system call arguments are in the six %o registers.
843: * Any arguments beyond that are in the `argument extension' area
844: * of the user's stack frame (see <machine/frame.h>).
845: *
846: * Check for ``special'' codes that alter this, namely syscall and
847: * __syscall. The latter takes a quad syscall number, so that other
848: * arguments are at their natural alignments. Adjust the number
849: * of ``easy'' arguments as appropriate; we will copy the hard
850: * ones later as needed.
851: */
852: ap = &tf->tf_out[0];
853: nap = 6;
854:
855: switch (code) {
856: case SYS_syscall:
857: code = *ap++;
858: nap--;
859: break;
860: case SYS___syscall:
861: if (callp != sysent)
862: break;
863: code = ap[_QUAD_LOWWORD];
864: ap += 2;
865: nap -= 2;
866: break;
867: }
868:
869: if (code < 0 || code >= nsys)
870: callp += p->p_emul->e_nosys;
871: else {
872: callp += code;
873: i = callp->sy_argsize / sizeof(register_t);
874: if (i > nap) { /* usually false */
875: if (i > 8)
876: panic("syscall nargs");
877: error = copyin((caddr_t)tf->tf_out[6] +
878: offsetof(struct frame, fr_argx),
879: (caddr_t)&args.i[nap], (i - nap) * sizeof(register_t));
880: if (error) {
881: #ifdef KTRACE
882: if (KTRPOINT(p, KTR_SYSCALL))
883: ktrsyscall(p, code,
884: callp->sy_argsize, args.i);
885: #endif
886: goto bad;
887: }
888: i = nap;
889: }
890: copywords(ap, args.i, i * sizeof(register_t));
891: }
892: #ifdef KTRACE
893: if (KTRPOINT(p, KTR_SYSCALL))
894: ktrsyscall(p, code, callp->sy_argsize, args.i);
895: #endif
896: rval[0] = 0;
897: rval[1] = tf->tf_out[1];
898: #if NSYSTRACE > 0
899: if (ISSET(p->p_flag, P_SYSTRACE))
900: error = systrace_redirect(code, p, &args, rval);
901: else
902: #endif
903: error = (*callp->sy_call)(p, &args, rval);
904:
905: switch (error) {
906: case 0:
907: /* Note: fork() does not return here in the child */
908: tf->tf_out[0] = rval[0];
909: tf->tf_out[1] = rval[1];
910: if (new) {
911: /* jmp %g2 (or %g7, deprecated) on success */
912: i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
913: if (i & 3) {
914: error = EINVAL;
915: goto bad;
916: }
917: } else {
918: /* old system call convention: clear C on success */
919: tf->tf_psr &= ~PSR_C; /* success */
920: i = tf->tf_npc;
921: }
922: tf->tf_pc = i;
923: tf->tf_npc = i + 4;
924: break;
925:
926: case ERESTART:
927: case EJUSTRETURN:
928: /* nothing to do */
929: break;
930:
931: default:
932: bad:
933: if (p->p_emul->e_errno)
934: error = p->p_emul->e_errno[error];
935: tf->tf_out[0] = error;
936: tf->tf_psr |= PSR_C; /* fail */
937: i = tf->tf_npc;
938: tf->tf_pc = i;
939: tf->tf_npc = i + 4;
940: break;
941: }
942:
943: userret(p);
944: #ifdef KTRACE
945: if (KTRPOINT(p, KTR_SYSRET))
946: ktrsysret(p, code, error, rval[0]);
947: #endif
948: share_fpu(p, tf);
949: }
950:
951: /*
952: * Process the tail end of a fork() for the child.
953: */
954: void
955: child_return(arg)
956: void *arg;
957: {
958: struct proc *p = arg;
959: struct trapframe *tf = p->p_md.md_tf;
960:
961: /*
962: * Return values in the frame set by cpu_fork().
963: */
964: tf->tf_out[0] = 0;
965: tf->tf_out[1] = 0;
966: tf->tf_psr &= ~PSR_C;
967:
968: userret(p);
969: #ifdef KTRACE
970: if (KTRPOINT(p, KTR_SYSRET))
971: ktrsysret(p,
972: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
973: #endif
974: }
CVSweb