* 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.
This commit is contained in:
Joel Sherrill
2002-03-08 16:24:48 +00:00
parent 9f9871f81e
commit 8264d230a9
13 changed files with 564 additions and 99 deletions

View File

@@ -1,3 +1,15 @@
2002-03-05 Greg Menke <gregory.menke@gsfc.nasa.gov>
* 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 <gregory.menke@gsfc.nasa.gov>
* cpu_asm.S: Fixed exception return address, modified FP context

View File

@@ -47,6 +47,18 @@
#include <rtems/score/wkspace.h>
/*
** 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.

View File

@@ -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)
/* already got t0 = cause in the interrupt test above */
STREG t0,R_CAUSE*R_SZ(sp)
STREG sp,SP_OFFSET*R_SZ(sp) /* save 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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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
*/