diff --git a/sys/arch/next68k/next68k/trap.c b/sys/arch/next68k/next68k/trap.c index a31b085c416d..4ff67cff7c11 100644 --- a/sys/arch/next68k/next68k/trap.c +++ b/sys/arch/next68k/next68k/trap.c @@ -1,10 +1,10 @@ -/* $NetBSD: trap.c,v 1.15 1999/07/08 18:08:57 thorpej Exp $ */ +/* $NetBSD: trap.c,v 1.16 1999/08/04 07:18:21 dbj Exp $ */ /* * This file was taken from mvme68k/mvme68k/trap.c * should probably be re-synced when needed. - * Darrin B. Jewell Tue Nov 10 05:07:16 1998 - * original cvs id: NetBSD: trap.c,v 1.24 1998/10/01 02:53:54 thorpej Exp + * Darrin B. Jewell Tue Aug 3 10:53:12 UTC 1999 + * original cvs id: NetBSD: trap.c,v 1.32 1999/08/03 10:52:06 dbj Exp */ /* @@ -70,10 +70,12 @@ #ifdef KTRACE #include #endif -#ifdef KGDB -#include + +#ifdef DEBUG +#include #endif +#include #include #include #include @@ -82,6 +84,8 @@ #include #include +#include + #include #ifdef COMPAT_HPUX @@ -102,7 +106,17 @@ extern struct emul emul_linux_elf32; #endif #endif -#include +int writeback __P((struct frame *fp, int docachepush)); +void trap __P((int type, u_int code, u_int v, struct frame frame)); +void syscall __P((register_t code, struct frame frame)); + +#ifdef DEBUG +void dumpssw __P((u_short)); +void dumpwb __P((int, u_short, u_int, u_int)); +#endif + +static inline void userret __P((struct proc *p, struct frame *fp, + u_quad_t oticks, u_int faultaddr, int fromtrap)); int astpending; @@ -128,11 +142,12 @@ int trap_types = sizeof trap_type / sizeof trap_type[0]; * Size of various exception stack frames (minus the standard 8 bytes) */ short exframesize[] = { - FMT0SIZE, /* type 0 - normal (68020/030/040) */ + FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ - FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */ - FMT3SIZE, /* type 3 - FP post-instruction (68040) */ - -1, -1, -1, /* type 4-6 - undefined */ + FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ + FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ + FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ + -1, -1, /* type 5-6 - undefined */ FMT7SIZE, /* type 7 - access error (68040) */ 58, /* type 8 - bus fault (68010) */ FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ @@ -141,29 +156,49 @@ short exframesize[] = { -1, -1, -1, -1 /* type C-F - undefined */ }; -#ifdef M68040 -#define KDFAULT(c) (mmutype == MMU_68040 ? \ - ((c) & SSW4_TMMASK) == SSW4_TMKD : \ - ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)) -#define WRFAULT(c) (mmutype == MMU_68040 ? \ - ((c) & SSW4_RW) == 0 : \ - ((c) & (SSW_DF|SSW_RW)) == SSW_DF) +#ifdef M68060 +#define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) +#define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) #else -#define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) -#define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF) +#define KDFAULT_060(c) 0 +#define WRFAULT_060(c) 0 #endif +#ifdef M68040 +#define KDFAULT_040(c) (cputype == CPU_68040 && \ + ((c) & SSW4_TMMASK) == SSW4_TMKD) +#define WRFAULT_040(c) (cputype == CPU_68040 && \ + ((c) & SSW4_RW) == 0) +#else +#define KDFAULT_040(c) 0 +#define WRFAULT_040(c) 0 +#endif + +#if defined(M68030) || defined(M68020) +#define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ + ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) +#define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ + ((c) & (SSW_DF|SSW_RW)) == SSW_DF) +#else +#define KDFAULT_OTH(c) 0 +#define WRFAULT_OTH(c) 0 +#endif + +#define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) +#define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) + #ifdef DEBUG int mmudebug = 0; int mmupid = -1; #define MDB_FOLLOW 1 #define MDB_WBFOLLOW 2 #define MDB_WBFAILED 4 -#define MDB_ISPID(p) (p) == mmupid +#define MDB_ISPID(p) ((p) == mmupid) #endif + #define NSIR 32 -void (*sir_routines[NSIR])(); +void (*sir_routines[NSIR])(void *); void *sir_args[NSIR]; int next_sir; @@ -225,7 +260,7 @@ again: * we just return to the user without sucessfully completing * the writebacks. Maybe we should just drop the sucker? */ - if (mmutype == MMU_68040 && fp->f_format == FMT7) { + if (cputype == CPU_68040 && fp->f_format == FMT7) { if (beenhere) { #ifdef DEBUG if (mmudebug & MDB_WBFAILED) @@ -234,7 +269,7 @@ again: "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", p->p_pid, p->p_comm, fp->f_pc, faultaddr); #endif - } else if (sig = writeback(fp, fromtrap)) { + } else if ((sig = writeback(fp, fromtrap))) { beenhere = 1; oticks = p->p_sticks; trapsignal(p, sig, faultaddr); @@ -251,6 +286,7 @@ again: * System calls are broken out for efficiency. */ /*ARGSUSED*/ +void trap(type, code, v, frame) int type; unsigned code; @@ -258,21 +294,24 @@ trap(type, code, v, frame) struct frame frame; { extern char fubail[], subail[]; -#ifdef DDB - extern char trap0[], trap1[], trap2[], trap12[], trap15[], illinst[]; -#endif struct proc *p; - register int i, tmp; + int i, s; u_int ucode; - u_quad_t sticks; -#ifdef COMPAT_HPUX - extern struct emul emul_hpux; -#endif + u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */; int bit; uvmexp.traps++; p = curproc; ucode = 0; + + /* I have verified that this DOES happen! -gwr */ + if (p == NULL) + p = &proc0; +#ifdef DIAGNOSTIC + if (p->p_addr == NULL) + panic("trap: no pcb"); +#endif + if (USERMODE(frame.f_sr)) { type |= T_USER; sticks = p->p_sticks; @@ -282,51 +321,52 @@ trap(type, code, v, frame) default: dopanic: - printf("trap type %d, code = %x, v = %x\n", type, code, v); + printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); + printf("%s program counter = 0x%x\n", + (type & T_USER) ? "user" : "kernel", frame.f_pc); /* * Let the kernel debugger see the trap frame that * caused us to panic. This is a convenience so * one can see registers at the point of failure. */ - tmp = splhigh(); + s = splhigh(); #ifdef KGDB /* If connected, step or cont returns 1 */ - if (kgdb_trap(type, (struct trapframe *)&frame)) + if (kgdb_trap(type, &frame)) goto kgdb_cont; #endif -#ifdef DDB - if (kdb_trap(type, &frame)) - return; +#ifdef DDB + (void)kdb_trap(type, (db_regs_t *)&frame); #endif #ifdef KGDB kgdb_cont: #endif - splx(tmp); + splx(s); if (panicstr) { - /* - * Note: panic is smart enough to do: - * boot(RB_AUTOBOOT | RB_NOSYNC, NULL) - * if we call it again. - */ - panic("trap during panic!"); + printf("trap during panic!\n"); +#ifdef DEBUG + /* XXX should be a machine-dependent hook */ + printf("(press a key)\n"); (void)cngetc(); +#endif } - regdump((struct trapframe *)&frame, 128); type &= ~T_USER; - if ((unsigned)type < trap_types) + if ((u_int)type < trap_types) panic(trap_type[type]); panic("trap"); case T_BUSERR: /* kernel bus error */ - if (!p->p_addr->u_pcb.pcb_onfault) + if (p->p_addr->u_pcb.pcb_onfault == 0) goto dopanic; + /* FALLTHROUGH */ + + copyfault: /* * If we have arranged to catch this fault in any of the * copy to/from user space routines, set PC to return to * indicated location and set flag informing buserror code * that it may need to clean up stack frame. */ -copyfault: frame.f_stackadj = exframesize[frame.f_format]; frame.f_format = frame.f_vector = 0; frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; @@ -448,31 +488,26 @@ copyfault: * XXX: Trace traps are a nightmare. * * HP-UX uses trap #1 for breakpoints, - * HPBSD uses trap #2, + * NetBSD/m68k uses trap #2, * SUN 3.x uses trap #15, - * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). + * DDB and KGDB uses trap #15 (for kernel breakpoints; + * handled elsewhere). * - * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. + * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. * SUN 3.x traps get passed through as T_TRAP15 and are not really * supported yet. + * + * XXX: We should never get kernel-mode T_TRACE or T_TRAP15 + * XXX: because locore.s now gives them special treatment. */ case T_TRACE: /* kernel trace trap */ - case T_TRAP15: /* SUN trace trap */ -#ifdef DDB - if (type == T_TRAP15 || - ((caddr_t)frame.f_pc != trap0 && - (caddr_t)frame.f_pc != trap1 && - (caddr_t)frame.f_pc != trap2 && - (caddr_t)frame.f_pc != trap12 && - (caddr_t)frame.f_pc != trap15 && - (caddr_t)frame.f_pc != illinst)) { - if (kdb_trap(type, &frame)) - return; - } + case T_TRAP15: /* kernel breakpoint */ +#ifdef DEBUG + printf("unexpected kernel trace trap, type = %d\n", type); + printf("program counter = 0x%x\n", frame.f_pc); #endif frame.f_sr &= ~PSL_T; - i = SIGTRAP; - break; + return; case T_TRACE|T_USER: /* user trace trap */ case T_TRAP15|T_USER: /* SUN user trace trap */ @@ -486,7 +521,7 @@ copyfault: DCIU(); return; } -#endif COMPAT_SUNOS +#endif frame.f_sr &= ~PSL_T; i = SIGTRAP; break; @@ -509,19 +544,18 @@ copyfault: case T_SSIR: /* software interrupt */ case T_SSIR|T_USER: - while (bit = ffs(ssir)) { + while ((bit = ffs(ssir))) { --bit; ssir &= ~(1 << bit); uvmexp.softs++; if (sir_routines[bit]) sir_routines[bit](sir_args[bit]); } - /* * If this was not an AST trap, we are all done. */ if (type != (T_ASTFLT|T_USER)) { - uvmexp.traps++; + uvmexp.traps--; return; } spl0(); @@ -532,16 +566,6 @@ copyfault: goto out; case T_MMUFLT: /* kernel mode page fault */ -#if 0 -#ifdef DDB - if (db_recover != 0) - goto dopanic; -#endif -#ifdef KGDB - if (kgdb_recover != 0) - goto dopanic; -#endif -#endif /* * If we were doing profiling ticks or other user mode * stuff from interrupt code, Just Say No. @@ -573,24 +597,29 @@ copyfault: * The last can occur during an exec() copyin where the * argument space is lazy-allocated. */ - if (type == T_MMUFLT && - (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code))) + if ((type & T_USER) == 0 && + ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) map = kernel_map; else - map = &vm->vm_map; + map = vm ? &vm->vm_map : kernel_map; + if (WRFAULT(code)) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; + va = trunc_page((vaddr_t)v); -#ifdef DEBUG + if (map == kernel_map && va == 0) { - printf("trap: bad kernel access at %x\n", v); + printf("trap: bad kernel %s access at 0x%x\n", + (ftype & VM_PROT_WRITE) ? "read/write" : + "read", v); goto dopanic; } -#endif + #ifdef COMPAT_HPUX if (ISHPMMADDR(va)) { + int pmap_mapmulti __P((pmap_t, vaddr_t)); vaddr_t bva; rv = pmap_mapmulti(map->pmap, va); @@ -606,7 +635,7 @@ copyfault: #ifdef DEBUG if (rv && MDB_ISPID(p->p_pid)) printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", - map, va, ftype, rv); + map, va, ftype, rv); #endif /* * If this was a stack access we keep track of the maximum @@ -615,7 +644,8 @@ copyfault: * the current limit and we need to reflect that as an access * error. */ - if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { + if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) + && map != kernel_map) { if (rv == KERN_SUCCESS) { unsigned nss; @@ -627,8 +657,8 @@ copyfault: } if (rv == KERN_SUCCESS) { if (type == T_MMUFLT) { -#if defined(M68040) - if (mmutype == MMU_68040) +#ifdef M68040 + if (cputype == CPU_68040) (void) writeback(&frame, 1); #endif return; @@ -639,7 +669,7 @@ copyfault: if (p->p_addr->u_pcb.pcb_onfault) goto copyfault; printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", - map, va, ftype, rv); + map, va, ftype, rv); printf(" type %x, code [mmu,,ssw]: %x\n", type, code); goto dopanic; @@ -679,9 +709,10 @@ char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", "M-code", "k-data", "k-code", "RES" }; char wberrstr[] = - "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; + "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; #endif +int writeback(fp, docachepush) struct frame *fp; int docachepush; @@ -912,10 +943,11 @@ writeback(fp, docachepush) p->p_addr->u_pcb.pcb_onfault = oonfault; if (err) err = SIGSEGV; - return(err); + return (err); } #ifdef DEBUG +void dumpssw(ssw) u_short ssw; { @@ -942,6 +974,7 @@ dumpssw(ssw) f7tm[ssw & SSW4_TMMASK]); } +void dumpwb(num, s, a, d) int num; u_short s; @@ -953,11 +986,11 @@ dumpwb(num, s, a, d) printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); - printf(" PA "); + printf(" PA "); if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE) printf(""); else - printf("%x, current value %x", pa, fuword((caddr_t)a)); + printf("%lx, current value %lx", pa, fuword((caddr_t)a)); printf("\n"); } #endif @@ -966,8 +999,9 @@ dumpwb(num, s, a, d) /* * Process a system call. */ +void syscall(code, frame) - int code; + register_t code; struct frame frame; { caddr_t params; @@ -975,7 +1009,7 @@ syscall(code, frame) struct proc *p; int error, opc, nsys; size_t argsize; - int args[8], rval[2]; + register_t args[8], rval[2]; u_quad_t sticks; uvmexp.syscalls++; @@ -1009,7 +1043,7 @@ syscall(code, frame) if (code != SUNOS_SYS_sigreturn) { frame.f_regs[SP] += sizeof (int); /* - * remember that we adjusted the SP, + * remember that we adjusted the SP, * might have to undo this if the system call * returns ERESTART. */ @@ -1165,7 +1199,7 @@ child_return(arg) f->f_sr &= ~PSL_C; f->f_format = FMT0; - userret(p, f, p->p_sticks, (u_int)0, 0); + userret(p, f, 0, (u_int)0, 0); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, SYS_fork, 0, 0); @@ -1177,7 +1211,7 @@ child_return(arg) */ u_long allocate_sir(proc, arg) - void (*proc)(); + void (*proc)(void *); void *arg; { int bit; @@ -1193,9 +1227,9 @@ allocate_sir(proc, arg) void init_sir() { - extern void netintr(); + extern void netintr(void); - sir_routines[0] = netintr; - sir_routines[1] = softclock; + sir_routines[0] = (void (*)(void *))netintr; + sir_routines[1] = (void (*)(void *))softclock; next_sir = 2; }