diff options
Diffstat (limited to 'cpukit/score/cpu/sparc/rtems/score')
-rw-r--r-- | cpukit/score/cpu/sparc/rtems/score/cpu.h | 115 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/rtems/score/cpuimpl.h | 33 |
2 files changed, 82 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 ); diff --git a/cpukit/score/cpu/sparc/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc/rtems/score/cpuimpl.h index 5563db8911..4f2311e755 100644 --- a/cpukit/score/cpu/sparc/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/sparc/rtems/score/cpuimpl.h @@ -67,6 +67,24 @@ /** This defines the size of the ISF area for use in assembly. */ #define CPU_INTERRUPT_FRAME_SIZE SPARC_MINIMUM_STACK_FRAME_SIZE + 0x50 +#define SPARC_FP_CONTEXT_OFFSET_F0_F1 0 +#define SPARC_FP_CONTEXT_OFFSET_F2_F3 8 +#define SPARC_FP_CONTEXT_OFFSET_F4_F5 16 +#define SPARC_FP_CONTEXT_OFFSET_F6_F7 24 +#define SPARC_FP_CONTEXT_OFFSET_F8_F9 32 +#define SPARC_FP_CONTEXT_OFFSET_F10_F11 40 +#define SPARC_FP_CONTEXT_OFFSET_F12_F13 48 +#define SPARC_FP_CONTEXT_OFFSET_F14_F15 56 +#define SPARC_FP_CONTEXT_OFFSET_F16_F17 64 +#define SPARC_FP_CONTEXT_OFFSET_F18_F19 72 +#define SPARC_FP_CONTEXT_OFFSET_F20_F21 80 +#define SPARC_FP_CONTEXT_OFFSET_F22_F23 88 +#define SPARC_FP_CONTEXT_OFFSET_F24_F25 96 +#define SPARC_FP_CONTEXT_OFFSET_F26_F27 104 +#define SPARC_FP_CONTEXT_OFFSET_F28_F29 112 +#define SPARC_FP_CONTEXT_OFFSET_F30_F31 120 +#define SPARC_FP_CONTEXT_OFFSET_FSR 128 + #if ( SPARC_HAS_FPU == 1 ) #define CPU_PER_CPU_CONTROL_SIZE 8 #else @@ -79,6 +97,14 @@ * Per_CPU_Control begin. */ #define SPARC_PER_CPU_FSR_OFFSET 0 + + #if defined(SPARC_USE_LAZY_FP_SWITCH) + /** + * @brief Offset of the CPU_Per_CPU_control::fp_owner field relative to the + * Per_CPU_Control begin. + */ + #define SPARC_PER_CPU_FP_OWNER_OFFSET 4 + #endif #endif #ifndef ASM @@ -98,9 +124,16 @@ typedef struct { */ uint32_t fsr; +#if defined(SPARC_USE_LAZY_FP_SWITCH) + /** + * @brief The current floating point owner. + */ + struct _Thread_Control *fp_owner; +#else /* See Per_CPU_Control::Interrupt_frame */ uint32_t reserved_for_alignment_of_interrupt_frame; #endif +#endif } CPU_Per_CPU_control; /** |