forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user