📄 excep.c
字号:
if( !nmi )
{
/* CAUSE does not make sense for NMI, since the reset code,
* which is excecuted upon an NMI, changes CAUSE.
*/
printf("CAUSE = 0x%08x ", (UINT32)context->cp0_cause );
}
printf("STATUS = 0x%08x\n", (UINT32)context->cp0_status );
printf("EPC = 0x%08x%08x ERROREPC = 0x%08x%08x\n",
HI32(context->cp0_epc),
LO32(context->cp0_epc),
HI32(context->cp0_errorepc),
LO32(context->cp0_errorepc) );
printf("BADVADDR = 0x%08x%08x\n",
HI32(context->cp0_badvaddr),
LO32(context->cp0_badvaddr) );
if( EXCEP_ejtag )
{
printf("DEBUG = 0x%08x%08x DEPC = 0x%08x%08x\n",
HI32(context->cp0_debug),
LO32(context->cp0_debug),
HI32(context->cp0_depc),
LO32(context->cp0_depc) );
}
}
else
{
if( !nmi )
{
/* CAUSE does not make sense for NMI, since the reset code,
* which is excecuted upon an NMI, changes CAUSE.
*/
printf("CAUSE = 0x%08x ", (UINT32)context->cp0_cause );
}
printf("STATUS = 0x%08x\n", (UINT32)context->cp0_status );
printf("EPC = 0x%08x ERROREPC = 0x%08x\n",
(UINT32)context->cp0_epc,
(UINT32)context->cp0_errorepc );
printf("BADVADDR = 0x%08x\n", (UINT32)context->cp0_badvaddr );
if( EXCEP_ejtag )
{
printf("DEBUG = 0x%08x DEPC = 0x%08x\n",
(UINT32)context->cp0_debug,
(UINT32)context->cp0_depc );
}
}
printf( "\n" );
regs = (UINT64 *)&context->reg0;
for(i=0; i<REG_NAMES_COUNT; i++)
{
if( sys_64bit )
{
j = ((i & 1) << 4) + (i >> 1);
reg64 = regs[j];
printf("$%2d(%s):0x%08x%08x%s", j, reg_names[j],
HI32(reg64), LO32(reg64),
(i & 1) == 1 ? "\n" : " ");
}
else
{
j = ((i & 3) << 3) + (i >> 2);
printf("$%2d(%s):0x%08x%s", j, reg_names[j], (UINT32)regs[j],
(i & 3) == 3 ? "\n" : " ");
}
}
if( nmi )
while(1);
}
/************************************************************************
* Implementation : Static functions
************************************************************************/
/************************************************************************
*
* exception_sr
* Description :
* -------------
*
* This function implements the exception handler, which gets called
* by the first-level exception handler. According to the parameter
* 'exc_code', any user registered exception handler for the asserted
* exception, will be called from this function.
*
* Parameters :
* ------------
*
* exc_code the exception code from the 5-bit ExcCode-field in
* the CP0-status register.
*
* Return values :
* ---------------
*
* None
*
************************************************************************/
static void
exception_sr(
UINT32 exc_code,
bool ejtag )
{
t_EXCEP_handler *reg_esr;
bool default_handling;
t_EXCEP_handler int_esr;
bool nmi;
EXCEP_ejtag = ejtag;
/* First check for NMI */
if( SYSCON_read( SYSCON_BOARD_NMI_STATUS_ID,
(void *)&nmi,
sizeof(bool) ) == OK )
{
if( nmi )
{
default_handler( NULL );
}
}
if( ejtag )
{
reg_esr = &table.ejtag;
}
else if( exc_code < MAX_EXCEPTIONS )
{
reg_esr = &table.exception[exc_code];
}
else
reg_esr = NULL;
default_handling =
( (reg_esr == NULL) || (reg_esr->handler == NULL) ) ?
TRUE : FALSE;
if( EXCEP_return_flag )
{
/* A registered exception handler was invoked for this
* exception, but it called EXCEP_return().
* This means that it does not want to handle the exception,
* so we must handle it.
*
* Case 1 : If the exception handler was the ESR registered
* for interrupts, we assume an application has
* registered an ESR for the interrupt exception.
* So, we call the ESR, which is used by YAMON
* for handling interrupt exceptions, i.e.
* interrupt_sr().
*
* Case 2 : If the exception handler was a specific one,
* other than interrupt, we try default handling.
*
* Case 3 : If the exception handler was the default ESR,
* we must call default_handler().
*/
if( exc_code == C0_CAUSE_CODE_INT )
{
/* Case 1 */
int_esr.handler = interrupt_sr;
int_esr.raw = FALSE;
reg_esr = &int_esr;
}
else if( !default_handling )
{
/* Case 2 */
default_handling = TRUE;
}
else
{
/* Case 3 */
default_handler( NULL );
}
}
if( default_handling )
{
/* Either EXCEP_return() was called (se above), or
* there is no registered ESR for the specific exception.
* Check if there is a registered default ESR.
*/
reg_esr = &table.default_exception;
if( reg_esr->handler == NULL )
{
/* No default ESR has been registered, so call our own
* (never returns).
*/
default_handler( NULL );
}
}
if( reg_esr->raw )
EXCEP_exc_handler_jump( reg_esr->handler );
else
reg_esr->handler();
}
/************************************************************************
*
* interrupt_sr
* Description :
* -------------
*
* This function implements the CPU interrupt handler, which is
* registered for the interrupt exception.
*
* Return values :
* ---------------
*
* None
*
************************************************************************/
static void
interrupt_sr( void )
{
UINT32 h, i, count, index;
bool old_EXCEP_ejtag;
UINT32 int_pending;
t_EXCEP_int_handler_list *table_interrupt;
t_INT_handler *int_handler;
interrupt_context = TRUE;
/* Determine the pending interrupts based on CAUSE register IP field
* masked with STATUS register IM (Interrupt mask) field.
*/
int_pending = REGFIELD( EXCEP_gdb_regs.cp0_cause, C0_CAUSE_IP ) &
REGFIELD( EXCEP_gdb_regs.cp0_status, C0_STATUS_IM );
/* Save old setting of EXCEP_ejtag and set EXCEP_ejtag to FALSE.
* This way, if EXCEP_print_context is called due to this
* interrupt, it will be know that we are not handling an
* ejtag exception.
* Before this function returns, EXCEP_ejtag value is restored
* since EXCEP_ejtag must indicate whether the last "non-interrupt"
* exception was an EJTAG exception.
*/
old_EXCEP_ejtag = EXCEP_ejtag;
EXCEP_ejtag = FALSE;
/* validate 'int_pending' */
if(int_pending <= (C0_CAUSE_IP_MSK >> C0_CAUSE_IP_SHF) )
{
/* Handle the 8 possible interrupts: 0..7 */
/* Calculate how many interrupts are pending */
count = EXCEP_set_to_list[int_pending].list_size;
/* do call handlers for all pending interrupts ('count') */
for( i = 0; i < count; i++)
{
/* Handle the interrupts in a sequence, controlled
* by the EXCEP_set_to_list-table.
*/
index = EXCEP_set_to_list[int_pending].index[i];
/* Now, use the derived index to call into the
* handler table (index = interrupt line).
*/
table_interrupt = &table.interrupt[index];
if( table_interrupt->list_size == 0 )
{
/* No registered handler, so use default */
if( table.default_int.handler )
{
/* A default handler has been registered, so call it */
table.default_int.handler(table.default_int.data);
}
else
{
/* No default handler has been registered, so call our own */
default_handler( "Unregistered CPU interrupt occurred" );
}
}
else
{
/* For one int. line, more handlers may be registered */
for( h=0; h < INT_HANDLERS_PER_LINE; h++)
{
int_handler = &table_interrupt->int_handler[h];
if( int_handler->handler != NULL)
(*int_handler->handler)(int_handler->data);
}
}
}
}
else
{
/* Should not happen */
while(1);
}
/* Restore setting of EXCEP_ejtag (see comment above) */
EXCEP_ejtag = old_EXCEP_ejtag;
interrupt_context = FALSE;
}
/************************************************************************
*
* controller_sr
* Description :
* -------------
*
* This function implements the generic interrupt handler for the
* interrupt controller. It gets called by the second-level
* interrupt handler (interrupt_sr), when the HW-INT-line of
* the interrupt controller is asserted.
*
* Return values :
* ---------------
*
* None
*
************************************************************************/
static void
controller_sr(
void *data ) /* Data pointer set during registration (NULL) */
{
UINT32 pending, mask, int_set;
UINT32 h, i, j, count, index;
char msg[80];
/* get the pending controller interrupts */
while( (pending = arch_excep_pending()) != 0)
{
mask = pending;
/* handle the max. int. sources in rounds of 8 */
j = 0;
while( j<MAX_IC )
{
/* select this round's max. 8 int. sources */
int_set = (pending & 0x000000ff);
/* check for any set */
if(int_set)
{
/* calculate how many interrupts are pending */
count = EXCEP_set_to_list[int_set].list_size;
/* do call handlers for all pending interrupts ('count') */
for( i = 0; i < count; i++)
{
/* Handle the interrupts in a sequence, controlled
* by the EXCEP_set_to_list-table.
*/
index = EXCEP_set_to_list[int_set].index[i];
/* index + j == interrupt line */
/* Now, use the derived index to call into the
* handler table.
*/
if( table.controller[index+j].list_size == 0 )
{
/* No registered handler, so use default */
if( table.default_ctrl.handler )
{
/* A default handler has been registered, so call it */
table.default_ctrl.handler(table.default_int.data);
}
else
{
/* No default handler has been registered, so call our own */
sprintf( msg, "Unregistered interrupt controller event occurred,"
" mask = 0x%08x", mask );
default_handler( msg );
}
}
else
{
for( h=0; h < CTRL_HANDLERS_PER_LINE; h++)
{
/* For one int. line, more handlers may be registered */
if(table.controller[index+j].ctrl_handler[h].handler != NULL)
{
/* call the handlers in sequence */
(*table.controller[index+j].ctrl_handler[h].handler)
(table.controller[index+j].ctrl_handler[h].data);
}
}
}
/* Issue End Of Interrupt (EOI) */
arch_excep_eoi(index+j);
}
}
pending /= 256;
j += 8;
}
}
}
/************************************************************************
*
* default_handler
* Description :
* -------------
*
* Default exception handler
*
************************************************************************/
static void
default_handler(
char *msg )
{
/* Print context */
EXCEP_print_context( &EXCEP_gdb_regs, msg, FALSE, TRUE );
/* loop forever */
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -