diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-09-06 15:07:44 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-09-06 15:07:44 +0000 |
commit | 186f9fd4734291b623da7ab771b9ded4d862a4b1 (patch) | |
tree | 362f8762ddc0cc49e380e2f74b431b0757382538 | |
parent | 57d5084e30b5cd5b3a983917582de441ba734128 (diff) |
Large cleaning of exception handling:
- faster code paths in eh.S, especially for 88110 cpus
- do not service data access exceptions more than one time; also, be sure
that interrupts are disabled while servicing them.
- cleanup the 88110 trap handler in the same way the 88100 flavour has been
cleaned recently.
This spotted two bugs, which are fixed there as well:
- add systrace support to the 88110 syscall code
- add emulation support to the 88100 syscall code
-rw-r--r-- | sys/arch/mvme88k/mvme88k/eh.S | 213 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/machdep.c | 57 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/trap.c | 307 |
3 files changed, 274 insertions, 303 deletions
diff --git a/sys/arch/mvme88k/mvme88k/eh.S b/sys/arch/mvme88k/mvme88k/eh.S index a3a09040133..0f78a42c0d1 100644 --- a/sys/arch/mvme88k/mvme88k/eh.S +++ b/sys/arch/mvme88k/mvme88k/eh.S @@ -1,4 +1,4 @@ -/* $OpenBSD: eh.S,v 1.36 2003/09/05 20:28:36 miod Exp $ */ +/* $OpenBSD: eh.S,v 1.37 2003/09/06 15:07:43 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1991 Carnegie Mellon University @@ -250,19 +250,7 @@ ASLOCAL(Lbadcpupanic) align 8 -#define OFF_VEC 0 -#define OFF_EPSR 4 -#define OFF_EXIP 8 -#define OFF_ENIP 12 -#define OFF_DSR 16 -#define OFF_DLAR 20 -#define OFF_DPAR 24 -#define OFF_ISR 28 -#define OFF_ILAR 32 -#define OFF_IPAR 36 -#define OFF_TMP 40 - - +#ifdef M88110 #define SAVE_CTX \ stcr r31, SRX ; \ or.u r31, r0, hi16(_ASM_LABEL(save_frame)) ; \ @@ -316,6 +304,7 @@ ASLOCAL(Lbadcpupanic) ld r1 , r31, GENREG_OFF(1) ; \ ld.d r2 , r31, GENREG_OFF(2) ; \ ld r31, r31, GENREG_OFF(31) +#endif /* * @@ -469,6 +458,13 @@ ASGLOBAL(eh_debug) ldcr r4, SR1 ; \ CALL(_C_LABEL(MY_info_done), r31, r4) ; \ 2: br _ASM_LABEL(return_from_exception_handler) +#define DONE2(DebugNumber) \ + or.u r2, r0, hi16(_ASM_LABEL(eh_debug)) ; \ + ld r3, r2, lo16(_ASM_LABEL(eh_debug)) ; \ + bb0 DebugNumber, r3, 2f ; \ + ldcr r4, SR1 ; \ + CALL(_C_LABEL(MY_info_done), r31, r4) ; \ +2: br _ASM_LABEL(m88110_return_code) #else /* * If not debugging, then no debug-prep to do. @@ -477,6 +473,8 @@ ASGLOBAL(eh_debug) #define PREP_DEBUG(bit, name) #define DONE(num) \ br _ASM_LABEL(return_from_exception_handler) +#define DONE2(num) \ + br _ASM_LABEL(m88110_return_code) #endif /* EH_DEBUG */ #ifdef M88100 @@ -493,7 +491,6 @@ GLOBAL(unknown_handler) /* interrupt exception handler */ GLOBAL(interrupt_handler) PREP("interrupt", 1, DEBUG_INTERRUPT_BIT, No_SSBR_Stuff, No_Precheck) - /* interrupt_func is set in mvme_bootstrap() */ CALL(_C_LABEL(m88100_trap), T_INT, r30) DONE(DEBUG_INTERRUPT_BIT) @@ -509,6 +506,7 @@ GLOBAL(instruction_access_handler) */ GLOBAL(data_exception_handler) PREP("data", 3, DEBUG_DATA_BIT, No_SSBR_Stuff, Data_Precheck) + /* No need to call m88100_trap(T_DATAFLT) as PREP will do this for us */ DONE(DEBUG_DATA_BIT) /* misaligned access exception handler */ @@ -538,10 +536,7 @@ GLOBAL(privilege_handler) CALL(_C_LABEL(m88100_trap), T_PRIVINFLT, r30) DONE(DEBUG_PRIVILEGE_BIT) -/* - * I'm not sure what the trap(T_BNDFLT,...) does, but it doesn't send - * a signal to the process... - */ +/* bounds checking exception handler */ GLOBAL(bounds_handler) PREP("bounds", 7, DEBUG_BOUNDS_BIT, Clear_SSBR_Dest, No_Precheck) CALL(_C_LABEL(m88100_trap), T_BNDFLT, r30) @@ -636,7 +631,7 @@ GLOBAL(trace) DONE(DEBUG_TRACE_BIT) GLOBAL(entry) - PREP("unknown", 132, DEBUG_UNKNOWN_BIT, No_SSBR_Stuff, No_Precheck) + PREP("unknown", 132, DEBUG_KDB_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88100_trap), T_UNKNOWNFLT, r30) DONE(DEBUG_KDB_BIT) #endif @@ -1289,11 +1284,13 @@ ASLOCAL(have_pcb) * Save Pbus fault status register from data and inst CMMU. */ #ifdef MVME188 +#if defined(MVME187) || defined(MVME197) /* check if it's a mvme188 */ or.u TMP, r0, hi16(_C_LABEL(brdtyp)) ld TMP2, TMP, lo16(_C_LABEL(brdtyp)) cmp TMP, TMP2, BRD_188 bb1 ne, TMP, 5f +#endif extu TMP, FLAGS, FLAG_CPU_FIELD_WIDTH<0> /* TMP = cpu# */ cmp TMP2, TMP, 0x0 /* CPU0 ? */ @@ -1344,6 +1341,7 @@ ASLOCAL(have_pcb) br _ASM_LABEL(pfsr_done) 5: #endif /* MVME188 */ +#if defined(MVME187) || defined(MVME197) /* it's a single processor SBC */ or.u TMP, r0, hi16(SBC_CMMU_I) ld TMP2, TMP, lo16(SBC_CMMU_I) + 0x108 @@ -1351,6 +1349,7 @@ ASLOCAL(have_pcb) or.u TMP, r0, hi16(SBC_CMMU_D) ld TMP2, TMP, lo16(SBC_CMMU_D) + 0x108 st TMP2, r31, REG_OFF(EF_DPFSR) +#endif ASLOCAL(pfsr_done) ldcr TMP, SSBR @@ -1683,7 +1682,6 @@ ASLOCAL(setup_phase_two) RESTORE_TMP3 /* done with extra temp regs */ /* Get the current PSR and modify for the rte to enable the FPU */ -#if 1 ldcr TMP, PSR clr TMP, TMP, 1<PSR_FPU_DISABLE_BIT> /* enable the FPU */ clr TMP, TMP, 1<PSR_SHADOW_FREEZE_BIT> /* and shadowing */ @@ -1695,18 +1693,6 @@ ASLOCAL(setup_phase_two) stcr TMP, SNIP /* jump to here fpu_enable */ addu TMP, TMP, 4 stcr TMP, SFIP /* and then continue after that */ -#else - ldcr TMP, PSR - or.u TMP, TMP, 0x8000 /* set supervisor mode */ - and TMP, TMP, 0xfff7 /* also enable shadowing */ - stcr TMP, EPSR - stcr r0, SXIP /* clear valid bit */ - stcr r0, SNIP /* clear valid bit */ - or.u TMP, r0, hi16(_ASM_LABEL(fpu_enable)) - or TMP, TMP, lo16(_ASM_LABEL(fpu_enable)) - or TMP, TMP, 0x2 /* set the VALID_BIT and clear Exception bit */ - stcr TMP, SFIP /* jump to here fpu_enable */ -#endif set FLAGS, FLAGS, 1<FLAG_ENABLING_FPU> xcr FLAGS, FLAGS, SR1 @@ -1835,17 +1821,19 @@ ASLOCAL(fpu_enable) or.u r31, r0, hi16(_ASM_LABEL(kstack)) ld r31, r31, lo16(_ASM_LABEL(kstack)) addu r31, r31, USIZE /* point at proper end */ +#ifdef INTSTACK br 3f 1: -#ifdef INTSTACK ld r3, r31, REG_OFF(EF_VECTOR) cmp r3, r3, 1 /* is interrupt ? */ bb0 eq, r3, 3f /* no, we will stay on kern stack */ or.u r31, r0, hi16(_ASM_LABEL(intstack_end)) or r31, r31, lo16(_ASM_LABEL(intstack_end)) +3: +#else +1: #endif -3: /* * here - r30 holds a pointer to the exception frame. * r31 is a pointer to the kernel stack/interrupt stack. @@ -1859,6 +1847,11 @@ ASLOCAL(fpu_enable) ld r2, r30, REG_OFF(EF_VECTOR) bcnd.n eq0, r2, 8f /* is error */ ld r14, r30, REG_OFF(EF_RET) + + /* + * Do not process possible data exceptions here if this is an interrupt. + * Instead, the interrupt handler will take care of this by itself. + */ cmp r3, r2, 1 /* is an interrupt? */ bb1.n eq, r3, 8f /* skip if so */ @@ -1871,8 +1864,8 @@ ASLOCAL(fpu_enable) /* service any outstanding data pipeline stuff */ - ld r3, r30, REG_OFF(EF_DMT0) - bb0 DMT_VALID_BIT, r3, 8f + ld r3, r30, REG_OFF(EF_DMT0) + bb0 DMT_VALID_BIT, r3, 7f /* * r30 can be clobbered by calls. So stuff its value into a preserved @@ -1882,8 +1875,9 @@ ASLOCAL(fpu_enable) CALL(_C_LABEL(m88100_trap), T_DATAFLT, r15) or r30, r0, r15 +7: /* enable interrupts */ - ldcr r2, PSR + ldcr r2, PSR clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> stcr r2, PSR FLUSH_PIPELINE @@ -1924,41 +1918,43 @@ ENTRY(proc_do_uret) ld r3,r2,P_ADDR /* p->p_addr */ addu r3,r3,PCB_USER_STATE /* p->p_addr.u_pcb.user_state */ st r3,r31,0 /* put it on the stack */ - br _ASM_LABEL(return_from_exception_handler) +#if defined(M88100) && defined(M88110) +#ifdef M88110 + or.u r2, r0, hi16(_C_LABEL(cputyp)) + ld r3, r2, lo16(_C_LABEL(cputyp)) + cmp r2, r3, CPU_88110 + bb1 eq, r2, _ASM_LABEL(m88110_return_code) + /* br _ASM_LABEL(return_from_exception_handler) */ +#endif +#endif -ASLOCAL(return_from_exception_handler) /* * Regs r1-r30 are free. R31 is pointing at the word * on the kernel stack where our pointer to the exception frame * it stored. Reload it now. * - * At this point, if EF_DMT0 is not zero, then + * At this point, if EF_DMT0 is not zero on MC88100, then * this must have been an interrupt where the fault didn't * get corrected above. We'll do that now. * * We load it into r14 since it is preserved across function * calls, and we may have to call some routines from within here. * - * control is transfered here from obvious places in this file - * and thread_bootstrap in luna88k/locore.c. - * + * Control is transfered here from obvious places in this file. */ -#ifdef M88110 - or.u r2, r0, hi16(_C_LABEL(cputyp)) - ld r3, r2, lo16(_C_LABEL(cputyp)) - cmp r2, r3, CPU_88110 - bb1 eq, r2, _ASM_LABEL(m88110_return_code) -#endif + #ifdef M88100 +ASLOCAL(return_from_exception_handler) + /* + * if there happens to be a data fault that hasn't been serviced yet, + * go off and service that... + */ + #define FPTR r14 ld FPTR, r31, 0 /* grab exception frame pointer */ ld r3, FPTR, REG_OFF(EF_DMT0) bb0 DMT_VALID_BIT, r3, _ASM_LABEL(check_ast) - /* - * if there happens to be a data fault that hasn't been serviced yet, - * go off and service that... - */ CALL(_C_LABEL(m88100_trap), T_DATAFLT, r30) br _ASM_LABEL(check_ast) #endif /* M88100 */ @@ -1968,9 +1964,9 @@ ASLOCAL(m88110_return_code) #define FPTR r14 ld FPTR, r31, 0 /* grab exception frame pointer */ +#if 0 /* * If it's the interrupt exception, enable interrupt. - * If it's the data access exception, take care of it. */ /* @@ -1991,22 +1987,7 @@ ASLOCAL(m88110_return_code) stcr r2, PSR FLUSH_PIPELINE 1: - br 2f /* temp XXX smurph */ - ld r2, FPTR, REG_OFF(EF_VECTOR) - cmp r2, r2, 3 /* Is it a data access exception? */ - bb1 ne, r2, 2f /* If not, skip */ - - /* - * if there happens to be a data fault that hasn't been serviced yet, - * go off and service that... - */ - CALL(_C_LABEL(m88110_trap), T_DATAFLT, r30) - - /* clear the dsr word in the E.F. */ - st r0, FPTR, REG_OFF(EF_DSR) - st r0, FPTR, REG_OFF(EF_DLAR) - st r0, FPTR, REG_OFF(EF_DPAR) -2: +#endif #endif /* M88110 */ /* @@ -2154,19 +2135,19 @@ ASLOCAL(no_ast) GLOBAL(m88110_unknown_handler) PREP2("unknown", 0, DEBUG_UNKNOWN_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_UNKNOWNFLT, r30) - DONE(DEBUG_UNKNOWN_BIT) + DONE2(DEBUG_UNKNOWN_BIT) /* interrupt exception handler */ GLOBAL(m88110_interrupt_handler) PREP2("interrupt", 1, DEBUG_INTERRUPT_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_INT, r30) - DONE(DEBUG_INTERRUPT_BIT) + DONE2(DEBUG_INTERRUPT_BIT) /* instruction access exception handler */ GLOBAL(m88110_instruction_access_handler) PREP2("inst", 2, DEBUG_INSTRUCTION_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_INSTFLT, r30) - DONE(DEBUG_INSTRUCTION_BIT) + DONE2(DEBUG_INSTRUCTION_BIT) /* * data access exception handler -- * See badaddr() below for info about Data_Precheck. @@ -2174,25 +2155,25 @@ GLOBAL(m88110_instruction_access_handler) GLOBAL(m88110_data_exception_handler) PREP2("data", 3, DEBUG_DATA_BIT, No_SSBR_Stuff, M88110_Data_Precheck) CALL(_C_LABEL(m88110_trap), T_DATAFLT, r30) - DONE(DEBUG_DATA_BIT) + DONE2(DEBUG_DATA_BIT) /* misaligned access exception handler */ GLOBAL(m88110_misaligned_handler) PREP2("misalign", 4, DEBUG_MISALIGN_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_MISALGNFLT, r30) - DONE(DEBUG_MISALIGN_BIT) + DONE2(DEBUG_MISALIGN_BIT) /* unimplemented opcode exception handler */ GLOBAL(m88110_unimplemented_handler) PREP2("unimp", 5, DEBUG_UNIMPLEMENTED_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_ILLFLT, r30) - DONE(DEBUG_UNIMPLEMENTED_BIT) + DONE2(DEBUG_UNIMPLEMENTED_BIT) /* privilege exception handler */ GLOBAL(m88110_privilege_handler) PREP2("privilege", 6, DEBUG_PRIVILEGE_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_PRIVINFLT, r30) - DONE(DEBUG_PRIVILEGE_BIT) + DONE2(DEBUG_PRIVILEGE_BIT) /* * I'm not sure what the trap(T_BNDFLT,...) does, but it doesn't send @@ -2201,114 +2182,114 @@ GLOBAL(m88110_privilege_handler) GLOBAL(m88110_bounds_handler) PREP2("bounds", 7, DEBUG_BOUNDS_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_BNDFLT, r30) - DONE(DEBUG_BOUNDS_BIT) + DONE2(DEBUG_BOUNDS_BIT) /* integer divide-by-zero exception handler */ GLOBAL(m88110_divide_handler) PREP2("divide", 8, DEBUG_DIVIDE_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_ZERODIV, r30) - DONE(DEBUG_DIVIDE_BIT) + DONE2(DEBUG_DIVIDE_BIT) /* integer overflow exception handler */ GLOBAL(m88110_overflow_handler) PREP2("overflow", 9, DEBUG_OVERFLOW_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_OVFFLT, r30) - DONE(DEBUG_OVERFLOW_BIT) + DONE2(DEBUG_OVERFLOW_BIT) /* Floating-point precise handler */ GLOBAL(m88110_fp_precise_handler) PREP2("FPU precise", 114, DEBUG_FPp_BIT, No_SSBR_Stuff, No_Precheck) CALL(_ASM_LABEL(m88110_Xfp_precise), r0, r30) - DONE(DEBUG_FPp_BIT) + DONE2(DEBUG_FPp_BIT) /* MVME197 non-maskable interrupt handler (ABORT button) */ GLOBAL(m88110_nonmaskable) PREP2("MVME197 non-mask", 11, DEBUG_NON_MASK_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_NON_MASK, r30) - DONE(DEBUG_NON_MASK_BIT) + DONE2(DEBUG_NON_MASK_BIT) /* MVME197 data MMU read miss handler */ GLOBAL(m88110_data_read_miss) PREP2("MVME197 read miss", 12, DEBUG_197_READ_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_197_READ, r30) - DONE(DEBUG_197_READ_BIT) + DONE2(DEBUG_197_READ_BIT) /* MVME197 data MMU write miss handler */ GLOBAL(m88110_data_write_miss) PREP2("MVME197 write miss", 13, DEBUG_197_WRITE_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_197_WRITE, r30) - DONE(DEBUG_197_WRITE_BIT) + DONE2(DEBUG_197_WRITE_BIT) /* MVME197 inst MMU ATC miss handler */ GLOBAL(m88110_inst_atc_miss) PREP2("MVME197 inst miss", 14, DEBUG_197_INST_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_197_INST, r30) - DONE(DEBUG_197_INST_BIT) + DONE2(DEBUG_197_INST_BIT) /* All standard system calls. */ GLOBAL(m88110_syscall_handler) PREP2("syscall", 128, DEBUG_SYSCALL_BIT, No_SSBR_Stuff, No_Precheck) ld r13, r30, GENREG_OFF(13) CALL(_C_LABEL(m88110_syscall), r13, r30) - DONE(DEBUG_SYSCALL_BIT) + DONE2(DEBUG_SYSCALL_BIT) /* trap 496 comes here */ GLOBAL(m88110_bugtrap) PREP2("bugsyscall", 496, DEBUG_BUGCALL_BIT, No_SSBR_Stuff, No_Precheck) ld r9, r30, GENREG_OFF(9) CALL(_C_LABEL(bugsyscall), r9, r30) - DONE(DEBUG_BUGCALL_BIT) + DONE2(DEBUG_BUGCALL_BIT) GLOBAL(m88110_sigsys) PREP2("sigsys", 501, DEBUG_SIGSYS_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_SIGSYS, r30) - DONE(DEBUG_SIGSYS_BIT) + DONE2(DEBUG_SIGSYS_BIT) GLOBAL(m88110_sigtrap) PREP2("sigtrap", 510, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_SIGTRAP, r30) - DONE(DEBUG_SIGTRAP_BIT) + DONE2(DEBUG_SIGTRAP_BIT) GLOBAL(m88110_stepbpt) PREP2("stepbpt", 504, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_STEPBPT, r30) - DONE(DEBUG_SIGTRAP_BIT) + DONE2(DEBUG_SIGTRAP_BIT) GLOBAL(m88110_userbpt) PREP2("userbpt", 511, DEBUG_SIGTRAP_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_USERBPT, r30) - DONE(DEBUG_SIGTRAP_BIT) + DONE2(DEBUG_SIGTRAP_BIT) #ifdef DDB GLOBAL(m88110_break) PREP2("break", 130, DEBUG_BREAK_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_KDB_BREAK, r30) - DONE(DEBUG_BREAK_BIT) + DONE2(DEBUG_BREAK_BIT) GLOBAL(m88110_trace) PREP2("trace", 131, DEBUG_TRACE_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_KDB_TRACE, r30) - DONE(DEBUG_TRACE_BIT) + DONE2(DEBUG_TRACE_BIT) GLOBAL(m88110_entry) PREP2("kdb", 132, DEBUG_KDB_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_KDB_ENTRY, r30) - DONE(DEBUG_KDB_BIT) + DONE2(DEBUG_KDB_BIT) #else GLOBAL(m88110_break) PREP2("break", 130, DEBUG_BREAK_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_UNKNOWNFLT, r30) - DONE(DEBUG_BREAK_BIT) + DONE2(DEBUG_BREAK_BIT) GLOBAL(m88110_trace) PREP2("trace", 131, DEBUG_TRACE_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_UNKNOWNFLT, r30) - DONE(DEBUG_TRACE_BIT) + DONE2(DEBUG_TRACE_BIT) GLOBAL(m88110_entry) - PREP2("unknown", 132, DEBUG_UNKNOWN_BIT, No_SSBR_Stuff, No_Precheck) + PREP2("unknown", 132, DEBUG_KDB_BIT, No_SSBR_Stuff, No_Precheck) CALL(_C_LABEL(m88110_trap), T_UNKNOWNFLT, r30) - DONE(DEBUG_KDB_BIT) + DONE2(DEBUG_KDB_BIT) #endif /* @@ -2867,17 +2848,20 @@ ASLOCAL(m88110_fpu_enable) or.u r31, r0, hi16(_ASM_LABEL(kstack)) ld r31, r31, lo16(_ASM_LABEL(kstack)) addu r31, r31, USIZE /* point at proper end */ +#ifdef INTSTACK br 3f 1: -#ifdef INTSTACK ld r3, r31, REG_OFF(EF_VECTOR) cmp r3, r3, 1 /* is interrupt ? */ bb0 eq, r3, 3f /* no, we will stay on kern stack */ or.u r31, r0, hi16(_ASM_LABEL(intstack_end)) or r31, r31, lo16(_ASM_LABEL(intstack_end)) +3: +#else +1: #endif -3: /* + /* * here - r30 holds a pointer to the exception frame. * r31 is a pointer to the kernel stack/interrupt stack. */ @@ -2902,36 +2886,13 @@ ASLOCAL(m88110_fpu_enable) #endif /* enable interrupts */ - ldcr r2, PSR + ldcr r2, PSR clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> stcr r2, PSR FLUSH_PIPELINE -#if 1 /* XXX test */ - br 8f -#else - /* service any outstanding data pipeline stuff - - check dsr... anything outstanding? */ - ld r3, r30, REG_OFF(EF_DSR) - cmp r3, r3, 0 - bb1 eq, r3, 8f - -/* - * r30 can be clobbered by calls. So stuff its value into a - * preserved register, say r15. R14 is in use (see return_to_... below). - */ - or r15, r0, r30 - CALL(_C_LABEL(m88110_trap), T_DATAFLT, r15) - - /* restore it... */ - or r30, r0, r15 - - /* clear the dsr word in the E.F */ - st r0, r30, REG_OFF(EF_DSR) - -#endif 8: - jmp r14 /* loaded above */ + jmp r14 /* loaded above */ data .align 8 diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index fdccd66759c..ffd7dd45cd8 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.108 2003/09/02 20:14:08 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.109 2003/09/06 15:07:43 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -810,6 +810,10 @@ setregs(p, pack, stack, retval) * graphics unit, fp enabled */ tf->epsr = PSR_SRM | PSR_SFD; + /* + * XXX disable OoO for now... + */ + tf->epsr |= PSR_SER; } else { /* * user mode, interrupts enabled, @@ -1637,6 +1641,14 @@ m188_ext_int(u_int v, struct m88100_saved_state *eframe) setipl(level); + /* + * Contrary to other traps, we have not checked for the + * data pipeline status yet. + * Do it now, before we reenable interrupts. + */ + if (eframe->dmt0 & DMT_VALID) + m88100_trap(T_DATAFLT, eframe); + enable_interrupt(); /* generate IACK and get the vector */ @@ -1725,25 +1737,10 @@ m188_ext_int(u_int v, struct m88100_saved_state *eframe) } while ((cur_mask = ISR_GET_CURRENT_MASK(cpu)) != 0); /* - * process any remaining data access exceptions before - * returning to assembler - */ - disable_interrupt(); - if (eframe->dmt0 & DMT_VALID) { - m88100_trap(T_DATAFLT, eframe); - if (eframe->dmt0 & DMT_VALID) { -#ifdef DEBUG - printf("m188_ext_int: T_DATAFLT not fixed\n"); -#endif - data_access_emulation((unsigned *)eframe); - eframe->dmt0 &= ~DMT_VALID; - } - } - - /* * Restore the mask level to what it was when the interrupt * was taken. */ + disable_interrupt(); setipl(eframe->mask); flush_pipeline(); } @@ -1808,6 +1805,14 @@ m187_ext_int(u_int v, struct m88100_saved_state *eframe) flush_pipeline(); flush_pipeline(); + /* + * Contrary to other traps, we have not checked for the + * data pipeline status yet. + * Do it now, before we reenable interrupts. + */ + if (eframe->dmt0 & DMT_VALID) + m88100_trap(T_DATAFLT, eframe); + enable_interrupt(); if ((intr = intr_handlers[vec]) == NULL) { @@ -1847,26 +1852,10 @@ m187_ext_int(u_int v, struct m88100_saved_state *eframe) } /* - * process any remaining data access exceptions before - * returning to assembler - */ - disable_interrupt(); - - if (eframe->dmt0 & DMT_VALID) { - m88100_trap(T_DATAFLT, eframe); - if (eframe->dmt0 & DMT_VALID) { -#ifdef DEBUG - printf("m187_ext_int: T_DATAFLT not fixed\n"); -#endif - data_access_emulation((unsigned *)eframe); - eframe->dmt0 &= ~DMT_VALID; - } - } - - /* * Restore the mask level to what it was when the interrupt * was taken. */ + disable_interrupt(); setipl(eframe->mask); } #endif /* MVME187 */ diff --git a/sys/arch/mvme88k/mvme88k/trap.c b/sys/arch/mvme88k/mvme88k/trap.c index 96cb8dfe265..8c64e67c1bc 100644 --- a/sys/arch/mvme88k/mvme88k/trap.c +++ b/sys/arch/mvme88k/mvme88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.48 2003/09/04 18:14:46 miod Exp $ */ +/* $OpenBSD: trap.c,v 1.49 2003/09/06 15:07:43 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -178,18 +178,18 @@ panictrap(int type, struct m88100_saved_state *frame) static int panicing = 0; if (panicing++ == 0) { - if (cputyp != CPU_88110) { - if (type == 2) { /* instruction exception */ + if (type == 2 && cputyp == CPU_88100) { + /* instruction exception */ DEBUG_MSG("\nInstr access fault (%s) v = %x, frame %x\n", pbus_exception_type[(frame->ipfsr >> 16) & 0x7], frame->sxip & ~3, frame); - } else if (type == 3) { /* data access exception */ + } else if (type == 3 && cputyp == CPU_88100) { + /* data access exception */ DEBUG_MSG("\nData access fault (%s) v = %x, frame %x\n", pbus_exception_type[(frame->dpfsr >> 16) & 0x7], frame->sxip & ~3, frame); } else DEBUG_MSG("\ntrap type %d, v = %x, frame %x\n", type, frame->sxip & ~3, frame); - } regdump(frame); } if ((u_int)type < trap_types) @@ -202,7 +202,6 @@ panictrap(int type, struct m88100_saved_state *frame) unsigned last_trap[4] = {0,0,0,0}; unsigned last_vector = 0; -/*ARGSUSED*/ void m88100_trap(unsigned type, struct m88100_saved_state *frame) { @@ -280,6 +279,10 @@ m88100_trap(unsigned type, struct m88100_saved_state *frame) } #endif /* 0 */ #endif /* DDB */ + case T_ILLFLT: + DEBUG_MSG("Unimplemented opcode!\n"); + panictrap(frame->vector, frame); + break; case T_INT: case T_INT+T_USER: /* This function pointer is set in machdep.c @@ -312,11 +315,6 @@ m88100_trap(unsigned type, struct m88100_saved_state *frame) goto user_fault; } - /* - * If the faulting address is in user space, handle it in - * the context of the user process. Else, use kernel map. - */ - fault_addr = frame->dma0; if (frame->dmt0 & (DMT_WRITE|DMT_LOCKBAR)) { ftype = VM_PROT_READ|VM_PROT_WRITE; @@ -426,7 +424,7 @@ m88100_trap(unsigned type, struct m88100_saved_state *frame) return; case T_INSTFLT+T_USER: /* User mode instruction access fault */ - /* FALLTHRU */ + /* FALLTHROUGH */ case T_DATAFLT+T_USER: user_fault: if (type == T_INSTFLT+T_USER) { @@ -664,10 +662,8 @@ user_fault: userret(p, frame, sticks); } #endif /* m88100 */ -unsigned v_fault = 0; #ifdef M88110 -/*ARGSUSED*/ void m88110_trap(unsigned type, struct m88100_saved_state *frame) { @@ -684,21 +680,21 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) #ifdef DDB int s; /* IPL */ #endif - int result = 0; /* Assume Success */ + int result; int sig = 0; unsigned pc = PC_REGS(frame); /* get program counter (exip) */ - unsigned user = 0, data = 0; pt_entry_t *pte; + extern struct vm_map *kernel_map; extern unsigned guarded_access_start; extern unsigned guarded_access_end; extern pt_entry_t *pmap_pte(pmap_t, vm_offset_t); uvmexp.traps++; - if ((p = curproc) == NULL) p = &proc0; -#if 1 + +#ifdef DEBUG if (type != T_INT && type != T_ASTFLT #ifdef DDB && type != T_KDB_ENTRY @@ -714,9 +710,7 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) p->p_md.md_tf = frame; /* for ptrace/signals */ fault_type = 0; fault_code = 0; - user = 1; } - switch (type) { default: panictrap(frame->vector, frame); @@ -759,7 +753,7 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) if (frame->enip) { frame->exip = frame->enip; } else { - frame->exip += 4; + frame->exip += 4; } splx(s); return; @@ -805,92 +799,82 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) case T_DATAFLT: /* kernel mode data fault */ - /* - * If the faulting address is in user space, handle it in - * the context of the user process. Else, use kernel map. - */ - if (type == T_DATAFLT) { - fault_addr = frame->dlar; - if (frame->dsr & CMMU_DSR_RW) { - ftype = VM_PROT_READ; - fault_code = VM_PROT_READ; - } else { - ftype = VM_PROT_READ|VM_PROT_WRITE; - fault_code = VM_PROT_WRITE; - } - data = 1; - } else { - fault_addr = frame->exip & XIP_ADDR; + + /* data fault on the user address? */ + if ((frame->dsr & CMMU_DSR_SU) == 0) { + type = T_DATAFLT + T_USER; + goto m88110_user_fault; + } + + fault_addr = frame->dlar; + if (frame->dsr & CMMU_DSR_RW) { ftype = VM_PROT_READ; fault_code = VM_PROT_READ; + } else { + ftype = VM_PROT_READ|VM_PROT_WRITE; + fault_code = VM_PROT_WRITE; } va = trunc_page((vm_offset_t)fault_addr); + if (va == 0) { + panic("trap: bad kernel access at %x", fault_addr); + } + vm = p->p_vmspace; - map = &vm->vm_map; + map = kernel_map; - /* data fault on a kernel address... */ - if (type == T_DATAFLT) { - if (frame->dsr & CMMU_DSR_SU) { - map = kernel_map; + if (frame->dsr & CMMU_DSR_BE) { + /* + * If it is a guarded access, bus error is OK. + */ + if ((frame->exip & ~3) >= + (unsigned)&guarded_access_start && + (frame->exip & ~3) <= + (unsigned)&guarded_access_end) { + return; } } - - /* data fault on the user address */ - if (type == T_DATAFLT && (frame->dsr & CMMU_DSR_SU) == 0) { - type = T_DATAFLT + T_USER; - goto m88110_user_fault; - } - - /* - * If it is a guarded access, bus error is OK. - */ - - if ((frame->dsr & CMMU_DSR_BE) && /* bus error */ - (frame->exip & ~3) >= (unsigned)&guarded_access_start && - (frame->exip & ~3) <= (unsigned)&guarded_access_end) { - return; + if (frame->dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) { + /* + * On a segment or a page fault, call uvm_fault() to + * resolve the fault. + */ + result = uvm_fault(map, va, 0, ftype); + if (result == 0) + return; } - /* - * On a segment or a page fault, call vm_fault() to resolve - * the fault. - */ - if (type == T_DATAFLT) { - if ((frame->dsr & CMMU_DSR_SI) /* seg fault */ - || (frame->dsr & CMMU_DSR_PI)) { /* page fault */ - result = uvm_fault(map, va, 0, ftype); - if (result == 0) { - return; - } - } - if (frame->dsr & CMMU_DSR_WE) { /* write fault */ - /* This could be a write protection fault or an + if (frame->dsr & CMMU_DSR_WE) { /* write fault */ + /* + * This could be a write protection fault or an * exception to set the used and modified bits - * in the pte. Basicly, if we got a write error, + * in the pte. Basically, if we got a write error, * then we already have a pte entry that faulted * in from a previous seg fault or page fault. * Get the pte and check the status of the * modified and valid bits to determine if this * indeed a real write fault. XXX smurph */ - pte = pmap_pte(map->pmap, va); - if (pte == PT_ENTRY_NULL) - panic("NULL pte on write fault??"); - if (!(*pte & PG_M) && !(*pte & PG_RO)) { - /* Set modified bit and try the write again. */ - *pte |= PG_M; - return; - } - } - } else { - if ((frame->isr & CMMU_ISR_SI) /* seg fault */ - || (frame->isr & CMMU_ISR_PI)) { /* page fault */ + pte = pmap_pte(map->pmap, va); + if (pte == PT_ENTRY_NULL) + panic("NULL pte on write fault??"); + if (!(*pte & PG_M) && !(*pte & PG_RO)) { + /* Set modified bit and try the write again. */ + *pte |= PG_M; + return; +#if 1 /* shouldn't happen */ + } else { + /* must be a real wp fault */ +#ifdef DEBUG + printf("Kernel Write protect???? pte %x\n", + *pte); +#endif result = uvm_fault(map, va, 0, ftype); - if (result == 0) { + if (result == 0) return; - } +#endif } } + /* * if still the fault is not resolved ... */ @@ -901,7 +885,7 @@ m88110_trap(unsigned type, struct m88100_saved_state *frame) return; case T_INSTFLT+T_USER: /* User mode instruction access fault */ - /*FALLTHRU*/ + /* FALLTHROUGH */ case T_DATAFLT+T_USER: m88110_user_fault: if (type == T_INSTFLT+T_USER) { @@ -924,55 +908,86 @@ m88110_user_fault: vm = p->p_vmspace; map = &vm->vm_map; - /* Call vm_fault() to resolve non-bus error faults */ + /* + * Call uvm_fault() to resolve non-bus error faults + * whenever possible. + */ if (type == T_DATAFLT+T_USER) { - - if (frame->dsr & (CMMU_DSR_SI | /* seg fault */ - CMMU_DSR_PI)) { /* page fault */ + /* data faults */ + if (frame->dsr & CMMU_DSR_BE) { + /* bus error */ + result = EACCES; + } else + if (frame->dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) { + /* segment or page fault */ result = uvm_fault(map, va, 0, ftype); - if (result != 0) { +#ifdef DEBUG + if (result != 0) printf("Data Access Error @ 0x%x\n", va); - } - v_fault++; - } else if (frame->dsr & CMMU_DSR_BE) { /* bus error */ - result = EFAULT; - } else if ((frame->dsr & CMMU_DSR_CP) - || (frame->dsr & CMMU_DSR_WA)) { +#endif + } else + if (frame->dsr & (CMMU_DSR_CP | CMMU_DSR_WA)) { + /* copyback or write allocate error */ result = 0; - } else if (frame->dsr & CMMU_DSR_WE) { /* write fault */ - /* This could be a write protection fault or an - * exception to set the used and modified bits - * in the pte. Basicly, if we got a write error, - * then we already have a pte entry that faulted - * in from a previous seg fault or page fault. - * Get the pte and check the status of the - * modified and valid bits to determine if this - * indeed a real write fault. XXX smurph - */ + } else + if (frame->dsr & CMMU_DSR_WE) { + /* write fault */ + /* This could be a write protection fault or an + * exception to set the used and modified bits + * in the pte. Basically, if we got a write + * error, then we already have a pte entry that + * faulted in from a previous seg fault or page + * fault. + * Get the pte and check the status of the + * modified and valid bits to determine if this + * indeed a real write fault. XXX smurph + */ pte = pmap_pte(vm_map_pmap(map), va); if (pte == PT_ENTRY_NULL) panic("NULL pte on write fault??"); - if (!(*pte & PG_M) && !(*pte & PG_PROT)) { - /* Set modified bit and try the write again. */ + if (!(*pte & PG_M) && !(*pte & PG_RO)) { + /* + * Set modified bit and try the + * write again. + */ *pte |= PG_M; - /* invalidate ATCs to force table search */ + /* + * invalidate ATCs to force + * table search + */ set_dcmd(CMMU_DCMD_INV_UATC); return; } else { - /* This must be a real write protection fault */ - printf("Write protect???? mod = %d, wp = %d\n", !!(*pte & PG_M), !!(*pte & PG_PROT)); + /* must be a real wp fault */ +#ifdef DEBUG + printf("Write protect???? pte %x\n", + *pte); +#endif result = uvm_fault(map, va, 0, ftype); } + } else { +#ifdef DEBUG + printf("unexpected data fault dsr %x\n", + frame->dsr); +#endif + result = uvm_fault(map, va, 0, ftype); } } else { - if ((frame->isr & CMMU_ISR_SI) /* seg fault */ - || (frame->isr & CMMU_ISR_PI)) { /* page fault */ + /* instruction faults */ + if (frame->isr & (CMMU_ISR_SI | CMMU_ISR_PI)) { + /* segment or page fault */ result = uvm_fault(map, va, 0, ftype); - v_fault++; - } else if ((frame->isr & CMMU_ISR_BE) - || (frame->isr & CMMU_ISR_SP) - || (frame->isr & CMMU_ISR_TBE)) { /* bus error */ + } else + if (frame->isr & + (CMMU_ISR_BE | CMMU_ISR_SP | CMMU_ISR_TBE)) { + /* bus error, supervisor protection */ result = EACCES; + } else { +#ifdef DEBUG + printf("unexpected instr fault dsr %x\n", + frame->isr); +#endif + result = uvm_fault(map, va, 0, ftype); } } @@ -986,14 +1001,9 @@ m88110_user_fault: } if (result != 0) { -#ifdef smurph_debug - printf("Access failed! result = %d\n\n", result); - frame->mode = v_fault; - regdump(frame); - Debugger(); sig = result == EACCES ? SIGBUS : SIGSEGV; - fault_type = result == EACCES ? BUS_ADRERR : SEGV_MAPERR; -#endif + fault_type = result == EACCES ? + BUS_ADRERR : SEGV_MAPERR; } break; case T_MISALGNFLT+T_USER: @@ -1046,11 +1056,6 @@ m88110_user_fault: * is executed. When this breakpoint is hit, we get the * T_STEPBPT trap. */ -#if 0 - frame->sfip = frame->snip; /* set up next FIP */ - frame->snip = frame->sxip; /* set up next NIP */ - break; -#endif { register unsigned va; unsigned instr; @@ -1062,7 +1067,7 @@ m88110_user_fault: /* read break instruction */ copyin((caddr_t)pc, &instr, sizeof(unsigned)); -#if 1 +#if 0 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", p->p_comm, p->p_pid, instr, pc, p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ @@ -1078,10 +1083,7 @@ m88110_user_fault: /* restore original instruction and clear BP */ /*sig = suiword((caddr_t)pc, p->p_md.md_ss_instr);*/ instr = p->p_md.md_ss_instr; - if (instr == 0) { - printf("Warning: can't restore instruction at %x: %x\n", - p->p_md.md_ss_addr, p->p_md.md_ss_instr); - } else { + if (instr != 0) { iov.iov_base = (caddr_t)&instr; iov.iov_len = sizeof(int); uio.uio_iov = &iov; @@ -1117,10 +1119,11 @@ m88110_user_fault: } break; } + /* * If trap from supervisor mode, just return */ - if (SYSTEMMODE(frame->epsr)) + if (type < T_USER) return; if (sig) { @@ -1130,9 +1133,9 @@ m88110_user_fault: * don't want multiple faults - we are going to * deliver signal. */ - frame->dsr = 0; - frame->isr = 0; + frame->dsr = frame->isr = 0; } + userret(p, frame, sticks); } @@ -1358,6 +1361,8 @@ m88100_syscall(register_t code, struct m88100_saved_state *tf) break; default: /* error != ERESTART && error != EJUSTRETURN*/ + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; tf->r[2] = error; tf->epsr |= PSR_C; /* fail */ tf->snip = tf->snip & ~NIP_E; @@ -1437,7 +1442,9 @@ m88110_syscall(register_t code, struct m88100_saved_state *tf) } /* Callp currently points to syscall, which returns ENOSYS. */ +#ifdef DEBUG printf("syscall code is %d\n", code); +#endif if (code < 0 || code >= nsys) callp += p->p_emul->e_nosys; else { @@ -1460,7 +1467,12 @@ m88110_syscall(register_t code, struct m88100_saved_state *tf) #endif rval[0] = 0; rval[1] = 0; - error = (*callp->sy_call)(p, &args, rval); +#if NSYSTRACE > 0 + if (ISSET(p->p_flag, P_SYSTRACE)) + error = systrace_redirect(code, p, &args, rval); + else +#endif + error = (*callp->sy_call)(p, &args, rval); /* * system call will look like: * ld r10, r31, 32; r10,r11,r12 might be garbage. @@ -1491,7 +1503,9 @@ m88110_syscall(register_t code, struct m88100_saved_state *tf) switch (error) { case 0: +#ifdef DEBUG printf("syscall success!\n"); +#endif /* * If fork succeeded and we are the child, our stack * has moved and the pointer tf is no longer valid, @@ -1504,11 +1518,13 @@ m88110_syscall(register_t code, struct m88100_saved_state *tf) tf->r[2] = rval[0]; tf->r[3] = rval[1]; tf->epsr &= ~PSR_C; - tf->exip += 8; + tf->exip += 4 + 4; tf->exip &= ~3; break; case ERESTART: +#ifdef DEBUG printf("syscall restart!\n"); +#endif /* * Reexecute the trap. * exip is already at the trap instruction, so @@ -1517,14 +1533,17 @@ m88110_syscall(register_t code, struct m88100_saved_state *tf) tf->epsr &= ~PSR_C; break; case EJUSTRETURN: +#ifdef DEBUG printf("syscall just return!\n"); - /* if (error == EJUSTRETURN) */ +#endif tf->epsr &= ~PSR_C; tf->exip += 4; tf->exip &= ~3; break; default: +#ifdef DEBUG printf("syscall error %d!\n", error); +#endif /* error != ERESTART && error != EJUSTRETURN*/ if (p->p_emul->e_errno) error = p->p_emul->e_errno[error]; @@ -1565,7 +1584,7 @@ child_return(arg) tf->snip = tf->sfip & ~3; tf->sfip = tf->snip + 4; } else { - tf->exip += 8; + tf->exip += 4 + 4; tf->exip &= ~3; } @@ -1790,8 +1809,10 @@ register struct proc *p; } if (p->p_md.md_ss_addr) { +#if 0 printf("SS %s (%d): breakpoint already set at %x (va %x)\n", p->p_comm, p->p_pid, p->p_md.md_ss_addr, pc); /* XXX */ +#endif return (EFAULT); } |