Ticket #211: fpctxt.diff

File fpctxt.diff, 7.1 KB (added by strauman, on Dec 3, 2006 at 1:31:13 PM)

fpctxt.diff

Line 
1This patch (against rtems-ss-20020301) fixes saving / restoring
2floating point context.
3The fpsave / fprestore routines are only used in a executing
4context which _is_ fp and hence has the FPU enabled. The current
5behavior required the FPU always to be on which is very dangerous
6if lazy context switching is used.
7
8The patch also makes sure (on powerpc only) that the FPU is disabled
9for integer tasks. Note that this is crucial if deferred fp context
10switching is used. Otherwise, fp context corruption may go undetected!
11Also note that even tasks which merely push/pop FP registers to/from the stack
12without modifying them still MUST be FP tasks - otherwise (if lazy FP
13context switching is used), FP register corruption (of other, FP, tasks
14may occur)!
15
16Furthermore, (on PPC) by default, lazy FP context save/restore is _disabled_
17
18
19Author: Till Straumann <strauman@slac.stanford.edu>, 4/2002
20
21Index: c/src/exec/score/src/threaddispatch.c
22===================================================================
23RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/exec/score/src/threaddispatch.c,v
24retrieving revision 1.1.1.1
25retrieving revision 1.4
26diff -c -r1.1.1.1 -r1.4
27*** c/src/exec/score/src/threaddispatch.c       2001/12/14 22:49:52     1.1.1.1
28--- c/src/exec/score/src/threaddispatch.c       2002/04/24 22:50:28     1.4
29***************
30*** 93,115 ****
31       */
32 
33  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
34  #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
35!     if ( (heir->fp_context != NULL) && !_Thread_Is_allocated_fp( heir ) ) {
36        if ( _Thread_Allocated_fp != NULL )
37          _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
38!       _Context_Restore_fp( &heir->fp_context );
39!       _Thread_Allocated_fp = heir;
40      }
41  #else
42      if ( executing->fp_context != NULL )
43!       _Context_Save_fp( &executing->fp_context );
44!
45!     if ( heir->fp_context != NULL )
46!       _Context_Restore_fp( &heir->fp_context );
47  #endif
48  #endif
49-
50-     _Context_Switch( &executing->Registers, &heir->Registers );
51 
52      executing = _Thread_Executing;
53 
54--- 93,119 ----
55       */
56 
57  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
58+ #if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
59+     if ( executing->fp_context != NULL )
60+       _Context_Save_fp( &executing->fp_context );
61+ #endif
62+ #endif
63+
64+     _Context_Switch( &executing->Registers, &heir->Registers );
65+
66+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
67  #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
68!     if ( (executing->fp_context != NULL) && !_Thread_Is_allocated_fp( executing ) ) {
69        if ( _Thread_Allocated_fp != NULL )
70          _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
71!       _Context_Restore_fp( &executing->fp_context );
72!       _Thread_Allocated_fp = executing;
73      }
74  #else
75      if ( executing->fp_context != NULL )
76!       _Context_Restore_fp( &executing->fp_context );
77  #endif
78  #endif
79 
80      executing = _Thread_Executing;
81 
82Index: c/src/exec/score/src/threadhandler.c
83===================================================================
84RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/exec/score/src/threadhandler.c,v
85retrieving revision 1.1.1.2
86retrieving revision 1.3
87diff -c -r1.1.1.2 -r1.3
88*** c/src/exec/score/src/threadhandler.c        2001/12/15 00:08:12     1.1.1.2
89--- c/src/exec/score/src/threadhandler.c        2002/05/05 18:14:53     1.3
90***************
91*** 78,83 ****
92--- 78,94 ----
93    doneConstructors = 1;
94  #endif
95 
96+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
97+ #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
98+   if ( (executing->fp_context != NULL) && !_Thread_Is_allocated_fp( executing ) ) {
99+     if ( _Thread_Allocated_fp != NULL )
100+       _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
101+     _Thread_Allocated_fp = executing;
102+   }
103+ #endif
104+ #endif
105+
106+
107    /*
108     * Take care that 'begin' extensions get to complete before
109     * 'switch' extensions can run.  This means must keep dispatch
110Index: c/src/lib/libbsp/powerpc/support/new_exception_processing/cpu.c
111===================================================================
112RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libbsp/powerpc/support/new_exception_processing/cpu.c,v
113retrieving revision 1.1.1.1
114retrieving revision 1.2
115diff -c -r1.1.1.1 -r1.2
116*** c/src/lib/libbsp/powerpc/support/new_exception_processing/cpu.c     2001/12/15 00:14:11     1.1.1.1
117--- c/src/lib/libbsp/powerpc/support/new_exception_processing/cpu.c     2002/04/21 00:17:39     1.2
118***************
119*** 93,100 ****
120     *  time (7 July 1997), this restructuring is not being done.
121     */
122 
123!   /*if ( is_fp ) */
124      the_context->msr |= PPC_MSR_FP;
125 
126    the_context->pc = (unsigned32)entry_point;
127  }
128--- 93,112 ----
129     *  time (7 July 1997), this restructuring is not being done.
130     */
131 
132!   /* Till Straumann: For deferred FPContext save/restore, make sure integer
133!    *                 tasks have no FPU access in order to catch violations.
134!    *                 Otherwise, the FP registers may be corrupted.
135!    *                           Since we set the_contex->msr using our current MSR,
136!    *                           we must make sure MSR_FP is off if (!is_fp)...
137!    */
138! #if defined(CPU_USE_DEFERRED_FP_SWITCH) && (CPU_USE_DEFERRED_FP_SWITCH==TRUE)
139!   if ( is_fp )
140! #endif
141      the_context->msr |= PPC_MSR_FP;
142+ #if defined(CPU_USE_DEFERRED_FP_SWITCH) && (CPU_USE_DEFERRED_FP_SWITCH==TRUE)
143+   else
144+       the_context->msr &= ~PPC_MSR_FP;
145+ #endif
146 
147    the_context->pc = (unsigned32)entry_point;
148  }
149Index: c/src/lib/libbsp/powerpc/support/new_exception_processing/rtems/score/cpu.h
150===================================================================
151RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libbsp/powerpc/support/new_exception_processing/rtems/score/cpu.h,v
152retrieving revision 1.1.1.1
153retrieving revision 1.3
154diff -c -r1.1.1.1 -r1.3
155*** c/src/lib/libbsp/powerpc/support/new_exception_processing/rtems/score/cpu.h 2001/12/15 00:14:11     1.1.1.1
156--- c/src/lib/libbsp/powerpc/support/new_exception_processing/rtems/score/cpu.h 2002/04/24 22:50:29     1.3
157***************
158*** 229,240 ****
159   *  until a context switch is made to another, different FP task.
160   *  Thus in a system with only one FP task, the FP context will never
161   *  be saved or restored.
162   */
163  /*
164   *  ACB Note:  This could make debugging tricky..
165   */
166 
167! #define CPU_USE_DEFERRED_FP_SWITCH       TRUE
168 
169  /*
170   *  Does this port provide a CPU dependent IDLE task implementation?
171--- 229,247 ----
172   *  until a context switch is made to another, different FP task.
173   *  Thus in a system with only one FP task, the FP context will never
174   *  be saved or restored.
175+  *
176+  *  Note, however that compilers may use floating point registers/
177+  *  instructions for optimization or they may save/restore FP registers
178+  *  on the stack. You must not use deferred switching in these cases
179+  *  and on the PowerPC attempting to do so will raise a "FP unavailable"
180+  *  exception.
181   */
182  /*
183   *  ACB Note:  This could make debugging tricky..
184   */
185 
186! /* conservative setting (FALSE); probably doesn't affect performance too much */
187! #define CPU_USE_DEFERRED_FP_SWITCH       FALSE
188 
189  /*
190   *  Does this port provide a CPU dependent IDLE task implementation?