summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/sparc/rtems/score/cpu.h
diff options
context:
space:
mode:
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 );