Annotation of sys/arch/m88k/m88k/trap.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: trap.c,v 1.40 2007/05/11 10:06:55 pedro Exp $ */
2: /*
3: * Copyright (c) 2004, Miodrag Vallat.
4: * Copyright (c) 1998 Steve Murphree, Jr.
5: * Copyright (c) 1996 Nivas Madhur
6: * All rights reserved.
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 Nivas Madhur.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: *
33: */
34: /*
35: * Mach Operating System
36: * Copyright (c) 1991 Carnegie Mellon University
37: * Copyright (c) 1991 OMRON Corporation
38: * All Rights Reserved.
39: *
40: * Permission to use, copy, modify and distribute this software and its
41: * documentation is hereby granted, provided that both the copyright
42: * notice and this permission notice appear in all copies of the
43: * software, derivative works or modified versions, and any portions
44: * thereof, and that both notices appear in supporting documentation.
45: *
46: */
47:
48: #include <sys/types.h>
49: #include <sys/param.h>
50: #include <sys/proc.h>
51: #include <sys/signalvar.h>
52: #include <sys/user.h>
53: #include <sys/syscall.h>
54: #include <sys/systm.h>
55: #include <sys/ktrace.h>
56:
57: #include "systrace.h"
58: #include <dev/systrace.h>
59:
60: #include <uvm/uvm_extern.h>
61:
62: #include <machine/asm_macro.h> /* enable/disable interrupts */
63: #include <machine/cmmu.h>
64: #include <machine/cpu.h>
65: #ifdef M88100
66: #include <machine/m88100.h> /* DMT_xxx */
67: #include <machine/m8820x.h> /* CMMU_PFSR_xxx */
68: #endif
69: #ifdef M88110
70: #include <machine/m88110.h>
71: #endif
72: #include <machine/pcb.h> /* FIP_E, etc. */
73: #include <machine/psl.h> /* FIP_E, etc. */
74: #include <machine/trap.h>
75:
76: #include <machine/db_machdep.h>
77:
78: #define SSBREAKPOINT (0xF000D1F8U) /* Single Step Breakpoint */
79:
80: #define USERMODE(PSR) (((PSR) & PSR_MODE) == 0)
81: #define SYSTEMMODE(PSR) (((PSR) & PSR_MODE) != 0)
82:
83: __dead void panictrap(int, struct trapframe *);
84: __dead void error_fatal(struct trapframe *);
85: int double_reg_fixup(struct trapframe *);
86: int ss_put_value(struct proc *, vaddr_t, u_int);
87:
88: extern void regdump(struct trapframe *f);
89:
90: const char *trap_type[] = {
91: "Reset",
92: "Interrupt Exception",
93: "Instruction Access",
94: "Data Access Exception",
95: "Misaligned Access",
96: "Unimplemented Opcode",
97: "Privilege Violation"
98: "Bounds Check Violation",
99: "Illegal Integer Divide",
100: "Integer Overflow",
101: "Error Exception",
102: "Non-Maskable Exception",
103: };
104:
105: const int trap_types = sizeof trap_type / sizeof trap_type[0];
106:
107: #ifdef M88100
108: const char *pbus_exception_type[] = {
109: "Success (No Fault)",
110: "unknown 1",
111: "unknown 2",
112: "Bus Error",
113: "Segment Fault",
114: "Page Fault",
115: "Supervisor Violation",
116: "Write Violation",
117: };
118: #endif
119:
120: static inline void
121: userret(struct proc *p)
122: {
123: int sig;
124:
125: /* take pending signals */
126: while ((sig = CURSIG(p)) != 0)
127: postsig(sig);
128:
129: curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri;
130: }
131:
132: __dead void
133: panictrap(int type, struct trapframe *frame)
134: {
135: static int panicing = 0;
136:
137: if (panicing++ == 0) {
138: #ifdef M88100
139: if (CPU_IS88100) {
140: if (type == 2) {
141: /* instruction exception */
142: printf("\nInstr access fault (%s) v = %x, "
143: "frame %p\n",
144: pbus_exception_type[
145: CMMU_PFSR_FAULT(frame->tf_ipfsr)],
146: frame->tf_sxip & XIP_ADDR, frame);
147: } else if (type == 3) {
148: /* data access exception */
149: printf("\nData access fault (%s) v = %x, "
150: "frame %p\n",
151: pbus_exception_type[
152: CMMU_PFSR_FAULT(frame->tf_dpfsr)],
153: frame->tf_sxip & XIP_ADDR, frame);
154: } else
155: printf("\nTrap type %d, v = %x, frame %p\n",
156: type, frame->tf_sxip & XIP_ADDR, frame);
157: }
158: #endif
159: #ifdef M88110
160: if (CPU_IS88110) {
161: printf("\nTrap type %d, v = %x, frame %p\n",
162: type, frame->tf_exip, frame);
163: }
164: #endif
165: #ifdef DDB
166: regdump(frame);
167: #endif
168: }
169: if ((u_int)type < trap_types)
170: panic(trap_type[type]);
171: else
172: panic("trap %d", type);
173: /*NOTREACHED*/
174: }
175:
176: #ifdef M88100
177: void
178: m88100_trap(unsigned type, struct trapframe *frame)
179: {
180: struct proc *p;
181: struct vm_map *map;
182: vaddr_t va, pcb_onfault;
183: vm_prot_t ftype;
184: int fault_type, pbus_type;
185: u_long fault_code;
186: unsigned fault_addr;
187: struct vmspace *vm;
188: union sigval sv;
189: int result;
190: #ifdef DDB
191: int s;
192: u_int psr;
193: #endif
194: int sig = 0;
195:
196: extern struct vm_map *kernel_map;
197:
198: uvmexp.traps++;
199: if ((p = curproc) == NULL)
200: p = &proc0;
201:
202: if (USERMODE(frame->tf_epsr)) {
203: type += T_USER;
204: p->p_md.md_tf = frame; /* for ptrace/signals */
205: }
206: fault_type = 0;
207: fault_code = 0;
208: fault_addr = frame->tf_sxip & XIP_ADDR;
209:
210: switch (type) {
211: default:
212: panictrap(frame->tf_vector, frame);
213: break;
214: /*NOTREACHED*/
215:
216: #if defined(DDB)
217: case T_KDB_BREAK:
218: s = splhigh();
219: set_psr((psr = get_psr()) & ~PSR_IND);
220: ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
221: set_psr(psr);
222: splx(s);
223: return;
224: case T_KDB_ENTRY:
225: s = splhigh();
226: set_psr((psr = get_psr()) & ~PSR_IND);
227: ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
228: set_psr(psr);
229: splx(s);
230: return;
231: #endif /* DDB */
232: case T_ILLFLT:
233: printf("Unimplemented opcode!\n");
234: panictrap(frame->tf_vector, frame);
235: break;
236: case T_INT:
237: case T_INT+T_USER:
238: curcpu()->ci_intrdepth++;
239: md_interrupt_func(T_INT, frame);
240: curcpu()->ci_intrdepth--;
241: return;
242:
243: case T_MISALGNFLT:
244: printf("kernel misaligned access exception @ 0x%08x\n",
245: frame->tf_sxip);
246: panictrap(frame->tf_vector, frame);
247: break;
248:
249: case T_INSTFLT:
250: /* kernel mode instruction access fault.
251: * Should never, never happen for a non-paged kernel.
252: */
253: #ifdef TRAPDEBUG
254: pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
255: printf("Kernel Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
256: pbus_type, pbus_exception_type[pbus_type],
257: fault_addr, frame, frame->tf_cpu);
258: #endif
259: panictrap(frame->tf_vector, frame);
260: break;
261:
262: case T_DATAFLT:
263: /* kernel mode data fault */
264:
265: /* data fault on the user address? */
266: if ((frame->tf_dmt0 & DMT_DAS) == 0) {
267: type = T_DATAFLT + T_USER;
268: goto user_fault;
269: }
270:
271: fault_addr = frame->tf_dma0;
272: if (frame->tf_dmt0 & (DMT_WRITE|DMT_LOCKBAR)) {
273: ftype = VM_PROT_READ|VM_PROT_WRITE;
274: fault_code = VM_PROT_WRITE;
275: } else {
276: ftype = VM_PROT_READ;
277: fault_code = VM_PROT_READ;
278: }
279:
280: va = trunc_page((vaddr_t)fault_addr);
281: if (va == 0) {
282: panic("trap: bad kernel access at %x", fault_addr);
283: }
284:
285: KERNEL_LOCK();
286: vm = p->p_vmspace;
287: map = kernel_map;
288:
289: pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
290: #ifdef TRAPDEBUG
291: printf("Kernel Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
292: pbus_type, pbus_exception_type[pbus_type],
293: fault_addr, frame, frame->tf_cpu);
294: #endif
295:
296: switch (pbus_type) {
297: case CMMU_PFSR_SUCCESS:
298: /*
299: * The fault was resolved. Call data_access_emulation
300: * to drain the data unit pipe line and reset dmt0
301: * so that trap won't get called again.
302: */
303: data_access_emulation((unsigned *)frame);
304: frame->tf_dpfsr = 0;
305: frame->tf_dmt0 = 0;
306: KERNEL_UNLOCK();
307: return;
308: case CMMU_PFSR_SFAULT:
309: case CMMU_PFSR_PFAULT:
310: if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
311: p->p_addr->u_pcb.pcb_onfault = 0;
312: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
313: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
314: if (result == 0) {
315: /*
316: * We could resolve the fault. Call
317: * data_access_emulation to drain the data
318: * unit pipe line and reset dmt0 so that trap
319: * won't get called again.
320: */
321: data_access_emulation((unsigned *)frame);
322: frame->tf_dpfsr = 0;
323: frame->tf_dmt0 = 0;
324: KERNEL_UNLOCK();
325: return;
326: }
327: break;
328: }
329: #ifdef TRAPDEBUG
330: printf("PBUS Fault %d (%s) va = 0x%x\n", pbus_type,
331: pbus_exception_type[pbus_type], va);
332: #endif
333: KERNEL_UNLOCK();
334: panictrap(frame->tf_vector, frame);
335: /* NOTREACHED */
336: case T_INSTFLT+T_USER:
337: /* User mode instruction access fault */
338: /* FALLTHROUGH */
339: case T_DATAFLT+T_USER:
340: user_fault:
341: if (type == T_INSTFLT + T_USER) {
342: pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
343: #ifdef TRAPDEBUG
344: printf("User Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
345: pbus_type, pbus_exception_type[pbus_type],
346: fault_addr, frame, frame->tf_cpu);
347: #endif
348: } else {
349: fault_addr = frame->tf_dma0;
350: pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
351: #ifdef TRAPDEBUG
352: printf("User Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
353: pbus_type, pbus_exception_type[pbus_type],
354: fault_addr, frame, frame->tf_cpu);
355: #endif
356: }
357:
358: if (frame->tf_dmt0 & (DMT_WRITE | DMT_LOCKBAR)) {
359: ftype = VM_PROT_READ | VM_PROT_WRITE;
360: fault_code = VM_PROT_WRITE;
361: } else {
362: ftype = VM_PROT_READ;
363: fault_code = VM_PROT_READ;
364: }
365:
366: va = trunc_page((vaddr_t)fault_addr);
367:
368: KERNEL_PROC_LOCK(p);
369: vm = p->p_vmspace;
370: map = &vm->vm_map;
371: if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
372: p->p_addr->u_pcb.pcb_onfault = 0;
373:
374: /* Call uvm_fault() to resolve non-bus error faults */
375: switch (pbus_type) {
376: case CMMU_PFSR_SUCCESS:
377: result = 0;
378: break;
379: case CMMU_PFSR_BERROR:
380: result = EACCES;
381: break;
382: default:
383: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
384: break;
385: }
386:
387: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
388:
389: if ((caddr_t)va >= vm->vm_maxsaddr) {
390: if (result == 0)
391: uvm_grow(p, va);
392: else if (result == EACCES)
393: result = EFAULT;
394: }
395: KERNEL_PROC_UNLOCK(p);
396:
397: /*
398: * This could be a fault caused in copyin*()
399: * while accessing user space.
400: */
401: if (result != 0 && pcb_onfault != 0) {
402: frame->tf_snip = pcb_onfault | NIP_V;
403: frame->tf_sfip = (pcb_onfault + 4) | FIP_V;
404: frame->tf_sxip = 0;
405: /*
406: * Continue as if the fault had been resolved, but
407: * do not try to complete the faulting access.
408: */
409: frame->tf_dmt0 |= DMT_SKIP;
410: result = 0;
411: }
412:
413: if (result == 0) {
414: if (type == T_DATAFLT+T_USER) {
415: /*
416: * We could resolve the fault. Call
417: * data_access_emulation to drain the data unit
418: * pipe line and reset dmt0 so that trap won't
419: * get called again.
420: */
421: data_access_emulation((unsigned *)frame);
422: frame->tf_dpfsr = 0;
423: frame->tf_dmt0 = 0;
424: } else {
425: /*
426: * back up SXIP, SNIP,
427: * clearing the Error bit
428: */
429: frame->tf_sfip = frame->tf_snip & ~FIP_E;
430: frame->tf_snip = frame->tf_sxip & ~NIP_E;
431: frame->tf_ipfsr = 0;
432: }
433: } else {
434: sig = result == EACCES ? SIGBUS : SIGSEGV;
435: fault_type = result == EACCES ?
436: BUS_ADRERR : SEGV_MAPERR;
437: }
438: break;
439: case T_MISALGNFLT+T_USER:
440: /* Fix any misaligned ld.d or st.d instructions */
441: sig = double_reg_fixup(frame);
442: fault_type = BUS_ADRALN;
443: break;
444: case T_PRIVINFLT+T_USER:
445: case T_ILLFLT+T_USER:
446: #ifndef DDB
447: case T_KDB_BREAK:
448: case T_KDB_ENTRY:
449: #endif
450: case T_KDB_BREAK+T_USER:
451: case T_KDB_ENTRY+T_USER:
452: case T_KDB_TRACE:
453: case T_KDB_TRACE+T_USER:
454: sig = SIGILL;
455: break;
456: case T_BNDFLT+T_USER:
457: sig = SIGFPE;
458: break;
459: case T_ZERODIV+T_USER:
460: sig = SIGFPE;
461: fault_type = FPE_INTDIV;
462: break;
463: case T_OVFFLT+T_USER:
464: sig = SIGFPE;
465: fault_type = FPE_INTOVF;
466: break;
467: case T_FPEPFLT+T_USER:
468: sig = SIGFPE;
469: break;
470: case T_SIGSYS+T_USER:
471: sig = SIGSYS;
472: break;
473: case T_STEPBPT+T_USER:
474: #ifdef PTRACE
475: /*
476: * This trap is used by the kernel to support single-step
477: * debugging (although any user could generate this trap
478: * which should probably be handled differently). When a
479: * process is continued by a debugger with the PT_STEP
480: * function of ptrace (single step), the kernel inserts
481: * one or two breakpoints in the user process so that only
482: * one instruction (or two in the case of a delayed branch)
483: * is executed. When this breakpoint is hit, we get the
484: * T_STEPBPT trap.
485: */
486: {
487: u_int instr;
488: vaddr_t pc = PC_REGS(&frame->tf_regs);
489:
490: /* read break instruction */
491: copyin((caddr_t)pc, &instr, sizeof(u_int));
492:
493: /* check and see if we got here by accident */
494: if ((p->p_md.md_bp0va != pc &&
495: p->p_md.md_bp1va != pc) ||
496: instr != SSBREAKPOINT) {
497: sig = SIGTRAP;
498: fault_type = TRAP_TRACE;
499: break;
500: }
501:
502: /* restore original instruction and clear breakpoint */
503: if (p->p_md.md_bp0va == pc) {
504: ss_put_value(p, pc, p->p_md.md_bp0save);
505: p->p_md.md_bp0va = 0;
506: }
507: if (p->p_md.md_bp1va == pc) {
508: ss_put_value(p, pc, p->p_md.md_bp1save);
509: p->p_md.md_bp1va = 0;
510: }
511:
512: #if 1
513: frame->tf_sfip = frame->tf_snip;
514: frame->tf_snip = pc | NIP_V;
515: #endif
516: sig = SIGTRAP;
517: fault_type = TRAP_BRKPT;
518: }
519: #else
520: sig = SIGTRAP;
521: fault_type = TRAP_TRACE;
522: #endif
523: break;
524:
525: case T_USERBPT+T_USER:
526: /*
527: * This trap is meant to be used by debuggers to implement
528: * breakpoint debugging. When we get this trap, we just
529: * return a signal which gets caught by the debugger.
530: */
531: frame->tf_sfip = frame->tf_snip;
532: frame->tf_snip = frame->tf_sxip;
533: sig = SIGTRAP;
534: fault_type = TRAP_BRKPT;
535: break;
536:
537: case T_ASTFLT+T_USER:
538: uvmexp.softs++;
539: p->p_md.md_astpending = 0;
540: if (p->p_flag & P_OWEUPC) {
541: KERNEL_PROC_LOCK(p);
542: ADDUPROF(p);
543: KERNEL_PROC_UNLOCK(p);
544: }
545: if (curcpu()->ci_want_resched)
546: preempt(NULL);
547: break;
548: }
549:
550: /*
551: * If trap from supervisor mode, just return
552: */
553: if (type < T_USER)
554: return;
555:
556: if (sig) {
557: sv.sival_int = fault_addr;
558: KERNEL_PROC_LOCK(p);
559: trapsignal(p, sig, fault_code, fault_type, sv);
560: KERNEL_PROC_UNLOCK(p);
561: /*
562: * don't want multiple faults - we are going to
563: * deliver signal.
564: */
565: frame->tf_dmt0 = 0;
566: frame->tf_ipfsr = frame->tf_dpfsr = 0;
567: }
568:
569: userret(p);
570: }
571: #endif /* M88100 */
572:
573: #ifdef M88110
574: void
575: m88110_trap(unsigned type, struct trapframe *frame)
576: {
577: struct proc *p;
578: struct vm_map *map;
579: vaddr_t va, pcb_onfault;
580: vm_prot_t ftype;
581: int fault_type;
582: u_long fault_code;
583: unsigned fault_addr;
584: struct vmspace *vm;
585: union sigval sv;
586: int result;
587: #ifdef DDB
588: int s;
589: u_int psr;
590: #endif
591: int sig = 0;
592: pt_entry_t *pte;
593:
594: extern struct vm_map *kernel_map;
595: extern pt_entry_t *pmap_pte(pmap_t, vaddr_t);
596:
597: uvmexp.traps++;
598: if ((p = curproc) == NULL)
599: p = &proc0;
600:
601: if (USERMODE(frame->tf_epsr)) {
602: type += T_USER;
603: p->p_md.md_tf = frame; /* for ptrace/signals */
604: }
605: fault_type = 0;
606: fault_code = 0;
607: fault_addr = frame->tf_exip & XIP_ADDR;
608:
609: switch (type) {
610: default:
611: panictrap(frame->tf_vector, frame);
612: break;
613: /*NOTREACHED*/
614:
615: case T_110_DRM+T_USER:
616: case T_110_DRM:
617: #ifdef DEBUG
618: printf("DMMU read miss: Hardware Table Searches should be enabled!\n");
619: #endif
620: panictrap(frame->tf_vector, frame);
621: break;
622: /*NOTREACHED*/
623: case T_110_DWM+T_USER:
624: case T_110_DWM:
625: #ifdef DEBUG
626: printf("DMMU write miss: Hardware Table Searches should be enabled!\n");
627: #endif
628: panictrap(frame->tf_vector, frame);
629: break;
630: /*NOTREACHED*/
631: case T_110_IAM+T_USER:
632: case T_110_IAM:
633: #ifdef DEBUG
634: printf("IMMU miss: Hardware Table Searches should be enabled!\n");
635: #endif
636: panictrap(frame->tf_vector, frame);
637: break;
638: /*NOTREACHED*/
639:
640: #ifdef DDB
641: case T_KDB_TRACE:
642: s = splhigh();
643: set_psr((psr = get_psr()) & ~PSR_IND);
644: ddb_break_trap(T_KDB_TRACE, (db_regs_t*)frame);
645: set_psr(psr);
646: splx(s);
647: return;
648: case T_KDB_BREAK:
649: s = splhigh();
650: set_psr((psr = get_psr()) & ~PSR_IND);
651: ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
652: set_psr(psr);
653: splx(s);
654: return;
655: case T_KDB_ENTRY:
656: s = splhigh();
657: set_psr((psr = get_psr()) & ~PSR_IND);
658: ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
659: set_psr(psr);
660: /* skip one instruction */
661: if (frame->tf_exip & 1)
662: frame->tf_exip = frame->tf_enip;
663: else
664: frame->tf_exip += 4;
665: splx(s);
666: return;
667: #if 0
668: case T_ILLFLT:
669: s = splhigh();
670: set_psr((psr = get_psr()) & ~PSR_IND);
671: ddb_error_trap(type == T_ILLFLT ? "unimplemented opcode" :
672: "error fault", (db_regs_t*)frame);
673: set_psr(psr);
674: splx(s);
675: return;
676: #endif /* 0 */
677: #endif /* DDB */
678: case T_ILLFLT:
679: printf("Unimplemented opcode!\n");
680: panictrap(frame->tf_vector, frame);
681: break;
682: case T_NON_MASK:
683: case T_NON_MASK+T_USER:
684: curcpu()->ci_intrdepth++;
685: md_interrupt_func(T_NON_MASK, frame);
686: curcpu()->ci_intrdepth--;
687: return;
688: case T_INT:
689: case T_INT+T_USER:
690: curcpu()->ci_intrdepth++;
691: md_interrupt_func(T_INT, frame);
692: curcpu()->ci_intrdepth--;
693: return;
694: case T_MISALGNFLT:
695: printf("kernel mode misaligned access exception @ 0x%08x\n",
696: frame->tf_exip);
697: panictrap(frame->tf_vector, frame);
698: break;
699: /*NOTREACHED*/
700:
701: case T_INSTFLT:
702: /* kernel mode instruction access fault.
703: * Should never, never happen for a non-paged kernel.
704: */
705: #ifdef TRAPDEBUG
706: printf("Kernel Instruction fault exip %x isr %x ilar %x\n",
707: frame->tf_exip, frame->tf_isr, frame->tf_ilar);
708: #endif
709: panictrap(frame->tf_vector, frame);
710: break;
711: /*NOTREACHED*/
712:
713: case T_DATAFLT:
714: /* kernel mode data fault */
715:
716: /* data fault on the user address? */
717: if ((frame->tf_dsr & CMMU_DSR_SU) == 0) {
718: type = T_DATAFLT + T_USER;
719: goto m88110_user_fault;
720: }
721:
722: #ifdef TRAPDEBUG
723: printf("Kernel Data access fault exip %x dsr %x dlar %x\n",
724: frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
725: #endif
726:
727: fault_addr = frame->tf_dlar;
728: if (frame->tf_dsr & CMMU_DSR_RW) {
729: ftype = VM_PROT_READ;
730: fault_code = VM_PROT_READ;
731: } else {
732: ftype = VM_PROT_READ|VM_PROT_WRITE;
733: fault_code = VM_PROT_WRITE;
734: }
735:
736: va = trunc_page((vaddr_t)fault_addr);
737: if (va == 0) {
738: panic("trap: bad kernel access at %x", fault_addr);
739: }
740:
741: KERNEL_LOCK();
742: vm = p->p_vmspace;
743: map = kernel_map;
744:
745: if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
746: frame->tf_dsr &= ~CMMU_DSR_WE; /* undefined */
747: /*
748: * On a segment or a page fault, call uvm_fault() to
749: * resolve the fault.
750: */
751: if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
752: p->p_addr->u_pcb.pcb_onfault = 0;
753: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
754: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
755: if (result == 0) {
756: KERNEL_UNLOCK();
757: return;
758: }
759: }
760: if (frame->tf_dsr & CMMU_DSR_WE) { /* write fault */
761: /*
762: * This could be a write protection fault or an
763: * exception to set the used and modified bits
764: * in the pte. Basically, if we got a write error,
765: * then we already have a pte entry that faulted
766: * in from a previous seg fault or page fault.
767: * Get the pte and check the status of the
768: * modified and valid bits to determine if this
769: * indeed a real write fault. XXX smurph
770: */
771: pte = pmap_pte(map->pmap, va);
772: #ifdef DEBUG
773: if (pte == NULL) {
774: KERNEL_UNLOCK();
775: panic("NULL pte on write fault??");
776: }
777: #endif
778: if (!(*pte & PG_M) && !(*pte & PG_RO)) {
779: /* Set modified bit and try the write again. */
780: #ifdef TRAPDEBUG
781: printf("Corrected kernel write fault, map %x pte %x\n",
782: map->pmap, *pte);
783: #endif
784: *pte |= PG_M;
785: KERNEL_UNLOCK();
786: return;
787: #if 1 /* shouldn't happen */
788: } else {
789: /* must be a real wp fault */
790: #ifdef TRAPDEBUG
791: printf("Uncorrected kernel write fault, map %x pte %x\n",
792: map->pmap, *pte);
793: #endif
794: if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
795: p->p_addr->u_pcb.pcb_onfault = 0;
796: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
797: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
798: if (result == 0) {
799: KERNEL_UNLOCK();
800: return;
801: }
802: #endif
803: }
804: }
805: KERNEL_UNLOCK();
806: panictrap(frame->tf_vector, frame);
807: /* NOTREACHED */
808: case T_INSTFLT+T_USER:
809: /* User mode instruction access fault */
810: /* FALLTHROUGH */
811: case T_DATAFLT+T_USER:
812: m88110_user_fault:
813: if (type == T_INSTFLT+T_USER) {
814: ftype = VM_PROT_READ;
815: fault_code = VM_PROT_READ;
816: #ifdef TRAPDEBUG
817: printf("User Instruction fault exip %x isr %x ilar %x\n",
818: frame->tf_exip, frame->tf_isr, frame->tf_ilar);
819: #endif
820: } else {
821: fault_addr = frame->tf_dlar;
822: if (frame->tf_dsr & CMMU_DSR_RW) {
823: ftype = VM_PROT_READ;
824: fault_code = VM_PROT_READ;
825: } else {
826: ftype = VM_PROT_READ|VM_PROT_WRITE;
827: fault_code = VM_PROT_WRITE;
828: }
829: #ifdef TRAPDEBUG
830: printf("User Data access fault exip %x dsr %x dlar %x\n",
831: frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
832: #endif
833: }
834:
835: va = trunc_page((vaddr_t)fault_addr);
836:
837: KERNEL_PROC_LOCK(p);
838: vm = p->p_vmspace;
839: map = &vm->vm_map;
840: if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
841: p->p_addr->u_pcb.pcb_onfault = 0;
842:
843: /*
844: * Call uvm_fault() to resolve non-bus error faults
845: * whenever possible.
846: */
847: if (type == T_DATAFLT+T_USER) {
848: /* data faults */
849: if (frame->tf_dsr & CMMU_DSR_BE) {
850: /* bus error */
851: result = EACCES;
852: } else
853: if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
854: /* segment or page fault */
855: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
856: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
857: } else
858: if (frame->tf_dsr & (CMMU_DSR_CP | CMMU_DSR_WA)) {
859: /* copyback or write allocate error */
860: result = EACCES;
861: } else
862: if (frame->tf_dsr & CMMU_DSR_WE) {
863: /* write fault */
864: /* This could be a write protection fault or an
865: * exception to set the used and modified bits
866: * in the pte. Basically, if we got a write
867: * error, then we already have a pte entry that
868: * faulted in from a previous seg fault or page
869: * fault.
870: * Get the pte and check the status of the
871: * modified and valid bits to determine if this
872: * indeed a real write fault. XXX smurph
873: */
874: pte = pmap_pte(vm_map_pmap(map), va);
875: #ifdef DEBUG
876: if (pte == NULL) {
877: KERNEL_PROC_UNLOCK(p);
878: panic("NULL pte on write fault??");
879: }
880: #endif
881: if (!(*pte & PG_M) && !(*pte & PG_RO)) {
882: /*
883: * Set modified bit and try the
884: * write again.
885: */
886: #ifdef TRAPDEBUG
887: printf("Corrected userland write fault, map %x pte %x\n",
888: map->pmap, *pte);
889: #endif
890: *pte |= PG_M;
891: /*
892: * invalidate ATCs to force
893: * table search
894: */
895: set_dcmd(CMMU_DCMD_INV_UATC);
896: KERNEL_PROC_UNLOCK(p);
897: return;
898: } else {
899: /* must be a real wp fault */
900: #ifdef TRAPDEBUG
901: printf("Uncorrected userland write fault, map %x pte %x\n",
902: map->pmap, *pte);
903: #endif
904: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
905: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
906: }
907: } else {
908: #ifdef TRAPDEBUG
909: printf("Unexpected Data access fault dsr %x\n",
910: frame->tf_dsr);
911: #endif
912: KERNEL_PROC_UNLOCK(p);
913: panictrap(frame->tf_vector, frame);
914: }
915: } else {
916: /* instruction faults */
917: if (frame->tf_isr &
918: (CMMU_ISR_BE | CMMU_ISR_SP | CMMU_ISR_TBE)) {
919: /* bus error, supervisor protection */
920: result = EACCES;
921: } else
922: if (frame->tf_isr & (CMMU_ISR_SI | CMMU_ISR_PI)) {
923: /* segment or page fault */
924: result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
925: p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
926: } else {
927: #ifdef TRAPDEBUG
928: printf("Unexpected Instruction fault isr %x\n",
929: frame->tf_isr);
930: #endif
931: KERNEL_PROC_UNLOCK(p);
932: panictrap(frame->tf_vector, frame);
933: }
934: }
935:
936: if ((caddr_t)va >= vm->vm_maxsaddr) {
937: if (result == 0)
938: uvm_grow(p, va);
939: else if (result == EACCES)
940: result = EFAULT;
941: }
942: KERNEL_PROC_UNLOCK(p);
943:
944: /*
945: * This could be a fault caused in copyin*()
946: * while accessing user space.
947: */
948: if (result != 0 && pcb_onfault != 0) {
949: frame->tf_exip = pcb_onfault;
950: /*
951: * Continue as if the fault had been resolved.
952: */
953: result = 0;
954: }
955:
956: if (result != 0) {
957: sig = result == EACCES ? SIGBUS : SIGSEGV;
958: fault_type = result == EACCES ?
959: BUS_ADRERR : SEGV_MAPERR;
960: }
961: break;
962: case T_MISALGNFLT+T_USER:
963: /* Fix any misaligned ld.d or st.d instructions */
964: sig = double_reg_fixup(frame);
965: fault_type = BUS_ADRALN;
966: break;
967: case T_PRIVINFLT+T_USER:
968: case T_ILLFLT+T_USER:
969: #ifndef DDB
970: case T_KDB_BREAK:
971: case T_KDB_ENTRY:
972: case T_KDB_TRACE:
973: #endif
974: case T_KDB_BREAK+T_USER:
975: case T_KDB_ENTRY+T_USER:
976: case T_KDB_TRACE+T_USER:
977: sig = SIGILL;
978: break;
979: case T_BNDFLT+T_USER:
980: sig = SIGFPE;
981: break;
982: case T_ZERODIV+T_USER:
983: sig = SIGFPE;
984: fault_type = FPE_INTDIV;
985: break;
986: case T_OVFFLT+T_USER:
987: sig = SIGFPE;
988: fault_type = FPE_INTOVF;
989: break;
990: case T_FPEPFLT+T_USER:
991: sig = SIGFPE;
992: break;
993: case T_SIGSYS+T_USER:
994: sig = SIGSYS;
995: break;
996: case T_STEPBPT+T_USER:
997: #ifdef PTRACE
998: /*
999: * This trap is used by the kernel to support single-step
1000: * debugging (although any user could generate this trap
1001: * which should probably be handled differently). When a
1002: * process is continued by a debugger with the PT_STEP
1003: * function of ptrace (single step), the kernel inserts
1004: * one or two breakpoints in the user process so that only
1005: * one instruction (or two in the case of a delayed branch)
1006: * is executed. When this breakpoint is hit, we get the
1007: * T_STEPBPT trap.
1008: */
1009: {
1010: u_int instr;
1011: vaddr_t pc = PC_REGS(&frame->tf_regs);
1012:
1013: /* read break instruction */
1014: copyin((caddr_t)pc, &instr, sizeof(u_int));
1015:
1016: /* check and see if we got here by accident */
1017: if ((p->p_md.md_bp0va != pc &&
1018: p->p_md.md_bp1va != pc) ||
1019: instr != SSBREAKPOINT) {
1020: sig = SIGTRAP;
1021: fault_type = TRAP_TRACE;
1022: break;
1023: }
1024:
1025: /* restore original instruction and clear breakpoint */
1026: if (p->p_md.md_bp0va == pc) {
1027: ss_put_value(p, pc, p->p_md.md_bp0save);
1028: p->p_md.md_bp0va = 0;
1029: }
1030: if (p->p_md.md_bp1va == pc) {
1031: ss_put_value(p, pc, p->p_md.md_bp1save);
1032: p->p_md.md_bp1va = 0;
1033: }
1034:
1035: sig = SIGTRAP;
1036: fault_type = TRAP_BRKPT;
1037: }
1038: #else
1039: sig = SIGTRAP;
1040: fault_type = TRAP_TRACE;
1041: #endif
1042: break;
1043: case T_USERBPT+T_USER:
1044: /*
1045: * This trap is meant to be used by debuggers to implement
1046: * breakpoint debugging. When we get this trap, we just
1047: * return a signal which gets caught by the debugger.
1048: */
1049: sig = SIGTRAP;
1050: fault_type = TRAP_BRKPT;
1051: break;
1052:
1053: case T_ASTFLT+T_USER:
1054: uvmexp.softs++;
1055: p->p_md.md_astpending = 0;
1056: if (p->p_flag & P_OWEUPC) {
1057: KERNEL_PROC_LOCK(p);
1058: ADDUPROF(p);
1059: KERNEL_PROC_UNLOCK(p);
1060: }
1061: if (curcpu()->ci_want_resched)
1062: preempt(NULL);
1063: break;
1064: }
1065:
1066: /*
1067: * If trap from supervisor mode, just return
1068: */
1069: if (type < T_USER)
1070: return;
1071:
1072: if (sig) {
1073: sv.sival_int = fault_addr;
1074: KERNEL_PROC_LOCK(p);
1075: trapsignal(p, sig, fault_code, fault_type, sv);
1076: KERNEL_PROC_UNLOCK(p);
1077: }
1078:
1079: userret(p);
1080: }
1081: #endif /* M88110 */
1082:
1083: __dead void
1084: error_fatal(struct trapframe *frame)
1085: {
1086: if (frame->tf_vector == 0)
1087: printf("\nCPU %d Reset Exception\n", cpu_number());
1088: else
1089: printf("\nCPU %d Error Exception\n", cpu_number());
1090:
1091: #ifdef DDB
1092: regdump((struct trapframe*)frame);
1093: #endif
1094: panic("unrecoverable exception %d", frame->tf_vector);
1095: }
1096:
1097: #ifdef M88100
1098: void
1099: m88100_syscall(register_t code, struct trapframe *tf)
1100: {
1101: int i, nsys, nap;
1102: struct sysent *callp;
1103: struct proc *p;
1104: int error;
1105: register_t args[8], rval[2], *ap;
1106:
1107: uvmexp.syscalls++;
1108:
1109: p = curproc;
1110:
1111: callp = p->p_emul->e_sysent;
1112: nsys = p->p_emul->e_nsysent;
1113:
1114: p->p_md.md_tf = tf;
1115:
1116: /*
1117: * For 88k, all the arguments are passed in the registers (r2-r9),
1118: * and further arguments (if any) on stack.
1119: * For syscall (and __syscall), r2 (and r3) has the actual code.
1120: * __syscall takes a quad syscall number, so that other
1121: * arguments are at their natural alignments.
1122: */
1123: ap = &tf->tf_r[2];
1124: nap = 8; /* r2-r9 */
1125:
1126: switch (code) {
1127: case SYS_syscall:
1128: code = *ap++;
1129: nap--;
1130: break;
1131: case SYS___syscall:
1132: if (callp != sysent)
1133: break;
1134: code = ap[_QUAD_LOWWORD];
1135: ap += 2;
1136: nap -= 2;
1137: break;
1138: }
1139:
1140: if (code < 0 || code >= nsys)
1141: callp += p->p_emul->e_nosys;
1142: else
1143: callp += code;
1144:
1145: i = callp->sy_argsize / sizeof(register_t);
1146: if (i > sizeof(args) / sizeof(register_t))
1147: panic("syscall nargs");
1148: if (i > nap) {
1149: bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
1150: error = copyin((caddr_t)tf->tf_r[31], (caddr_t)(args + nap),
1151: (i - nap) * sizeof(register_t));
1152: } else {
1153: bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
1154: error = 0;
1155: }
1156:
1157: if (error != 0)
1158: goto bad;
1159: KERNEL_PROC_LOCK(p);
1160: #ifdef SYSCALL_DEBUG
1161: scdebug_call(p, code, args);
1162: #endif
1163: #ifdef KTRACE
1164: if (KTRPOINT(p, KTR_SYSCALL))
1165: ktrsyscall(p, code, callp->sy_argsize, args);
1166: #endif
1167: rval[0] = 0;
1168: rval[1] = tf->tf_r[3];
1169: #if NSYSTRACE > 0
1170: if (ISSET(p->p_flag, P_SYSTRACE))
1171: error = systrace_redirect(code, p, args, rval);
1172: else
1173: #endif
1174: error = (*callp->sy_call)(p, args, rval);
1175: /*
1176: * system call will look like:
1177: * or r13, r0, <code>
1178: * tb0 0, r0, <128> <- sxip
1179: * br err <- snip
1180: * jmp r1 <- sfip
1181: * err: or.u r3, r0, hi16(errno)
1182: * st r2, r3, lo16(errno)
1183: * subu r2, r0, 1
1184: * jmp r1
1185: *
1186: * So, when we take syscall trap, sxip/snip/sfip will be as
1187: * shown above.
1188: * Given this,
1189: * 1. If the system call returned 0, need to skip nip.
1190: * nip = fip, fip += 4
1191: * (doesn't matter what fip + 4 will be but we will never
1192: * execute this since jmp r1 at nip will change the execution flow.)
1193: * 2. If the system call returned an errno > 0, plug the value
1194: * in r2, and leave nip and fip unchanged. This will have us
1195: * executing "br err" on return to user space.
1196: * 3. If the system call code returned ERESTART,
1197: * we need to rexecute the trap instruction. Back up the pipe
1198: * line.
1199: * fip = nip, nip = xip
1200: * 4. If the system call returned EJUSTRETURN, don't need to adjust
1201: * any pointers.
1202: */
1203:
1204: KERNEL_PROC_UNLOCK(p);
1205: switch (error) {
1206: case 0:
1207: tf->tf_r[2] = rval[0];
1208: tf->tf_r[3] = rval[1];
1209: tf->tf_epsr &= ~PSR_C;
1210: tf->tf_snip = tf->tf_sfip & ~NIP_E;
1211: tf->tf_sfip = tf->tf_snip + 4;
1212: break;
1213: case ERESTART:
1214: tf->tf_epsr &= ~PSR_C;
1215: tf->tf_sfip = tf->tf_snip & ~FIP_E;
1216: tf->tf_snip = tf->tf_sxip & ~NIP_E;
1217: break;
1218: case EJUSTRETURN:
1219: tf->tf_epsr &= ~PSR_C;
1220: break;
1221: default:
1222: bad:
1223: if (p->p_emul->e_errno)
1224: error = p->p_emul->e_errno[error];
1225: tf->tf_r[2] = error;
1226: tf->tf_epsr |= PSR_C; /* fail */
1227: tf->tf_snip = tf->tf_snip & ~NIP_E;
1228: tf->tf_sfip = tf->tf_sfip & ~FIP_E;
1229: break;
1230: }
1231: #ifdef SYSCALL_DEBUG
1232: KERNEL_PROC_LOCK(p);
1233: scdebug_ret(p, code, error, rval);
1234: KERNEL_PROC_UNLOCK(p);
1235: #endif
1236: userret(p);
1237: #ifdef KTRACE
1238: if (KTRPOINT(p, KTR_SYSRET)) {
1239: KERNEL_PROC_LOCK(p);
1240: ktrsysret(p, code, error, rval[0]);
1241: KERNEL_PROC_UNLOCK(p);
1242: }
1243: #endif
1244: }
1245: #endif /* M88100 */
1246:
1247: #ifdef M88110
1248: /* Instruction pointers operate differently on mc88110 */
1249: void
1250: m88110_syscall(register_t code, struct trapframe *tf)
1251: {
1252: int i, nsys, nap;
1253: struct sysent *callp;
1254: struct proc *p;
1255: int error;
1256: register_t args[8], rval[2], *ap;
1257:
1258: uvmexp.syscalls++;
1259:
1260: p = curproc;
1261:
1262: callp = p->p_emul->e_sysent;
1263: nsys = p->p_emul->e_nsysent;
1264:
1265: p->p_md.md_tf = tf;
1266:
1267: /*
1268: * For 88k, all the arguments are passed in the registers (r2-r9),
1269: * and further arguments (if any) on stack.
1270: * For syscall (and __syscall), r2 (and r3) has the actual code.
1271: * __syscall takes a quad syscall number, so that other
1272: * arguments are at their natural alignments.
1273: */
1274: ap = &tf->tf_r[2];
1275: nap = 8; /* r2-r9 */
1276:
1277: switch (code) {
1278: case SYS_syscall:
1279: code = *ap++;
1280: nap--;
1281: break;
1282: case SYS___syscall:
1283: if (callp != sysent)
1284: break;
1285: code = ap[_QUAD_LOWWORD];
1286: ap += 2;
1287: nap -= 2;
1288: break;
1289: }
1290:
1291: if (code < 0 || code >= nsys)
1292: callp += p->p_emul->e_nosys;
1293: else
1294: callp += code;
1295:
1296: i = callp->sy_argsize / sizeof(register_t);
1297: if (i > sizeof(args) > sizeof(register_t))
1298: panic("syscall nargs");
1299: if (i > nap) {
1300: bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
1301: error = copyin((caddr_t)tf->tf_r[31], (caddr_t)(args + nap),
1302: (i - nap) * sizeof(register_t));
1303: } else {
1304: bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
1305: error = 0;
1306: }
1307:
1308: if (error != 0)
1309: goto bad;
1310: KERNEL_PROC_LOCK(p);
1311: #ifdef SYSCALL_DEBUG
1312: scdebug_call(p, code, args);
1313: #endif
1314: #ifdef KTRACE
1315: if (KTRPOINT(p, KTR_SYSCALL))
1316: ktrsyscall(p, code, callp->sy_argsize, args);
1317: #endif
1318: rval[0] = 0;
1319: rval[1] = tf->tf_r[3];
1320: #if NSYSTRACE > 0
1321: if (ISSET(p->p_flag, P_SYSTRACE))
1322: error = systrace_redirect(code, p, args, rval);
1323: else
1324: #endif
1325: error = (*callp->sy_call)(p, args, rval);
1326: /*
1327: * system call will look like:
1328: * or r13, r0, <code>
1329: * tb0 0, r0, <128> <- exip
1330: * br err <- enip
1331: * jmp r1
1332: * err: or.u r3, r0, hi16(errno)
1333: * st r2, r3, lo16(errno)
1334: * subu r2, r0, 1
1335: * jmp r1
1336: *
1337: * So, when we take syscall trap, exip/enip will be as
1338: * shown above.
1339: * Given this,
1340: * 1. If the system call returned 0, need to jmp r1.
1341: * exip += 8
1342: * 2. If the system call returned an errno > 0, increment
1343: * exip += 4 and plug the value in r2. This will have us
1344: * executing "br err" on return to user space.
1345: * 3. If the system call code returned ERESTART,
1346: * we need to rexecute the trap instruction. leave exip as is.
1347: * 4. If the system call returned EJUSTRETURN, just return.
1348: * exip += 4
1349: */
1350:
1351: KERNEL_PROC_UNLOCK(p);
1352: switch (error) {
1353: case 0:
1354: tf->tf_r[2] = rval[0];
1355: tf->tf_r[3] = rval[1];
1356: tf->tf_epsr &= ~PSR_C;
1357: /* skip two instructions */
1358: if (tf->tf_exip & 1)
1359: tf->tf_exip = tf->tf_enip + 4;
1360: else
1361: tf->tf_exip += 4 + 4;
1362: break;
1363: case ERESTART:
1364: /*
1365: * Reexecute the trap.
1366: * exip is already at the trap instruction, so
1367: * there is nothing to do.
1368: */
1369: tf->tf_epsr &= ~PSR_C;
1370: break;
1371: case EJUSTRETURN:
1372: tf->tf_epsr &= ~PSR_C;
1373: /* skip one instruction */
1374: if (tf->tf_exip & 1)
1375: tf->tf_exip = tf->tf_enip;
1376: else
1377: tf->tf_exip += 4;
1378: break;
1379: default:
1380: bad:
1381: if (p->p_emul->e_errno)
1382: error = p->p_emul->e_errno[error];
1383: tf->tf_r[2] = error;
1384: tf->tf_epsr |= PSR_C; /* fail */
1385: /* skip one instruction */
1386: if (tf->tf_exip & 1)
1387: tf->tf_exip = tf->tf_enip;
1388: else
1389: tf->tf_exip += 4;
1390: break;
1391: }
1392:
1393: #ifdef SYSCALL_DEBUG
1394: KERNEL_PROC_LOCK(p);
1395: scdebug_ret(p, code, error, rval);
1396: KERNEL_PROC_UNLOCK(p);
1397: #endif
1398: userret(p);
1399: #ifdef KTRACE
1400: if (KTRPOINT(p, KTR_SYSRET)) {
1401: KERNEL_PROC_LOCK(p);
1402: ktrsysret(p, code, error, rval[0]);
1403: KERNEL_PROC_UNLOCK(p);
1404: }
1405: #endif
1406: }
1407: #endif /* M88110 */
1408:
1409: /*
1410: * Set up return-value registers as fork() libc stub expects,
1411: * and do normal return-to-user-mode stuff.
1412: */
1413: void
1414: child_return(arg)
1415: void *arg;
1416: {
1417: struct proc *p = arg;
1418: struct trapframe *tf;
1419:
1420: tf = (struct trapframe *)USER_REGS(p);
1421: tf->tf_r[2] = 0;
1422: tf->tf_r[3] = 0;
1423: tf->tf_epsr &= ~PSR_C;
1424: /* skip br instruction as in syscall() */
1425: #ifdef M88100
1426: if (CPU_IS88100) {
1427: tf->tf_snip = tf->tf_sfip & XIP_ADDR;
1428: tf->tf_sfip = tf->tf_snip + 4;
1429: }
1430: #endif
1431: #ifdef M88110
1432: if (CPU_IS88110) {
1433: /* skip two instructions */
1434: if (tf->tf_exip & 1)
1435: tf->tf_exip = tf->tf_enip + 4;
1436: else
1437: tf->tf_exip += 4 + 4;
1438: }
1439: #endif
1440:
1441: KERNEL_PROC_UNLOCK(p);
1442: userret(p);
1443:
1444: #ifdef KTRACE
1445: if (KTRPOINT(p, KTR_SYSRET)) {
1446: KERNEL_PROC_LOCK(p);
1447: ktrsysret(p,
1448: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
1449: KERNEL_PROC_UNLOCK(p);
1450: }
1451: #endif
1452: }
1453:
1454: #ifdef PTRACE
1455:
1456: /*
1457: * User Single Step Debugging Support
1458: */
1459:
1460: #include <sys/ptrace.h>
1461:
1462: vaddr_t ss_branch_taken(u_int, vaddr_t, struct reg *);
1463: int ss_get_value(struct proc *, vaddr_t, u_int *);
1464: int ss_inst_branch_or_call(u_int);
1465: int ss_put_breakpoint(struct proc *, vaddr_t, vaddr_t *, u_int *);
1466:
1467: #define SYSCALL_INSTR 0xf000d080 /* tb0 0,r0,128 */
1468:
1469: int
1470: ss_get_value(struct proc *p, vaddr_t addr, u_int *value)
1471: {
1472: struct uio uio;
1473: struct iovec iov;
1474:
1475: iov.iov_base = (caddr_t)value;
1476: iov.iov_len = sizeof(u_int);
1477: uio.uio_iov = &iov;
1478: uio.uio_iovcnt = 1;
1479: uio.uio_offset = (off_t)addr;
1480: uio.uio_resid = sizeof(u_int);
1481: uio.uio_segflg = UIO_SYSSPACE;
1482: uio.uio_rw = UIO_READ;
1483: uio.uio_procp = curproc;
1484: return (process_domem(curproc, p, &uio, PT_READ_I));
1485: }
1486:
1487: int
1488: ss_put_value(struct proc *p, vaddr_t addr, u_int value)
1489: {
1490: struct uio uio;
1491: struct iovec iov;
1492:
1493: iov.iov_base = (caddr_t)&value;
1494: iov.iov_len = sizeof(u_int);
1495: uio.uio_iov = &iov;
1496: uio.uio_iovcnt = 1;
1497: uio.uio_offset = (off_t)addr;
1498: uio.uio_resid = sizeof(u_int);
1499: uio.uio_segflg = UIO_SYSSPACE;
1500: uio.uio_rw = UIO_WRITE;
1501: uio.uio_procp = curproc;
1502: return (process_domem(curproc, p, &uio, PT_WRITE_I));
1503: }
1504:
1505: /*
1506: * ss_branch_taken(instruction, pc, regs)
1507: *
1508: * instruction will be a control flow instruction location at address pc.
1509: * Branch taken is supposed to return the address to which the instruction
1510: * would jump if the branch is taken.
1511: *
1512: * This is different from branch_taken() in ddb, as we also need to process
1513: * system calls.
1514: */
1515: vaddr_t
1516: ss_branch_taken(u_int inst, vaddr_t pc, struct reg *regs)
1517: {
1518: u_int regno;
1519:
1520: /*
1521: * Quick check of the instruction. Note that we know we are only
1522: * invoked if ss_inst_branch_or_call() returns TRUE, so we do not
1523: * need to repeat the jpm, jsr and syscall stricter checks here.
1524: */
1525: switch (inst >> (32 - 5)) {
1526: case 0x18: /* br */
1527: case 0x19: /* bsr */
1528: /* signed 26 bit pc relative displacement, shift left 2 bits */
1529: inst = (inst & 0x03ffffff) << 2;
1530: /* check if sign extension is needed */
1531: if (inst & 0x08000000)
1532: inst |= 0xf0000000;
1533: return (pc + inst);
1534:
1535: case 0x1a: /* bb0 */
1536: case 0x1b: /* bb1 */
1537: case 0x1d: /* bcnd */
1538: /* signed 16 bit pc relative displacement, shift left 2 bits */
1539: inst = (inst & 0x0000ffff) << 2;
1540: /* check if sign extension is needed */
1541: if (inst & 0x00020000)
1542: inst |= 0xfffc0000;
1543: return (pc + inst);
1544:
1545: case 0x1e: /* jmp or jsr */
1546: regno = inst & 0x1f; /* get the register value */
1547: return (regno == 0 ? 0 : regs->r[regno]);
1548:
1549: default: /* system call */
1550: /*
1551: * The regular (pc + 4) breakpoint will match the error
1552: * return. Successfull system calls return at (pc + 8),
1553: * so we'll set up a branch breakpoint there.
1554: */
1555: return (pc + 8);
1556: }
1557: }
1558:
1559: int
1560: ss_inst_branch_or_call(u_int ins)
1561: {
1562: /* check high five bits */
1563: switch (ins >> (32 - 5)) {
1564: case 0x18: /* br */
1565: case 0x19: /* bsr */
1566: case 0x1a: /* bb0 */
1567: case 0x1b: /* bb1 */
1568: case 0x1d: /* bcnd */
1569: return (TRUE);
1570: case 0x1e: /* could be jmp or jsr */
1571: if ((ins & 0xfffff3e0) == 0xf400c000)
1572: return (TRUE);
1573: }
1574:
1575: return (FALSE);
1576: }
1577:
1578: int
1579: ss_put_breakpoint(struct proc *p, vaddr_t va, vaddr_t *bpva, u_int *bpsave)
1580: {
1581: int rc;
1582:
1583: /* Restore previous breakpoint if we did not trigger it. */
1584: if (*bpva != 0) {
1585: ss_put_value(p, *bpva, *bpsave);
1586: *bpva = 0;
1587: }
1588:
1589: /* Save instruction. */
1590: if ((rc = ss_get_value(p, va, bpsave)) != 0)
1591: return (rc);
1592:
1593: /* Store breakpoint instruction at the location now. */
1594: *bpva = va;
1595: return (ss_put_value(p, va, SSBREAKPOINT));
1596: }
1597:
1598: int
1599: process_sstep(struct proc *p, int sstep)
1600: {
1601: struct reg *sstf = USER_REGS(p);
1602: unsigned pc, brpc;
1603: unsigned instr;
1604: int rc;
1605:
1606: if (sstep == 0) {
1607: /* Restore previous breakpoints if any. */
1608: if (p->p_md.md_bp0va != 0) {
1609: ss_put_value(p, p->p_md.md_bp0va, p->p_md.md_bp0save);
1610: p->p_md.md_bp0va = 0;
1611: }
1612: if (p->p_md.md_bp1va != 0) {
1613: ss_put_value(p, p->p_md.md_bp1va, p->p_md.md_bp1save);
1614: p->p_md.md_bp1va = 0;
1615: }
1616:
1617: return (0);
1618: }
1619:
1620: /*
1621: * User was stopped at pc, e.g. the instruction at pc was not executed.
1622: * Fetch what's at the current location.
1623: */
1624: pc = PC_REGS(sstf);
1625: if ((rc = ss_get_value(p, pc, &instr)) != 0)
1626: return (rc);
1627:
1628: /*
1629: * Find if this instruction may cause a branch, and set up a breakpoint
1630: * at the branch location.
1631: */
1632: if (ss_inst_branch_or_call(instr) || instr == SYSCALL_INSTR) {
1633: brpc = ss_branch_taken(instr, pc, sstf);
1634:
1635: /* self-branches are hopeless */
1636: if (brpc != pc && brpc != 0) {
1637: if ((rc = ss_put_breakpoint(p, brpc,
1638: &p->p_md.md_bp1va, &p->p_md.md_bp1save)) != 0)
1639: return (rc);
1640: }
1641: }
1642:
1643: if ((rc = ss_put_breakpoint(p, pc + 4,
1644: &p->p_md.md_bp0va, &p->p_md.md_bp0save)) != 0)
1645: return (rc);
1646:
1647: return (0);
1648: }
1649:
1650: #endif /* PTRACE */
1651:
1652: #ifdef DIAGNOSTIC
1653: void
1654: splassert_check(int wantipl, const char *func)
1655: {
1656: int oldipl;
1657:
1658: /*
1659: * This will raise the spl if too low,
1660: * in a feeble attempt to reduce further damage.
1661: */
1662: oldipl = raiseipl(wantipl);
1663:
1664: if (oldipl < wantipl) {
1665: splassert_fail(wantipl, oldipl, func);
1666: }
1667: }
1668: #endif
1669:
1670: /*
1671: * ld.d and st.d instructions referencing long aligned but not long long
1672: * aligned addresses will trigger a misaligned address exception.
1673: *
1674: * This routine attempts to recover these (valid) statements, by simulating
1675: * the split form of the instruction. If it fails, it returns the appropriate
1676: * signal number to deliver.
1677: *
1678: * Note that we do not attempt to do anything for .d.usr instructions - the
1679: * kernel never issues such instructions, and they cause a privileged
1680: * isntruction exception from userland.
1681: */
1682: int
1683: double_reg_fixup(struct trapframe *frame)
1684: {
1685: u_int32_t pc, instr, value;
1686: int regno, store;
1687: vaddr_t addr;
1688:
1689: /*
1690: * Decode the faulting instruction.
1691: */
1692:
1693: pc = PC_REGS(&frame->tf_regs);
1694: if (copyin((void *)pc, &instr, sizeof(u_int32_t)) != 0)
1695: return SIGSEGV;
1696:
1697: switch (instr & 0xfc00ff00) {
1698: case 0xf4001000: /* ld.d rD, rS1, rS2 */
1699: addr = frame->tf_r[(instr >> 16) & 0x1f]
1700: + frame->tf_r[(instr & 0x1f)];
1701: store = 0;
1702: break;
1703: case 0xf4002000: /* st.d rD, rS1, rS2 */
1704: addr = frame->tf_r[(instr >> 16) & 0x1f]
1705: + frame->tf_r[(instr & 0x1f)];
1706: store = 1;
1707: break;
1708: default:
1709: switch (instr & 0xfc000000) {
1710: case 0x10000000: /* ld.d rD, rS, imm16 */
1711: addr = (instr & 0x0000ffff) +
1712: frame->tf_r[(instr >> 16) & 0x1f];
1713: store = 0;
1714: break;
1715: case 0x20000000: /* st.d rD, rS, imm16 */
1716: addr = (instr & 0x0000ffff) +
1717: frame->tf_r[(instr >> 16) & 0x1f];
1718: store = 1;
1719: break;
1720: default:
1721: return SIGBUS;
1722: }
1723: break;
1724: }
1725:
1726: /* We only handle long but not long long aligned access here */
1727: if ((addr & 0x07) != 4)
1728: return SIGBUS;
1729:
1730: regno = (instr >> 21) & 0x1f;
1731:
1732: if (store) {
1733: /*
1734: * Two word stores.
1735: */
1736: value = frame->tf_r[regno++];
1737: if (copyout(&value, (void *)addr, sizeof(u_int32_t)) != 0)
1738: return SIGSEGV;
1739: if (regno == 32)
1740: value = 0;
1741: else
1742: value = frame->tf_r[regno];
1743: if (copyout(&value, (void *)(addr + 4), sizeof(u_int32_t)) != 0)
1744: return SIGSEGV;
1745: } else {
1746: /*
1747: * Two word loads. r0 should be left unaltered, but the
1748: * value should still be fetched even if it is discarded.
1749: */
1750: if (copyin((void *)addr, &value, sizeof(u_int32_t)) != 0)
1751: return SIGSEGV;
1752: if (regno != 0)
1753: frame->tf_r[regno] = value;
1754: if (copyin((void *)(addr + 4), &value, sizeof(u_int32_t)) != 0)
1755: return SIGSEGV;
1756: if (regno != 31)
1757: frame->tf_r[regno + 1] = value;
1758: }
1759:
1760: return 0;
1761: }
1762:
1763: void
1764: cache_flush(struct trapframe *tf)
1765: {
1766: struct proc *p;
1767: struct pmap *pmap;
1768: paddr_t pa;
1769: vaddr_t va;
1770: vsize_t len, count;
1771:
1772: if ((p = curproc) == NULL)
1773: p = &proc0;
1774:
1775: p->p_md.md_tf = tf;
1776:
1777: pmap = vm_map_pmap(&p->p_vmspace->vm_map);
1778: va = tf->tf_r[2];
1779: len = tf->tf_r[3];
1780:
1781: if (/* va < VM_MIN_ADDRESS || */ va >= VM_MAXUSER_ADDRESS ||
1782: va + len <= va || va + len >= VM_MAXUSER_ADDRESS)
1783: len = 0;
1784:
1785: while (len != 0) {
1786: count = min(len, PAGE_SIZE - (va & PAGE_MASK));
1787: if (pmap_extract(pmap, va, &pa) != FALSE)
1788: dma_cachectl_pa(pa, count, DMA_CACHE_SYNC);
1789: va += count;
1790: len -= count;
1791: }
1792:
1793: if (CPU_IS88100) {
1794: tf->tf_snip = tf->tf_snip & ~NIP_E;
1795: tf->tf_sfip = tf->tf_sfip & ~FIP_E;
1796: } else {
1797: /* skip instruction */
1798: if (tf->tf_exip & 1)
1799: tf->tf_exip = tf->tf_enip;
1800: else
1801: tf->tf_exip += 4;
1802: }
1803:
1804: userret(p);
1805: }
CVSweb