source: rtems/cpukit/score/cpu/sparc/cpu.c @ 80f7732

4.104.115
Last change on this file since 80f7732 was 80f7732, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/02/09 at 09:48:25

Whitespace removal.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*
2 *  SPARC Dependent Source
3 *
4 *  COPYRIGHT (c) 1989-2007.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#include <rtems/system.h>
15#include <rtems/score/isr.h>
16#include <rtems/rtems/cache.h>
17
18/*
19 *  This initializes the set of opcodes placed in each trap
20 *  table entry.  The routine which installs a handler is responsible
21 *  for filling in the fields for the _handler address and the _vector
22 *  trap type.
23 *
24 *  The constants following this structure are masks for the fields which
25 *  must be filled in when the handler is installed.
26 */
27
28const CPU_Trap_table_entry _CPU_Trap_slot_template = {
29  0xa1480000,      /* mov   %psr, %l0           */
30  0x29000000,      /* sethi %hi(_handler), %l4  */
31  0x81c52000,      /* jmp   %l4 + %lo(_handler) */
32  0xa6102000       /* mov   _vector, %l3        */
33};
34
35/*PAGE
36 *
37 *  _CPU_Initialize
38 *
39 *  This routine performs processor dependent initialization.
40 *
41 *  INPUT PARAMETERS: NONE
42 *
43 *  Output Parameters: NONE
44 *
45 *  NOTE: There is no need to save the pointer to the thread dispatch routine.
46 *        The SPARC's assembly code can reference it directly with no problems.
47 */
48
49void _CPU_Initialize(void)
50{
51#if (SPARC_HAS_FPU == 1)
52  Context_Control_fp *pointer;
53
54  /*
55   *  This seems to be the most appropriate way to obtain an initial
56   *  FP context on the SPARC.  The NULL fp context is copied it to
57   *  the task's FP context during Context_Initialize.
58   */
59
60  pointer = &_CPU_Null_fp_context;
61  _CPU_Context_save_fp( &pointer );
62#endif
63
64  /*
65   *  Since no tasks have been created yet and no interrupts have occurred,
66   *  there is no way that the currently executing thread can have an
67   *  _ISR_Dispatch stack frame on its stack.
68   */
69  _CPU_ISR_Dispatch_disable = 0;
70}
71
72/*PAGE
73 *
74 *  _CPU_ISR_Get_level
75 *
76 *  Input Parameters: NONE
77 *
78 *  Output Parameters:
79 *    returns the current interrupt level (PIL field of the PSR)
80 */
81
82uint32_t   _CPU_ISR_Get_level( void )
83{
84  uint32_t   level;
85
86  sparc_get_interrupt_level( level );
87
88  return level;
89}
90
91/*PAGE
92 *
93 *  _CPU_ISR_install_raw_handler
94 *
95 *  This routine installs the specified handler as a "raw" non-executive
96 *  supported trap handler (a.k.a. interrupt service routine).
97 *
98 *  Input Parameters:
99 *    vector      - trap table entry number plus synchronous
100 *                    vs. asynchronous information
101 *    new_handler - address of the handler to be installed
102 *    old_handler - pointer to an address of the handler previously installed
103 *
104 *  Output Parameters: NONE
105 *    *new_handler - address of the handler previously installed
106 *
107 *  NOTE:
108 *
109 *  On the SPARC, there are really only 256 vectors.  However, the executive
110 *  has no easy, fast, reliable way to determine which traps are synchronous
111 *  and which are asynchronous.  By default, synchronous traps return to the
112 *  instruction which caused the interrupt.  So if you install a software
113 *  trap handler as an executive interrupt handler (which is desirable since
114 *  RTEMS takes care of window and register issues), then the executive needs
115 *  to know that the return address is to the trap rather than the instruction
116 *  following the trap.
117 *
118 *  So vectors 0 through 255 are treated as regular asynchronous traps which
119 *  provide the "correct" return address.  Vectors 256 through 512 are assumed
120 *  by the executive to be synchronous and to require that the return address
121 *  be fudged.
122 *
123 *  If you use this mechanism to install a trap handler which must reexecute
124 *  the instruction which caused the trap, then it should be installed as
125 *  an asynchronous trap.  This will avoid the executive changing the return
126 *  address.
127 */
128
129void _CPU_ISR_install_raw_handler(
130  uint32_t    vector,
131  proc_ptr    new_handler,
132  proc_ptr   *old_handler
133)
134{
135  uint32_t               real_vector;
136  CPU_Trap_table_entry  *tbr;
137  CPU_Trap_table_entry  *slot;
138  uint32_t               u32_tbr;
139  uint32_t               u32_handler;
140
141  /*
142   *  Get the "real" trap number for this vector ignoring the synchronous
143   *  versus asynchronous indicator included with our vector numbers.
144   */
145
146  real_vector = SPARC_REAL_TRAP_NUMBER( vector );
147
148  /*
149   *  Get the current base address of the trap table and calculate a pointer
150   *  to the slot we are interested in.
151   */
152
153  sparc_get_tbr( u32_tbr );
154
155  u32_tbr &= 0xfffff000;
156
157  tbr = (CPU_Trap_table_entry *) u32_tbr;
158
159  slot = &tbr[ real_vector ];
160
161  /*
162   *  Get the address of the old_handler from the trap table.
163   *
164   *  NOTE: The old_handler returned will be bogus if it does not follow
165   *        the RTEMS model.
166   */
167
168#define HIGH_BITS_MASK   0xFFFFFC00
169#define HIGH_BITS_SHIFT  10
170#define LOW_BITS_MASK    0x000003FF
171
172  if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
173    u32_handler =
174      (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) |
175      (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
176    *old_handler = (proc_ptr) u32_handler;
177  } else
178    *old_handler = 0;
179
180  /*
181   *  Copy the template to the slot and then fix it.
182   */
183
184  *slot = _CPU_Trap_slot_template;
185
186  u32_handler = (uint32_t) new_handler;
187
188  slot->mov_vector_l3 |= vector;
189  slot->sethi_of_handler_to_l4 |=
190    (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
191  slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
192
193  /* need to flush icache after this !!! */
194
195  rtems_cache_invalidate_entire_instruction();
196
197}
198
199/*PAGE
200 *
201 *  _CPU_ISR_install_vector
202 *
203 *  This kernel routine installs the RTEMS handler for the
204 *  specified vector.
205 *
206 *  Input parameters:
207 *    vector       - interrupt vector number
208 *    new_handler  - replacement ISR for this vector number
209 *    old_handler  - pointer to former ISR for this vector number
210 *
211 *  Output parameters:
212 *    *old_handler - former ISR for this vector number
213 *
214 */
215
216void _CPU_ISR_install_vector(
217  uint32_t    vector,
218  proc_ptr    new_handler,
219  proc_ptr   *old_handler
220)
221{
222   uint32_t   real_vector;
223   proc_ptr   ignored;
224
225  /*
226   *  Get the "real" trap number for this vector ignoring the synchronous
227   *  versus asynchronous indicator included with our vector numbers.
228   */
229
230   real_vector = SPARC_REAL_TRAP_NUMBER( vector );
231
232   /*
233    *  Return the previous ISR handler.
234    */
235
236   *old_handler = _ISR_Vector_table[ real_vector ];
237
238   /*
239    *  Install the wrapper so this ISR can be invoked properly.
240    */
241
242   _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
243
244   /*
245    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
246    *  be used by the _ISR_Handler so the user gets control.
247    */
248
249    _ISR_Vector_table[ real_vector ] = new_handler;
250}
251
252/*PAGE
253 *
254 *  _CPU_Context_Initialize
255 *
256 *  This kernel routine initializes the basic non-FP context area associated
257 *  with each thread.
258 *
259 *  Input parameters:
260 *    the_context  - pointer to the context area
261 *    stack_base   - address of memory for the SPARC
262 *    size         - size in bytes of the stack area
263 *    new_level    - interrupt level for this context area
264 *    entry_point  - the starting execution point for this this context
265 *    is_fp        - TRUE if this context is associated with an FP thread
266 *
267 *  Output parameters: NONE
268 */
269
270void _CPU_Context_Initialize(
271  Context_Control  *the_context,
272  uint32_t         *stack_base,
273  uint32_t          size,
274  uint32_t          new_level,
275  void             *entry_point,
276  bool              is_fp
277)
278{
279    uint32_t     stack_high;  /* highest "stack aligned" address */
280    uint32_t     the_size;
281    uint32_t     tmp_psr;
282
283    /*
284     *  On CPUs with stacks which grow down (i.e. SPARC), we build the stack
285     *  based on the stack_high address.
286     */
287
288    stack_high = ((uint32_t)(stack_base) + size);
289    stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
290
291    the_size = size & ~(CPU_STACK_ALIGNMENT - 1);
292
293    /*
294     *  See the README in this directory for a diagram of the stack.
295     */
296
297    the_context->o7    = ((uint32_t) entry_point) - 8;
298    the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE;
299    the_context->i6_fp = 0;
300
301    /*
302     *  Build the PSR for the task.  Most everything can be 0 and the
303     *  CWP is corrected during the context switch.
304     *
305     *  The EF bit determines if the floating point unit is available.
306     *  The FPU is ONLY enabled if the context is associated with an FP task
307     *  and this SPARC model has an FPU.
308     */
309
310    sparc_get_psr( tmp_psr );
311    tmp_psr &= ~SPARC_PSR_PIL_MASK;
312    tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK;
313    tmp_psr &= ~SPARC_PSR_EF_MASK;      /* disabled by default */
314
315#if (SPARC_HAS_FPU == 1)
316    /*
317     *  If this bit is not set, then a task gets a fault when it accesses
318     *  a floating point register.  This is a nice way to detect floating
319     *  point tasks which are not currently declared as such.
320     */
321
322    if ( is_fp )
323      tmp_psr |= SPARC_PSR_EF_MASK;
324#endif
325    the_context->psr = tmp_psr;
326
327  /*
328   *  Since THIS thread is being created, there is no way that THIS
329   *  thread can have an _ISR_Dispatch stack frame on its stack.
330   */
331    the_context->isr_dispatch_disable = 0;
332}
Note: See TracBrowser for help on using the repository browser.