[PATCH 1/4] sparc: Disable FPU in interrupt context

Gedare Bloom gedare at gwu.edu
Fri May 29 14:11:09 UTC 2015


I am missing something. When an interrupt happens, it disables
floating point. Where does fp get re-enabled afterward?

On Fri, May 29, 2015 at 8:54 AM, Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
> From: Alexander Krutwig <alexander.krutwig at 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 at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel



More information about the devel mailing list