source: rtems/cpukit/score/cpu/powerpc/rtems/score/cpu.h @ b7c7b75b

4.104.114.84.95
Last change on this file since b7c7b75b was b7c7b75b, checked in by Ralf Corsepius <ralf.corsepius@…>, on 02/18/05 at 06:24:48

(Context_Control, Context_Control_fp, CPU_Interrupt_frame): Add.

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/**
2 * @file rtems/score/cpu.h
3 */
4
5/*
6 * $Id$
7 */
8 
9#ifndef _RTEMS_SCORE_CPU_H
10#define _RTEMS_SCORE_CPU_H
11
12#include <rtems/score/powerpc.h>              /* pick up machine definitions */
13#ifndef ASM
14#include <rtems/score/types.h>
15#endif
16
17/* conditional compilation parameters */
18
19/*
20 *  Should the calls to _Thread_Enable_dispatch be inlined?
21 *
22 *  If TRUE, then they are inlined.
23 *  If FALSE, then a subroutine call is made.
24 *
25 *  Basically this is an example of the classic trade-off of size
26 *  versus speed.  Inlining the call (TRUE) typically increases the
27 *  size of RTEMS while speeding up the enabling of dispatching.
28 *  [NOTE: In general, the _Thread_Dispatch_disable_level will
29 *  only be 0 or 1 unless you are in an interrupt handler and that
30 *  interrupt handler invokes the executive.]  When not inlined
31 *  something calls _Thread_Enable_dispatch which in turns calls
32 *  _Thread_Dispatch.  If the enable dispatch is inlined, then
33 *  one subroutine call is avoided entirely.]
34 */
35
36#define CPU_INLINE_ENABLE_DISPATCH       FALSE
37
38/*
39 *  Should the body of the search loops in _Thread_queue_Enqueue_priority
40 *  be unrolled one time?  In unrolled each iteration of the loop examines
41 *  two "nodes" on the chain being searched.  Otherwise, only one node
42 *  is examined per iteration.
43 *
44 *  If TRUE, then the loops are unrolled.
45 *  If FALSE, then the loops are not unrolled.
46 *
47 *  The primary factor in making this decision is the cost of disabling
48 *  and enabling interrupts (_ISR_Flash) versus the cost of rest of the
49 *  body of the loop.  On some CPUs, the flash is more expensive than
50 *  one iteration of the loop body.  In this case, it might be desirable
51 *  to unroll the loop.  It is important to note that on some CPUs, this
52 *  code is the longest interrupt disable period in RTEMS.  So it is
53 *  necessary to strike a balance when setting this parameter.
54 */
55
56#define CPU_UNROLL_ENQUEUE_PRIORITY      FALSE
57
58/*
59 *  Processor defined structures required for cpukit/score.
60 */
61
62/*
63 * Contexts
64 *
65 *  Generally there are 2 types of context to save.
66 *     1. Interrupt registers to save
67 *     2. Task level registers to save
68 *
69 *  This means we have the following 3 context items:
70 *     1. task level context stuff::  Context_Control
71 *     2. floating point task stuff:: Context_Control_fp
72 *     3. special interrupt level context :: Context_Control_interrupt
73 *
74 *  On some processors, it is cost-effective to save only the callee
75 *  preserved registers during a task context switch.  This means
76 *  that the ISR code needs to save those registers which do not
77 *  persist across function calls.  It is not mandatory to make this
78 *  distinctions between the caller/callee saves registers for the
79 *  purpose of minimizing context saved during task switch and on interrupts.
80 *  If the cost of saving extra registers is minimal, simplicity is the
81 *  choice.  Save the same context on interrupt entry as for tasks in
82 *  this case.
83 *
84 *  Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
85 *  care should be used in designing the context area.
86 *
87 *  On some CPUs with hardware floating point support, the Context_Control_fp
88 *  structure will not be used or it simply consist of an array of a
89 *  fixed number of bytes.   This is done when the floating point context
90 *  is dumped by a "FP save context" type instruction and the format
91 *  is not really defined by the CPU.  In this case, there is no need
92 *  to figure out the exact format -- only the size.  Of course, although
93 *  this is enough information for RTEMS, it is probably not enough for
94 *  a debugger such as gdb.  But that is another problem.
95 */
96
97#ifndef ASM
98typedef struct {
99    uint32_t   gpr1;    /* Stack pointer for all */
100    uint32_t   gpr2;    /* Reserved SVR4, section ptr EABI + */
101    uint32_t   gpr13;   /* Section ptr SVR4/EABI */
102    uint32_t   gpr14;   /* Non volatile for all */
103    uint32_t   gpr15;   /* Non volatile for all */
104    uint32_t   gpr16;   /* Non volatile for all */
105    uint32_t   gpr17;   /* Non volatile for all */
106    uint32_t   gpr18;   /* Non volatile for all */
107    uint32_t   gpr19;   /* Non volatile for all */
108    uint32_t   gpr20;   /* Non volatile for all */
109    uint32_t   gpr21;   /* Non volatile for all */
110    uint32_t   gpr22;   /* Non volatile for all */
111    uint32_t   gpr23;   /* Non volatile for all */
112    uint32_t   gpr24;   /* Non volatile for all */
113    uint32_t   gpr25;   /* Non volatile for all */
114    uint32_t   gpr26;   /* Non volatile for all */
115    uint32_t   gpr27;   /* Non volatile for all */
116    uint32_t   gpr28;   /* Non volatile for all */
117    uint32_t   gpr29;   /* Non volatile for all */
118    uint32_t   gpr30;   /* Non volatile for all */
119    uint32_t   gpr31;   /* Non volatile for all */
120    uint32_t   cr;      /* PART of the CR is non volatile for all */
121    uint32_t   pc;      /* Program counter/Link register */
122    uint32_t   msr;     /* Initial interrupt level */
123} Context_Control;
124
125typedef struct {
126    /* The ABIs (PowerOpen/SVR4/EABI) only require saving f14-f31 over
127     * procedure calls.  However, this would mean that the interrupt
128     * frame had to hold f0-f13, and the fpscr.  And as the majority
129     * of tasks will not have an FP context, we will save the whole
130     * context here.
131     */
132#if (PPC_HAS_DOUBLE == 1)
133    double      f[32];
134    double      fpscr;
135#else
136    float       f[32];
137    float       fpscr;
138#endif
139} Context_Control_fp;
140#endif /* ASM */
141
142#ifndef ASM
143typedef struct CPU_Interrupt_frame {
144    uint32_t   stacklink;       /* Ensure this is a real frame (also reg1 save) */
145    uint32_t   calleeLr;        /* link register used by callees: SVR4/EABI */
146
147    /* This is what is left out of the primary contexts */
148    uint32_t   gpr0;
149    uint32_t   gpr2;            /* play safe */
150    uint32_t   gpr3;
151    uint32_t   gpr4;
152    uint32_t   gpr5;
153    uint32_t   gpr6;
154    uint32_t   gpr7;
155    uint32_t   gpr8;
156    uint32_t   gpr9;
157    uint32_t   gpr10;
158    uint32_t   gpr11;
159    uint32_t   gpr12;
160    uint32_t   gpr13;   /* Play safe */
161    uint32_t   gpr28;   /* For internal use by the IRQ handler */
162    uint32_t   gpr29;   /* For internal use by the IRQ handler */
163    uint32_t   gpr30;   /* For internal use by the IRQ handler */
164    uint32_t   gpr31;   /* For internal use by the IRQ handler */
165    uint32_t   cr;      /* Bits of this are volatile, so no-one may save */
166    uint32_t   ctr;
167    uint32_t   xer;
168    uint32_t   lr;
169    uint32_t   pc;
170    uint32_t   msr;
171    uint32_t   pad[3];
172} CPU_Interrupt_frame;
173#endif /* ASM */
174
175#ifdef _OLD_EXCEPTIONS
176#include <rtems/old-exceptions/cpu.h>
177#else
178#include <rtems/new-exceptions/cpu.h>
179#endif
180
181/*
182 *  Should be large enough to run all RTEMS tests.  This insures
183 *  that a "reasonable" small application should not have any problems.
184 */
185
186#define CPU_STACK_MINIMUM_SIZE          (1024*8)
187
188/*
189 *  CPU's worst alignment requirement for data types on a byte boundary.  This
190 *  alignment does not take into account the requirements for the stack.
191 */
192
193#define CPU_ALIGNMENT              (PPC_ALIGNMENT)
194
195/*
196 *  This number corresponds to the byte alignment requirement for the
197 *  heap handler.  This alignment requirement may be stricter than that
198 *  for the data types alignment specified by CPU_ALIGNMENT.  It is
199 *  common for the heap to follow the same alignment requirement as
200 *  CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
201 *  then this should be set to CPU_ALIGNMENT.
202 *
203 *  NOTE:  This does not have to be a power of 2.  It does have to
204 *         be greater or equal to than CPU_ALIGNMENT.
205 */
206
207#define CPU_HEAP_ALIGNMENT         (PPC_ALIGNMENT)
208
209/*
210 *  This number corresponds to the byte alignment requirement for memory
211 *  buffers allocated by the partition manager.  This alignment requirement
212 *  may be stricter than that for the data types alignment specified by
213 *  CPU_ALIGNMENT.  It is common for the partition to follow the same
214 *  alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
215 *  enough for the partition, then this should be set to CPU_ALIGNMENT.
216 *
217 *  NOTE:  This does not have to be a power of 2.  It does have to
218 *         be greater or equal to than CPU_ALIGNMENT.
219 */
220
221#define CPU_PARTITION_ALIGNMENT    (PPC_ALIGNMENT)
222
223/*
224 *  This number corresponds to the byte alignment requirement for the
225 *  stack.  This alignment requirement may be stricter than that for the
226 *  data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
227 *  is strict enough for the stack, then this should be set to 0.
228 *
229 *  NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
230 */
231
232#define CPU_STACK_ALIGNMENT        (PPC_STACK_ALIGNMENT)
233
234#ifndef ASM
235/*  The following routine swaps the endian format of an unsigned int.
236 *  It must be static because it is referenced indirectly.
237 *
238 *  This version will work on any processor, but if there is a better
239 *  way for your CPU PLEASE use it.  The most common way to do this is to:
240 *
241 *     swap least significant two bytes with 16-bit rotate
242 *     swap upper and lower 16-bits
243 *     swap most significant two bytes with 16-bit rotate
244 *
245 *  Some CPUs have special instructions which swap a 32-bit quantity in
246 *  a single instruction (e.g. i486).  It is probably best to avoid
247 *  an "endian swapping control bit" in the CPU.  One good reason is
248 *  that interrupts would probably have to be disabled to insure that
249 *  an interrupt does not try to access the same "chunk" with the wrong
250 *  endian.  Another good reason is that on some CPUs, the endian bit
251 *  endianness for ALL fetches -- both code and data -- so the code
252 *  will be fetched incorrectly.
253 */
254 
255static inline uint32_t CPU_swap_u32(
256  uint32_t value
257)
258{
259  uint32_t   swapped;
260 
261  asm volatile("rlwimi %0,%1,8,24,31;"
262               "rlwimi %0,%1,24,16,23;"
263               "rlwimi %0,%1,8,8,15;"
264               "rlwimi %0,%1,24,0,7;" :
265               "=&r" ((swapped)) : "r" ((value)));
266
267  return( swapped );
268}
269
270#define CPU_swap_u16( value ) \
271  (((value&0xff) << 8) | ((value >> 8)&0xff))
272
273#endif /* ASM */
274
275#ifndef ASM
276/*
277 *  Macros to access PowerPC specific additions to the CPU Table
278 */
279
280#define rtems_cpu_configuration_get_clicks_per_usec() \
281   (_CPU_Table.clicks_per_usec)
282
283#define rtems_cpu_configuration_get_exceptions_in_ram() \
284   (_CPU_Table.exceptions_in_RAM)
285
286#endif /* ASM */
287
288#ifndef ASM
289/*
290 *  Simple spin delay in microsecond units for device drivers.
291 *  This is very dependent on the clock speed of the target.
292 */
293
294#define CPU_Get_timebase_low( _value ) \
295    asm volatile( "mftb  %0" : "=r" (_value) )
296
297#define rtems_bsp_delay( _microseconds ) \
298  do { \
299    uint32_t   start, ticks, now; \
300    CPU_Get_timebase_low( start ) ; \
301    ticks = (_microseconds) * rtems_cpu_configuration_get_clicks_per_usec(); \
302    do \
303      CPU_Get_timebase_low( now ) ; \
304    while (now - start < ticks); \
305  } while (0)
306
307#define rtems_bsp_delay_in_bus_cycles( _cycles ) \
308  do { \
309    uint32_t   start, now; \
310    CPU_Get_timebase_low( start ); \
311    do \
312      CPU_Get_timebase_low( now ); \
313    while (now - start < (_cycles)); \
314  } while (0)
315
316#endif /* ASM */
317
318#ifndef ASM
319/*
320 *  Routines to access the decrementer register
321 */
322
323#define PPC_Set_decrementer( _clicks ) \
324  do { \
325    asm volatile( "mtdec %0" : : "r" ((_clicks)) ); \
326  } while (0)
327
328#define PPC_Get_decrementer( _clicks ) \
329    asm volatile( "mfdec  %0" : "=r" (_clicks) )
330
331#endif /* ASM */
332
333#ifndef ASM
334/*
335 *  Routines to access the time base register
336 */
337
338static inline uint64_t PPC_Get_timebase_register( void )
339{
340  uint32_t tbr_low;
341  uint32_t tbr_high;
342  uint32_t tbr_high_old;
343  uint64_t tbr;
344
345  do {
346    asm volatile( "mftbu %0" : "=r" (tbr_high_old));
347    asm volatile( "mftb  %0" : "=r" (tbr_low));
348    asm volatile( "mftbu %0" : "=r" (tbr_high));
349  } while ( tbr_high_old != tbr_high );
350
351  tbr = tbr_high;
352  tbr <<= 32;
353  tbr |= tbr_low;
354  return tbr;
355}
356
357static inline  void PPC_Set_timebase_register (uint64_t tbr)
358{
359  uint32_t tbr_low;
360  uint32_t tbr_high;
361
362  tbr_low = (tbr & 0xffffffff) ;
363  tbr_high = (tbr >> 32) & 0xffffffff;
364  asm volatile( "mtspr 284, %0" : : "r" (tbr_low));
365  asm volatile( "mtspr 285, %0" : : "r" (tbr_high));
366 
367}
368#endif /* ASM */
369
370#ifndef ASM
371/* Context handler macros */
372
373/*
374 *  Initialize the context to a state suitable for starting a
375 *  task after a context restore operation.  Generally, this
376 *  involves:
377 *
378 *     - setting a starting address
379 *     - preparing the stack
380 *     - preparing the stack and frame pointers
381 *     - setting the proper interrupt level in the context
382 *     - initializing the floating point context
383 *
384 *  This routine generally does not set any unnecessary register
385 *  in the context.  The state of the "general data" registers is
386 *  undefined at task start time.
387 */
388
389void _CPU_Context_Initialize(
390  Context_Control  *the_context,
391  uint32_t         *stack_base,
392  uint32_t          size,
393  uint32_t          new_level,
394  void             *entry_point,
395  boolean           is_fp
396);
397
398/*
399 *  This routine is responsible for somehow restarting the currently
400 *  executing task.  If you are lucky, then all that is necessary
401 *  is restoring the context.  Otherwise, there will need to be
402 *  a special assembly routine which does something special in this
403 *  case.  Context_Restore should work most of the time.  It will
404 *  not work if restarting self conflicts with the stack frame
405 *  assumptions of restoring a context.
406 */
407
408#define _CPU_Context_Restart_self( _the_context ) \
409   _CPU_Context_restore( (_the_context) );
410
411/*
412 *  The purpose of this macro is to allow the initial pointer into
413 *  a floating point context area (used to save the floating point
414 *  context) to be at an arbitrary place in the floating point
415 *  context area.
416 *
417 *  This is necessary because some FP units are designed to have
418 *  their context saved as a stack which grows into lower addresses.
419 *  Other FP units can be saved by simply moving registers into offsets
420 *  from the base of the context area.  Finally some FP units provide
421 *  a "dump context" instruction which could fill in from high to low
422 *  or low to high based on the whim of the CPU designers.
423 */
424
425#define _CPU_Context_Fp_start( _base, _offset ) \
426   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
427
428/*
429 *  This routine initializes the FP context area passed to it to.
430 *  There are a few standard ways in which to initialize the
431 *  floating point context.  The code included for this macro assumes
432 *  that this is a CPU in which a "initial" FP context was saved into
433 *  _CPU_Null_fp_context and it simply copies it to the destination
434 *  context passed to it.
435 *
436 *  Other models include (1) not doing anything, and (2) putting
437 *  a "null FP status word" in the correct place in the FP context.
438 */
439
440#define _CPU_Context_Initialize_fp( _destination ) \
441  { \
442   ((Context_Control_fp *) *((void **) _destination))->fpscr = PPC_INIT_FPSCR; \
443  }
444
445/* end of Context handler macros */
446#endif /* ASM */
447
448#ifndef ASM
449/* Bitfield handler macros */
450
451/*
452 *  This routine sets _output to the bit number of the first bit
453 *  set in _value.  _value is of CPU dependent type Priority_Bit_map_control.
454 *  This type may be either 16 or 32 bits wide although only the 16
455 *  least significant bits will be used.
456 *
457 *  There are a number of variables in using a "find first bit" type
458 *  instruction.
459 *
460 *    (1) What happens when run on a value of zero?
461 *    (2) Bits may be numbered from MSB to LSB or vice-versa.
462 *    (3) The numbering may be zero or one based.
463 *    (4) The "find first bit" instruction may search from MSB or LSB.
464 *
465 *  RTEMS guarantees that (1) will never happen so it is not a concern.
466 *  (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
467 *  _CPU_Priority_Bits_index().  These three form a set of routines
468 *  which must logically operate together.  Bits in the _value are
469 *  set and cleared based on masks built by _CPU_Priority_mask().
470 *  The basic major and minor values calculated by _Priority_Major()
471 *  and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
472 *  to properly range between the values returned by the "find first bit"
473 *  instruction.  This makes it possible for _Priority_Get_highest() to
474 *  calculate the major and directly index into the minor table.
475 *  This mapping is necessary to ensure that 0 (a high priority major/minor)
476 *  is the first bit found.
477 *
478 *  This entire "find first bit" and mapping process depends heavily
479 *  on the manner in which a priority is broken into a major and minor
480 *  components with the major being the 4 MSB of a priority and minor
481 *  the 4 LSB.  Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
482 *  priority.  And (15 << 4) + 14 corresponds to priority 254 -- the next
483 *  to the lowest priority.
484 *
485 *  If your CPU does not have a "find first bit" instruction, then
486 *  there are ways to make do without it.  Here are a handful of ways
487 *  to implement this in software:
488 *
489 *    - a series of 16 bit test instructions
490 *    - a "binary search using if's"
491 *    - _number = 0
492 *      if _value > 0x00ff
493 *        _value >>=8
494 *        _number = 8;
495 *
496 *      if _value > 0x0000f
497 *        _value >=8
498 *        _number += 4
499 *
500 *      _number += bit_set_table[ _value ]
501 *
502 *    where bit_set_table[ 16 ] has values which indicate the first
503 *      bit set
504 */
505
506#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
507  { \
508    asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \
509                  "1" ((_value))); \
510  }
511
512/* end of Bitfield handler macros */
513
514/*
515 *  This routine builds the mask which corresponds to the bit fields
516 *  as searched by _CPU_Bitfield_Find_first_bit().  See the discussion
517 *  for that routine.
518 */
519
520#define _CPU_Priority_Mask( _bit_number ) \
521  ( 0x80000000 >> (_bit_number) )
522
523/*
524 *  This routine translates the bit numbers returned by
525 *  _CPU_Bitfield_Find_first_bit() into something suitable for use as
526 *  a major or minor component of a priority.  See the discussion
527 *  for that routine.
528 */
529
530#define _CPU_Priority_bits_index( _priority ) \
531  (_priority)
532
533/* end of Priority handler macros */
534#endif /* ASM */
535
536/* functions */
537
538#ifndef ASM
539
540/*
541 *  _CPU_Initialize
542 *
543 *  This routine performs CPU dependent initialization.
544 */
545
546void _CPU_Initialize(
547  rtems_cpu_table  *cpu_table,
548  void            (*thread_dispatch)
549);
550
551/*
552 *  _CPU_ISR_install_vector
553 *
554 *  This routine installs an interrupt vector.
555 */
556
557void _CPU_ISR_install_vector(
558  uint32_t    vector,
559  proc_ptr    new_handler,
560  proc_ptr   *old_handler
561);
562
563/*
564 *  _CPU_Install_interrupt_stack
565 *
566 *  This routine installs the hardware interrupt stack pointer.
567 *
568 *  NOTE:  It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
569 *         is TRUE.
570 */
571
572void _CPU_Install_interrupt_stack( void );
573
574/*
575 *  _CPU_Context_switch
576 *
577 *  This routine switches from the run context to the heir context.
578 */
579
580void _CPU_Context_switch(
581  Context_Control  *run,
582  Context_Control  *heir
583);
584
585/*
586 *  _CPU_Context_restore
587 *
588 *  This routine is generallu used only to restart self in an
589 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
590 *
591 *  NOTE: May be unnecessary to reload some registers.
592 */
593
594void _CPU_Context_restore(
595  Context_Control *new_context
596);
597
598/*
599 *  _CPU_Context_save_fp
600 *
601 *  This routine saves the floating point context passed to it.
602 */
603
604void _CPU_Context_save_fp(
605  void **fp_context_ptr
606);
607
608/*
609 *  _CPU_Context_restore_fp
610 *
611 *  This routine restores the floating point context passed to it.
612 */
613
614void _CPU_Context_restore_fp(
615  void **fp_context_ptr
616);
617
618void _CPU_Fatal_error(
619  uint32_t   _error
620);
621
622#endif /* ASM */
623
624#endif /* _RTEMS_SCORE_CPU_H */
Note: See TracBrowser for help on using the repository browser.