From: Alexander Krutwig <alexander.krut...@embedded-brains.de> Update #2270. --- c/src/lib/libbsp/sparc/shared/irq_asm.S | 30 ++++++++++++++++++++++++++++++ cpukit/score/cpu/sparc/cpu.c | 8 ++++++++ cpukit/score/cpu/sparc/rtems/score/cpu.h | 25 ++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S index eef144f..8e1dc1f 100644 --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S @@ -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,19 @@ 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. + */ + 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 +492,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 f96d1ea..ee64b1e 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; /** -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel