Update #2270. --- cpukit/score/cpu/sparc/cpu.c | 16 ++++++++++++ cpukit/score/cpu/sparc/cpu_asm.S | 44 ++++++++++++++++++++++++++++++++ cpukit/score/cpu/sparc/rtems/score/cpu.h | 22 ++++++++++++++-- 3 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c index bab0040..b2f67c4 100644 --- a/cpukit/score/cpu/sparc/cpu.c +++ b/cpukit/score/cpu/sparc/cpu.c @@ -134,6 +134,10 @@ void _CPU_Initialize(void) #if (SPARC_HAS_FPU == 1) Context_Control_fp *pointer; uint32_t psr; +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + Per_CPU_Control *cpu_self; + uint32_t isr_dispatch_disable; +#endif sparc_get_psr( psr ); psr |= SPARC_PSR_EF_MASK; @@ -146,7 +150,19 @@ void _CPU_Initialize(void) */ pointer = &_CPU_Null_fp_context; + +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + cpu_self = _Per_CPU_Get(); + isr_dispatch_disable = cpu_self->cpu_per_cpu.isr_dispatch_disable; + cpu_self->cpu_per_cpu.isr_dispatch_disable = 1; + pointer->is_valid = 1; +#endif + _CPU_Context_save_fp( &pointer ); + +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + cpu_self->cpu_per_cpu.isr_dispatch_disable = isr_dispatch_disable; +#endif #endif } diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S index 3fa0532..fd63f19 100644 --- a/cpukit/score/cpu/sparc/cpu_asm.S +++ b/cpukit/score/cpu/sparc/cpu_asm.S @@ -44,7 +44,26 @@ .align 4 PUBLIC(_CPU_Context_save_fp) SYM(_CPU_Context_save_fp): +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE ld [%o0], %o1 +#else + /* + * On SMP configurations we cannot use the deferred floating point + * switch. Save the FP context only in case we have an interrupted + * thread (indicated by a non-zero per-CPU ISR dispatch disable flag). + * This works since the complete floating point context is volatile on + * SPARC. + */ + ld [%g6 + SPARC_PER_CPU_ISR_DISPATCH_DISABLE], %o2 + cmp %o2, 0 + bne do_save_fp + ld [%o0], %o1 + jmp %o7 + 8 + nop + +do_save_fp: +#endif + std %f0, [%o1 + FO_F1_OFFSET] std %f2, [%o1 + F2_F3_OFFSET] std %f4, [%o1 + F4_F5_OFFSET] @@ -61,6 +80,15 @@ SYM(_CPU_Context_save_fp): std %f26, [%o1 + F26_F27_OFFSET] std %f28, [%o1 + F28_F29_OFFSET] std %f30, [%o1 + F3O_F31_OFFSET] + +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + /* + * Set the is valid flag of the floating point context to true. It is + * store here to store the fields in sequence. + */ + st %o2, [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET] +#endif + jmp %o7 + 8 st %fsr, [%o1 + FSR_OFFSET] @@ -81,6 +109,22 @@ SYM(_CPU_Context_save_fp): PUBLIC(_CPU_Context_restore_fp) SYM(_CPU_Context_restore_fp): ld [%o0], %o1 + +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + /* + * Check if we have a valid floating point context. Clear the is valid + * flag. Restore the floating point context if necessary. + */ + ld [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET], %o2 + cmp %o2, 0 + bne do_restore_fp + st %g0, [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET] + jmp %o7 + 8 + nop + +do_restore_fp: +#endif + ldd [%o1 + FO_F1_OFFSET], %f0 ldd [%o1 + F2_F3_OFFSET], %f2 ldd [%o1 + F4_F5_OFFSET], %f4 diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h index 02891b0..e51a4ab 100644 --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h @@ -609,6 +609,10 @@ typedef struct { double f28_f29; /** This will contain the contents of the f30 and f31 register. */ double f30_f31; +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + /** Indicates if the context is valid. */ + uint32_t is_valid; +#endif /** This will contain the contents of the floating point status register. */ uint32_t fsr; } Context_Control_fp; @@ -651,11 +655,25 @@ typedef struct { #define F28_F29_OFFSET 0x70 /** This macro defines an offset into the FPU context for use in assembly. */ #define F3O_F31_OFFSET 0x78 + +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE + /** This macro defines an offset into the FPU context for use in assembly. */ + #define SPARC_FP_CONTEXT_IS_VALID_OFFSET 0x80 +#endif + /** This macro defines an offset into the FPU context for use in assembly. */ -#define FSR_OFFSET 0x80 +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE + #define FSR_OFFSET 0x80 +#else + #define FSR_OFFSET 0x84 +#endif /** This defines the size of the FPU context area for use in assembly. */ -#define CONTEXT_CONTROL_FP_SIZE 0x84 +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE + #define CONTEXT_CONTROL_FP_SIZE 0x84 +#else + #define CONTEXT_CONTROL_FP_SIZE 0x88 +#endif #ifndef ASM -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel