summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/sparc/rtems/score/cpu.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-07-17 07:30:46 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-07-25 11:41:12 +0200
commit146adb1edfaa0271ee0df5180a1f64d54e6e860d (patch)
tree4957ce3cfe1c5818ab121bf11465e131042f4952 /cpukit/score/cpu/sparc/rtems/score/cpu.h
parentINTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT (diff)
downloadrtems-146adb1edfaa0271ee0df5180a1f64d54e6e860d.tar.bz2
sparc: Add lazy floating point switch
The SPARC ABI is a bit special with respect to the floating point context. The complete floating point context is volatile. Thus, from an ABI point of view nothing needs to be saved and restored during a context switch. Instead the floating point context must be saved and restored during interrupt processing. Historically, the deferred floating point switch was used for SPARC and the complete floating point context is saved and restored during a context switch to the new floating point unit owner. This is a bit dangerous since post-switch actions (e.g. signal handlers) and context switch extensions may silently corrupt the floating point context. The floating point unit is disabled for interrupt handlers. Thus, in case an interrupt handler uses the floating point unit then this will result in a trap (INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT). In uniprocessor configurations, a lazy floating point context switch is used. In case an active floating point thread is interrupted (PSR[EF] == 1) and a thread dispatch is carried out, then this thread is registered as the floating point owner. When a floating point owner is present during a context switch, the floating point unit is disabled for the heir thread (PSR[EF] == 0). The floating point disabled trap checks that the use of the floating point unit is allowed and saves/restores the floating point context on demand. Update #3077.
Diffstat (limited to 'cpukit/score/cpu/sparc/rtems/score/cpu.h')
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/cpu.h115
1 files changed, 49 insertions, 66 deletions
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index 48db756ea6..2b50592e08 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -30,17 +30,28 @@ extern "C" {
/*
* The SPARC ABI is a bit special with respect to the floating point context.
- * The complete floating point context is volatile. Thus from an ABI point
+ * The complete floating point context is volatile. Thus, from an ABI point
* of view nothing needs to be saved and restored during a context switch.
* Instead the floating point context must be saved and restored during
- * interrupt processing. Historically, the deferred floating point switch is
+ * interrupt processing. Historically, the deferred floating point switch was
* used for SPARC and the complete floating point context is saved and
* restored during a context switch to the new floating point unit owner.
* This is a bit dangerous since post-switch actions (e.g. signal handlers)
* and context switch extensions may silently corrupt the floating point
- * context. The floating point unit is disabled for interrupt handlers.
- * Thus in case an interrupt handler uses the floating point unit then this
- * will result in a trap.
+ * context.
+ *
+ * The floating point unit is disabled for interrupt handlers. Thus, in case
+ * an interrupt handler uses the floating point unit then this will result in a
+ * trap (INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT).
+ *
+ * In uniprocessor configurations, a lazy floating point context switch is
+ * used. In case an active floating point thread is interrupted (PSR[EF] == 1)
+ * and a thread dispatch is carried out, then this thread is registered as the
+ * floating point owner. When a floating point owner is present during a
+ * context switch, the floating point unit is disabled for the heir thread
+ * (PSR[EF] == 0). The floating point disabled trap checks that the use of the
+ * floating point unit is allowed and saves/restores the floating point context
+ * on demand.
*
* In SMP configurations, the deferred floating point switch is not supported
* in principle. So, use here a synchronous floating point switching.
@@ -52,6 +63,8 @@ extern "C" {
#if SPARC_HAS_FPU == 1
#if defined(RTEMS_SMP)
#define SPARC_USE_SYNCHRONOUS_FP_SWITCH
+ #else
+ #define SPARC_USE_LAZY_FP_SWITCH
#endif
#endif
@@ -152,28 +165,7 @@ extern "C" {
*/
#define CPU_IDLE_TASK_IS_FP FALSE
-/**
- * Should the saving of the floating point registers be deferred
- * until a context switch is made to another different floating point
- * task?
- *
- * - If TRUE, then the floating point context will not be stored until
- * necessary. It will remain in the floating point registers and not
- * disturned until another floating point task is switched to.
- *
- * - If FALSE, then the floating point context is saved when a floating
- * point task is switched out and restored when the next floating point
- * task is restored. The state of the floating point registers between
- * those two operations is not specified.
- *
- * On the SPARC, we can disable the FPU for integer only tasks so
- * it is safe to defer floating point context switches.
- */
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
- #define CPU_USE_DEFERRED_FP_SWITCH FALSE
-#else
- #define CPU_USE_DEFERRED_FP_SWITCH TRUE
-#endif
+#define CPU_USE_DEFERRED_FP_SWITCH FALSE
#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
@@ -356,6 +348,7 @@ typedef struct {
/**@{**/
#ifndef ASM
+typedef struct Context_Control_fp Context_Control_fp;
/**
* @brief SPARC basic context.
@@ -433,6 +426,10 @@ typedef struct {
*/
uint32_t isr_dispatch_disable;
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+ Context_Control_fp *fp_context;
+#endif
+
#if defined(RTEMS_SMP)
volatile uint32_t is_executing;
#endif
@@ -528,7 +525,7 @@ typedef struct {
*
* This structure defines floating point context area.
*/
-typedef struct {
+struct Context_Control_fp {
/** This will contain the contents of the f0 and f1 register. */
double f0_f1;
/** This will contain the contents of the f2 and f3 register. */
@@ -563,7 +560,7 @@ typedef struct {
double f30_f31;
/** This will contain the contents of the floating point status register. */
uint32_t fsr;
-} Context_Control_fp;
+};
#endif /* ASM */
@@ -670,13 +667,6 @@ typedef struct {
#ifndef ASM
/**
- * This variable is contains the initialize context for the FP unit.
- * It is filled in by _CPU_Initialize and copied into the task's FP
- * context area during _CPU_Context_Initialize.
- */
-extern Context_Control_fp _CPU_Null_fp_context;
-
-/**
* The following type defines an entry in the SPARC's trap table.
*
* NOTE: The instructions chosen are RTEMS dependent although one is
@@ -958,18 +948,22 @@ void _CPU_Context_Initialize(
_CPU_Context_restore( (_the_context) );
/**
- * This routine initializes the FP context area passed to it to.
- *
- * The SPARC allows us to use the simple initialization model
- * in which an "initial" FP context was saved into _CPU_Null_fp_context
- * at CPU initialization and it is simply copied into the destination
- * context.
+ * @brief Nothing to do due to the synchronous or lazy floating point switch.
*/
#define _CPU_Context_Initialize_fp( _destination ) \
- do { \
- *(*(_destination)) = _CPU_Null_fp_context; \
- } while (0)
+ do { } while ( 0 )
+/**
+ * @brief Nothing to do due to the synchronous or lazy floating point switch.
+ */
+#define _CPU_Context_save_fp( _fp_context_ptr ) \
+ do { } while ( 0 )
+
+/**
+ * @brief Nothing to do due to the synchronous or lazy floating point switch.
+ */
+#define _CPU_Context_restore_fp( _fp_context_ptr ) \
+ do { } while ( 0 )
/* end of Context handler macros */
/* Fatal Error manager macros */
@@ -1095,27 +1089,16 @@ void _CPU_Context_restore(
}
#endif
-/**
- * @brief SPARC specific save FPU method.
- *
- * This routine saves the floating point context passed to it.
- *
- * @param[in] fp_context_ptr is the area to save into
- */
-void _CPU_Context_save_fp(
- Context_Control_fp **fp_context_ptr
-);
-
-/**
- * @brief SPARC specific restore FPU method.
- *
- * This routine restores the floating point context passed to it.
- *
- * @param[in] fp_context_ptr is the area to restore from
- */
-void _CPU_Context_restore_fp(
- Context_Control_fp **fp_context_ptr
-);
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+#define _CPU_Context_Destroy( _the_thread, _the_context ) \
+ do { \
+ Per_CPU_Control *cpu_self = _Per_CPU_Get(); \
+ Thread_Control *_fp_owner = cpu_self->cpu_per_cpu.fp_owner; \
+ if ( _fp_owner == _the_thread ) { \
+ cpu_self->cpu_per_cpu.fp_owner = NULL; \
+ } \
+ } while ( 0 )
+#endif
void _CPU_Context_volatile_clobber( uintptr_t pattern );