Changeset 146adb1 in rtems


Ignore:
Timestamp:
Jul 17, 2017, 5:30:46 AM (2 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
3a3d85c
Parents:
600d88d
git-author:
Sebastian Huber <sebastian.huber@…> (07/17/17 05:30:46)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/25/17 09:41:12)
Message:

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.

Files:
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/erc32/startup/spurious.c

    r600d88d r146adb1  
    134134  };
    135135
     136#if !defined(SPARC_USE_LAZY_FP_SWITCH)
    136137  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
    137138    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
    138139  }
     140#endif
    139141
    140142  rtems_fatal(
     
    171173
    172174    if (( trap == 5 || trap == 6 ) ||
     175#if defined(SPARC_USE_LAZY_FP_SWITCH)
     176        ( trap == 4 ) ||
     177#endif
    173178        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
    174179        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
    175180        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
    176 #if SPARC_HAS_FPU == 1
     181#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    177182        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
    178183#endif
  • c/src/lib/libbsp/sparc/leon2/startup/spurious.c

    r600d88d r146adb1  
    121121  };
    122122
     123#if !defined(SPARC_USE_LAZY_FP_SWITCH)
    123124  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
    124125    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
    125126  }
     127#endif
    126128
    127129  rtems_fatal(
     
    158160
    159161    if (( trap == 5 || trap == 6 ) ||
     162#if defined(SPARC_USE_LAZY_FP_SWITCH)
     163        ( trap == 4 ) ||
     164#endif
    160165        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
    161166        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
    162167        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
    163 #if SPARC_HAS_FPU == 1
     168#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    164169        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
    165170#endif
  • c/src/lib/libbsp/sparc/leon3/startup/spurious.c

    r600d88d r146adb1  
    120120  };
    121121
     122#if !defined(SPARC_USE_LAZY_FP_SWITCH)
    122123  if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) {
    123124    _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT );
    124125  }
     126#endif
    125127
    126128  rtems_fatal(
     
    157159
    158160    if (( trap == 5 ) || ( trap == 6 ) ||
     161#if defined(SPARC_USE_LAZY_FP_SWITCH)
     162        ( trap == 4 ) ||
     163#endif
    159164        (( trap >= 0x11 ) && ( trap <= 0x1f )) ||
    160165        (( trap >= 0x70 ) && ( trap <= 0x83 )) ||
    161166        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) ||
    162 #if SPARC_HAS_FPU == 1
     167#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    163168        ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) ||
    164169#endif
  • c/src/lib/libbsp/sparc/shared/irq_asm.S

    r600d88d r146adb1  
    88 *  On-Line Applications Research Corporation (OAR).
    99 *
    10  *  Copyright (c) 2014, 2016 embedded brains GmbH
     10 *  Copyright (c) 2014, 2017 embedded brains GmbH
    1111 *
    1212 *  The license and distribution terms for this file may be
     
    219219#endif
    220220
     221#if defined(SPARC_USE_LAZY_FP_SWITCH)
     222        ld      [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %g2
     223#endif
    221224        ld      [%o1 + PSR_OFFSET], %g1       ! g1 = heir psr with traps enabled
     225#if defined(SPARC_USE_LAZY_FP_SWITCH)
     226        sethi   %hi(SPARC_PSR_EF_MASK), %g5
     227        cmp     %g2, %g0
     228        bne,a   .Lclear_psr_ef_done
     229         andn   %g1, %g5, %g1                 ! g1 = heir psr w/o PSR[EF]
     230.Lclear_psr_ef_done:
     231#endif
    222232        andn    %g1, SPARC_PSR_CWP_MASK, %g1  ! g1 = heir psr w/o cwp
    223233        or      %g1, %g3, %g1                 ! g1 = heir psr with cwp
     
    584594#endif
    585595
    586 #if SPARC_HAS_FPU == 1
     596#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    587597        mov      %l0, %g1               ! PSR[EF] value of interrupted context
    588598        ta       SPARC_SWTRAP_IRQDIS_FP ! **** DISABLE INTERRUPTS ****
     
    653663        mov      0, %o1                 ! ISR level for _Thread_Do_dispatch()
    654664
    655 #if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
     665#if defined(SPARC_USE_LAZY_FP_SWITCH)
    656666        /* Test if we interrupted a floating point thread (PSR[EF] == 1) */
    657667        andcc   %l0, %l5, %g0
    658         be      non_fp_thread_dispatch
     668        be      .Lnon_fp_thread_dispatch
     669         ld     [%g6 + PER_CPU_OFFSET_EXECUTING], %l6
     670
     671        /* Set new floating point unit owner to executing thread */
     672        st      %l6, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
     673
     674        call    SYM(_Thread_Do_dispatch)
     675         mov    %g6, %o0
     676
     677        /*
     678         * If we are still the floating point unit owner, then reset the
     679         * floating point unit owner to NULL, otherwise clear PSR[EF] in the
     680         * interrupt frame and let the FP disabled system call do the floating
     681         * point context save/restore.
     682         */
     683        ld      [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7
     684        cmp     %l6, %l7
     685        bne     .Ldisable_fp
     686         andn   %l0, %l5, %l0
     687        ba      .Lthread_dispatch_done
     688         st     %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
     689.Ldisable_fp:
     690        ba      .Lthread_dispatch_done
     691         st      %l0, [%fp + ISF_PSR_OFFSET]
     692.Lnon_fp_thread_dispatch:
     693#elif defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
     694        /* Test if we interrupted a floating point thread (PSR[EF] == 1) */
     695        andcc   %l0, %l5, %g0
     696        be      .Lnon_fp_thread_dispatch
    659697         nop
    660698
     
    723761        ldd     [%sp + FP_FRAME_OFFSET_F3O_F31], %f30
    724762        ld      [%sp + FP_FRAME_OFFSET_FSR], %fsr
    725         ba      thread_dispatch_done
     763        ba      .Lthread_dispatch_done
    726764         add    %sp, FP_FRAME_SIZE, %sp
    727765
    728 non_fp_thread_dispatch:
     766.Lnon_fp_thread_dispatch:
    729767#endif
    730768
     
    732770         mov    %g6, %o0
    733771
    734 #if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    735 thread_dispatch_done:
     772#if SPARC_HAS_FPU == 1
     773.Lthread_dispatch_done:
    736774#endif
    737775
  • c/src/lib/libbsp/sparc/shared/start/start.S

    r600d88d r146adb1  
    3636 * System call optimized trap table entry
    3737 */
     38#define FPDIS_TRAP(_handler)  \
     39  mov   %psr, %l0 ; \
     40  sethi %hi(_handler), %l4 ; \
     41  jmp   %l4+%lo(_handler); \
     42   sethi %hi(SPARC_PSR_EF_MASK), %l3
     43
     44/*
     45 * System call optimized trap table entry
     46 */
    3847#define IRQDIS_TRAP(_handler)  \
    3948  mov   %psr, %l0 ; \
     
    101110  BAD_TRAP;                                     ! 02 illegal instruction
    102111  BAD_TRAP;                                     ! 03 privileged instruction
     112#if defined(SPARC_USE_LAZY_FP_SWITCH)
     113  FPDIS_TRAP(SYM(syscall_lazy_fp_switch));      ! 04 fp disabled
     114#else
    103115  BAD_TRAP;                                     ! 04 fp disabled
     116#endif
    104117  WOTRAP(5, SYM(window_overflow_trap_handler)); ! 05 window overflow
    105118  WUTRAP(6, SYM(window_underflow_trap_handler));! 06 window underflow
     
    210223  IRQDIS_TRAP(SYM(syscall_irqdis));             ! 89 IRQ Disable syscall trap
    211224  IRQEN_TRAP(SYM(syscall_irqen));               ! 8A IRQ Enable syscall trap
    212 #if SPARC_HAS_FPU == 1
     225#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    213226  IRQDIS_TRAP(SYM(syscall_irqdis_fp));          ! 8B IRQ disable
    214227                                                ! and set PSR[EF] syscall trap
  • c/src/lib/libcpu/sparc/syscall/syscall.S

    r600d88d r146adb1  
    1212 *
    1313 *  COPYRIGHT (c) 1995. European Space Agency.
     14 *  Copyright (c) 2016, 2017 embedded brains GmbH
    1415 *
    1516 *  This terms of the RTEMS license apply to this file.
     
    1819
    1920#include <rtems/asm.h>
     21#include <rtems/score/cpuimpl.h>
     22#include <rtems/score/percpu.h>
    2023#include "syscall.h"
    2124
     
    9699         rett   %l2 + 4
    97100
    98 #if SPARC_HAS_FPU == 1
     101#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    99102        /*
    100103         *  system call - Interrupt disable and set PSR[EF] according to caller
     
    133136#endif
    134137
     138#if defined(SPARC_USE_LAZY_FP_SWITCH)
     139
     140        /*
     141         *  system call - Perform a lazy floating point switch
     142         *
     143         *  On entry:
     144         *
     145         *    l0 = psr (from trap table)
     146         *    l1 = pc
     147         *    l2 = npc
     148         *    l3 = SPARC_PSR_EF_MASK
     149         */
     150
     151.align 32                               ! Align to 32-byte cache-line
     152        PUBLIC(syscall_lazy_fp_switch)
     153
     154SYM(syscall_lazy_fp_switch):
     155        ld      [%g6 + PER_CPU_OFFSET_EXECUTING], %l4
     156        ld      [%g6 + PER_CPU_ISR_NEST_LEVEL], %l5
     157        ld      [%l4 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l6
     158        ld      [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7
     159
     160        /* Ensure that we are not in interrupt context */
     161        cmp     %l5, 0
     162        bne     .Lillegal_use_of_floating_point_unit
     163         or     %l0, %l3, %l0
     164
     165        /* Ensure that we are a proper floating point thread */
     166        cmp     %l6, 0
     167        be      .Lillegal_use_of_floating_point_unit
     168         ld     [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)], %l6
     169
     170        /* Set PSR[EF] to 1, PSR write delay 3 instructions! */
     171        mov     %l0, %psr
     172
     173        /*
     174         * Check if there is a floating point owner.  We have to check this
     175         * here, since the floating point owner may have been deleted in the
     176         * meantime.  Save the floating point context if necessary.
     177         */
     178        cmp     %l7, 0
     179        be      .Lfp_save_done
     180         nop
     181        ld      [%l7 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l5
     182        std     %f0, [%l5 + SPARC_FP_CONTEXT_OFFSET_F0_F1]
     183        SPARC_LEON3FT_B2BST_NOP
     184        std     %f2, [%l5 + SPARC_FP_CONTEXT_OFFSET_F2_F3]
     185        SPARC_LEON3FT_B2BST_NOP
     186        std     %f4, [%l5 + SPARC_FP_CONTEXT_OFFSET_F4_F5]
     187        SPARC_LEON3FT_B2BST_NOP
     188        std     %f6, [%l5 + SPARC_FP_CONTEXT_OFFSET_F6_F7]
     189        SPARC_LEON3FT_B2BST_NOP
     190        std     %f8, [%l5 + SPARC_FP_CONTEXT_OFFSET_F8_F9]
     191        SPARC_LEON3FT_B2BST_NOP
     192        std     %f10, [%l5 + SPARC_FP_CONTEXT_OFFSET_F10_F11]
     193        SPARC_LEON3FT_B2BST_NOP
     194        std     %f12, [%l5 + SPARC_FP_CONTEXT_OFFSET_F12_F13]
     195        SPARC_LEON3FT_B2BST_NOP
     196        std     %f14, [%l5 + SPARC_FP_CONTEXT_OFFSET_F14_F15]
     197        SPARC_LEON3FT_B2BST_NOP
     198        std     %f16, [%l5 + SPARC_FP_CONTEXT_OFFSET_F16_F17]
     199        SPARC_LEON3FT_B2BST_NOP
     200        std     %f18, [%l5 + SPARC_FP_CONTEXT_OFFSET_F18_F19]
     201        SPARC_LEON3FT_B2BST_NOP
     202        std     %f20, [%l5 + SPARC_FP_CONTEXT_OFFSET_F20_F21]
     203        SPARC_LEON3FT_B2BST_NOP
     204        std     %f22, [%l5 + SPARC_FP_CONTEXT_OFFSET_F22_F23]
     205        SPARC_LEON3FT_B2BST_NOP
     206        std     %f24, [%l5 + SPARC_FP_CONTEXT_OFFSET_F24_F25]
     207        SPARC_LEON3FT_B2BST_NOP
     208        std     %f26, [%l5 + SPARC_FP_CONTEXT_OFFSET_F26_F27]
     209        SPARC_LEON3FT_B2BST_NOP
     210        std     %f28, [%l5 + SPARC_FP_CONTEXT_OFFSET_F28_F29]
     211        SPARC_LEON3FT_B2BST_NOP
     212        std     %f30, [%l5 + SPARC_FP_CONTEXT_OFFSET_F30_F31]
     213        SPARC_LEON3FT_B2BST_NOP
     214        st      %fsr, [%l5 + SPARC_FP_CONTEXT_OFFSET_FSR]
     215        SPARC_LEON3FT_B2BST_NOP
     216        st      %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
     217        SPARC_LEON3FT_B2BST_NOP
     218        st      %l5, [%l7 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
     219
     220.Lfp_save_done:
     221
     222        /* Restore the floating point context if necessary */
     223        cmp     %l6, 0
     224        be      .Lfp_restore_done
     225         st     %g0, [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
     226        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F0_F1], %f0
     227        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F2_F3], %f2
     228        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F4_F5], %f4
     229        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F6_F7], %f6
     230        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F8_F9], %f8
     231        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F10_F11], %f10
     232        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F12_F13], %f12
     233        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F14_F15], %f14
     234        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F16_F17], %f16
     235        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F18_F19], %f18
     236        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F20_F21], %f20
     237        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F22_F23], %f22
     238        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F24_F25], %f24
     239        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F26_F27], %f26
     240        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F28_F29], %f28
     241        ldd     [%l6 + SPARC_FP_CONTEXT_OFFSET_F30_F31], %f30
     242        ld      [%l6 + SPARC_FP_CONTEXT_OFFSET_FSR], %fsr
     243
     244.Lfp_restore_done:
     245
     246        /* Now, retry the floating point instruction with PSR[EF] == 1 */
     247        jmp     %l1
     248         rett   %l1 + 4
     249
     250.Lillegal_use_of_floating_point_unit:
     251
     252        sethi   %hi(_Internal_error), %l1
     253        or      %l1, %lo(_Internal_error), %l1
     254        mov     38, %i0
     255        jmp     %l1
     256         rett   %l1 + 4
     257#endif
     258
    135259#if defined(RTEMS_PARAVIRT)
    136260
  • cpukit/score/cpu/sparc/Makefile.am

    r600d88d r146adb1  
    1313
    1414noinst_LIBRARIES = libscorecpu.a
    15 libscorecpu_a_SOURCES = cpu.c cpu_asm.S
     15libscorecpu_a_SOURCES = cpu.c
    1616libscorecpu_a_SOURCES += sparc-context-volatile-clobber.S
    1717libscorecpu_a_SOURCES += sparc-context-validate.S
  • cpukit/score/cpu/sparc/cpu.c

    r600d88d r146adb1  
    88 *  COPYRIGHT (c) 1989-2007.
    99 *  On-Line Applications Research Corporation (OAR).
     10 *
     11 *  Copyright (c) 2017 embedded brains GmbH
    1012 *
    1113 *  The license and distribution terms for this file may be
     
    2224#include <rtems/score/percpu.h>
    2325#include <rtems/score/tls.h>
     26#include <rtems/score/thread.h>
    2427#include <rtems/rtems/cache.h>
    2528
     
    3033    SPARC_PER_CPU_FSR_OFFSET
    3134  );
     35
     36  #if defined(SPARC_USE_LAZY_FP_SWITCH)
     37    RTEMS_STATIC_ASSERT(
     38      offsetof( Per_CPU_Control, cpu_per_cpu.fp_owner)
     39        == SPARC_PER_CPU_FP_OWNER_OFFSET,
     40      SPARC_PER_CPU_FP_OWNER_OFFSET
     41    );
     42  #endif
    3243#endif
    3344
     
    100111SPARC_ASSERT_ISF_OFFSET(tpc, TPC);
    101112
     113#define SPARC_ASSERT_FP_OFFSET(field, off) \
     114  RTEMS_STATIC_ASSERT( \
     115    offsetof(Context_Control_fp, field) == SPARC_FP_CONTEXT_OFFSET_ ## off, \
     116    Context_Control_fp_offset_ ## field \
     117  )
     118
     119SPARC_ASSERT_FP_OFFSET(f0_f1, F0_F1);
     120SPARC_ASSERT_FP_OFFSET(f2_f3, F2_F3);
     121SPARC_ASSERT_FP_OFFSET(f4_f5, F4_F5);
     122SPARC_ASSERT_FP_OFFSET(f6_f7, F6_F7);
     123SPARC_ASSERT_FP_OFFSET(f8_f9, F8_F9);
     124SPARC_ASSERT_FP_OFFSET(f10_f11, F10_F11);
     125SPARC_ASSERT_FP_OFFSET(f12_f13, F12_F13);
     126SPARC_ASSERT_FP_OFFSET(f14_f15, F14_F15);
     127SPARC_ASSERT_FP_OFFSET(f16_f17, F16_F17);
     128SPARC_ASSERT_FP_OFFSET(f18_f19, F18_F19);
     129SPARC_ASSERT_FP_OFFSET(f20_f21, F20_F21);
     130SPARC_ASSERT_FP_OFFSET(f22_f23, F22_F23);
     131SPARC_ASSERT_FP_OFFSET(f24_f25, F24_F25);
     132SPARC_ASSERT_FP_OFFSET(f26_f27, F26_F27);
     133SPARC_ASSERT_FP_OFFSET(f28_f29, F28_F29);
     134SPARC_ASSERT_FP_OFFSET(f30_f31, F30_F31);
     135SPARC_ASSERT_FP_OFFSET(fsr, FSR);
     136
    102137RTEMS_STATIC_ASSERT(
    103138  sizeof(SPARC_Minimum_stack_frame) == SPARC_MINIMUM_STACK_FRAME_SIZE,
     
    111146);
    112147
    113 #if (SPARC_HAS_FPU == 1) && !defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    114 Context_Control_fp _CPU_Null_fp_context;
    115 #endif
    116 
    117148/*
    118149 *  _CPU_Initialize
     
    130161void _CPU_Initialize(void)
    131162{
    132 #if (SPARC_HAS_FPU == 1) && !defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    133   Context_Control_fp *pointer;
    134   uint32_t            psr;
    135 
    136   sparc_get_psr( psr );
    137   psr |= SPARC_PSR_EF_MASK;
    138   sparc_set_psr( psr );
    139 
    140   /*
    141    *  This seems to be the most appropriate way to obtain an initial
    142    *  FP context on the SPARC.  The NULL fp context is copied it to
    143    *  the task's FP context during Context_Initialize.
    144    */
    145 
    146   pointer = &_CPU_Null_fp_context;
    147   _CPU_Context_save_fp( &pointer );
     163#if defined(SPARC_USE_LAZY_FP_SWITCH)
     164  __asm__ volatile (
     165    ".global SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET\n"
     166    ".set SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET, %0\n"
     167    ".global SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET\n"
     168    ".set SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET, %1\n"
     169    :
     170    : "i" (offsetof(Thread_Control, Registers.fp_context)),
     171      "i" (offsetof(Thread_Control, fp_context))
     172  );
    148173#endif
    149174}
  • cpukit/score/cpu/sparc/rtems/score/cpu.h

    r600d88d r146adb1  
    3131/*
    3232 * The SPARC ABI is a bit special with respect to the floating point context.
    33  * The complete floating point context is volatile.  Thus from an ABI point
     33 * The complete floating point context is volatile.  Thus, from an ABI point
    3434 * of view nothing needs to be saved and restored during a context switch.
    3535 * Instead the floating point context must be saved and restored during
    36  * interrupt processing.  Historically, the deferred floating point switch is
     36 * interrupt processing.  Historically, the deferred floating point switch was
    3737 * used for SPARC and the complete floating point context is saved and
    3838 * restored during a context switch to the new floating point unit owner.
    3939 * This is a bit dangerous since post-switch actions (e.g. signal handlers)
    4040 * and context switch extensions may silently corrupt the floating point
    41  * context.  The floating point unit is disabled for interrupt handlers.
    42  * Thus in case an interrupt handler uses the floating point unit then this
    43  * will result in a trap.
     41 * context.
     42 *
     43 * The floating point unit is disabled for interrupt handlers.  Thus, in case
     44 * an interrupt handler uses the floating point unit then this will result in a
     45 * trap (INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT).
     46 *
     47 * In uniprocessor configurations, a lazy floating point context switch is
     48 * used.  In case an active floating point thread is interrupted (PSR[EF] == 1)
     49 * and a thread dispatch is carried out, then this thread is registered as the
     50 * floating point owner.  When a floating point owner is present during a
     51 * context switch, the floating point unit is disabled for the heir thread
     52 * (PSR[EF] == 0).  The floating point disabled trap checks that the use of the
     53 * floating point unit is allowed and saves/restores the floating point context
     54 * on demand.
    4455 *
    4556 * In SMP configurations, the deferred floating point switch is not supported
     
    5364  #if defined(RTEMS_SMP)
    5465    #define SPARC_USE_SYNCHRONOUS_FP_SWITCH
     66  #else
     67    #define SPARC_USE_LAZY_FP_SWITCH
    5568  #endif
    5669#endif
     
    153166#define CPU_IDLE_TASK_IS_FP      FALSE
    154167
    155 /**
    156  * Should the saving of the floating point registers be deferred
    157  * until a context switch is made to another different floating point
    158  * task?
    159  *
    160  * - If TRUE, then the floating point context will not be stored until
    161  * necessary.  It will remain in the floating point registers and not
    162  * disturned until another floating point task is switched to.
    163  *
    164  * - If FALSE, then the floating point context is saved when a floating
    165  * point task is switched out and restored when the next floating point
    166  * task is restored.  The state of the floating point registers between
    167  * those two operations is not specified.
    168  *
    169  * On the SPARC, we can disable the FPU for integer only tasks so
    170  * it is safe to defer floating point context switches.
    171  */
    172 #if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
    173   #define CPU_USE_DEFERRED_FP_SWITCH FALSE
    174 #else
    175   #define CPU_USE_DEFERRED_FP_SWITCH TRUE
    176 #endif
     168#define CPU_USE_DEFERRED_FP_SWITCH FALSE
    177169
    178170#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
     
    357349
    358350#ifndef ASM
     351typedef struct Context_Control_fp Context_Control_fp;
    359352
    360353/**
     
    434427  uint32_t   isr_dispatch_disable;
    435428
     429#if defined(SPARC_USE_LAZY_FP_SWITCH)
     430  Context_Control_fp *fp_context;
     431#endif
     432
    436433#if defined(RTEMS_SMP)
    437434  volatile uint32_t is_executing;
     
    529526 * This structure defines floating point context area.
    530527 */
    531 typedef struct {
     528struct Context_Control_fp {
    532529  /** This will contain the contents of the f0 and f1 register. */
    533530  double      f0_f1;
     
    564561  /** This will contain the contents of the floating point status register. */
    565562  uint32_t    fsr;
    566 } Context_Control_fp;
     563};
    567564
    568565#endif /* ASM */
     
    671668#ifndef ASM
    672669/**
    673  * This variable is contains the initialize context for the FP unit.
    674  * It is filled in by _CPU_Initialize and copied into the task's FP
    675  * context area during _CPU_Context_Initialize.
    676  */
    677 extern Context_Control_fp _CPU_Null_fp_context;
    678 
    679 /**
    680670 * The following type defines an entry in the SPARC's trap table.
    681671 *
     
    959949
    960950/**
    961  * This routine initializes the FP context area passed to it to.
    962  *
    963  * The SPARC allows us to use the simple initialization model
    964  * in which an "initial" FP context was saved into _CPU_Null_fp_context
    965  * at CPU initialization and it is simply copied into the destination
    966  * context.
     951 * @brief Nothing to do due to the synchronous or lazy floating point switch.
    967952 */
    968953#define _CPU_Context_Initialize_fp( _destination ) \
    969   do { \
    970    *(*(_destination)) = _CPU_Null_fp_context; \
    971   } while (0)
    972 
     954  do { } while ( 0 )
     955
     956/**
     957 * @brief Nothing to do due to the synchronous or lazy floating point switch.
     958 */
     959#define _CPU_Context_save_fp( _fp_context_ptr ) \
     960  do { } while ( 0 )
     961
     962/**
     963 * @brief Nothing to do due to the synchronous or lazy floating point switch.
     964 */
     965#define _CPU_Context_restore_fp( _fp_context_ptr ) \
     966  do { } while ( 0 )
    973967/* end of Context handler macros */
    974968
     
    10961090#endif
    10971091
    1098 /**
    1099  * @brief SPARC specific save FPU method.
    1100  *
    1101  * This routine saves the floating point context passed to it.
    1102  *
    1103  * @param[in] fp_context_ptr is the area to save into
    1104  */
    1105 void _CPU_Context_save_fp(
    1106   Context_Control_fp **fp_context_ptr
    1107 );
    1108 
    1109 /**
    1110  * @brief SPARC specific restore FPU method.
    1111  *
    1112  * This routine restores the floating point context passed to it.
    1113  *
    1114  * @param[in] fp_context_ptr is the area to restore from
    1115  */
    1116 void _CPU_Context_restore_fp(
    1117   Context_Control_fp **fp_context_ptr
    1118 );
     1092#if defined(SPARC_USE_LAZY_FP_SWITCH)
     1093#define _CPU_Context_Destroy( _the_thread, _the_context ) \
     1094  do { \
     1095    Per_CPU_Control *cpu_self = _Per_CPU_Get(); \
     1096    Thread_Control *_fp_owner = cpu_self->cpu_per_cpu.fp_owner; \
     1097    if ( _fp_owner == _the_thread ) { \
     1098      cpu_self->cpu_per_cpu.fp_owner = NULL; \
     1099    } \
     1100  } while ( 0 )
     1101#endif
    11191102
    11201103void _CPU_Context_volatile_clobber( uintptr_t pattern );
  • cpukit/score/cpu/sparc/rtems/score/cpuimpl.h

    r600d88d r146adb1  
    6868#define CPU_INTERRUPT_FRAME_SIZE SPARC_MINIMUM_STACK_FRAME_SIZE + 0x50
    6969
     70#define SPARC_FP_CONTEXT_OFFSET_F0_F1 0
     71#define SPARC_FP_CONTEXT_OFFSET_F2_F3 8
     72#define SPARC_FP_CONTEXT_OFFSET_F4_F5 16
     73#define SPARC_FP_CONTEXT_OFFSET_F6_F7 24
     74#define SPARC_FP_CONTEXT_OFFSET_F8_F9 32
     75#define SPARC_FP_CONTEXT_OFFSET_F10_F11 40
     76#define SPARC_FP_CONTEXT_OFFSET_F12_F13 48
     77#define SPARC_FP_CONTEXT_OFFSET_F14_F15 56
     78#define SPARC_FP_CONTEXT_OFFSET_F16_F17 64
     79#define SPARC_FP_CONTEXT_OFFSET_F18_F19 72
     80#define SPARC_FP_CONTEXT_OFFSET_F20_F21 80
     81#define SPARC_FP_CONTEXT_OFFSET_F22_F23 88
     82#define SPARC_FP_CONTEXT_OFFSET_F24_F25 96
     83#define SPARC_FP_CONTEXT_OFFSET_F26_F27 104
     84#define SPARC_FP_CONTEXT_OFFSET_F28_F29 112
     85#define SPARC_FP_CONTEXT_OFFSET_F30_F31 120
     86#define SPARC_FP_CONTEXT_OFFSET_FSR 128
     87
    7088#if ( SPARC_HAS_FPU == 1 )
    7189  #define CPU_PER_CPU_CONTROL_SIZE 8
     
    8098   */
    8199  #define SPARC_PER_CPU_FSR_OFFSET 0
     100
     101  #if defined(SPARC_USE_LAZY_FP_SWITCH)
     102    /**
     103     * @brief Offset of the CPU_Per_CPU_control::fp_owner field relative to the
     104     * Per_CPU_Control begin.
     105     */
     106    #define SPARC_PER_CPU_FP_OWNER_OFFSET 4
     107  #endif
    82108#endif
    83109
     
    99125  uint32_t fsr;
    100126
     127#if defined(SPARC_USE_LAZY_FP_SWITCH)
     128  /**
     129   * @brief The current floating point owner.
     130   */
     131  struct _Thread_Control *fp_owner;
     132#else
    101133  /* See Per_CPU_Control::Interrupt_frame */
    102134  uint32_t reserved_for_alignment_of_interrupt_frame;
     135#endif
    103136#endif
    104137} CPU_Per_CPU_control;
  • cpukit/score/cpu/sparc/sparc-context-validate.S

    r600d88d r146adb1  
    11/*
    2  * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2015, 2017 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    1919#include <rtems/asm.h>
    2020#include <rtems/score/cpuimpl.h>
     21#include <rtems/score/percpu.h>
    2122
    2223#define FRAME_OFFSET_BUFFER_0 (SPARC_MINIMUM_STACK_FRAME_SIZE)
     
    7475SYM(_CPU_Context_validate):
    7576
    76         /*
    77          * g2 checks if the Floating Point Unit in the Processor Status
    78          * Register (PSR) is set.
    79          */
     77        /* g2 indicates if the FPU should be checked */
     78#if defined(SPARC_USE_LAZY_FP_SWITCH)
     79        ld      [%g6 + PER_CPU_OFFSET_EXECUTING], %g2
     80        ld      [%g2 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %g2
     81#else
    8082        mov     %psr, %g2
    8183        sethi   %hi(SPARC_PSR_EF_MASK), %g3
    8284        and     %g2, %g3, %g2
     85#endif
    8386
    8487        /* g1 is used to save the original pattern */
  • testsuites/sptests/spfatal30/init.c

    r600d88d r146adb1  
    2424const char rtems_test_name[] = "SPFATAL 30";
    2525
    26 #if CPU_HARDWARE_FP == TRUE && CPU_ALL_TASKS_ARE_FP == FALSE
     26#if (CPU_HARDWARE_FP == TRUE && CPU_ALL_TASKS_ARE_FP == FALSE) \
     27  || SPARC_HAS_FPU == 1
    2728#define EXPECT_ILLEGAL_USE_OF_FLOATING_POINT_UNIT
    2829#endif
  • testsuites/sptests/spfatal31/init.c

    r600d88d r146adb1  
    2424const char rtems_test_name[] = "SPFATAL 31";
    2525
    26 #if CPU_HARDWARE_FP == TRUE && defined(__sparc__)
     26#if SPARC_HAS_FPU == 1
    2727#define EXPECT_ILLEGAL_USE_OF_FLOATING_POINT_UNIT
    2828#endif
  • testsuites/sptests/spsize/size.c

    r600d88d r146adb1  
    411411/* cpu.h */
    412412uninitialized += (sizeof _CPU_Interrupt_stack_low) +
    413                  (sizeof _CPU_Interrupt_stack_high) +
    414                  (sizeof _CPU_Null_fp_context);
     413                 (sizeof _CPU_Interrupt_stack_high);
    415414
    416415#endif
Note: See TracChangeset for help on using the changeset viewer.