[rtems commit] sparc: More reliable bad trap handling

Sebastian Huber sebh at rtems.org
Thu Jun 24 10:29:28 UTC 2021


Module:    rtems
Branch:    master
Commit:    d73e657e063e3d34db16fa4bce6c2ab1e5e22ec4
Changeset: http://git.rtems.org/rtems/commit/?id=d73e657e063e3d34db16fa4bce6c2ab1e5e22ec4

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Jun 21 11:24:27 2021 +0200

sparc: More reliable bad trap handling

Statically initialize the trap table in start.S to jump to _SPARC_Bad_trap()
for all unexpected traps.  This enables a proper RTEMS fatal error handling
right from the start.  Do not rely on the stack and register settings which
caused an unexpected trap.  Use the ISR stack of the processor to do the fatal
error handling.  Save the full context which caused the trap.  Fatal error
handler may use it for error logging.

Unify the _CPU_Exception_frame_print() implementations and move it to cpukit.

Update #4459.

---

 bsps/sparc/erc32/include/bsp.h                     |   2 -
 bsps/sparc/erc32/start/bspstart.c                  |   2 -
 bsps/sparc/erc32/start/spurious.c                  | 194 -----------------
 bsps/sparc/leon2/include/bsp.h                     |   2 -
 bsps/sparc/leon2/start/bspstart.c                  |   2 -
 bsps/sparc/leon2/start/spurious.c                  | 184 ----------------
 bsps/sparc/leon3/include/bsp.h                     |   2 -
 bsps/sparc/leon3/start/bspstart.c                  |   2 -
 bsps/sparc/leon3/start/spurious.c                  | 183 ----------------
 bsps/sparc/shared/start/start.S                    |   7 +-
 c/src/lib/libbsp/sparc/erc32/Makefile.am           |   1 -
 c/src/lib/libbsp/sparc/leon2/Makefile.am           |   1 -
 c/src/lib/libbsp/sparc/leon3/Makefile.am           |   1 -
 cpukit/Makefile.am                                 |   2 +
 cpukit/score/cpu/sparc/cpu.c                       |  51 +++++
 cpukit/score/cpu/sparc/include/rtems/score/cpu.h   |  53 ++++-
 .../score/cpu/sparc/include/rtems/score/cpuimpl.h  |  22 ++
 cpukit/score/cpu/sparc/sparc-bad-trap.S            | 231 +++++++++++++++++++++
 .../score/cpu/sparc/sparc-exception-frame-print.c  | 157 ++++++++++++++
 spec/build/bsps/sparc/erc32/bsperc32.yml           |   1 -
 spec/build/bsps/sparc/leon2/obj.yml                |   1 -
 spec/build/bsps/sparc/leon3/obj.yml                |   1 -
 spec/build/cpukit/cpusparc.yml                     |   2 +
 23 files changed, 519 insertions(+), 585 deletions(-)

diff --git a/bsps/sparc/erc32/include/bsp.h b/bsps/sparc/erc32/include/bsp.h
index 6347c58..300202b 100644
--- a/bsps/sparc/erc32/include/bsp.h
+++ b/bsps/sparc/erc32/include/bsp.h
@@ -90,8 +90,6 @@ rtems_isr_entry set_vector(                     /* returns old vector */
 
 void BSP_fatal_exit(uint32_t error);
 
-void bsp_spurious_initialize( void );
-
 /* Interrupt Service Routine (ISR) pointer */
 typedef void (*bsp_shared_isr)(void *arg);
 
diff --git a/bsps/sparc/erc32/start/bspstart.c b/bsps/sparc/erc32/start/bspstart.c
index 80447b9..d56d3b2 100644
--- a/bsps/sparc/erc32/start/bspstart.c
+++ b/bsps/sparc/erc32/start/bspstart.c
@@ -20,8 +20,6 @@
  */
 static void erc32_pre_driver_hook( void )
 {
-  bsp_spurious_initialize();
-
   /* Initialize shared interrupt handling, must be done after IRQ
    * controller has been found and initialized.
    */
diff --git a/bsps/sparc/erc32/start/spurious.c b/bsps/sparc/erc32/start/spurious.c
deleted file mode 100644
index b022f96..0000000
--- a/bsps/sparc/erc32/start/spurious.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *  ERC32 Spurious Trap Handler
- *
- *  This is just enough of a trap handler to let us know what
- *  the likely source of the trap was.
- *
- *  Developed as part of the port of RTEMS to the ERC32 implementation
- *  of the SPARC by On-Line Applications Research Corporation (OAR)
- *  under contract to the European Space Agency (ESA).
- *
- *  COPYRIGHT (c) 1995. European Space Agency.
- *
- *  This terms of the RTEMS license apply to this file.
- */
-
-#include <bsp.h>
-#include <rtems/bspIo.h>
-#include <inttypes.h>
-
-void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
-{
-  uint32_t                   trap;
-  uint32_t                   real_trap;
-  const CPU_Interrupt_frame *isf;
-
-  trap = frame->trap;
-  real_trap = SPARC_REAL_TRAP_NUMBER(trap);
-  isf = frame->isf;
-
-  printk(
-    "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n",
-    real_trap,
-    isf->tpc
-  );
-
-  switch (real_trap) {
-
-    /*
-     *  First the ones defined by the basic architecture
-     */
-
-    case 0x00:
-      printk( "reset\n" );
-      break;
-    case 0x01:
-      printk( "instruction access exception\n" );
-      break;
-    case 0x02:
-      printk( "illegal instruction\n" );
-      break;
-    case 0x03:
-      printk( "privileged instruction\n" );
-      break;
-    case 0x04:
-      printk( "fp disabled\n" );
-      break;
-    case 0x07:
-      printk( "memory address not aligned\n" );
-      break;
-    case 0x08:
-      printk( "fp exception\n" );
-      break;
-    case 0x09:
-      printk("data access exception at 0x%08" PRIx32 "\n",
-        ERC32_MEC.First_Failing_Address );
-      break;
-    case 0x0A:
-      printk( "tag overflow\n" );
-      break;
-
-    /*
-     *  Then the ones defined by the ERC32 in particular
-     */
-
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ):
-      printk( "ERC32_INTERRUPT_MASKED_ERRORS\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_1 ):
-      printk( "ERC32_INTERRUPT_EXTERNAL_1\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_2 ):
-      printk( "ERC32_INTERRUPT_EXTERNAL_2\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX ):
-      printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX ):
-      printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR ):
-      printk( "ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_ERROR ):
-      printk( "ERC32_INTERRUPT_UART_ERROR\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_ACCESS_ERROR ):
-      printk( "ERC32_INTERRUPT_DMA_ACCESS_ERROR\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_TIMEOUT ):
-      printk( "ERC32_INTERRUPT_DMA_TIMEOUT\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_3 ):
-      printk( "ERC32_INTERRUPT_EXTERNAL_3\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_4 ):
-      printk( "ERC32_INTERRUPT_EXTERNAL_4\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER ):
-      printk( "ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ):
-      printk( "ERC32_INTERRUPT_REAL_TIME_CLOCK\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_5 ):
-      printk( "ERC32_INTERRUPT_EXTERNAL_5\n" );
-      break;
-    case ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ):
-      printk( "ERC32_INTERRUPT_WATCHDOG_TIMEOUT\n" );
-      break;
-
-    default:
-      break;
-  }
-}
-
-static rtems_isr bsp_spurious_handler(
-   rtems_vector_number trap,
-   CPU_Interrupt_frame *isf
-)
-{
-  CPU_Exception_frame frame = {
-    .trap = trap,
-    .isf = isf
-  };
-
-#if !defined(SPARC_USE_LAZY_FP_SWITCH)
-  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
-    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
-  }
-#endif
-
-  rtems_fatal(
-    RTEMS_FATAL_SOURCE_EXCEPTION,
-    (rtems_fatal_code) &frame
-  );
-}
-
-/*
- *  bsp_spurious_initialize
- *
- *  Install the spurious handler for most traps. Note that set_vector()
- *  will unmask the corresponding asynchronous interrupt, so the initial
- *  interrupt mask is restored after the handlers are installed.
- */
-
-void bsp_spurious_initialize()
-{
-  uint32_t   trap;
-  uint32_t   level = 15;
-  uint32_t   mask;
-
-  level = sparc_disable_interrupts();
-  mask = ERC32_MEC.Interrupt_Mask;
-
-  for ( trap=0 ; trap<256 ; trap++ ) {
-
-    /*
-     *  Skip window overflow, underflow, and flush as well as software
-     *  trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable.
-     *  Also avoid trap 0x70 - 0x7f which cannot happen and where some of the
-     *  space is used to pass parameters to the program.
-     */
-
-    if (( trap == 5 || trap == 6 ) ||
-#if defined(SPARC_USE_LAZY_FP_SWITCH)
-        ( trap == 4 ) ||
-#endif
-        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
-        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
-#endif
-        ( trap == 0x80 + SPARC_SWTRAP_IRQEN ))
-      continue;
-
-    set_vector( (rtems_isr_entry) bsp_spurious_handler,
-         SPARC_SYNCHRONOUS_TRAP( trap ), 1 );
-  }
-
-  ERC32_MEC.Interrupt_Mask = mask;
-  sparc_enable_interrupts(level);
-
-}
diff --git a/bsps/sparc/leon2/include/bsp.h b/bsps/sparc/leon2/include/bsp.h
index 5fe39d0..f97d78b 100644
--- a/bsps/sparc/leon2/include/bsp.h
+++ b/bsps/sparc/leon2/include/bsp.h
@@ -114,8 +114,6 @@ rtems_isr_entry set_vector(                     /* returns old vector */
 
 void BSP_fatal_exit(uint32_t error);
 
-void bsp_spurious_initialize( void );
-
 /* Interrupt Service Routine (ISR) pointer */
 typedef void (*bsp_shared_isr)(void *arg);
 
diff --git a/bsps/sparc/leon2/start/bspstart.c b/bsps/sparc/leon2/start/bspstart.c
index e3b9141..8ffd0aa 100644
--- a/bsps/sparc/leon2/start/bspstart.c
+++ b/bsps/sparc/leon2/start/bspstart.c
@@ -108,8 +108,6 @@ struct drvmgr_bus_res leon2_amba_res __attribute__((weak)) =
  */
 static void leon2_pre_driver_hook( void )
 {
-  bsp_spurious_initialize();
-
   /* Initialize shared interrupt handling, must be done after IRQ
    * controller has been found and initialized.
    */
diff --git a/bsps/sparc/leon2/start/spurious.c b/bsps/sparc/leon2/start/spurious.c
deleted file mode 100644
index 0d5fb16..0000000
--- a/bsps/sparc/leon2/start/spurious.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * @file
- * @ingroup RTEMSBSPsSPARCLEON2
- * @brief LEON Spurious Trap Handler
- */
-
-/*
- *  LEON Spurious Trap Handler
- *
- *  This is just enough of a trap handler to let us know what
- *  the likely source of the trap was.
- *
- *  Developed as part of the port of RTEMS to the LEON implementation
- *  of the SPARC by On-Line Applications Research Corporation (OAR)
- *  under contract to the European Space Agency (ESA).
- *
- *  COPYRIGHT (c) 1995. European Space Agency.
- *
- *  This terms of the RTEMS license apply to this file.
- */
-
-#include <bsp.h>
-#include <rtems/bspIo.h>
-#include <inttypes.h>
-
-void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
-{
-  uint32_t                   trap;
-  uint32_t                   real_trap;
-  const CPU_Interrupt_frame *isf;
-
-  trap = frame->trap;
-  real_trap = SPARC_REAL_TRAP_NUMBER(trap);
-  isf = frame->isf;
-
-  printk(
-    "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n",
-    real_trap,
-    isf->tpc
-  );
-
-  switch (real_trap) {
-
-    /*
-     *  First the ones defined by the basic architecture
-     */
-
-    case 0x00:
-      printk( "reset\n" );
-      break;
-    case 0x01:
-      printk( "instruction access exception\n" );
-      break;
-    case 0x02:
-      printk( "illegal instruction\n" );
-      break;
-    case 0x03:
-      printk( "privileged instruction\n" );
-      break;
-    case 0x04:
-      printk( "fp disabled\n" );
-      break;
-    case 0x07:
-      printk( "memory address not aligned\n" );
-      break;
-    case 0x08:
-      printk( "fp exception\n" );
-      break;
-    case 0x09:
-      printk("data access exception at 0x%08x\n", LEON_REG.Failed_Address );
-      break;
-    case 0x0A:
-      printk( "tag overflow\n" );
-      break;
-
-    /*
-     *  Then the ones defined by the LEON in particular
-     */
-
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ):
-      printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ):
-      printk( "LEON_INTERRUPT_UART_2_RX_TX\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ):
-      printk( "LEON_INTERRUPT_UART_1_RX_TX\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_0\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_1\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_2\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_3\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ):
-      printk( "LEON_INTERRUPT_TIMER1\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ):
-      printk( "LEON_INTERRUPT_TIMER2\n" );
-      break;
-
-    default:
-      break;
-  }
-}
-
-static rtems_isr bsp_spurious_handler(
-   rtems_vector_number trap,
-   CPU_Interrupt_frame *isf
-)
-{
-  CPU_Exception_frame frame = {
-    .trap = trap,
-    .isf = isf
-  };
-
-#if !defined(SPARC_USE_LAZY_FP_SWITCH)
-  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
-    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
-  }
-#endif
-
-  rtems_fatal(
-    RTEMS_FATAL_SOURCE_EXCEPTION,
-    (rtems_fatal_code) &frame
-  );
-}
-
-/*
- *  bsp_spurious_initialize
- *
- *  Install the spurious handler for most traps. Note that set_vector()
- *  will unmask the corresponding asynchronous interrupt, so the initial
- *  interrupt mask is restored after the handlers are installed.
- */
-
-void bsp_spurious_initialize()
-{
-  uint32_t trap;
-  uint32_t level;
-  uint32_t mask;
-
-  level = sparc_disable_interrupts();
-  mask = LEON_REG.Interrupt_Mask;
-
-  for ( trap=0 ; trap<256 ; trap++ ) {
-
-    /*
-     *  Skip window overflow, underflow, and flush as well as software
-     *  trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable.
-     *  Also avoid trap 0x70 - 0x7f which cannot happen and where some of the
-     *  space is used to pass parameters to the program.
-     */
-
-    if (( trap == 5 || trap == 6 ) ||
-#if defined(SPARC_USE_LAZY_FP_SWITCH)
-        ( trap == 4 ) ||
-#endif
-        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
-        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
-#endif
-        ( trap == 0x80 + SPARC_SWTRAP_IRQEN ))
-      continue;
-
-    set_vector(
-        (rtems_isr_entry) bsp_spurious_handler,
-        SPARC_SYNCHRONOUS_TRAP( trap ),
-        1
-    );
-  }
-
-  LEON_REG.Interrupt_Mask = mask;
-  sparc_enable_interrupts(level);
-
-}
diff --git a/bsps/sparc/leon3/include/bsp.h b/bsps/sparc/leon3/include/bsp.h
index 85730b5..6a96b91 100644
--- a/bsps/sparc/leon3/include/bsp.h
+++ b/bsps/sparc/leon3/include/bsp.h
@@ -129,8 +129,6 @@ rtems_isr_entry set_vector(                     /* returns old vector */
 
 void BSP_fatal_exit(uint32_t error);
 
-void bsp_spurious_initialize( void );
-
 /*
  *  Delay for the specified number of microseconds.
  */
diff --git a/bsps/sparc/leon3/start/bspstart.c b/bsps/sparc/leon3/start/bspstart.c
index e4c3f10..69ff519 100644
--- a/bsps/sparc/leon3/start/bspstart.c
+++ b/bsps/sparc/leon3/start/bspstart.c
@@ -98,8 +98,6 @@ static void leon3_interrupt_common_init( void )
  */
 static void leon3_pre_driver_hook( void )
 {
-  bsp_spurious_initialize();
-
 #ifndef RTEMS_DRVMGR_STARTUP
   leon3_interrupt_common_init();
 #endif
diff --git a/bsps/sparc/leon3/start/spurious.c b/bsps/sparc/leon3/start/spurious.c
deleted file mode 100644
index 23ac4bf..0000000
--- a/bsps/sparc/leon3/start/spurious.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  LEON Spurious Trap Handler
- *
- *  This is just enough of a trap handler to let us know what
- *  the likely source of the trap was.
- *
- *  Developed as part of the port of RTEMS to the LEON implementation
- *  of the SPARC by On-Line Applications Research Corporation (OAR)
- *  under contract to the European Space Agency (ESA).
- *
- *  COPYRIGHT (c) 1995. European Space Agency.
- *
- *  Modified for LEON3 BSP.
- *  COPYRIGHT (c) 2004.
- *  Gaisler Research.
- *
- *  This terms of the RTEMS license apply to this file.
- */
-
-#include <bsp.h>
-#include <rtems/score/cpu.h>
-#include <rtems/bspIo.h>
-#include <inttypes.h>
-
-void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
-{
-  uint32_t                   trap;
-  uint32_t                   real_trap;
-  const CPU_Interrupt_frame *isf;
-
-  trap = frame->trap;
-  real_trap = SPARC_REAL_TRAP_NUMBER(trap);
-  isf = frame->isf;
-
-  printk(
-    "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n",
-    real_trap,
-    isf->tpc
-  );
-
-  switch (real_trap) {
-
-    /*
-     *  First the ones defined by the basic architecture
-     */
-
-    case 0x00:
-      printk( "reset\n" );
-      break;
-    case 0x01:
-      printk( "instruction access exception\n" );
-      break;
-    case 0x02:
-      printk( "illegal instruction\n" );
-      break;
-    case 0x03:
-      printk( "privileged instruction\n" );
-      break;
-    case 0x04:
-      printk( "fp disabled\n" );
-      break;
-    case 0x07:
-      printk( "memory address not aligned\n" );
-      break;
-    case 0x08:
-      printk( "fp exception\n" );
-      break;
-    case 0x0A:
-      printk( "tag overflow\n" );
-      break;
-
-    /*
-     *  Then the ones defined by the LEON in particular
-     */
-      /* FIXME */
-
-      /*
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ):
-      printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ):
-      printk( "LEON_INTERRUPT_UART_2_RX_TX\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ):
-      printk( "LEON_INTERRUPT_UART_1_RX_TX\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_0\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_1\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_2\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ):
-      printk( "LEON_INTERRUPT_EXTERNAL_3\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ):
-      printk( "LEON_INTERRUPT_TIMER1\n" );
-      break;
-    case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ):
-      printk( "LEON_INTERRUPT_TIMER2\n" );
-      break;
-      */
-
-    default:
-      break;
-  }
-}
-
-static rtems_isr bsp_spurious_handler(
-   rtems_vector_number trap,
-   CPU_Interrupt_frame *isf
-)
-{
-  CPU_Exception_frame frame = {
-    .trap = trap,
-    .isf = isf
-  };
-
-#if !defined(SPARC_USE_LAZY_FP_SWITCH)
-  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
-    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
-  }
-#endif
-
-  rtems_fatal(
-    RTEMS_FATAL_SOURCE_EXCEPTION,
-    (rtems_fatal_code) &frame
-  );
-}
-
-/*
- *  bsp_spurious_initialize
- *
- *  Install the spurious handler for most traps. Note that set_vector()
- *  will unmask the corresponding asynchronous interrupt, so the initial
- *  interrupt mask is restored after the handlers are installed.
- */
-
-void bsp_spurious_initialize()
-{
-  uint32_t trap;
-  uint32_t level;
-  /* uint32_t mask; */
-
-  level = sparc_disable_interrupts();
-  /* mask = LEON3_IrqCtrl_Regs->mask_p0; */
-
-  for ( trap=0 ; trap<256 ; trap++ ) {
-
-    /*
-     *  Skip window overflow, underflow, and flush as well as software
-     *  trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable.
-     *  Also avoid trap 0x70 - 0x7f which cannot happen and where some of the
-     *  space is used to pass parameters to the program.
-     */
-
-    if (( trap == 5 ) || ( trap == 6 ) ||
-#if defined(SPARC_USE_LAZY_FP_SWITCH)
-        ( trap == 4 ) ||
-#endif
-        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
-        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
-        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
-#endif
-        ( trap == 0x80 + SPARC_SWTRAP_IRQEN ))
-      continue;
-
-    set_vector(
-        (rtems_isr_entry) bsp_spurious_handler,
-        SPARC_SYNCHRONOUS_TRAP( trap ),
-        1
-    );
-  }
-
-  /* LEON3_IrqCtrl_Regs->mask_p0 = mask; */
-  sparc_enable_interrupts(level);
-
-}
diff --git a/bsps/sparc/shared/start/start.S b/bsps/sparc/shared/start/start.S
index 9bdc752..cd43f08 100644
--- a/bsps/sparc/shared/start/start.S
+++ b/bsps/sparc/shared/start/start.S
@@ -26,14 +26,11 @@
 #define TRAP_SYM(_vector) SYM(trap_##_vector)
 
 /*
- *  Unexpected trap will halt the processor by forcing it to error state
+ *  Unexpected trap will lead to an RTEMS fatal error.
  */
 #define BAD_TRAP(_vector) \
   TRAP_SYM(_vector):; \
-  ta 0; \
-  nop; \
-  nop; \
-  nop;
+  TRAP(_vector, _SPARC_Bad_trap)
 
 /*
  * System call optimized trap table entry
diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am
index a718284..1c1c35a 100644
--- a/c/src/lib/libbsp/sparc/erc32/Makefile.am
+++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am
@@ -28,7 +28,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/gettargethash-default.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/setvec.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/spurious.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/erc32mec.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/boardinit.S
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/bspidle.c
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index a2570e1..b2c55f8 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -30,7 +30,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/gettargethash-default.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/setvec.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/spurious.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspidle.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspdelay.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_exit.c
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index c10dbe9..464f225 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -32,7 +32,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/gettargethash-defau
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bspgetworkarea.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/setvec.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/spurious.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/bspidle.S
 librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/bspdelay.c
 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 8947d7e..83c14cd 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1618,9 +1618,11 @@ librtemscpu_a_SOURCES += score/cpu/sparc/access_le.c
 librtemscpu_a_SOURCES += score/cpu/sparc/cpu.c
 librtemscpu_a_SOURCES += score/cpu/sparc/cpu_asm.S
 librtemscpu_a_SOURCES += score/cpu/sparc/sparc-access.S
+librtemscpu_a_SOURCES += score/cpu/sparc/sparc-bad-trap.S
 librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-validate.S
 librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-volatile-clobber.S
 librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter-asm.S
+librtemscpu_a_SOURCES += score/cpu/sparc/sparc-exception-frame-print.c
 librtemscpu_a_SOURCES += score/cpu/sparc/sparc-isr-install.c
 librtemscpu_a_SOURCES += score/cpu/sparc/syscall.S
 librtemscpu_a_SOURCES += score/cpu/sparc/window.S
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
index a7bf7df..10ad440 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -147,6 +147,57 @@ RTEMS_STATIC_ASSERT(
   CPU_Interrupt_frame_alignment
 );
 
+#define SPARC_ASSERT_REGISTER_WINDOW_OFFSET( member, off ) \
+  RTEMS_STATIC_ASSERT( \
+    offsetof( SPARC_Register_window, member ) == \
+      RTEMS_XCONCAT( SPARC_REGISTER_WINDOW_OFFSET_, off ), \
+    SPARC_Register_window ## member \
+  )
+
+SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 0 ], LOCAL( 0 ) );
+SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 1 ], LOCAL( 1 ) );
+SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 0 ], INPUT( 0 ) );
+SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 1 ], INPUT( 1 ) );
+
+RTEMS_STATIC_ASSERT(
+  sizeof( SPARC_Register_window ) == SPARC_REGISTER_WINDOW_SIZE,
+  SPARC_REGISTER_WINDOW_SIZE
+);
+
+#define SPARC_ASSERT_EXCEPTION_OFFSET( member, off ) \
+  RTEMS_STATIC_ASSERT( \
+    offsetof( CPU_Exception_frame, member ) == \
+      RTEMS_XCONCAT( SPARC_EXCEPTION_OFFSET_, off ), \
+    CPU_Exception_frame_offset_ ## member \
+  )
+
+SPARC_ASSERT_EXCEPTION_OFFSET( psr, PSR );
+SPARC_ASSERT_EXCEPTION_OFFSET( pc, PC );
+SPARC_ASSERT_EXCEPTION_OFFSET( npc, NPC );
+SPARC_ASSERT_EXCEPTION_OFFSET( trap, TRAP );
+SPARC_ASSERT_EXCEPTION_OFFSET( wim, WIM );
+SPARC_ASSERT_EXCEPTION_OFFSET( y, Y );
+SPARC_ASSERT_EXCEPTION_OFFSET( global[ 0 ], GLOBAL( 0 ) );
+SPARC_ASSERT_EXCEPTION_OFFSET( global[ 1 ], GLOBAL( 1 ) );
+SPARC_ASSERT_EXCEPTION_OFFSET( output[ 0 ], OUTPUT( 0 ) );
+SPARC_ASSERT_EXCEPTION_OFFSET( output[ 1 ], OUTPUT( 1 ) );
+
+#if SPARC_HAS_FPU == 1
+SPARC_ASSERT_EXCEPTION_OFFSET( fsr, FSR );
+SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 0 ], FP( 0 ) );
+SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 1 ], FP( 1 ) );
+#endif
+
+RTEMS_STATIC_ASSERT(
+  sizeof( CPU_Exception_frame ) == SPARC_EXCEPTION_FRAME_SIZE,
+  SPARC_EXCEPTION_FRAME_SIZE
+);
+
+RTEMS_STATIC_ASSERT(
+  sizeof( CPU_Exception_frame ) % CPU_ALIGNMENT == 0,
+  CPU_Exception_frame_alignment
+);
+
 /*
  *  _CPU_Initialize
  *
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
index 0daf1d9..f3f50d4 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
@@ -1023,9 +1023,60 @@ RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
   } while ( 0 )
 #endif
 
+/**
+ * @brief This structure contains the local and input registers of a register
+ *   window.
+ */
 typedef struct {
+  /** @brief This member contains the local 0..7 register values. */
+  uint32_t local[ 8 ];
+
+  /** @brief This member contains the input 0..7 register values. */
+  uint32_t input[ 8 ];
+} SPARC_Register_window;
+
+/**
+ * @brief This structure contains the register set of a context which caused an
+ *   unexpected trap.
+ */
+typedef struct {
+  /** @brief This member contains the PSR register value. */
+  uint32_t psr;
+
+  /** @brief This member contains the PC value. */
+  uint32_t pc;
+
+  /** @brief This member contains the nPC value. */
+  uint32_t npc;
+
+  /** @brief This member contains the trap number. */
   uint32_t trap;
-  CPU_Interrupt_frame *isf;
+
+  /** @brief This member contains the WIM register value. */
+  uint32_t wim;
+
+  /** @brief This member contains the Y register value. */
+  uint32_t y;
+
+  /** @brief This member contains the global 0..7 register values. */
+  uint32_t global[ 8 ];
+
+  /** @brief This member contains the output 0..7 register values. */
+  uint32_t output[ 8 ] ;
+
+  /**
+   * @brief This member contains the additional register windows according to
+   *   the saved WIM.
+   */
+  SPARC_Register_window windows[ SPARC_NUMBER_OF_REGISTER_WINDOWS - 1 ];
+
+#if SPARC_HAS_FPU == 1
+  /** This member contain the FSR register value. */
+  uint32_t fsr;
+
+  /** @brief This member contains the floating point 0..31 register values. */
+  uint64_t fp[ 16 ];
+#endif
 } CPU_Exception_frame;
 
 void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
index a99da74..a8ed0ae 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
@@ -117,6 +117,28 @@
   #endif
 #endif
 
+#define SPARC_REGISTER_WINDOW_OFFSET_LOCAL( i ) ( ( i ) * 4 )
+#define SPARC_REGISTER_WINDOW_OFFSET_INPUT( i ) ( ( i ) * 4 + 32 )
+#define SPARC_REGISTER_WINDOW_SIZE 64
+
+#define SPARC_EXCEPTION_OFFSET_PSR 0
+#define SPARC_EXCEPTION_OFFSET_PC 4
+#define SPARC_EXCEPTION_OFFSET_NPC 8
+#define SPARC_EXCEPTION_OFFSET_TRAP 12
+#define SPARC_EXCEPTION_OFFSET_WIM 16
+#define SPARC_EXCEPTION_OFFSET_Y 20
+#define SPARC_EXCEPTION_OFFSET_GLOBAL( i ) ( ( i ) * 4 + 24 )
+#define SPARC_EXCEPTION_OFFSET_OUTPUT( i ) ( ( i ) * 4 + 56 )
+#define SPARC_EXCEPTION_OFFSET_WINDOWS( i ) ( ( i ) * 64 + 88 )
+
+#if SPARC_HAS_FPU == 1
+#define SPARC_EXCEPTION_OFFSET_FSR 536
+#define SPARC_EXCEPTION_OFFSET_FP( i ) ( ( i ) * 8 + 544 )
+#define SPARC_EXCEPTION_FRAME_SIZE 672
+#else
+#define SPARC_EXCEPTION_FRAME_SIZE 536
+#endif
+
 #ifndef ASM
 
 #ifdef __cplusplus
diff --git a/cpukit/score/cpu/sparc/sparc-bad-trap.S b/cpukit/score/cpu/sparc/sparc-bad-trap.S
new file mode 100644
index 0000000..2e73a4a
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-bad-trap.S
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreCPUSPARC
+ *
+ * @brief This source file contains the implementation of _SPARC_Bad_trap().
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/asm.h>
+#include <rtems/score/percpu.h>
+
+        /*
+         * The trap handler entry was set up by TRAP().
+         */
+        PUBLIC(_SPARC_Bad_trap)
+SYM(_SPARC_Bad_trap):
+
+        /*
+         * Do not use the existing stack since it may be invalid.  Use the ISR
+         * stack for this processor.  If the trap was caused from within
+         * interrupt context, then a return to the context which caused the
+         * trap would be unreliable.
+         */
+        set     SYM(_ISR_Stack_size), %l5
+
+#if defined(RTEMS_SMP) && defined(__leon__)
+        rd      %asr17, %l6
+        srl     %l6, LEON3_ASR17_PROCESSOR_INDEX_SHIFT, %l6
+        add     %l6, 1, %l4
+        smul    %l4, %l5, %l5
+#endif
+        set     SYM(_ISR_Stack_area_begin), %l7
+        add     %l7, %l5, %l7
+        andn    %l7, CPU_STACK_ALIGNMENT - 1, %l7
+
+        /*
+         * Establish an area on the stack for a CPU_Exception_frame.
+         */
+        sub     %l7, SPARC_EXCEPTION_FRAME_SIZE, %l7
+
+        /*
+         * Start saving the context which caused the trap.
+         */
+        mov     %wim, %l4
+        rd      %y, %l5
+        std     %l0, [%l7 + SPARC_EXCEPTION_OFFSET_PSR]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %l2, [%l7 + SPARC_EXCEPTION_OFFSET_NPC]
+        SPARC_LEON3FT_B2BST_NOP
+        st      %l4, [%l7 + SPARC_EXCEPTION_OFFSET_WIM]
+        st      %l5, [%l7 + SPARC_EXCEPTION_OFFSET_Y]
+        std     %g0, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(0)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %g2, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(2)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %g4, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(4)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %g6, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(6)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i0, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(0)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i2, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(2)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i4, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(4)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i6, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(6)]
+
+        /*
+         * Initialize %g6 since it may be corrupt.
+         */
+        set     SYM(_Per_CPU_Information), %g6
+#if defined(RTEMS_SMP) && defined(__leon__)
+        sll     %l6, PER_CPU_CONTROL_SIZE_LOG2, %l4
+        add     %g6, %l4, %g6
+#endif
+
+        /*
+         * Disable WIM traps.
+         */
+        mov     %g0, %wim
+        nop
+        nop
+        nop
+
+        /*
+         * Save the remaining register windows.
+         */
+        set     SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g2
+        add     %l7, SPARC_EXCEPTION_OFFSET_WINDOWS(0), %g3
+
+.Lsave_register_windows:
+
+        restore
+        std     %l0, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(0)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %l2, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(2)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %l4, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(4)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %l6, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(6)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i0, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(0)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i2, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(2)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i4, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(4)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %i6, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(6)]
+        add     %g3, SPARC_REGISTER_WINDOW_SIZE, %g3
+        subcc   %g2, 1, %g2
+        bne     .Lsave_register_windows
+         nop
+
+        /*
+         * Go back to register window at trap entry.
+         */
+        restore
+
+        /*
+         * Initialize the WIM based on the PSR[CWP] to have all register
+         * windows available for the fatal error procedure.
+         */
+        and     %l0, SPARC_PSR_CWP_MASK, %l4
+        set     1, %l5
+        sll     %l5, %l4, %l5
+        mov     %l5, %wim
+
+#if SPARC_HAS_FPU == 1
+        /*
+         * Enable the FPU in the new PSR (PSR[EF] == 1).
+         */
+        sethi   %hi(SPARC_PSR_EF_MASK), %l4
+        or      %l0, %l4, %l0
+#endif
+
+        /*
+         * Enable traps and disable interrupts.
+         */
+        or      %l0, 0xf20, %l0
+        wr      %l0, %psr
+        nop
+        nop
+        nop
+
+#if SPARC_HAS_FPU == 1
+        st      %fsr, [%l7 + SPARC_EXCEPTION_OFFSET_FSR]
+        std     %f0, [%l7 + SPARC_EXCEPTION_OFFSET_FP(0)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f2, [%l7 + SPARC_EXCEPTION_OFFSET_FP(1)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f4, [%l7 + SPARC_EXCEPTION_OFFSET_FP(2)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f6, [%l7 + SPARC_EXCEPTION_OFFSET_FP(3)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f8, [%l7 + SPARC_EXCEPTION_OFFSET_FP(4)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f10, [%l7 + SPARC_EXCEPTION_OFFSET_FP(5)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f12, [%l7 + SPARC_EXCEPTION_OFFSET_FP(6)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f14, [%l7 + SPARC_EXCEPTION_OFFSET_FP(7)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f16, [%l7 + SPARC_EXCEPTION_OFFSET_FP(8)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f18, [%l7 + SPARC_EXCEPTION_OFFSET_FP(9)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f20, [%l7 + SPARC_EXCEPTION_OFFSET_FP(10)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f22, [%l7 + SPARC_EXCEPTION_OFFSET_FP(11)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f24, [%l7 + SPARC_EXCEPTION_OFFSET_FP(12)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f26, [%l7 + SPARC_EXCEPTION_OFFSET_FP(13)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f28, [%l7 + SPARC_EXCEPTION_OFFSET_FP(14)]
+        SPARC_LEON3FT_B2BST_NOP
+        std     %f30, [%l7 + SPARC_EXCEPTION_OFFSET_FP(15)]
+#endif
+
+#if !defined(SPARC_USE_LAZY_FP_SWITCH)
+        /*
+         * Call
+         * _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT )
+         * if necessary.
+         */
+        cmp     %l3, 4
+        bne     .Lno_fp_disable_trap
+         nop
+        call    SYM(_Internal_error)
+         set    38, %o0
+.Lno_fp_disable_trap:
+#endif
+
+        /*
+         * Call _Terminate( RTEMS_FATAL_SOURCE_EXCEPTION, %l0 ).
+         */
+        sub     %l7, SPARC_MINIMUM_STACK_FRAME_SIZE, %sp
+        set     9, %o0
+        call    SYM(_Terminate)
+         mov    %l7, %o1
diff --git a/cpukit/score/cpu/sparc/sparc-exception-frame-print.c b/cpukit/score/cpu/sparc/sparc-exception-frame-print.c
new file mode 100644
index 0000000..f216c1d
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-exception-frame-print.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreCPUSPARC
+ *
+ * @brief This source file contains the SPARC-specific implementation of
+ *   _CPU_Exception_frame_print().
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/cpu.h>
+#include <rtems/bspIo.h>
+#include <inttypes.h>
+
+void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
+{
+  size_t i;
+  size_t j;
+  const char *desc;
+
+  switch ( SPARC_REAL_TRAP_NUMBER( frame->trap ) ) {
+    case 0x01:
+      desc = " (instruction access exception)";
+      break;
+    case 0x02:
+      desc = " (illegal instruction)";
+      break;
+    case 0x03:
+      desc = " (privileged instruction)";
+      break;
+    case 0x04:
+      desc = " (fp disabled)";
+      break;
+    case 0x05:
+      desc = " (window overflow)";
+      break;
+    case 0x06:
+      desc = " (window underflow)";
+      break;
+    case 0x07:
+      desc = " (memory address not aligned)";
+      break;
+    case 0x08:
+      desc = " (fp exception)";
+      break;
+    case 0x09:
+      desc = " (data access exception)";
+      break;
+    case 0x0A:
+      desc = " (tag overflow)";
+      break;
+    case 0x11:
+    case 0x12:
+    case 0x13:
+    case 0x14:
+    case 0x15:
+    case 0x16:
+    case 0x17:
+    case 0x18:
+    case 0x19:
+    case 0x1A:
+    case 0x1B:
+    case 0x1C:
+    case 0x1D:
+    case 0x1E:
+    case 0x1F:
+      desc = " (external interrupt)";
+      break;
+    case 0x24:
+      desc = " (cp disabled)";
+      break;
+    case 0x28:
+      desc = " (cp exception)";
+      break;
+    default:
+      desc = "";
+      break;
+  }
+
+  printk(
+    "\n"
+    "unexpected trap %" PRIu32 "%s\n"
+    "PSR = 0x%08" PRIx32 "\n"
+    "PC = 0x%08" PRIx32 "\n"
+    "nPC = 0x%08" PRIx32 "\n"
+    "WIM = 0x%08" PRIx32 "\n"
+    "Y = 0x%08" PRIx32 "\n",
+    frame->trap,
+    desc,
+    frame->psr,
+    frame->pc,
+    frame->npc,
+    frame->wim,
+    frame->y
+  );
+
+  for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->global ); ++i ) {
+    printk( "g%zu = 0x%08" PRIx32 "\n", i, frame->global[ i ] );
+  }
+
+  for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->output ); ++i ) {
+    printk( "o%zu[CWP - 0] = 0x%08" PRIx32 "\n", i, frame->output[ i ] );
+  }
+
+  for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->windows ); ++i ) {
+    const SPARC_Register_window *win;
+
+    win = &frame->windows[ i ];
+
+    for ( j = 0; j < RTEMS_ARRAY_SIZE( win->local ); ++j ) {
+      printk( "l%zu[CWP - %zu] = 0x%08" PRIx32 "\n", j, i, win->local[ j ] );
+    }
+
+    for ( j = 0; j < RTEMS_ARRAY_SIZE( win->input ); ++j ) {
+      printk( "i%zu[CWP - %zu] = 0x%08" PRIx32 "\n", j, i, win->input[ j ] );
+    }
+  }
+
+#if SPARC_HAS_FPU == 1
+  printk( "FSR = 0x%08" PRIx32 "\n", frame->fsr );
+
+  for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->fp ); ++i ) {
+    j = i * 2;
+    printk( "fp%zu:fp%zu = 0x%016" PRIx64 "\n", j, j + 1, frame->fp[ i ] );
+  }
+#endif
+}
diff --git a/spec/build/bsps/sparc/erc32/bsperc32.yml b/spec/build/bsps/sparc/erc32/bsperc32.yml
index 1df75fc..455aec1 100644
--- a/spec/build/bsps/sparc/erc32/bsperc32.yml
+++ b/spec/build/bsps/sparc/erc32/bsperc32.yml
@@ -65,7 +65,6 @@ source:
 - bsps/sparc/erc32/start/bspstart.c
 - bsps/sparc/erc32/start/erc32mec.c
 - bsps/sparc/erc32/start/setvec.c
-- bsps/sparc/erc32/start/spurious.c
 - bsps/sparc/shared/gnatcommon.c
 - bsps/sparc/shared/irq/bsp_isr_handler.c
 - bsps/sparc/shared/irq/irq-shared.c
diff --git a/spec/build/bsps/sparc/leon2/obj.yml b/spec/build/bsps/sparc/leon2/obj.yml
index 92c07b6..f1a5e52 100644
--- a/spec/build/bsps/sparc/leon2/obj.yml
+++ b/spec/build/bsps/sparc/leon2/obj.yml
@@ -41,7 +41,6 @@ source:
 - bsps/sparc/leon2/start/bspstart.c
 - bsps/sparc/leon2/start/cache.c
 - bsps/sparc/leon2/start/setvec.c
-- bsps/sparc/leon2/start/spurious.c
 - bsps/sparc/shared/drvmgr/ambapp_bus_leon2.c
 - bsps/sparc/shared/drvmgr/leon2_amba_bus.c
 - bsps/sparc/shared/gnatcommon.c
diff --git a/spec/build/bsps/sparc/leon3/obj.yml b/spec/build/bsps/sparc/leon3/obj.yml
index 3b58835..19ce633 100644
--- a/spec/build/bsps/sparc/leon3/obj.yml
+++ b/spec/build/bsps/sparc/leon3/obj.yml
@@ -51,7 +51,6 @@ source:
 - bsps/sparc/leon3/start/drvmgr_def_drivers.c
 - bsps/sparc/leon3/start/eirq.c
 - bsps/sparc/leon3/start/setvec.c
-- bsps/sparc/leon3/start/spurious.c
 - bsps/sparc/shared/gnatcommon.c
 - bsps/sparc/shared/irq/bsp_isr_handler.c
 - bsps/sparc/shared/irq/irq-shared.c
diff --git a/spec/build/cpukit/cpusparc.yml b/spec/build/cpukit/cpusparc.yml
index 10dabed..2186505 100644
--- a/spec/build/cpukit/cpusparc.yml
+++ b/spec/build/cpukit/cpusparc.yml
@@ -34,9 +34,11 @@ source:
 - cpukit/score/cpu/sparc/cpu.c
 - cpukit/score/cpu/sparc/cpu_asm.S
 - cpukit/score/cpu/sparc/sparc-access.S
+- cpukit/score/cpu/sparc/sparc-bad-trap.S
 - cpukit/score/cpu/sparc/sparc-context-validate.S
 - cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
 - cpukit/score/cpu/sparc/sparc-counter-asm.S
+- cpukit/score/cpu/sparc/sparc-exception-frame-print.c
 - cpukit/score/cpu/sparc/sparc-isr-install.c
 - cpukit/score/cpu/sparc/syscall.S
 - cpukit/score/cpu/sparc/window.S



More information about the vc mailing list