source: rtems/cpukit/score/cpu/sparc/cpu.c @ 9700578

4.104.114.84.95
Last change on this file since 9700578 was 9700578, checked in by Joel Sherrill <joel.sherrill@…>, on 10/30/95 at 21:54:45

SPARC port passes all tests

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