Annotation of sys/arch/mac68k/mac68k/trap.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: trap.c,v 1.54 2007/05/15 13:46:22 martin Exp $ */
2: /* $NetBSD: trap.c,v 1.68 1998/12/22 08:47:07 scottr Exp $ */
3:
4: /*
5: * Copyright (c) 1988 University of Utah.
6: * Copyright (c) 1982, 1986, 1990, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * the Systems Programming Group of the University of Utah Computer
11: * Science Department.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * from: Utah $Hdr: trap.c 1.37 92/12/20$
38: *
39: * @(#)trap.c 8.5 (Berkeley) 1/4/94
40: */
41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/proc.h>
45: #include <sys/acct.h>
46: #include <sys/kernel.h>
47: #include <sys/signalvar.h>
48: #include <sys/resourcevar.h>
49: #include <sys/syscall.h>
50: #include <sys/syslog.h>
51: #include <sys/user.h>
52: #ifdef KGDB
53: #include <sys/kgdb.h>
54: #endif
55: #ifdef KTRACE
56: #include <sys/ktrace.h>
57: #endif
58: #ifdef DEBUG
59: #include <dev/cons.h>
60: #endif
61:
62: #include <machine/db_machdep.h>
63: #include <machine/psl.h>
64: #include <machine/trap.h>
65: #include <machine/cpu.h>
66: #include <machine/reg.h>
67:
68: #include <m68k/fpe/fpu_emulate.h>
69:
70: #include "systrace.h"
71: #include <dev/systrace.h>
72:
73: #include <uvm/uvm_extern.h>
74: #include <uvm/uvm_pmap.h>
75:
76: #ifdef COMPAT_SUNOS
77: #include <compat/sunos/sunos_syscall.h>
78: extern struct emul emul_sunos;
79: #endif
80:
81: int astpending;
82:
83: char *trap_type[] = {
84: "Bus error",
85: "Address error",
86: "Illegal instruction",
87: "Zero divide",
88: "CHK instruction",
89: "TRAPV instruction",
90: "Privilege violation",
91: "Trace trap",
92: "MMU fault",
93: "SSIR trap",
94: "Format error",
95: "68881 exception",
96: "Coprocessor violation",
97: "Async system trap"
98: };
99: int trap_types = sizeof trap_type / sizeof trap_type[0];
100:
101: /*
102: * Size of various exception stack frames (minus the standard 8 bytes)
103: */
104: short exframesize[] = {
105: FMT0SIZE, /* type 0 - normal (68020/030/040) */
106: FMT1SIZE, /* type 1 - throwaway (68020/030/040) */
107: FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */
108: FMT3SIZE, /* type 3 - FP post-instruction (68040) */
109: FMT4SIZE, /* type 4 - LC040 FP exception (68LC040) */
110: -1, -1, /* type 5-6 - undefined */
111: FMT7SIZE, /* type 7 - access error (68040) */
112: 58, /* type 8 - bus fault (68010) */
113: FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */
114: FMTASIZE, /* type A - short bus fault (68020/030) */
115: FMTBSIZE, /* type B - long bus fault (68020/030) */
116: -1, -1, -1, -1 /* type C-F - undefined */
117: };
118:
119: #ifdef M68040
120: #define KDFAULT(c) (mmutype == MMU_68040 ? \
121: ((c) & SSW4_TMMASK) == SSW4_TMKD : \
122: ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
123: #define WRFAULT(c) (mmutype == MMU_68040 ? \
124: ((c) & SSW4_RW) == 0 : \
125: ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
126: #else
127: #define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
128: #define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF)
129: #endif
130:
131: #ifdef DEBUG
132: int mmudebug = 0;
133: int mmupid = -1;
134: #define MDB_FOLLOW 1
135: #define MDB_WBFOLLOW 2
136: #define MDB_WBFAILED 4
137: #define MDB_ISPID(pid) ((pid) == mmupid)
138: #endif
139:
140: /* trap() and syscall() only called from locore */
141: void trap(int, u_int, u_int, struct frame);
142: void syscall(register_t, struct frame);
143:
144: #if defined(M68040)
145: int writeback(struct frame *);
146: void wb_userret(struct proc *, struct frame *);
147: #if DEBUG
148: static void dumpssw(u_short);
149: static void dumpwb(int, u_short, u_int, u_int);
150: #endif
151: #endif
152:
153: /*
154: * Trap and syscall both need the following work done before returning
155: * to user mode.
156: */
157: void
158: userret(struct proc *p)
159: {
160: int sig;
161:
162: /* take pending signals */
163: while ((sig = CURSIG(p)) != 0)
164: postsig(sig);
165: curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri;
166: }
167:
168: #ifdef M68040
169: /*
170: * Same as above, but also handles writeback completion on 68040.
171: */
172: void
173: wb_userret(struct proc *p, struct frame *fp)
174: {
175: int sig;
176: union sigval sv;
177:
178: /* take pending signals */
179: while ((sig = CURSIG(p)) != 0)
180: postsig(sig);
181: p->p_priority = p->p_usrpri;
182:
183: /*
184: * Deal with user mode writebacks (from trap, or from sigreturn).
185: * If any writeback fails, go back and attempt signal delivery
186: * unless we have already been here and attempted the writeback
187: * (e.g. bad address with user ignoring SIGSEGV). In that case,
188: * we just return to the user without successfully completing
189: * the writebacks. Maybe we should just drop the sucker?
190: */
191: if (mmutype == MMU_68040 && fp->f_format == FMT7) {
192: if ((sig = writeback(fp)) != 0) {
193: sv.sival_ptr = (void *)fp->f_fmt7.f_fa;
194: trapsignal(p, sig, T_MMUFLT, SEGV_MAPERR, sv);
195:
196: while ((sig = CURSIG(p)) != 0)
197: postsig(sig);
198: p->p_priority = p->p_usrpri;
199: }
200: }
201: curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
202: }
203: #endif
204:
205: /*
206: * Trap is called from locore to handle most types of processor traps,
207: * including events such as simulated software interrupts/AST's.
208: * System calls are broken out for efficiency.
209: */
210: /*ARGSUSED*/
211: void
212: trap(type, code, v, frame)
213: int type;
214: u_int code;
215: u_int v;
216: struct frame frame;
217: {
218: struct proc *p;
219: int i, s;
220: u_int ucode;
221: int typ = 0;
222: union sigval sv;
223:
224: uvmexp.traps++;
225: p = curproc;
226: ucode = 0;
227:
228: /* I have verified that this DOES happen! -gwr */
229: if (p == NULL)
230: p = &proc0;
231: #ifdef DIAGNOSTIC
232: if (p->p_addr == NULL)
233: panic("trap: type 0x%x, code 0x%x, v 0x%x -- no pcb",
234: type, code, v);
235: #endif
236:
237: if (USERMODE(frame.f_sr)) {
238: type |= T_USER;
239: p->p_md.md_regs = frame.f_regs;
240: }
241:
242: switch (type) {
243: default:
244: dopanic:
245: printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
246: printf("%s program counter = 0x%x\n",
247: (type & T_USER) ? "user" : "kernel", frame.f_pc);
248: /*
249: * Let the kernel debugger see the trap frame that
250: * caused us to panic. This is a convenience so
251: * one can see registers at the point of failure.
252: */
253: s = splhigh();
254: #ifdef KGDB
255: /* If connected, step or cont returns 1 */
256: if (kgdb_trap(type, (db_regs_t *)&frame))
257: goto kgdb_cont;
258: #endif
259: #ifdef DDB
260: (void)kdb_trap(type, (db_regs_t *)&frame);
261: #endif
262: #ifdef KGDB
263: kgdb_cont:
264: #endif
265: splx(s);
266: if (panicstr) {
267: printf("trap during panic!\n");
268: #ifdef DEBUG
269: /* XXX should be a machine-dependent hook */
270: printf("(press a key)\n"); (void)cngetc();
271: #endif
272: }
273: regdump(&(frame.F_t), 128);
274: type &= ~T_USER;
275: if ((u_int)type < trap_types)
276: panic(trap_type[type]);
277: panic("trap");
278:
279: case T_BUSERR: /* Kernel bus error */
280: if (!p->p_addr->u_pcb.pcb_onfault)
281: goto dopanic;
282: /*
283: * If we have arranged to catch this fault in any of the
284: * copy to/from user space routines, set PC to return to
285: * indicated location and set flag informing buserror code
286: * that it may need to clean up stack frame.
287: */
288: copyfault:
289: frame.f_stackadj = exframesize[frame.f_format];
290: frame.f_format = frame.f_vector = 0;
291: frame.f_pc = (int)p->p_addr->u_pcb.pcb_onfault;
292: return;
293:
294: case T_BUSERR|T_USER: /* Bus error */
295: typ = BUS_OBJERR;
296: ucode = code & ~T_USER;
297: i = SIGBUS;
298: break;
299: case T_ADDRERR|T_USER: /* Address error */
300: typ = BUS_ADRALN;
301: ucode = code & ~T_USER;
302: i = SIGBUS;
303: break;
304:
305: case T_ILLINST|T_USER: /* Illegal instruction fault */
306: ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
307: typ = ILL_ILLOPC;
308: i = SIGILL;
309: v = frame.f_pc;
310: break;
311:
312: case T_PRIVINST|T_USER: /* Privileged instruction fault */
313: ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
314: typ = ILL_PRVOPC;
315: i = SIGILL;
316: v = frame.f_pc;
317: break;
318: /*
319: * divde by zero, CHK/TRAPV inst
320: */
321: case T_ZERODIV|T_USER: /* Divide by zero trap */
322: ucode = frame.f_format;
323: typ = FPE_INTDIV;
324: i = SIGFPE;
325: v = frame.f_pc;
326: break;
327:
328: case T_CHKINST|T_USER: /* CHK instruction trap */
329: ucode = frame.f_format;
330: type = FPE_FLTSUB;
331: i = SIGFPE;
332: v = frame.f_pc;
333: break;
334:
335: case T_TRAPVINST|T_USER: /* TRAPV instruction trap */
336: ucode = frame.f_format;
337: typ = ILL_ILLTRP;
338: i = SIGILL;
339: v = frame.f_pc;
340: break;
341: /*
342: * User coprocessor violation
343: */
344: case T_COPERR|T_USER:
345: typ = ILL_COPROC;
346: ucode = 0;
347: i = SIGILL;
348: break;
349: /*
350: * 6888x exceptions
351: */
352: case T_FPERR|T_USER:
353: typ = FPE_FLTRES;
354: ucode = code;
355: i = SIGFPE;
356: v = frame.f_pc;
357: break;
358:
359: /*
360: * FPU faults in supervisor mode.
361: */
362: case T_ILLINST: /* fnop generates this, apparently. */
363: case T_FPEMULI:
364: case T_FPEMULD: {
365: extern label_t *nofault;
366:
367: if (nofault) /* If we're probing. */
368: longjmp(nofault);
369: if (type == T_ILLINST)
370: printf("Kernel Illegal Instruction trap.\n");
371: else
372: printf("Kernel FPU trap.\n");
373: goto dopanic;
374: }
375:
376: /*
377: * Unimplemented FPU instructions/datatypes.
378: */
379: case T_FPEMULI|T_USER:
380: case T_FPEMULD|T_USER:
381: #ifdef FPU_EMULATE
382: i = fpu_emulate(&frame, &p->p_addr->u_pcb.pcb_fpregs,
383: &typ);
384: /* XXX -- deal with tracing? (frame.f_sr & PSL_T) */
385: if (i == 0)
386: goto out;
387: #else
388: uprintf("pid %d killed: no floating point support.\n",
389: p->p_pid);
390: i = SIGILL;
391: typ = ILL_COPROC;
392: #endif
393: ucode = frame.f_format;
394: v = frame.f_pc;
395: break;
396:
397: case T_COPERR: /* Kernel coprocessor violation */
398: case T_FMTERR: /* Kernel format error */
399: case T_FMTERR|T_USER: /* User format error */
400: /*
401: * The user has most likely trashed the RTE or FP state info
402: * in the stack frame of a signal handler.
403: */
404: printf("pid %d: kernel %s exception\n", p->p_pid,
405: type==T_COPERR ? "coprocessor" : "format");
406: type |= T_USER;
407: p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
408: i = sigmask(SIGILL);
409: p->p_sigignore &= ~i;
410: p->p_sigcatch &= ~i;
411: p->p_sigmask &= ~i;
412: i = SIGILL;
413: ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
414: typ = ILL_COPROC;
415: v = frame.f_pc;
416: break;
417:
418: /*
419: * XXX: Trace traps are a nightmare.
420: *
421: * HP-UX uses trap #1 for breakpoints,
422: * OpenBSD/m68k uses trap #2,
423: * SUN 3.x uses trap #15,
424: * DDB and KGDB uses trap #15 (for kernel breakpoints;
425: * handled elsewhere).
426: *
427: * OpenBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
428: * SUN 3.x traps get passed through as T_TRAP15 and are not really
429: * supported yet.
430: *
431: * XXX: We should never get kernel-mode T_TRACE or T_TRAP15
432: * XXX: because locore.s now gives them special treatment.
433: */
434: case T_TRAP15: /* kernel breakpoint */
435: frame.f_sr &= ~PSL_T;
436: return;
437:
438: case T_TRACE|T_USER: /* user trace trap */
439: #ifdef COMPAT_SUNOS
440: /*
441: * SunOS uses Trap #2 for a "CPU cache flush"
442: * Just flush the on-chip caches and return.
443: * XXX - Too bad OpenBSD uses trap 2...
444: */
445: if (p->p_emul == &emul_sunos) {
446: ICIA();
447: DCIU();
448: /* get out fast */
449: return;
450: }
451: #endif
452: /* FALLTHROUGH */
453: case T_TRACE: /* Kernel trace trap */
454: case T_TRAP15|T_USER: /* Sun user trace trap */
455: frame.f_sr &= ~PSL_T;
456: i = SIGTRAP;
457: typ = TRAP_TRACE;
458: break;
459:
460: case T_ASTFLT: /* System async trap, cannot happen */
461: goto dopanic;
462:
463: case T_ASTFLT|T_USER: /* User async trap. */
464: astpending = 0;
465: /*
466: * We check for software interrupts first. This is because
467: * they are at a higher level than ASTs, and on a VAX would
468: * interrupt the AST. We assume that if we are processing
469: * an AST that we must be at IPL0 so we don't bother to
470: * check. Note that we ensure that we are at least at SIR
471: * IPL while processing the SIR.
472: */
473: splsoft();
474: /* FALLTHROUGH */
475:
476: case T_SSIR: /* Software interrupt */
477: case T_SSIR|T_USER:
478: if (ssir & SIR_SERIAL) {
479: void zssoft(int);
480: siroff(SIR_SERIAL);
481: uvmexp.softs++;
482: zssoft(0);
483: }
484: if (ssir & SIR_NET) {
485: void netintr(void);
486: siroff(SIR_NET);
487: uvmexp.softs++;
488: netintr();
489: }
490: if (ssir & SIR_CLOCK) {
491: void softclock(void);
492: siroff(SIR_CLOCK);
493: uvmexp.softs++;
494: softclock();
495: }
496: if (ssir & SIR_ADB) {
497: void adb_soft_intr(void);
498: siroff(SIR_ADB);
499: uvmexp.softs++;
500: adb_soft_intr();
501: }
502: /*
503: * If this was not an AST trap, we are all done.
504: */
505: if (type != (T_ASTFLT|T_USER)) {
506: uvmexp.traps--;
507: return;
508: }
509: spl0();
510: if (p->p_flag & P_OWEUPC) {
511: ADDUPROF(p);
512: }
513: if (type == (T_ASTFLT | T_USER) && want_resched) {
514: preempt(NULL);
515: }
516: goto out;
517:
518: case T_MMUFLT: /* Kernel mode page fault */
519: case T_MMUFLT|T_USER: /* page fault */
520: {
521: vaddr_t va;
522: struct vmspace *vm = p->p_vmspace;
523: struct vm_map *map;
524: int rv;
525: vm_prot_t ftype, vftype;
526: extern struct vm_map *kernel_map;
527:
528: #ifdef DEBUG
529: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
530: printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
531: p->p_pid, code, v, frame.f_pc, frame.f_sr);
532: #endif
533: /*
534: * It is only a kernel address space fault iff:
535: * 1. (type & T_USER) == 0 and
536: * 2. pcb_onfault not set or
537: * 3. pcb_onfault set but supervisor data fault
538: * The last can occur during an exec() copyin where the
539: * argument space is lazy-allocated.
540: */
541: if ((type & T_USER) == 0 &&
542: (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
543: map = kernel_map;
544: else
545: map = vm ? &vm->vm_map : kernel_map;
546:
547: if (WRFAULT(code)) {
548: vftype = VM_PROT_WRITE;
549: ftype = VM_PROT_READ | VM_PROT_WRITE;
550: }
551: else
552: vftype = ftype = VM_PROT_READ;
553:
554: va = trunc_page((vaddr_t)v);
555:
556: if (map == kernel_map && va == 0) {
557: printf("trap: bad kernel %s access at 0x%x\n",
558: (ftype & VM_PROT_WRITE) ? "read/write" : "read", v);
559: goto dopanic;
560: }
561: rv = uvm_fault(map, va, 0, ftype);
562: #ifdef DEBUG
563: if (rv && MDB_ISPID(p->p_pid))
564: printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
565: map, va, ftype, rv);
566: #endif
567: /*
568: * If this was a stack access, we keep track of the maximum
569: * accessed stack size. Also, if vm_fault gets a protection
570: * failure, it is due to accessing the stack region outside
571: * the current limit and we need to reflect that as an access
572: * error.
573: */
574: if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
575: && map != kernel_map) {
576: if (rv == 0)
577: uvm_grow(p, va);
578: else if (rv == EACCES)
579: rv = EFAULT;
580: }
581: if (rv == 0) {
582: if (type == T_MMUFLT) {
583: #if defined(M68040)
584: if (mmutype == MMU_68040)
585: (void)writeback(&frame);
586: #endif
587: return;
588: }
589: goto out;
590: }
591: if (type == T_MMUFLT) {
592: if (p->p_addr->u_pcb.pcb_onfault)
593: goto copyfault;
594: printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
595: map, va, ftype, rv);
596: printf(" type %x, code [mmu,,ssw]: %x\n",
597: type, code);
598: goto dopanic;
599: }
600: frame.f_pad = code & 0xffff;
601: ucode = vftype;
602: typ = SEGV_MAPERR;
603: i = SIGSEGV;
604: break;
605: }
606: }
607: sv.sival_ptr = (void *)v;
608: trapsignal(p, i, ucode, typ, sv);
609: out:
610: if ((type & T_USER) == 0)
611: return;
612: #ifdef M68040
613: wb_userret(p, &frame);
614: #else
615: userret(p);
616: #endif
617: }
618:
619: #if defined(M68040)
620: #ifdef DEBUG
621: struct writebackstats {
622: int calls;
623: int cpushes;
624: int move16s;
625: int wb1s, wb2s, wb3s;
626: int wbsize[4];
627: } wbstats;
628:
629: char *f7sz[] = { "longword", "byte", "word", "line" };
630: char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
631: char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
632: "M-code", "k-data", "k-code", "RES" };
633: char wberrstr[] =
634: "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
635: #endif
636:
637: int
638: writeback(struct frame *fp)
639: {
640: struct fmt7 *f = &fp->f_fmt7;
641: struct proc *p = curproc;
642: int err = 0;
643: u_int fa;
644: paddr_t pa;
645: caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
646:
647: #ifdef DEBUG
648: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
649: printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
650: dumpssw(f->f_ssw);
651: }
652: wbstats.calls++;
653: #endif
654: /*
655: * Deal with special cases first.
656: */
657: if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
658: /*
659: * Dcache push fault.
660: * Line-align the address and write out the push data to
661: * the indicated physical address.
662: */
663: #ifdef DEBUG
664: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
665: printf(" pushing %s to PA %x, data %x",
666: f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
667: f->f_fa, f->f_pd0);
668: if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
669: printf("/%x/%x/%x",
670: f->f_pd1, f->f_pd2, f->f_pd3);
671: printf("\n");
672: }
673: if (f->f_wb1s & SSW4_WBSV)
674: panic("writeback: cache push with WB1S valid");
675: wbstats.cpushes++;
676: #endif
677: /*
678: * XXX there are security problems if we attempt to do a
679: * cache push after a signal handler has been called.
680: */
681: pmap_kenter_pa((vaddr_t)vmmap,
682: trunc_page((vaddr_t)f->f_fa), VM_PROT_WRITE);
683: pmap_update(pmap_kernel());
684: fa = (u_int)&vmmap[m68k_page_offset(f->f_fa) & ~0x000f];
685: bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
686: pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
687: DCFL(pa);
688: pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
689: pmap_update(pmap_kernel());
690: } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
691: /*
692: * MOVE16 fault.
693: * Line-align the address and write out the push data to
694: * the indicated virtual address.
695: */
696: #ifdef DEBUG
697: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
698: printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
699: f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
700: f->f_pd2, f->f_pd3);
701: if (f->f_wb1s & SSW4_WBSV)
702: panic("writeback: MOVE16 with WB1S valid");
703: wbstats.move16s++;
704: #endif
705: if (KDFAULT(f->f_wb1s))
706: bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
707: else
708: err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
709: if (err) {
710: fa = f->f_fa & ~0xF;
711: #ifdef DEBUG
712: if (mmudebug & MDB_WBFAILED)
713: printf(wberrstr, p->p_pid, p->p_comm,
714: "MOVE16", fp->f_pc, f->f_fa,
715: f->f_fa & ~0xF, f->f_pd0);
716: #endif
717: }
718: } else if (f->f_wb1s & SSW4_WBSV) {
719: /*
720: * Writeback #1.
721: * Position the "memory-aligned" data and write it out.
722: */
723: u_int wb1d = f->f_wb1d;
724: int off;
725:
726: #ifdef DEBUG
727: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
728: dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
729: wbstats.wb1s++;
730: wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
731: #endif
732: off = (f->f_wb1a & 3) * 8;
733: switch (f->f_wb1s & SSW4_SZMASK) {
734: case SSW4_SZLW:
735: if (off)
736: wb1d = (wb1d >> (32 - off)) | (wb1d << off);
737: if (KDFAULT(f->f_wb1s))
738: *(long *)f->f_wb1a = wb1d;
739: else
740: err = copyout(&wb1d, (caddr_t)f->f_wb1a,
741: sizeof(int));
742: break;
743: case SSW4_SZB:
744: off = 24 - off;
745: if (off)
746: wb1d >>= off;
747: if (KDFAULT(f->f_wb1s))
748: *(char *)f->f_wb1a = wb1d;
749: else {
750: char tmp = wb1d;
751:
752: err = copyout(&tmp, (caddr_t)f->f_wb1a,
753: sizeof(char));
754: }
755: break;
756: case SSW4_SZW:
757: off = (off + 16) % 32;
758: if (off)
759: wb1d = (wb1d >> (32 - off)) | (wb1d << off);
760: if (KDFAULT(f->f_wb1s))
761: *(short *)f->f_wb1a = wb1d;
762: else {
763: short tmp = wb1d;
764:
765: err = copyout(&tmp, (caddr_t)f->f_wb1a,
766: sizeof(short));
767: }
768: break;
769: }
770: if (err) {
771: fa = f->f_wb1a;
772: #ifdef DEBUG
773: if (mmudebug & MDB_WBFAILED)
774: printf(wberrstr, p->p_pid, p->p_comm,
775: "#1", fp->f_pc, f->f_fa,
776: f->f_wb1a, f->f_wb1d);
777: #endif
778: }
779: }
780: /*
781: * Deal with the "normal" writebacks.
782: *
783: * XXX writeback2 is known to reflect a LINE size writeback after
784: * a MOVE16 was already dealt with above. Ignore it.
785: */
786: if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
787: (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
788: #ifdef DEBUG
789: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
790: dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
791: wbstats.wb2s++;
792: wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
793: #endif
794: switch (f->f_wb2s & SSW4_SZMASK) {
795: case SSW4_SZLW:
796: if (KDFAULT(f->f_wb2s))
797: *(long *)f->f_wb2a = f->f_wb2d;
798: else
799: err = copyout(&f->f_wb2d, (caddr_t)f->f_wb2a,
800: sizeof(int));
801: break;
802: case SSW4_SZB:
803: if (KDFAULT(f->f_wb2s))
804: *(char *)f->f_wb2a = f->f_wb2d;
805: else {
806: char tmp = f->f_wb2d;
807:
808: err = copyout(&tmp, (caddr_t)f->f_wb2a,
809: sizeof(char));
810: }
811: break;
812: case SSW4_SZW:
813: if (KDFAULT(f->f_wb2s))
814: *(short *)f->f_wb2a = f->f_wb2d;
815: else {
816: short tmp = f->f_wb2d;
817:
818: err = copyout(&tmp, (caddr_t)f->f_wb2a,
819: sizeof(short));
820: }
821: break;
822: }
823: if (err) {
824: fa = f->f_wb2a;
825: #ifdef DEBUG
826: if (mmudebug & MDB_WBFAILED) {
827: printf(wberrstr, p->p_pid, p->p_comm,
828: "#2", fp->f_pc, f->f_fa,
829: f->f_wb2a, f->f_wb2d);
830: dumpssw(f->f_ssw);
831: dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
832: }
833: #endif
834: }
835: }
836: if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
837: #ifdef DEBUG
838: if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
839: dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
840: wbstats.wb3s++;
841: wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
842: #endif
843: switch (f->f_wb3s & SSW4_SZMASK) {
844: case SSW4_SZLW:
845: if (KDFAULT(f->f_wb3s))
846: *(long *)f->f_wb3a = f->f_wb3d;
847: else
848: err = copyout(&f->f_wb3d, (caddr_t)f->f_wb3a,
849: sizeof(int));
850: break;
851: case SSW4_SZB:
852: if (KDFAULT(f->f_wb3s))
853: *(char *)f->f_wb3a = f->f_wb3d;
854: else {
855: char tmp = f->f_wb3d;
856:
857: err = copyout(&tmp, (caddr_t)f->f_wb3a,
858: sizeof(char));
859: }
860: break;
861: case SSW4_SZW:
862: if (KDFAULT(f->f_wb3s))
863: *(short *)f->f_wb3a = f->f_wb3d;
864: else {
865: short tmp = f->f_wb3d;
866:
867: err = copyout(&tmp, (caddr_t)f->f_wb3a,
868: sizeof(short));
869: }
870: break;
871: #ifdef DEBUG
872: case SSW4_SZLN:
873: panic("writeback: wb3s indicates LINE write");
874: #endif
875: }
876: if (err) {
877: fa = f->f_wb3a;
878: #ifdef DEBUG
879: if (mmudebug & MDB_WBFAILED)
880: printf(wberrstr, p->p_pid, p->p_comm,
881: "#3", fp->f_pc, f->f_fa,
882: f->f_wb3a, f->f_wb3d);
883: #endif
884: }
885: }
886: p->p_addr->u_pcb.pcb_onfault = oonfault;
887: /*
888: * Any problems are SIGSEGV's
889: */
890: if (err)
891: err = SIGSEGV;
892: return (err);
893: }
894:
895: #ifdef DEBUG
896: void
897: dumpssw(ssw)
898: u_short ssw;
899: {
900: printf(" SSW: %x: ", ssw);
901: if (ssw & SSW4_CP)
902: printf("CP,");
903: if (ssw & SSW4_CU)
904: printf("CU,");
905: if (ssw & SSW4_CT)
906: printf("CT,");
907: if (ssw & SSW4_CM)
908: printf("CM,");
909: if (ssw & SSW4_MA)
910: printf("MA,");
911: if (ssw & SSW4_ATC)
912: printf("ATC,");
913: if (ssw & SSW4_LK)
914: printf("LK,");
915: if (ssw & SSW4_RW)
916: printf("RW,");
917: printf(" SZ=%s, TT=%s, TM=%s\n",
918: f7sz[(ssw & SSW4_SZMASK) >> 5],
919: f7tt[(ssw & SSW4_TTMASK) >> 3],
920: f7tm[ssw & SSW4_TMMASK]);
921: }
922:
923: void
924: dumpwb(num, s, a, d)
925: int num;
926: u_short s;
927: u_int a, d;
928: {
929: struct proc *p = curproc;
930: paddr_t pa;
931: int tmp;
932:
933: printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
934: num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
935: f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
936: printf(" PA ");
937: if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
938: printf("<invalid address>");
939: else {
940: if (copyin((caddr_t)a, &tmp, sizeof(int)) == 0)
941: printf("%lx, current value %lx", pa, tmp);
942: else
943: printf("%lx, current value inaccessible", pa);
944: }
945: printf("\n");
946: }
947: #endif
948: #endif
949:
950: /*
951: * Process a system call.
952: */
953: void
954: syscall(code, frame)
955: register_t code;
956: struct frame frame;
957: {
958: caddr_t params;
959: struct sysent *callp;
960: struct proc *p;
961: int error, opc, nsys;
962: size_t argsize;
963: register_t args[8], rval[2];
964:
965: uvmexp.syscalls++;
966: if (!USERMODE(frame.f_sr))
967: panic("syscall");
968: p = curproc;
969: p->p_md.md_regs = frame.f_regs;
970: opc = frame.f_pc;
971:
972: nsys = p->p_emul->e_nsysent;
973: callp = p->p_emul->e_sysent;
974:
975: #ifdef COMPAT_SUNOS
976: if (p->p_emul == &emul_sunos) {
977: /*
978: * SunOS passes the syscall-number on the stack, whereas
979: * BSD passes it in D0. So, we have to get the real "code"
980: * from the stack, and clean up the stack, as SunOS glue
981: * code assumes the kernel pops the syscall argument the
982: * glue pushed on the stack. Sigh...
983: */
984: if (copyin((caddr_t)frame.f_regs[SP], &code,
985: sizeof(register_t)) != 0)
986: code = -1;
987:
988: /*
989: * XXX
990: * Don't do this for sunos_sigreturn, as there's no stored pc
991: * on the stack to skip, the argument follows the syscall
992: * number without a gap.
993: */
994: if (code != SUNOS_SYS_sigreturn) {
995: frame.f_regs[SP] += sizeof (int);
996: /*
997: * remember that we adjusted the SP,
998: * might have to undo this if the system call
999: * returns ERESTART.
1000: */
1001: p->p_md.md_flags |= MDP_STACKADJ;
1002: } else
1003: p->p_md.md_flags &= ~MDP_STACKADJ;
1004: }
1005: #endif
1006:
1007: params = (caddr_t)frame.f_regs[SP] + sizeof(int);
1008:
1009: switch (code) {
1010: case SYS_syscall:
1011: /*
1012: * Code is first argument, followed by actual args.
1013: */
1014: if (copyin(params, &code, sizeof(register_t)) != 0)
1015: code = -1;
1016: params += sizeof(int);
1017: /*
1018: * XXX sigreturn requires special stack manipulation
1019: * that is only done if entered via the sigreturn
1020: * trap. Cannot allow here, so make sure we fail.
1021: */
1022: if (code == SYS_sigreturn)
1023: code = nsys;
1024: break;
1025: case SYS___syscall:
1026: /*
1027: * Like syscall, but code is a quad, so as to maintain
1028: * quad alignment for the rest of the arguments.
1029: */
1030: if (callp != sysent)
1031: break;
1032: if (copyin(params + _QUAD_LOWWORD * sizeof(int), &code,
1033: sizeof(register_t)) != 0)
1034: code = -1;
1035: params += sizeof(quad_t);
1036: break;
1037: default:
1038: break;
1039: }
1040: if (code < 0 || code >= nsys)
1041: callp += p->p_emul->e_nosys; /* illegal */
1042: else
1043: callp += code;
1044: argsize = callp->sy_argsize;
1045: if (argsize)
1046: error = copyin(params, (caddr_t)args, argsize);
1047: else
1048: error = 0;
1049: #ifdef SYSCALL_DEBUG
1050: scdebug_call(p, code, args);
1051: #endif
1052: #ifdef KTRACE
1053: if (KTRPOINT(p, KTR_SYSCALL))
1054: ktrsyscall(p, code, argsize, args);
1055: #endif
1056: if (error)
1057: goto bad;
1058: rval[0] = 0;
1059: rval[1] = frame.f_regs[D1];
1060: #if NSYSTRACE > 0
1061: if (ISSET(p->p_flag, P_SYSTRACE))
1062: error = systrace_redirect(code, p, args, rval);
1063: else
1064: #endif
1065: error = (*callp->sy_call)(p, args, rval);
1066: switch (error) {
1067: case 0:
1068: frame.f_regs[D0] = rval[0];
1069: frame.f_regs[D1] = rval[1];
1070: frame.f_sr &= ~PSL_C; /* carry bit */
1071: break;
1072: case ERESTART:
1073: /*
1074: * We always enter through a `trap' instruction, which is 2
1075: * bytes, so adjust the pc by that amount.
1076: */
1077: frame.f_pc = opc - 2;
1078: break;
1079: case EJUSTRETURN:
1080: /* nothing to do */
1081: break;
1082: default:
1083: bad:
1084: if (p->p_emul->e_errno)
1085: error = p->p_emul->e_errno[error];
1086: frame.f_regs[D0] = error;
1087: frame.f_sr |= PSL_C; /* carry bit */
1088: break;
1089: }
1090:
1091: #ifdef SYSCALL_DEBUG
1092: scdebug_ret(p, code, error, rval);
1093: #endif
1094: #ifdef COMPAT_SUNOS
1095: /* need new p-value for this */
1096: if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ))
1097: frame.f_regs[SP] -= sizeof (int);
1098: #endif
1099: userret(p);
1100: #ifdef KTRACE
1101: if (KTRPOINT(p, KTR_SYSRET))
1102: ktrsysret(p, code, error, rval[0]);
1103: #endif
1104: }
CVSweb