[PATCH 05/10] sparc: Move ISR handler install routines

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 23 06:49:31 UTC 2021


Move _CPU_ISR_install_raw_handler() and _CPU_ISR_install_vector() to separate
files.  The goal is to make their use optional.

Update #4458.
Update #4459.
---
 cpukit/Makefile.am                         |   1 +
 cpukit/score/cpu/sparc/cpu.c               | 181 +------------------
 cpukit/score/cpu/sparc/sparc-isr-install.c | 194 +++++++++++++++++++++
 spec/build/cpukit/cpusparc.yml             |   1 +
 4 files changed, 203 insertions(+), 174 deletions(-)
 create mode 100644 cpukit/score/cpu/sparc/sparc-isr-install.c

diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 25382f38ca..8947d7eb5a 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1621,6 +1621,7 @@ librtemscpu_a_SOURCES += score/cpu/sparc/sparc-access.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-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 9f84c28fc5..a7bf7dfcaf 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -1,7 +1,12 @@
 /**
- *  @file
+ * @file
  *
- *  @brief SPARC CPU Dependent Source
+ * @ingroup RTEMSScoreCPUSPARC
+ *
+ * @brief This source file contains static assertions to ensure the consistency
+ *   of interfaces used in C and assembler and it contains the SPARC-specific
+ *   implementation of _CPU_Initialize(), _CPU_ISR_Get_level(), and
+ *   _CPU_Context_Initialize().
  */
 
 /*
@@ -19,11 +24,9 @@
 #include "config.h"
 #endif
 
-#include <rtems/score/isr.h>
 #include <rtems/score/percpu.h>
 #include <rtems/score/tls.h>
 #include <rtems/score/thread.h>
-#include <rtems/rtems/cache.h>
 
 #if SPARC_HAS_FPU == 1
   RTEMS_STATIC_ASSERT(
@@ -144,22 +147,6 @@ RTEMS_STATIC_ASSERT(
   CPU_Interrupt_frame_alignment
 );
 
-/*
- *  This initializes the set of opcodes placed in each trap
- *  table entry.  The routine which installs a handler is responsible
- *  for filling in the fields for the _handler address and the _vector
- *  trap type.
- *
- *  The constants following this structure are masks for the fields which
- *  must be filled in when the handler is installed.
- */
-const CPU_Trap_table_entry _CPU_Trap_slot_template = {
-  0xa1480000,      /* mov   %psr, %l0           */
-  0x29000000,      /* sethi %hi(_handler), %l4  */
-  0x81c52000,      /* jmp   %l4 + %lo(_handler) */
-  0xa6102000       /* mov   _vector, %l3        */
-};
-
 /*
  *  _CPU_Initialize
  *
@@ -197,160 +184,6 @@ uint32_t   _CPU_ISR_Get_level( void )
   return level;
 }
 
-/*
- *  _CPU_ISR_install_raw_handler
- *
- *  This routine installs the specified handler as a "raw" non-executive
- *  supported trap handler (a.k.a. interrupt service routine).
- *
- *  Input Parameters:
- *    vector      - trap table entry number plus synchronous
- *                    vs. asynchronous information
- *    new_handler - address of the handler to be installed
- *    old_handler - pointer to an address of the handler previously installed
- *
- *  Output Parameters: NONE
- *    *new_handler - address of the handler previously installed
- *
- *  NOTE:
- *
- *  On the SPARC, there are really only 256 vectors.  However, the executive
- *  has no easy, fast, reliable way to determine which traps are synchronous
- *  and which are asynchronous.  By default, synchronous traps return to the
- *  instruction which caused the interrupt.  So if you install a software
- *  trap handler as an executive interrupt handler (which is desirable since
- *  RTEMS takes care of window and register issues), then the executive needs
- *  to know that the return address is to the trap rather than the instruction
- *  following the trap.
- *
- *  So vectors 0 through 255 are treated as regular asynchronous traps which
- *  provide the "correct" return address.  Vectors 256 through 512 are assumed
- *  by the executive to be synchronous and to require that the return address
- *  be fudged.
- *
- *  If you use this mechanism to install a trap handler which must reexecute
- *  the instruction which caused the trap, then it should be installed as
- *  an asynchronous trap.  This will avoid the executive changing the return
- *  address.
- */
-
-void _CPU_ISR_install_raw_handler(
-  uint32_t             vector,
-  CPU_ISR_raw_handler  new_handler,
-  CPU_ISR_raw_handler *old_handler
-)
-{
-  uint32_t               real_vector;
-  CPU_Trap_table_entry  *tbr;
-  CPU_Trap_table_entry  *slot;
-  uint32_t               u32_tbr;
-  uint32_t               u32_handler;
-
-  /*
-   *  Get the "real" trap number for this vector ignoring the synchronous
-   *  versus asynchronous indicator included with our vector numbers.
-   */
-
-  real_vector = SPARC_REAL_TRAP_NUMBER( vector );
-
-  /*
-   *  Get the current base address of the trap table and calculate a pointer
-   *  to the slot we are interested in.
-   */
-
-  sparc_get_tbr( u32_tbr );
-
-  u32_tbr &= 0xfffff000;
-
-  tbr = (CPU_Trap_table_entry *) u32_tbr;
-
-  slot = &tbr[ real_vector ];
-
-  /*
-   *  Get the address of the old_handler from the trap table.
-   *
-   *  NOTE: The old_handler returned will be bogus if it does not follow
-   *        the RTEMS model.
-   */
-
-#define HIGH_BITS_MASK   0xFFFFFC00
-#define HIGH_BITS_SHIFT  10
-#define LOW_BITS_MASK    0x000003FF
-
-  if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
-    u32_handler =
-      (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) |
-      (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
-    *old_handler = (CPU_ISR_raw_handler) u32_handler;
-  } else
-    *old_handler = 0;
-
-  /*
-   *  Copy the template to the slot and then fix it.
-   */
-
-  *slot = _CPU_Trap_slot_template;
-
-  u32_handler = (uint32_t) new_handler;
-
-  slot->mov_vector_l3 |= vector;
-  slot->sethi_of_handler_to_l4 |=
-    (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
-  slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
-
-  /*
-   * There is no instruction cache snooping, so we need to invalidate
-   * the instruction cache to make sure that the processor sees the
-   * changes to the trap table. This step is required on both single-
-   * and multiprocessor systems.
-   *
-   * In a SMP configuration a change to the trap table might be
-   * missed by other cores. If the system state is up, the other
-   * cores can be notified using SMP messages that they need to
-   * flush their icache. If the up state has not been reached
-   * there is no need to notify other cores. They will do an
-   * automatic flush of the icache just after entering the up
-   * state, but before enabling interrupts.
-   */
-  rtems_cache_invalidate_entire_instruction();
-}
-
-void _CPU_ISR_install_vector(
-  uint32_t         vector,
-  CPU_ISR_handler  new_handler,
-  CPU_ISR_handler *old_handler
-)
-{
-   uint32_t            real_vector;
-   CPU_ISR_raw_handler ignored;
-
-  /*
-   *  Get the "real" trap number for this vector ignoring the synchronous
-   *  versus asynchronous indicator included with our vector numbers.
-   */
-
-   real_vector = SPARC_REAL_TRAP_NUMBER( vector );
-
-   /*
-    *  Return the previous ISR handler.
-    */
-
-   *old_handler = _ISR_Vector_table[ real_vector ];
-
-   /*
-    *  Install the wrapper so this ISR can be invoked properly.
-    */
-
-   _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
-
-   /*
-    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
-    *  be used by the _ISR_Handler so the user gets control.
-    */
-
-    _ISR_Vector_table[ real_vector ] = new_handler;
-}
-
 void _CPU_Context_Initialize(
   Context_Control  *the_context,
   uint32_t         *stack_base,
diff --git a/cpukit/score/cpu/sparc/sparc-isr-install.c b/cpukit/score/cpu/sparc/sparc-isr-install.c
new file mode 100644
index 0000000000..017173c489
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-isr-install.c
@@ -0,0 +1,194 @@
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreCPUSPARC
+ *
+ * @brief This source file contains the SPARC-specific implementation of
+ *   _CPU_ISR_install_raw_handler() and _CPU_ISR_install_vector().
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2007.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/isr.h>
+#include <rtems/rtems/cache.h>
+
+/*
+ *  This initializes the set of opcodes placed in each trap
+ *  table entry.  The routine which installs a handler is responsible
+ *  for filling in the fields for the _handler address and the _vector
+ *  trap type.
+ *
+ *  The constants following this structure are masks for the fields which
+ *  must be filled in when the handler is installed.
+ */
+const CPU_Trap_table_entry _CPU_Trap_slot_template = {
+  0xa1480000,      /* mov   %psr, %l0           */
+  0x29000000,      /* sethi %hi(_handler), %l4  */
+  0x81c52000,      /* jmp   %l4 + %lo(_handler) */
+  0xa6102000       /* mov   _vector, %l3        */
+};
+
+/*
+ *  _CPU_ISR_install_raw_handler
+ *
+ *  This routine installs the specified handler as a "raw" non-executive
+ *  supported trap handler (a.k.a. interrupt service routine).
+ *
+ *  Input Parameters:
+ *    vector      - trap table entry number plus synchronous
+ *                    vs. asynchronous information
+ *    new_handler - address of the handler to be installed
+ *    old_handler - pointer to an address of the handler previously installed
+ *
+ *  Output Parameters: NONE
+ *    *new_handler - address of the handler previously installed
+ *
+ *  NOTE:
+ *
+ *  On the SPARC, there are really only 256 vectors.  However, the executive
+ *  has no easy, fast, reliable way to determine which traps are synchronous
+ *  and which are asynchronous.  By default, synchronous traps return to the
+ *  instruction which caused the interrupt.  So if you install a software
+ *  trap handler as an executive interrupt handler (which is desirable since
+ *  RTEMS takes care of window and register issues), then the executive needs
+ *  to know that the return address is to the trap rather than the instruction
+ *  following the trap.
+ *
+ *  So vectors 0 through 255 are treated as regular asynchronous traps which
+ *  provide the "correct" return address.  Vectors 256 through 512 are assumed
+ *  by the executive to be synchronous and to require that the return address
+ *  be fudged.
+ *
+ *  If you use this mechanism to install a trap handler which must reexecute
+ *  the instruction which caused the trap, then it should be installed as
+ *  an asynchronous trap.  This will avoid the executive changing the return
+ *  address.
+ */
+
+void _CPU_ISR_install_raw_handler(
+  uint32_t             vector,
+  CPU_ISR_raw_handler  new_handler,
+  CPU_ISR_raw_handler *old_handler
+)
+{
+  uint32_t               real_vector;
+  CPU_Trap_table_entry  *tbr;
+  CPU_Trap_table_entry  *slot;
+  uint32_t               u32_tbr;
+  uint32_t               u32_handler;
+
+  /*
+   *  Get the "real" trap number for this vector ignoring the synchronous
+   *  versus asynchronous indicator included with our vector numbers.
+   */
+
+  real_vector = SPARC_REAL_TRAP_NUMBER( vector );
+
+  /*
+   *  Get the current base address of the trap table and calculate a pointer
+   *  to the slot we are interested in.
+   */
+
+  sparc_get_tbr( u32_tbr );
+
+  u32_tbr &= 0xfffff000;
+
+  tbr = (CPU_Trap_table_entry *) u32_tbr;
+
+  slot = &tbr[ real_vector ];
+
+  /*
+   *  Get the address of the old_handler from the trap table.
+   *
+   *  NOTE: The old_handler returned will be bogus if it does not follow
+   *        the RTEMS model.
+   */
+
+#define HIGH_BITS_MASK   0xFFFFFC00
+#define HIGH_BITS_SHIFT  10
+#define LOW_BITS_MASK    0x000003FF
+
+  if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
+    u32_handler =
+      (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) |
+      (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
+    *old_handler = (CPU_ISR_raw_handler) u32_handler;
+  } else
+    *old_handler = 0;
+
+  /*
+   *  Copy the template to the slot and then fix it.
+   */
+
+  *slot = _CPU_Trap_slot_template;
+
+  u32_handler = (uint32_t) new_handler;
+
+  slot->mov_vector_l3 |= vector;
+  slot->sethi_of_handler_to_l4 |=
+    (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
+  slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
+
+  /*
+   * There is no instruction cache snooping, so we need to invalidate
+   * the instruction cache to make sure that the processor sees the
+   * changes to the trap table. This step is required on both single-
+   * and multiprocessor systems.
+   *
+   * In a SMP configuration a change to the trap table might be
+   * missed by other cores. If the system state is up, the other
+   * cores can be notified using SMP messages that they need to
+   * flush their icache. If the up state has not been reached
+   * there is no need to notify other cores. They will do an
+   * automatic flush of the icache just after entering the up
+   * state, but before enabling interrupts.
+   */
+  rtems_cache_invalidate_entire_instruction();
+}
+
+void _CPU_ISR_install_vector(
+  uint32_t         vector,
+  CPU_ISR_handler  new_handler,
+  CPU_ISR_handler *old_handler
+)
+{
+   uint32_t            real_vector;
+   CPU_ISR_raw_handler ignored;
+
+  /*
+   *  Get the "real" trap number for this vector ignoring the synchronous
+   *  versus asynchronous indicator included with our vector numbers.
+   */
+
+   real_vector = SPARC_REAL_TRAP_NUMBER( vector );
+
+   /*
+    *  Return the previous ISR handler.
+    */
+
+   *old_handler = _ISR_Vector_table[ real_vector ];
+
+   /*
+    *  Install the wrapper so this ISR can be invoked properly.
+    */
+
+   _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
+
+   /*
+    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
+    *  be used by the _ISR_Handler so the user gets control.
+    */
+
+    _ISR_Vector_table[ real_vector ] = new_handler;
+}
diff --git a/spec/build/cpukit/cpusparc.yml b/spec/build/cpukit/cpusparc.yml
index 85fbdc4b3c..10dabed494 100644
--- a/spec/build/cpukit/cpusparc.yml
+++ b/spec/build/cpukit/cpusparc.yml
@@ -37,6 +37,7 @@ source:
 - 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-isr-install.c
 - cpukit/score/cpu/sparc/syscall.S
 - cpukit/score/cpu/sparc/window.S
 type: build
-- 
2.26.2



More information about the devel mailing list