mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-10-06 10:59:48 +08:00
bsps/mips: Report an exception as one
An exception which no handler consumed ended in rtems_fatal_error_occurred(1), which is INTERNAL_ERROR_RTEMS_API, where every other port reports RTEMS_FATAL_SOURCE_EXCEPTION with the exception frame as the code. A fatal error extension cannot recognise the former, so a test which expects an exception and returns from its extension with longjmp() could not resume. That pattern is how tc-compiler-builtins.c checks the break which the compiler emits for a division by zero, and it stopped ts-unit-no-clock-0. The exception vectors are dispatched like interrupt vectors and the GDB stub installs handlers on several of them, so the dispatch stays and the frame of the exception being vectored is published for the default handler to recognise. Report a vector without a frame as a spurious interrupt, which is what the shared default handler does. Do not print here. The fatal error extension prints the frame when the system really terminates, so a recovered exception stays silent instead of writing two lines into the test output on every recovery. The cause table moves next to _CPU_Exception_frame_print(), which gains the cause of the exception it prints. Update #5691. Assisted-by: Claude:claude-opus-5 claude-code Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
committed by
Joel Sherrill
parent
b28d2837a5
commit
7ec23f42d6
@@ -39,6 +39,11 @@
|
||||
extern void mips_install_isr_entries( void );
|
||||
extern void mips_vector_isr_handlers( CPU_Interrupt_frame *frame );
|
||||
|
||||
/*
|
||||
* The frame of the exception being vectored, or NULL outside such a vector.
|
||||
*/
|
||||
extern CPU_Exception_frame *mips_exception_frame;
|
||||
|
||||
#if __mips == 1
|
||||
extern void exc_utlb_code(void);
|
||||
extern void exc_dbg_code(void);
|
||||
|
||||
+16
-50
@@ -36,48 +36,12 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp/irq-generic.h>
|
||||
#include <libcpu/isr_entries.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
static const char *const cause_strings[32] = {
|
||||
/* 0 */ "Int",
|
||||
/* 1 */ "TLB Mods",
|
||||
/* 2 */ "TLB Load",
|
||||
/* 3 */ "TLB Store",
|
||||
/* 4 */ "Address Load",
|
||||
/* 5 */ "Address Store",
|
||||
/* 6 */ "Instruction Bus Error",
|
||||
/* 7 */ "Data Bus Error",
|
||||
/* 8 */ "Syscall",
|
||||
/* 9 */ "Breakpoint",
|
||||
/* 10 */ "Reserved Instruction",
|
||||
/* 11 */ "Coprocessor Unuseable",
|
||||
/* 12 */ "Overflow",
|
||||
/* 13 */ "Trap",
|
||||
/* 14 */ "Instruction Virtual Coherency Error",
|
||||
/* 15 */ "FP Exception",
|
||||
/* 16 */ "Reserved 16",
|
||||
/* 17 */ "Reserved 17",
|
||||
/* 18 */ "Reserved 18",
|
||||
/* 19 */ "Reserved 19",
|
||||
/* 20 */ "Reserved 20",
|
||||
/* 21 */ "Reserved 21",
|
||||
/* 22 */ "Reserved 22",
|
||||
/* 23 */ "Watch",
|
||||
/* 24 */ "Reserved 24",
|
||||
/* 25 */ "Reserved 25",
|
||||
/* 26 */ "Reserved 26",
|
||||
/* 27 */ "Reserved 27",
|
||||
/* 28 */ "Reserved 28",
|
||||
/* 29 */ "Reserved 29",
|
||||
/* 30 */ "Reserved 30",
|
||||
/* 31 */ "Data Virtual Coherency Error"
|
||||
};
|
||||
#include <rtems/fatal.h>
|
||||
#include <rtems/score/interr.h>
|
||||
|
||||
static inline bool bsp_irq_is_valid(rtems_vector_number vector)
|
||||
{
|
||||
@@ -185,17 +149,19 @@ void bsp_interrupt_facility_initialize(void)
|
||||
|
||||
void bsp_interrupt_handler_default(rtems_vector_number vector)
|
||||
{
|
||||
uint32_t sr;
|
||||
uint32_t cause;
|
||||
/*
|
||||
* An exception which no handler consumed is reported with the source and
|
||||
* the argument every other port uses, so that a fatal error extension can
|
||||
* recognise it and, where the exception is expected, resume with a
|
||||
* longjmp(). Do not report it here: the extension prints the frame if the
|
||||
* system really terminates.
|
||||
*/
|
||||
if ( mips_exception_frame != NULL ) {
|
||||
rtems_fatal(
|
||||
RTEMS_FATAL_SOURCE_EXCEPTION,
|
||||
(rtems_fatal_code) mips_exception_frame
|
||||
);
|
||||
}
|
||||
|
||||
mips_get_sr( sr );
|
||||
mips_get_cause( cause );
|
||||
|
||||
printk( "Unhandled exception %" PRId32 "\n", vector );
|
||||
printk( "sr: 0x%08" PRIu32 " cause: 0x%08" PRIu32 " --> %s\n", sr, cause,
|
||||
cause_strings[(cause >> 2) &0x1f] );
|
||||
#if 0
|
||||
mips_dump_exception_frame( frame );
|
||||
#endif
|
||||
rtems_fatal_error_occurred(1);
|
||||
_Terminate( RTEMS_FATAL_SOURCE_SPURIOUS_INTERRUPT, vector );
|
||||
}
|
||||
|
||||
@@ -50,6 +50,41 @@ struct regdef
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const char *const cause_strings[32] = {
|
||||
/* 0 */ "Int",
|
||||
/* 1 */ "TLB Mods",
|
||||
/* 2 */ "TLB Load",
|
||||
/* 3 */ "TLB Store",
|
||||
/* 4 */ "Address Load",
|
||||
/* 5 */ "Address Store",
|
||||
/* 6 */ "Instruction Bus Error",
|
||||
/* 7 */ "Data Bus Error",
|
||||
/* 8 */ "Syscall",
|
||||
/* 9 */ "Breakpoint",
|
||||
/* 10 */ "Reserved Instruction",
|
||||
/* 11 */ "Coprocessor Unuseable",
|
||||
/* 12 */ "Overflow",
|
||||
/* 13 */ "Trap",
|
||||
/* 14 */ "Instruction Virtual Coherency Error",
|
||||
/* 15 */ "FP Exception",
|
||||
/* 16 */ "Reserved 16",
|
||||
/* 17 */ "Reserved 17",
|
||||
/* 18 */ "Reserved 18",
|
||||
/* 19 */ "Reserved 19",
|
||||
/* 20 */ "Reserved 20",
|
||||
/* 21 */ "Reserved 21",
|
||||
/* 22 */ "Reserved 22",
|
||||
/* 23 */ "Watch",
|
||||
/* 24 */ "Reserved 24",
|
||||
/* 25 */ "Reserved 25",
|
||||
/* 26 */ "Reserved 26",
|
||||
/* 27 */ "Reserved 27",
|
||||
/* 28 */ "Reserved 28",
|
||||
/* 29 */ "Reserved 29",
|
||||
/* 30 */ "Reserved 30",
|
||||
/* 31 */ "Data Virtual Coherency Error"
|
||||
};
|
||||
|
||||
static const struct regdef dumpregs[]= {
|
||||
{ R_RA, "R_RA" }, { R_V0, "R_V0" }, { R_V1, "R_V1" },
|
||||
{ R_A0, "R_A0" }, { R_A1, "R_A1" }, { R_A2, "R_A2" },
|
||||
@@ -67,6 +102,12 @@ void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
|
||||
int i;
|
||||
size_t j;
|
||||
|
||||
printk(
|
||||
" CAUSE %08" PRIx32 " --> %s\n",
|
||||
(uint32_t) frame->cause,
|
||||
cause_strings[ ( (uint32_t) frame->cause >> 2 ) & 0x1f ]
|
||||
);
|
||||
|
||||
frame_u32 = (uint32_t *)frame;
|
||||
for(i=0; dumpregs[i].offset > -1; i++)
|
||||
{
|
||||
@@ -89,6 +130,13 @@ void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
|
||||
* all be close to the same set.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The frame of the exception being vectored, or NULL outside such a vector.
|
||||
* bsp_interrupt_handler_default() uses it to tell an exception which no
|
||||
* handler consumed from a spurious interrupt.
|
||||
*/
|
||||
CPU_Exception_frame *mips_exception_frame;
|
||||
|
||||
void mips_vector_exceptions( CPU_Interrupt_frame *frame )
|
||||
{
|
||||
(void) frame;
|
||||
@@ -99,5 +147,7 @@ void mips_vector_exceptions( CPU_Interrupt_frame *frame )
|
||||
mips_get_cause( cause );
|
||||
exc = (cause >> 2) & 0x1f;
|
||||
|
||||
mips_exception_frame = frame;
|
||||
bsp_interrupt_handler_dispatch( exc );
|
||||
mips_exception_frame = NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user