[rtems commit] sparc: Disable FPU in interrupt context

Sebastian Huber sebh at rtems.org
Sat May 30 14:50:46 UTC 2015


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

Author:    Alexander Krutwig <alexander.krutwig at embedded-brains.de>
Date:      Fri May 29 15:54:27 2015 +0200

sparc: Disable FPU in interrupt context

Update #2270.

---

 c/src/lib/libbsp/sparc/shared/irq_asm.S  | 35 +++++++++++++++++++++++++++++++-
 cpukit/score/cpu/sparc/cpu.c             |  8 ++++++++
 cpukit/score/cpu/sparc/rtems/score/cpu.h | 25 ++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S
index eef144f..53b24f7 100644
--- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
+++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
@@ -7,7 +7,7 @@
  *  COPYRIGHT (c) 1989-2011.
  *  On-Line Applications Research Corporation (OAR).
  *
- *  Copyright (c) 2014 embedded brains GmbH
+ *  Copyright (c) 2014-2015 embedded brains GmbH
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -423,6 +423,14 @@ dont_do_the_window:
         add      %l6, 1, %l6
         st       %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
 
+#if SPARC_HAS_FPU == 1
+        /*
+         * We cannot use an intermediate value for operations with the PSR[EF]
+         * bit since they use a 13-bit sign extension and PSR[EF] is bit 12.
+         */
+        sethi    %hi(SPARC_PSR_EF_MASK), %l5
+#endif
+
         /*
          *  If ISR nest level was zero (now 1), then switch stack.
          */
@@ -441,6 +449,22 @@ dont_do_the_window:
 
         ld       [%g6 + PER_CPU_INTERRUPT_STACK_HIGH], %sp
 
+#if SPARC_HAS_FPU == 1
+        /*
+         * Test if the interrupted thread uses the floating point unit
+         * (PSR[EF] == 1).  In case it uses the floating point unit, then store
+         * the floating point status register.  This has the side-effect that
+         * all pending floating point operations complete before the store
+         * completes.  The PSR[EF] bit is restored after the call to the
+         * interrupt handler.  Thus post-switch actions (e.g. signal handlers)
+         * and context switch extensions may still corrupt the floating point
+         * context.
+         */
+        andcc    %l0, %l5, %g0
+        bne,a    dont_switch_stacks
+         st      %fsr, [%g6 + SPARC_PER_CPU_FSR_OFFSET]
+#endif
+
 dont_switch_stacks:
         /*
          *  Make sure we have a place on the stack for the window overflow
@@ -471,6 +495,15 @@ dont_switch_stacks:
 dont_fix_pil:
         or       %g5, SPARC_PSR_PIL_MASK, %g5
 pil_fixed:
+
+#if SPARC_HAS_FPU == 1
+        /*
+         * Clear the PSR[EF] bit of the interrupted context to ensure that
+         * interrupt service routines cannot corrupt the floating point context.
+         */
+        andn     %g5, %l5, %g5
+#endif
+
         wr       %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
 
         /*
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
index e967bf2..bab0040 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -29,6 +29,14 @@ RTEMS_STATIC_ASSERT(
   SPARC_PER_CPU_ISR_DISPATCH_DISABLE
 );
 
+#if SPARC_HAS_FPU == 1
+  RTEMS_STATIC_ASSERT(
+    offsetof( Per_CPU_Control, cpu_per_cpu.fsr)
+      == SPARC_PER_CPU_FSR_OFFSET,
+    SPARC_PER_CPU_FSR_OFFSET
+  );
+#endif
+
 #define SPARC_ASSERT_OFFSET(field, off) \
   RTEMS_STATIC_ASSERT( \
     offsetof(Context_Control, field) == off ## _OFFSET, \
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index 5d5f1e4..02891b0 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -341,7 +341,11 @@ typedef struct {
 /** This defines the size of the minimum stack frame. */
 #define CPU_MINIMUM_STACK_FRAME_SIZE          0x60
 
-#define CPU_PER_CPU_CONTROL_SIZE 4
+#if ( SPARC_HAS_FPU == 1 )
+  #define CPU_PER_CPU_CONTROL_SIZE 8
+#else
+  #define CPU_PER_CPU_CONTROL_SIZE 4
+#endif
 
 /**
  * @brief Offset of the CPU_Per_CPU_control::isr_dispatch_disable field
@@ -349,6 +353,14 @@ typedef struct {
  */
 #define SPARC_PER_CPU_ISR_DISPATCH_DISABLE 0
 
+#if ( SPARC_HAS_FPU == 1 )
+  /**
+   * @brief Offset of the CPU_Per_CPU_control::fsr field relative to the
+   * Per_CPU_Control begin.
+   */
+  #define SPARC_PER_CPU_FSR_OFFSET 4
+#endif
+
 /**
  * @defgroup Contexts SPARC Context Structures
  *
@@ -380,6 +392,17 @@ typedef struct {
    * attempts on a previously interrupted thread's stack.
    */
   uint32_t isr_dispatch_disable;
+
+#if ( SPARC_HAS_FPU == 1 )
+  /**
+   * @brief Memory location to store the FSR register during interrupt
+   * processing.
+   *
+   * This is a write-only field.  The FSR is written to force a completion of
+   * floating point operations in progress.
+   */
+  uint32_t fsr;
+#endif
 } CPU_Per_CPU_control;
 
 /**



More information about the vc mailing list