sparc: Disable FPU in interrupt context

Update #2270.
This commit is contained in:
Alexander Krutwig
2015-05-29 15:54:27 +02:00
committed by Sebastian Huber
parent 1f6cdba6e1
commit 2764bd43d0
3 changed files with 66 additions and 2 deletions

View File

@@ -7,7 +7,7 @@
* COPYRIGHT (c) 1989-2011. * COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR). * 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 * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -423,6 +423,14 @@ dont_do_the_window:
add %l6, 1, %l6 add %l6, 1, %l6
st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] 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. * 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 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: dont_switch_stacks:
/* /*
* Make sure we have a place on the stack for the window overflow * Make sure we have a place on the stack for the window overflow
@@ -471,6 +495,15 @@ dont_switch_stacks:
dont_fix_pil: dont_fix_pil:
or %g5, SPARC_PSR_PIL_MASK, %g5 or %g5, SPARC_PSR_PIL_MASK, %g5
pil_fixed: 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 **** wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
/* /*

View File

@@ -29,6 +29,14 @@ RTEMS_STATIC_ASSERT(
SPARC_PER_CPU_ISR_DISPATCH_DISABLE 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) \ #define SPARC_ASSERT_OFFSET(field, off) \
RTEMS_STATIC_ASSERT( \ RTEMS_STATIC_ASSERT( \
offsetof(Context_Control, field) == off ## _OFFSET, \ offsetof(Context_Control, field) == off ## _OFFSET, \

View File

@@ -341,7 +341,11 @@ typedef struct {
/** This defines the size of the minimum stack frame. */ /** This defines the size of the minimum stack frame. */
#define CPU_MINIMUM_STACK_FRAME_SIZE 0x60 #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 * @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 #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 * @defgroup Contexts SPARC Context Structures
* *
@@ -380,6 +392,17 @@ typedef struct {
* attempts on a previously interrupted thread's stack. * attempts on a previously interrupted thread's stack.
*/ */
uint32_t isr_dispatch_disable; 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; } CPU_Per_CPU_control;
/** /**