home *** CD-ROM | disk | FTP | other *** search
- /*
- * Mach Operating System
- * Copyright (c) 1992 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * HISTORY
- * $Log: trap.c,v $
- * Revision 2.12 91/08/01 14:09:28 dbg
- * Restore thread_should_halt test to exit path of
- * user_page_fault_continue. Fix user single-step handling.
- * [91/08/01 dbg]
- *
- * Revision 2.11 91/07/31 18:14:48 dbg
- * Support stack switching.
- * [91/03/25 dbg]
- *
- * Revision 2.8 91/03/16 14:59:20 rpd
- * Hacked for AST interface changes.
- * [91/03/15 rpd]
- *
- * Added resume, continuation arguments to vm_fault.
- * [91/03/13 rpd]
- *
- * Updated for new kmem_alloc interface.
- * [91/03/03 rpd]
- *
- * Revision 2.7 91/01/08 15:52:58 rpd
- * Added KEEP_STACKS support.
- * [91/01/07 rpd]
- * Added continuation argument to thread_block.
- * [90/12/08 rpd]
- *
- * Revision 2.6 90/10/25 14:48:07 rwd
- * Fixed the map argument to db_find_watchpoint.
- * Made the faultaddr argument to pagefault a vm_offset_t.
- * [90/10/18 rpd]
- * Added watchpoint support.
- * [90/10/16 rwd]
- *
- * Revision 2.5 90/08/27 22:12:12 dbg
- * Remove kdbnofault test - it's done in kdb_trap instead.
- * [90/07/26 dbg]
- *
- * Use jmp_buf_t instead of label_t.
- * [90/07/17 dbg]
- *
- * Revision 2.4 90/06/02 15:07:19 rpd
- * Updated to new csw_needed macro.
- * [90/03/26 23:01:08 rpd]
- *
- * Revision 2.3 89/10/23 12:02:14 dbg
- * Turn off debug_all_traps_with_kdb, to let user processes
- * handle traps. Always pass trap code, not MACH exception
- * code, to kdb_trap.
- * [89/10/20 dbg]
- *
- * Revision 2.2 89/09/08 11:27:39 dbg
- * On page fault in kernel mode: if the current task's map is a
- * submap of the kernel and the address falls within it, try it
- * first. Avoids deadlock (on the kernel map) with other kernel
- * tasks.
- * [89/09/06 dbg]
- *
- * Revision 2.1 89/08/03 16:53:50 rwd
- * Created.
- *
- * 18-May-89 Randall Dean (rwd) at Carnegie-Mellon University
- * Torn from old trap.c by dbg. Fixed non-thread case for
- * MACH_KERNEL
- *
- */
-
- /*
- * Trap handler for SUN3.
- *
- * From SUNOS 3.4
- */
-
- #include <platforms.h>
- #include <mach_kdb.h>
- #include <fpa.h>
-
- #include <mach/exception.h>
- #include <mach/kern_return.h>
- #include <mach/vm_param.h>
-
- #include <kern/thread.h>
- #include <kern/task.h>
-
- #include <vm/vm_map.h>
- #include <vm/vm_fault.h>
- #include <vm/vm_kern.h>
-
- #include <sun/fault.h>
-
- #include <mach/sun3/exception.h>
- #include <sun3/frame.h>
- #include <sun3/machparam.h>
- #include <sun3/psl.h>
- #include <sun3/trap.h>
-
- #if NFPA > 0
- #include <sundev/fpareg.h>
- #include <sun3/enable.h>
-
- extern short fpa_exist;
- extern enum fpa_state fpa_state;
- #endif
-
- char *trap_type[] = {
- "Vector address 0x0",
- "Vector address 0x4",
- "Bus error",
- "Address error",
- "Illegal instruction",
- "Divide by zero",
- "CHK, CHK2 instruction",
- "TRAPV, cpTRAPcc, cpTRAPcc instruction",
- "Privilege violation",
- "Trace",
- "1010 emulator trap",
- "1111 emulator trap",
- "Vector address 0x30",
- "Coprocessor protocol error",
- "Stack format error",
- "Uninitialized interrupt",
- "Vector address 0x40",
- "Vector address 0x44",
- "Vector address 0x48",
- "Vector address 0x4c",
- "Vector address 0x50",
- "Vector address 0x54",
- "Vector address 0x58",
- "Vector address 0x5c",
- "Spurious interrupt",
- };
- int TRAP_TYPES = sizeof(trap_type)/sizeof(trap_type[0]);
-
- #define DEBUG 1
-
- #if defined(DEBUG) || defined (lint)
- int tdebug = 0;
- int tudebug = 0;
- int lodebug = 0;
- int bedebug = 0;
- #else
- #define tdebug 0
- #define tudebug 0
- #define lodebug 0
- #define bedebug 0
- #endif defined(DEBUG) || defined(lint)
-
- #if MACH_KDB
- boolean_t debug_all_traps_with_kdb = FALSE;
- extern struct db_watchpoint *db_watchpoint_list;
- extern boolean_t db_watchpoints_inserted;
-
- void
- thread_kdb_return()
- {
- register thread_t self = current_thread();
- register struct mc68020_saved_state *regs = self->pcb->user_regs;
-
- if (kdb_trap(regs->vector, regs)) {
- thread_exception_return();
- /*NOTREACHED*/
- }
- }
- #endif MACH_KDB
-
- /*
- * Called from the trap handler when a processor trap occurs.
- * Returns amount to adjust the stack: > 0 removes bus error
- * info, == 0 does nothing.
- */
- int
- kernel_trap(type, regs)
- int type;
- register
- struct mc68020_saved_state *regs;
- {
- int besize = 0;
- int be;
-
- register thread_t thread = current_thread();
-
- be = (type == T_BUSERR) ? getbuserr() : 0;
-
- if (tdebug) {
- int i = type / sizeof(int);
- if ((unsigned)i < TRAP_TYPES)
- printf("trap: %s\n", trap_type[i]);
- showregs("trap", type, regs, be);
- }
-
- /*
- * Reset sp value to adjusted system sp.
- */
- regs->sp = (int)(regs+1);
- switch (regs->stkfmt) {
- case SF_NORMAL:
- case SF_THROWAWAY:
- break;
- case SF_NORMAL6:
- regs->sp += sizeof (struct bei_normal6);
- break;
- case SF_COPROC:
- regs->sp += sizeof (struct bei_coproc);
- break;
- case SF_MEDIUM:
- regs->sp += sizeof (struct bei_medium);
- besize = sizeof (struct bei_medium);
- break;
- case SF_LONGB:
- regs->sp += sizeof (struct bei_longb);
- besize = sizeof (struct bei_longb);
- break;
- default:
- panic("bad system stack format");
- /*NOTREACHED*/
- }
-
- switch (type) {
-
- case T_BUSERR:
-
- if (be & BE_TIMEOUT)
- DELAY(2000); /* allow for refresh recovery time */
-
- /* may have been expected by C */
- if (nofault) {
- jmp_buf_t *ftmp;
-
- ftmp = nofault;
- nofault = 0;
- longjmp(ftmp);
- }
-
- if (thread == THREAD_NULL)
- break; /* trap in boot phase */
-
- #if NFPA > 0
- /*
- * If enable register is not turned on, try to initialize
- * the FPA. Otherwise, panic if we cannot initialize it.
- * In case of FPA bus error in kernel mode, shut down the
- * FPA instead of the whole system.
- */
- if (fpa_exist
- && (be & BE_FPAENA)
- && fpa_state != FPA_DISABLED) {
-
- if (fpa_init(thread) == 0)
- return (0);
- }
- if (be & BE_FPAENA)
- panic("FPA not enabled");
- if (be & BE_FPABERR) {
- showregs("FPA KERNEL BUS ERROR",
- type,
- regs,
- be);
- traceback((long)regs->sp, (long)regs->pc);
- printf("FPA BUS ERROR: IERR == %x\n", fpa->fp_ierr);
- fpa_shutdown();
-
- exc = EXC_BAD_ACCESS;
- code = KERN_INVALID_ADDRESS;
- subcode = (int)fpa; /* fpa address as indicator */
- break;
- }
- #endif NFPA > 0
-
- switch (regs->stkfmt) {
- case SF_MEDIUM:
- {
- struct bei_medium *beip =
- (struct bei_medium *)(regs+1);
-
- #if NFPA > 0
- if (fpa_exist &&
- fpa_state != FPA_DISABLED &&
- (char *)beip->bei_fault >= (char *)fpa &&
- (char *)beip->bei_fault <=
- (char *)fpa + sizeof(struct fpa_device))
- if (fpa_init(thread) == 0)
- return (0);
- #endif NFPA > 0
- if (beip->bei_dfault) {
- if (kernel_page_fault(
- (vm_offset_t)beip->bei_fault,
- beip->bei_rw,
- regs)
- == KERN_SUCCESS)
- return (0);
- }
- break;
- }
- case SF_LONGB:
- {
- struct bei_longb *beip =
- (struct bei_longb *)(regs+1);
-
- #if NFPA > 0
- if (fpa_exist &&
- fpa_state != FPA_DISABLED &&
- (char *)beip->bei_fault >= (char *)fpa &&
- (char *)beip->bei_fault <=
- (char *)fpa + sizeof(struct fpa_device))
- if (fpa_init(thread) == 0)
- return (0);
- #endif NFPA > 0
- if (beip->bei_dfault) {
- if (kernel_page_fault(
- (vm_offset_t)beip->bei_fault,
- beip->bei_rw,
- regs)
- == KERN_SUCCESS)
- return (0);
- }
- break;
- }
- default:
- panic("bad bus error stack format");
- }
-
- if (lodebug) {
- showregs("lofault", type, regs, be);
- traceback((long)regs->sp, (long)regs->pc);
- }
-
- if (thread->recover != 0) {
- regs->pc = thread->recover;
- thread->recover = 0;
- return (besize);
- }
- break;
-
- case T_TRACE:
- {
- register pcb_t pcb;
-
- if (thread == THREAD_NULL)
- break; /* trap in boot phase */
-
- pcb = thread->pcb;
- #if MACH_KDB
- if (pcb->flag & TRACE_KDB) {
- /*
- * Trace trap to kernel debugger
- */
- pcb->flag &= ~TRACE_KDB;
- break;
- }
- #endif MACH_KDB
- /*
- * Trace trap in kernel mode immediately after 'trap'
- * instruction in user mode. Defer the trace until the
- * thread re-enters user mode.
- */
- pcb->flag |= TRACE_PENDING;
- return (0);
- }
-
- default:
- break;
- }
-
- #if MACH_KDB
- switch (kdb_trap(type, regs)) {
- case 2:
- /* clear bus error frame */
- return (besize);
- case 1:
- /* normal return */
- return (0);
- case 0:
- /* no debugger (!) */
- break;
- }
- #endif MACH_KDB
- (void) splhigh();
- showregs((char *)0, type, regs, be);
- traceback((long)regs->a6, (long)regs->sp);
- {
- int i = regs->vector/sizeof(int);
- if (i < TRAP_TYPES)
- panic(trap_type[i]);
- panic("trap");
- }
- /*NOTREACHED*/
- }
-
-
- void user_page_fault(); /* forward */
- void user_page_fault_continue(); /* forward */
-
- /*
- * User mode trap.
- */
- int
- user_trap(type, regs)
- int type;
- register
- struct mc68020_saved_state *regs;
- {
- int exc, code;
- int subcode = 0;
- int besize = 0;
- int be;
-
- register thread_t thread = current_thread();
- register pcb_t pcb = thread->pcb;
-
- pcb->user_regs = regs;
- pcb->discard_frame = FALSE;
-
- be = (type == T_BUSERR) ? getbuserr() : 0;
-
- if (tdebug) {
- int i = type / sizeof(int);
- if ((unsigned)i < TRAP_TYPES)
- printf("trap: %s\n", trap_type[i]);
- showregs("trap", type, regs, be);
- }
-
- switch (type) {
-
- case T_ADDRERR:
- exc = EXC_BAD_INSTRUCTION;
- code = regs->vector;
- break;
-
- case T_PRIVVIO:
- exc = EXC_BAD_INSTRUCTION;
- code = EXC_SUN3_PRIVILEGE_VIOLATION;
- break;
-
- case T_COPROCERR: /* coprocessor protocol error */
- /*
- * Dump out obnoxious info to warn user
- * that something isn`t right w/ the 68881
- */
- showregs("USER COPROCESSOR PROTOCOL ERROR", type, regs, be);
-
- exc = EXC_BAD_INSTRUCTION;
- code = EXC_SUN3_COPROCESSOR;
- break;
-
- case T_M_BADTRAP: /* (some) undefined trap */
- case T_ILLINST: /* illegal instruction fault */
- exc = EXC_BAD_INSTRUCTION;
- code = regs->vector;
- break;
-
- case T_M_FLOATERR: /* (some) floating error trap */
- case T_ZERODIV: /* divide by zero */
- code = regs->vector;
- if (code == EXC_SUN3_FLT_BSUN ||
- code == EXC_SUN3_FLT_OPERAND_ERROR) {
- exc = EXC_BAD_INSTRUCTION;
- }
- else {
- exc = EXC_ARITHMETIC;
- }
- break;
-
- case T_CHKINST: /* CHK [CHK2] instruction */
- case T_TRAPV: /* TRAPV [cpTRAPcc TRAPcc] instr */
- exc = EXC_SOFTWARE;
- code = regs->vector;
- break;
-
- case T_BUSERR:
- /*
- * User bus error. Try to handle FPA, then pagefault.
- */
-
- if (be & BE_TIMEOUT)
- DELAY(2000); /* allow for refresh recovery time */
-
- /*
- * Copy the "rerun" bits to the "fault" bits.
- *
- * This is what is going on here (don`t believe
- * the 2nd edition 68020 description in section
- * 6.4.1, it is full of errors). A rerun bit
- * being on means that the prefetch failed. A
- * fault bit being on means the processor tried
- * to use bad prefetch data. Upon return via
- * the RTE instruction, the `20 will retry the
- * instruction access only if BOTH the rerun and
- * the corresponding fault bit is on.
- *
- * We need to do guarantee that any time we have a
- * fault that we have actually just run the cycle,
- * otherwise the current external state (i.e. the
- * bus error register) might not anything to do with
- * what really happened to cause the prefetch to fail.
- * For example the prefetch might have occured previous
- * to an earlier bus error exception whose handling
- * might have resolved the prefetch problem. Thus by
- * copying the "rerun" bits, we force the `20 to rerun
- * every previously faulted prefetch upon return from
- * this bus error. This way we are guaranteed that we
- * never get a "bogus" `20 internal bus error when it
- * attempts to use a previously faulted prefetch. On
- * the downside, this hack might make the kernel fix up
- * a prefetch fault that the `20 was not going to use.
- * What we really need is a ``do not know anything about
- * a prefetch`` bit. If we had something like that then
- * the `20 could know enough to rerun the prefetch, but
- * only if it turns out that it really needs it.
- *
- * RISC does have its advantages.
- *
- * N.B. This code depends on not having an executable
- * where the last instruction in the text segment is
- * too close the end of a page. We do not want to get
- * ourselves in trouble trying to fix up a fault beyond
- * the end of the text segment. But because the loader
- * already pads out by an additional page when it sees
- * this problem due to microcode bugs with the first
- * year or so worth of 68020 chips, we should not get
- * in trouble here.
- */
-
- switch (regs->stkfmt) {
- case SF_MEDIUM:
- {
- struct bei_medium *beip =
- (struct bei_medium *)(regs+1);
-
- besize = sizeof (struct bei_medium);
- beip->bei_faultc = beip->bei_rerunc;
- beip->bei_faultb = beip->bei_rerunb;
- break;
- }
- case SF_LONGB:
- {
- struct bei_longb *beip =
- (struct bei_longb *)(regs+1);
-
- besize = sizeof (struct bei_longb);
- beip->bei_faultc = beip->bei_rerunc;
- beip->bei_faultb = beip->bei_rerunb;
- break;
- }
- default:
- panic("bad bus error stack format");
- }
-
- #if NFPA > 0
- if (fpa_exist && (be & BE_FPAENA) && fpa_state != FPA_DISABLED)
- if (fpa_init(thread) == 0)
- return(0);
- if (be & (BE_FPAENA | BE_FPABERR)) {
- /*
- * FPA exception from FPA board.
- * We save bus error PC in pcb_fpa_pc and save the
- * current bus error information at pcb_fpa_fmtptr.
- * Other information saved are: (high core) the bus
- * error exception frame, a short of frame type and
- * vector offset, the struct regs, a long of AST bits
- * of flag, short indicating the size of this area,
- * and a short indicating the size to restore to
- * the kernel stack.
- * The exception frame is returned to 68020 (by rte)
- * when pcb_fpa_pc equals PC in syscall: of
- * locore.s.
- */
- struct fpa_stack *fp;
-
- code = (be & BE_FPAENA) ? EXC_SUN3_FLT_FPA_ENABLE
- : EXC_SUN3_FLT_FPA_ERROR;
-
- if (pcb->pcb_fpa_fmtptr == NULL) {
- /* First FPA exception, alloc space */
- (void) kmem_alloc_wired(kernel_map,
- (vm_offset_t *) &fp,
- sizeof (struct fpa_stack));
- pcb->pcb_fpa_fmtptr = fp;
- fp->fpst_alloc_size = sizeof (struct fpa_stack);
- }
- else
- fp = pcb->pcb_fpa_fmtptr;
-
- pcb->pcb_fpa_pc = regs->pc;
- fp->fpst_ast_bits = pcb->flag & AST_CLR;
- /*
- * Current kernel stack: (high core)exception stk,
- * a short(stkfmt+vector offset), regs(low core).
- * We save regs, a short(stkfmt+vector offset),
- * and the exception stack.
- */
- fp->fpst_save_size = sizeof (struct regs)
- + sizeof (short) + besize;
- bcopy((char *)regs, (char *)&fp->fpst_regs,
- (unsigned)fp->fpst_save_size);
-
- exc = EXC_ARITHMETIC;
- break;
- }
- #endif NFPA > 0
-
- if (be & ~(BE_INVALID|BE_PROTERR)){
- /*
- * Some other error indicated in the bus error
- * invalid so there is nothing we can do now.
- */
- }
- else if (regs->stkfmt == SF_MEDIUM) {
- struct bei_medium *beip =
- (struct bei_medium *)(regs + 1);
-
- #if NFPA > 0
- if (fpa_exist && fpa_state != FPA_DISABLED &&
- (char *)beip->bei_fault >= (char *)fpa &&
- (char *)beip->bei_fault <
- (char *)fpa + sizeof(struct fpa_device))
-
- if (fpa_init(thread) == 0)
- return(0);
- #endif NFPA > 0
- if ((bedebug && (beip->bei_faultb || beip->bei_faultc))
- || (bedebug > 1 && beip->bei_fault))
- printf("medium fault b %d %x, c %d %x, d %d %x\n",
- beip->bei_faultb, regs->pc + 4,
- beip->bei_faultc, regs->pc + 2,
- beip->bei_dfault, beip->bei_fault);
-
- if (beip->bei_dfault) {
- user_page_fault((vm_offset_t)beip->bei_fault,
- beip->bei_rw,
- regs);
- /*NOTREACHED*/
- }
- else if (beip->bei_faultc) {
- user_page_fault((vm_offset_t)(regs->pc+2),
- TRUE,
- regs);
- /*NOTREACHED*/
- }
- else if (beip->bei_faultb) {
- user_page_fault((vm_offset_t)(regs->pc+4),
- TRUE,
- regs);
- /*NOTREACHED*/
- }
- }
- else {
- struct bei_longb *beip =
- (struct bei_longb *)(regs + 1);
-
- #if NFPA > 0
- if (fpa_exist && fpa_state != FPA_DISABLED &&
- (char *)beip->bei_fault >= (char *)fpa &&
- (char *)beip->bei_fault <
- (char *)fpa + sizeof(struct fpa_device))
-
- if (fpa_init(thread) == 0)
- return(0);
- #endif NFPA > 0
- if ((bedebug && (beip->bei_faultb || beip->bei_faultc))
- || (bedebug > 1 && beip->bei_fault))
- printf("long fault b %d %x, c %d %x, d %d %x\n",
- beip->bei_faultb, beip->bei_stageb,
- beip->bei_faultc, beip->bei_stageb-2,
- beip->bei_dfault, beip->bei_fault);
-
- if (beip->bei_dfault) {
- user_page_fault((vm_offset_t)beip->bei_fault,
- beip->bei_rw,
- regs);
- /*NOTREACHED*/
- }
- else if (beip->bei_faultc) {
- user_page_fault((vm_offset_t)(beip->bei_stageb-2),
- TRUE,
- regs);
- /*NOTREACHED*/
- }
- else if (beip->bei_faultb) {
- user_page_fault((vm_offset_t)beip->bei_stageb,
- TRUE,
- regs);
- /*NOTREACHED*/
- }
- }
- if (tudebug)
- showregs("USER BUS ERROR", type, regs, be);
-
- exc = EXC_BAD_ACCESS;
- break;
-
- case T_TRACE:
- {
- int s, r;
-
- #if MACH_KDB
- if (pcb->flag & TRACE_KDB) {
- /*
- * Trap to kernel debugger.
- */
- pcb->flag &= ~TRACE_KDB;
- (void) kdb_trap(T_TRACE, regs);
- return (0);
- }
- #endif MACH_KDB
- s = splhigh();
-
- r = pcb->flag & AST_CLR;
- pcb->flag &= ~AST_CLR;
-
- if (r & TRACE_AST) {
- /*
- * Tracing for AST - may also be tracing for
- * user.
- */
- if ((r & TRACE_USER) == 0) {
- regs->sr &= ~SR_TRACE;
- ast_taken();
- /* back at spl0 */
- return (0);
- }
- /*
- * User-mode trace takes priority over AST.
- * We`ll catch the AST when exception blocks.
- */
- }
- splx(s);
-
- exc = EXC_BREAKPOINT;
- code = EXC_SUN3_TRACE;
- break;
- }
-
- case T_BRKPT:
- exc = EXC_BREAKPOINT;
- code = EXC_SUN3_BREAKPOINT;
- break;
-
- case T_EMU1010: /* 1010 emulator trap */
- case T_EMU1111: /* 1111 emulator trap */
- exc = EXC_EMULATION;
- code = regs->vector;
- break;
- }
-
- /*
- * Exception occured - clear pending trace.
- */
- pcb->flag &= ~TRACE_PENDING;
-
- #if MACH_KDB
- if (debug_all_traps_with_kdb) {
- (void) kdb_trap(type, regs);
- thread_exception_return();
- /*NOTREACHED*/
- }
- #endif MACH_KDB
- exception(exc, code, subcode);
- /*NOTREACHED*/
- }
-
- void
- thread_exception_return()
- {
- register pcb_t pcb = current_thread()->pcb;
- int besize = 0;
-
- if (pcb->discard_frame) {
- switch (pcb->user_regs->stkfmt) {
- case SF_MEDIUM:
- besize = sizeof(struct bei_medium);
- break;
- case SF_LONGB:
- besize = sizeof(struct bei_longb);
- break;
- default:
- break;
- }
- }
-
- Thread_exception_return(besize);
- /*NOTREACHED*/
- }
-
-
- void
- user_page_fault(faultaddr, read_fault, regs)
- register vm_offset_t faultaddr;
- int read_fault;
- register struct mc68020_saved_state *regs;
- {
- register thread_t thread = current_thread();
- register pcb_t pcb = thread->pcb;
-
- pcb->fault_addr = faultaddr;
- pcb->fault_type = (read_fault) ? VM_PROT_READ
- : VM_PROT_READ | VM_PROT_WRITE,
-
- (void) vm_fault(thread->task->map,
- trunc_page(faultaddr),
- pcb->fault_type,
- FALSE,
- FALSE,
- user_page_fault_continue);
- /*NOTREACHED*/
- }
-
- void
- user_page_fault_continue(result)
- kern_return_t result;
- {
- register thread_t thread = current_thread();
- register pcb_t pcb = thread->pcb;
- register struct mc68020_saved_state *regs = pcb->user_regs;
-
- if (result == KERN_SUCCESS) {
- #if MACH_KDB
- if (db_watchpoint_list &&
- db_watchpoints_inserted &&
- (pcb->fault_type & VM_PROT_WRITE))
- {
- if (db_find_watchpoint(thread->task->map,
- pcb->fault_addr,
- regs))
- kdb_trap(T_WATCHPOINT, regs);
- }
- #endif MACH_KDB
- /*
- * If halt was requested, stop here instead of
- * waiting for instruction to complete. The page
- * is still missing, and we`ll never finish.
- */
- while (thread_should_halt(thread))
- thread_halt_self();
-
- thread_exception_return();
- /*NOTREACHED*/
- }
- exception(EXC_BAD_ACCESS, result, pcb->fault_addr);
- /*NOTREACHED*/
- }
-
-
- kern_return_t
- kernel_page_fault(faultaddr, read_fault, regs)
- register vm_offset_t faultaddr;
- int read_fault;
- register struct mc68020_saved_state *regs;
- {
- register vm_map_t map;
- kern_return_t result;
- register thread_t thread = current_thread();
- vm_prot_t fault_type;
-
- fault_type = (read_fault) ? VM_PROT_READ
- : VM_PROT_READ|VM_PROT_WRITE;
-
- /*
- * If the current map is a submap of the kernel map,
- * and the address is within that map, fault on that
- * map. If we wait until vm_fault (vm_map_lookup) to
- * look for the submap, we may deadlock on the kernel
- * map lock.
- */
- if (thread == THREAD_NULL)
- map = kernel_map;
- else {
- map = thread->task->map;
- if (faultaddr < vm_map_min(map) ||
- faultaddr >= vm_map_max(map))
- map = kernel_map;
- }
-
- result = vm_fault(map,
- trunc_page(faultaddr),
- fault_type,
- FALSE,
- FALSE,
- (void (*)()) 0);
-
- #if MACH_KDB
- if ((result == KERN_SUCCESS) &&
- db_watchpoint_list &&
- db_watchpoints_inserted &&
- !read_fault)
- {
- if (db_find_watchpoint(map, faultaddr, regs))
- kdb_trap(T_WATCHPOINT, regs);
- else {
- if ((regs->sr & SR_T1) && (thread != THREAD_NULL)) {
- (void) spl7();
- thread->pcb->flag |= TRACE_KDB;
- }
- }
- }
- #endif MACH_KDB
-
- return(result);
- }
-
- int syscall_error(regs, exc, code, subcode)
- struct mc68020_saved_state *regs;
- int exc, code, subcode;
- {
- register thread_t thread = current_thread();
- register pcb_t pcb;
-
- if (thread == 0)
- halt("syscall error in boot phase");
- pcb = thread->pcb;
- pcb->user_regs = regs;
-
- assert(USERMODE(regs->sr));
-
- /*
- * Exception occured - clear pending trace. XXX
- */
- pcb->flag &= ~TRACE_PENDING;
-
- exception(exc, code, subcode);
- /*NOTREACHED*/
- }
-
- /*
- * Print out a traceback for kernel traps
- */
- traceback(afp, sp)
- long afp, sp;
- {
- unsigned int tospage = btoc(sp);
- struct frame * fp = (struct frame *)afp;
- static int done = 0;
-
- extern char * panicstr;
-
- if (panicstr && done++ > 0)
- return;
-
- printf("Begin traceback...fp = %x, sp = %x\n", fp, sp);
- while (btoc(fp) == tospage) {
- if (fp == fp->fr_savfp) {
- printf("FP loop at %x", fp);
- break;
- }
- printf("Called from %x, fp=%x, args=%x %x %x %x\n",
- fp->fr_savpc, fp->fr_savfp,
- fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
- fp = fp->fr_savfp;
- }
- printf("End traceback...\n");
- DELAY(2000000);
- }
-
- showregs(str, type, regs, be)
- char * str;
- int type;
- struct mc68020_saved_state *regs;
- int be;
- {
- int s, fcode, accaddr;
- char * why;
-
- s = spl7();
-
- printf("trap address 0x%x, pc = %x, sr = %x, stkfmt %x, context %x\n",
- regs->vector,
- regs->pc,
- regs->sr,
- regs->stkfmt,
- getcontext());
-
- if (type == T_BUSERR)
- printf("Bus Error Reg %b\n", be, BUSERR_BITS);
- if (type == T_BUSERR || type == T_ADDRERR) {
- switch (regs->stkfmt) {
- case SF_MEDIUM:
- {
- struct bei_medium *beip =
- (struct bei_medium *)(regs + 1);
-
- fcode = beip->bei_fcode;
- if (beip->bei_dfault) {
- why = "data";
- accaddr = beip->bei_fault;
- }
- else if (beip->bei_faultc) {
- why = "stage c";
- accaddr = regs->pc + 2;
- }
- else if (beip->bei_faultc) {
- why = "stage b";
- accaddr = regs->pc + 4;
- }
- else {
- why = "unknown";
- accaddr = 0;
- }
- printf("%s fault address %x faultc %d faultb %d ",
- why,
- accaddr,
- beip->bei_faultc,
- beip->bei_faultb);
- printf("dfault %d rw %d size %d fcode %d\n",
- beip->bei_dfault,
- beip->bei_rw,
- beip->bei_size,
- fcode);
- break;
- }
- case SF_LONGB:
- {
- struct bei_longb *beip =
- (struct bei_longb *)(regs + 1);
-
- fcode = beip->bei_fcode;
- if (beip->bei_dfault) {
- why = "data";
- accaddr = beip->bei_fault;
- }
- else if (beip->bei_faultc) {
- why = "stage c";
- accaddr = beip->bei_stageb - 2;
- }
- else if (beip->bei_faultc) {
- why = "stage b";
- accaddr = beip->bei_stageb;
- }
- else {
- why = "unknown";
- accaddr = 0;
- }
- printf("%s fault address %x faultc %d faultb %d ",
- why,
- accaddr,
- beip->bei_faultc,
- beip->bei_faultb);
- printf("dfault %d rw %d size %d fcode %d\n",
- beip->bei_dfault,
- beip->bei_rw,
- beip->bei_size,
- fcode);
- break;
- }
- default:
- panic("bad bus error stack format");
- }
- if (fcode == FC_SD || fcode == FC_SP) {
- printf("KERNEL MODE\n");
- printf("page map %x\n", getpgmap((caddr_t)accaddr));
- }
- }
- printf("D0-D7 %x %x %x %x %x %x %x %x\n",
- regs->d0,
- regs->d1,
- regs->d2,
- regs->d3,
- regs->d4,
- regs->d5,
- regs->d6,
- regs->d7);
- printf("A0-A7 %x %x %x %x %x %x %x %x\n",
- regs->a0,
- regs->a1,
- regs->a2,
- regs->a3,
- regs->a4,
- regs->a5,
- regs->a6,
- regs->sp);
- DELAY(2000000);
- splx(s);
- }
-
-