From 8264d230a9f2f0312aec4c0fa6503139cea61d7c Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 8 Mar 2002 16:24:48 +0000 Subject: 2002-03-05 Greg Menke * cpu_asm.S: Added support for the debug exception vector, cleaned up the exception processing & exception return stuff. Re-added EPC in the task context structure so the gdb stub will know where a thread is executing. Should've left it there in the first place... * idtcpu.h: Added support for the debug exception vector. * cpu.c: Added ___exceptionTaskStack to hold a pointer to the stack frame in an interrupt so context switch code can get the userspace EPC when scheduling. * rtems/score/cpu.h: Re-added EPC to the task context. --- c/src/exec/score/cpu/mips/ChangeLog | 12 ++ c/src/exec/score/cpu/mips/cpu.c | 12 ++ c/src/exec/score/cpu/mips/cpu_asm.S | 190 ++++++++++++++++++++------- c/src/exec/score/cpu/mips/idtcpu.h | 29 +++- c/src/exec/score/cpu/mips/rtems/score/cpu.h | 2 +- c/src/exec/score/cpu/mips/rtems/score/mips.h | 72 ++++++++++ 6 files changed, 268 insertions(+), 49 deletions(-) (limited to 'c') diff --git a/c/src/exec/score/cpu/mips/ChangeLog b/c/src/exec/score/cpu/mips/ChangeLog index ef4c51c39f..888947d33c 100644 --- a/c/src/exec/score/cpu/mips/ChangeLog +++ b/c/src/exec/score/cpu/mips/ChangeLog @@ -1,3 +1,15 @@ +2002-03-05 Greg Menke + + * cpu_asm.S: Added support for the debug exception vector, cleaned + up the exception processing & exception return stuff. Re-added + EPC in the task context structure so the gdb stub will know where + a thread is executing. Should've left it there in the first place... + * idtcpu.h: Added support for the debug exception vector. + * cpu.c: Added ___exceptionTaskStack to hold a pointer to the + stack frame in an interrupt so context switch code can get the + userspace EPC when scheduling. + * rtems/score/cpu.h: Re-added EPC to the task context. + 2002-02-27 Greg Menke * cpu_asm.S: Fixed exception return address, modified FP context diff --git a/c/src/exec/score/cpu/mips/cpu.c b/c/src/exec/score/cpu/mips/cpu.c index 81439b3bd1..7777680655 100644 --- a/c/src/exec/score/cpu/mips/cpu.c +++ b/c/src/exec/score/cpu/mips/cpu.c @@ -47,6 +47,18 @@ #include + + +/* +** local dword used in cpu_asm to pass the exception stack frame to the +** context switch code. +*/ +unsigned __exceptionStackFrame = 0; + + + + + /* _CPU_Initialize * * This routine performs processor dependent initialization. diff --git a/c/src/exec/score/cpu/mips/cpu_asm.S b/c/src/exec/score/cpu/mips/cpu_asm.S index ab3b2280e7..e19a9f4f4e 100644 --- a/c/src/exec/score/cpu/mips/cpu_asm.S +++ b/c/src/exec/score/cpu/mips/cpu_asm.S @@ -124,7 +124,7 @@ #define FP_OFFSET 9 #define RA_OFFSET 10 #define C0_SR_OFFSET 11 -/* #define C0_EPC_OFFSET 12 */ +#define C0_EPC_OFFSET 12 /* NOTE: these constants must match the Context_Control_fp structure in cpu.h */ #define FP0_OFFSET 0 @@ -160,7 +160,11 @@ #define FP30_OFFSET 30 #define FP31_OFFSET 31 + +ASM_EXTERN(__exceptionStackFrame, SZ_INT) + + /* * _CPU_Context_save_fp_context * @@ -386,6 +390,32 @@ FRAME(_CPU_Context_switch,sp,0,ra) STREG s6,S6_OFFSET*R_SZ(a0) STREG s7,S7_OFFSET*R_SZ(a0) + + /* + ** this code grabs the userspace EPC if we're dispatching from + ** an interrupt frame or fakes an address as the EPC if we're + ** not. This is for the gdbstub's benefit so it can know + ** where each thread is running. + ** + ** Its value is only set when calling threadDispatch from + ** the interrupt handler and is cleared immediately when this + ** routine gets it. + */ + + la t0,__exceptionStackFrame /* see if we're coming in from an exception */ + LDREG t1, (t0) + NOP + beqz t1,1f + + STREG zero, (t0) /* and clear it */ + NOP + LDREG t0,R_EPC*R_SZ(t1) /* get the userspace EPC from the frame */ + b 2f + +1: la t0,_Thread_Dispatch /* if ==0, we're switched out */ + +2: STREG t0,C0_EPC_OFFSET*R_SZ(a0) + _CPU_Context_switch_restore: LDREG ra,RA_OFFSET*R_SZ(a1) /* restore context */ @@ -502,6 +532,33 @@ ASM_EXTERN(_Thread_Executing,SZ_INT) .extern _Thread_Dispatch .extern _ISR_Vector_table + + + + +/* void _DBG_Handler() + * + * This routine services the (at least) MIPS1 debug vector, + * only used the the hardware debugging features. This code, + * while optional, is best located here because its intrinsically + * associated with exceptions in general & thus tied pretty + * closely to _ISR_Handler. + * + */ + + +FRAME(_DBG_Handler,sp,0,ra) + .set noreorder + la k0,_ISR_Handler + j k0 + NOP + .set reorder +ENDFRAME(_DBG_Handler) + + + + + /* void __ISR_Handler() * * This routine provides the RTEMS interrupt management. @@ -561,6 +618,7 @@ FRAME(_ISR_Handler,sp,0,ra) STREG gp, R_GP*R_SZ(sp) STREG t0, R_MDHI*R_SZ(sp) STREG fp, R_FP*R_SZ(sp) + .set noat STREG AT, R_AT*R_SZ(sp) .set at @@ -579,16 +637,16 @@ FRAME(_ISR_Handler,sp,0,ra) /* determine if an interrupt generated this exception */ - MFC0 k0,C0_CAUSE + MFC0 t0,C0_CAUSE NOP - and k1,k0,CAUSE_EXCMASK - beq k1, 0, _ISR_Handler_1 + and t1,t0,CAUSE_EXCMASK + beq t1, 0, _ISR_Handler_1 _ISR_Handler_Exception: /* - sw k0,0x8001FF00 + sw t0,0x8001FF00 sw t1,0x8001FF04 */ @@ -600,19 +658,19 @@ _ISR_Handler_Exception: * NOTE: This is the path the debugger stub will take. */ - /* already got k0 = cause in the interrupt test above */ - STREG k0,R_CAUSE*R_SZ(sp) - - STREG sp,SP_OFFSET*R_SZ(sp) /* save sp */ + /* already got t0 = cause in the interrupt test above */ + STREG t0,R_CAUSE*R_SZ(sp) - STREG s0,S0_OFFSET*R_SZ(sp) /* save s0 - s7 */ - STREG s1,S1_OFFSET*R_SZ(sp) - STREG s2,S2_OFFSET*R_SZ(sp) - STREG s3,S3_OFFSET*R_SZ(sp) - STREG s4,S4_OFFSET*R_SZ(sp) - STREG s5,S5_OFFSET*R_SZ(sp) - STREG s6,S6_OFFSET*R_SZ(sp) - STREG s7,S7_OFFSET*R_SZ(sp) + STREG sp, R_SP*R_SZ(sp) + + STREG s0,R_S0*R_SZ(sp) /* save s0 - s7 */ + STREG s1,R_S1*R_SZ(sp) + STREG s2,R_S2*R_SZ(sp) + STREG s3,R_S3*R_SZ(sp) + STREG s4,R_S4*R_SZ(sp) + STREG s5,R_S5*R_SZ(sp) + STREG s6,R_S6*R_SZ(sp) + STREG s7,R_S7*R_SZ(sp) /* CP0 special registers */ @@ -644,24 +702,39 @@ _ISR_Handler_Exception: jal mips_vector_exceptions NOP - /* since we're returning, compute the address of the instruction we'll return to */ + + /* + ** note, if the exception vector returns, rely on it to have + ** adjusted EPC so we will return to some correct address. If + ** this is not done, we might get stuck in an infinite loop because + ** we'll return to the instruction where the exception occured and + ** it could throw again. + ** + ** It is expected the only code using the exception processing is + ** either the gdb stub or some user code which is either going to + ** panic or do something useful. + */ + + +/* ********************************************************************* + * compute the address of the instruction we'll return to * LDREG t1, R_CAUSE*R_SZ(sp) LDREG t0, R_EPC*R_SZ(sp) - /* first see if the exception happened in the delay slot */ + * first see if the exception happened in the delay slot * li t3,CAUSE_BD AND t4,t1,t3 beqz t4,excnodelay NOP - /* it did, now see if the branch occured or not */ + * it did, now see if the branch occured or not * li t3,CAUSE_BT AND t4,t1,t3 beqz t4,excnobranch NOP - /* branch was taken, we resume at the branch target */ + * branch was taken, we resume at the branch target * LDREG t0, R_TAR*R_SZ(sp) j excreturn NOP @@ -675,8 +748,24 @@ excnodelay: excreturn: STREG t0, R_EPC*R_SZ(sp) NOP +********************************************************************* */ + + /* if we're returning into mips_break, move to the next instruction */ + LDREG t0,R_EPC*R_SZ(sp) + la t1,mips_break + xor t2,t0,t1 + bnez t2,3f + + addu t0,R_SZ + STREG t0,R_EPC*R_SZ(sp) + NOP +3: + + + + #if ( CPU_HARDWARE_FP == TRUE ) MFC0 t0,C0_SR /* FPU is enabled, restore state */ NOP @@ -694,14 +783,14 @@ excreturn: MTC1 t1,C1_STATUS 2: #endif - LDREG s0,S0_OFFSET*R_SZ(sp) /* restore s0 - s7 */ - LDREG s1,S1_OFFSET*R_SZ(sp) - LDREG s2,S2_OFFSET*R_SZ(sp) - LDREG s3,S3_OFFSET*R_SZ(sp) - LDREG s4,S4_OFFSET*R_SZ(sp) - LDREG s5,S5_OFFSET*R_SZ(sp) - LDREG s6,S6_OFFSET*R_SZ(sp) - LDREG s7,S7_OFFSET*R_SZ(sp) + LDREG s0,R_S0*R_SZ(sp) /* restore s0 - s7 */ + LDREG s1,R_S1*R_SZ(sp) + LDREG s2,R_S2*R_SZ(sp) + LDREG s3,R_S3*R_SZ(sp) + LDREG s4,R_S4*R_SZ(sp) + LDREG s5,R_S5*R_SZ(sp) + LDREG s6,R_S6*R_SZ(sp) + LDREG s7,R_S7*R_SZ(sp) /* do NOT restore the sp as this could mess up the world */ /* do NOT restore the cause as this could mess up the world */ @@ -711,15 +800,15 @@ excreturn: _ISR_Handler_1: - MFC0 k1,C0_SR - and k0,CAUSE_IPMASK - and k0,k1 + MFC0 t1,C0_SR + and t0,CAUSE_IPMASK + and t0,t1 /* external interrupt not enabled, ignore */ /* but if it's not an exception or an interrupt, */ /* Then where did it come from??? */ - beq k0,zero,_ISR_Handler_exit + beq t0,zero,_ISR_Handler_exit @@ -794,10 +883,6 @@ _ISR_Handler_1: - - - - /* * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) @@ -838,13 +923,23 @@ _ISR_Handler_1: or t0, t1 MTC0 t0, C0_SR NOP - + + /* save off our stack frame so the context switcher can get to it */ + la t0,__exceptionStackFrame + STREG sp,(t0) + jal _Thread_Dispatch NOP + /* and make sure its clear in case we didn't dispatch. if we did, its + ** already cleared */ + la t0,__exceptionStackFrame + STREG zero,(t0) + NOP + /* ** turn interrupts back off while we restore context so -** a badly timed interrupt won't accidentally mess up k0 +** a badly timed interrupt won't accidentally mess things up */ MFC0 t0, C0_SR #if __mips == 3 @@ -888,12 +983,12 @@ _ISR_Handler_exit: sw t0, 0x8001FFFC #endif - LDREG k0, R_MDLO*R_SZ(sp) + LDREG t8, R_MDLO*R_SZ(sp) LDREG t0, R_T0*R_SZ(sp) - mtlo k0 - LDREG k0, R_MDHI*R_SZ(sp) + mtlo t8 + LDREG t8, R_MDHI*R_SZ(sp) LDREG t1, R_T1*R_SZ(sp) - mthi k0 + mthi t8 LDREG t2, R_T2*R_SZ(sp) LDREG t3, R_T3*R_SZ(sp) LDREG t4, R_T4*R_SZ(sp) @@ -912,14 +1007,14 @@ _ISR_Handler_exit: LDREG v1, R_V1*R_SZ(sp) LDREG v0, R_V0*R_SZ(sp) - LDREG k0, R_EPC*R_SZ(sp) + LDREG k1, R_EPC*R_SZ(sp) .set noat LDREG AT, R_AT*R_SZ(sp) .set at ADDIU sp,sp,EXCP_STACK_SIZE - j k0 + j k1 rfe NOP @@ -927,11 +1022,12 @@ _ISR_Handler_exit: ENDFRAME(_ISR_Handler) + - FRAME(mips_break,sp,0,ra) .set noreorder - break 0x0 + break 0x0 /* this statement must be first in this function, assumed so by mips-stub.c */ + NOP j ra NOP .set reorder diff --git a/c/src/exec/score/cpu/mips/idtcpu.h b/c/src/exec/score/cpu/mips/idtcpu.h index 2f450b21b1..3ff31aa8c8 100644 --- a/c/src/exec/score/cpu/mips/idtcpu.h +++ b/c/src/exec/score/cpu/mips/idtcpu.h @@ -58,7 +58,8 @@ LICENSED MATERIAL - PROGRAM PROPERTY OF IDT */ #if __mips == 1 #define UT_VEC K0BASE /* utlbmiss vector */ -#define E_VEC (K0BASE+0x80) /* exception vevtor */ +#define DB_VEC (K0BASE+0x40) /* debug vector */ +#define E_VEC (K0BASE+0x80) /* exception vector */ #elif __mips == 3 #define T_VEC (K0BASE+0x000) /* tlbmiss vector */ #define X_VEC (K0BASE+0x080) /* xtlbmiss vector */ @@ -253,6 +254,32 @@ LICENSED MATERIAL - PROGRAM PROPERTY OF IDT #endif #if __mips == 1 + + +/* definitions for Debug and Cache Invalidate control (DCIC) register bits */ +#define DCIC_TR 0x80000000 /* Trap enable */ +#define DCIC_UD 0x40000000 /* User debug enable */ +#define DCIC_KD 0x20000000 /* Kernel debug enable */ +#define DCIC_TE 0x10000000 /* Trace enable */ +#define DCIC_DW 0x08000000 /* Enable data breakpoints on write */ +#define DCIC_DR 0x04000000 /* Enable data breakpoints on read */ +#define DCIC_DAE 0x02000000 /* Enable data addresss breakpoints */ +#define DCIC_PCE 0x01000000 /* Enable instruction breakpoints */ +#define DCIC_DE 0x00800000 /* Debug enable */ +#define DCIC_DL 0x00008000 /* Data cache line invalidate */ +#define DCIC_IL 0x00004000 /* Instruction cache line invalidate */ +#define DCIC_D 0x00002000 /* Data cache invalidate enable */ +#define DCIC_I 0x00001000 /* Instr. cache invalidate enable */ +#define DCIC_T 0x00000020 /* Trace, set by CPU */ +#define DCIC_W 0x00000010 /* Write reference, set by CPU */ +#define DCIC_R 0x00000008 /* Read reference, set by CPU */ +#define DCIC_DA 0x00000004 /* Data address, set by CPU */ +#define DCIC_PC 0x00000002 /* Program counter, set by CPU */ +#define DCIC_DB 0x00000001 /* Debug, set by CPU */ + + + + #define SR_CUMASK 0xf0000000 /* coproc usable bits */ #define SR_CU3 0x80000000 /* Coprocessor 3 usable */ #define SR_CU2 0x40000000 /* Coprocessor 2 usable */ diff --git a/c/src/exec/score/cpu/mips/rtems/score/cpu.h b/c/src/exec/score/cpu/mips/rtems/score/cpu.h index d2a29ed4f0..ed87991c3c 100644 --- a/c/src/exec/score/cpu/mips/rtems/score/cpu.h +++ b/c/src/exec/score/cpu/mips/rtems/score/cpu.h @@ -385,7 +385,7 @@ typedef struct { __MIPS_REGISTER_TYPE fp; __MIPS_REGISTER_TYPE ra; __MIPS_REGISTER_TYPE c0_sr; -/* __MIPS_REGISTER_TYPE c0_epc; */ + __MIPS_REGISTER_TYPE c0_epc; } Context_Control; /* WARNING: If this structure is modified, the constants in cpu.h diff --git a/c/src/exec/score/cpu/mips/rtems/score/mips.h b/c/src/exec/score/cpu/mips/rtems/score/mips.h index 216e307ff7..ea5a4b545d 100644 --- a/c/src/exec/score/cpu/mips/rtems/score/mips.h +++ b/c/src/exec/score/cpu/mips/rtems/score/mips.h @@ -140,6 +140,78 @@ extern "C" { } while (0) + + +/* + * Access the Debug Cache Invalidate Control register + */ + +#define mips_get_dcic( _x ) \ + do { \ + asm volatile( "mfc0 %0, $7; nop" : "=r" (_x) : ); \ + } while (0) + + +#define mips_set_dcic( _x ) \ + do { \ + register unsigned int __x = (_x); \ + asm volatile( "mtc0 %0, $7; nop" : : "r" (__x) ); \ + } while (0) + + + + +/* + * Access the Breakpoint Program Counter & Mask registers + * (_x for BPC, _y for mask) + */ + +#define mips_get_bpcrm( _x, _y ) \ + do { \ + asm volatile( "mfc0 %0, $3; nop" : "=r" (_x) : ); \ + asm volatile( "mfc0 %0, $11; nop" : "=r" (_y) : ); \ + } while (0) + + +#define mips_set_bpcrm( _x, _y ) \ + do { \ + register unsigned int __x = (_x); \ + register unsigned int __y = (_y); \ + asm volatile( "mtc0 %0, $11; nop" : : "r" (__y) ); \ + asm volatile( "mtc0 %0, $3; nop" : : "r" (__x) ); \ + } while (0) + + + + + + +/* + * Access the Breakpoint Data Address & Mask registers + * (_x for BDA, _y for mask) + */ + +#define mips_get_bdarm( _x, _y ) \ + do { \ + asm volatile( "mfc0 %0, $5; nop" : "=r" (_x) : ); \ + asm volatile( "mfc0 %0, $9; nop" : "=r" (_y) : ); \ + } while (0) + + +#define mips_set_bdarm( _x, _y ) \ + do { \ + register unsigned int __x = (_x); \ + register unsigned int __y = (_y); \ + asm volatile( "mtc0 %0, $9; nop" : : "r" (__y) ); \ + asm volatile( "mtc0 %0, $5; nop" : : "r" (__x) ); \ + } while (0) + + + + + + + /* * Access FCR31 */ -- cgit v1.2.3