source: rtems/c/src/exec/score/cpu/powerpc/other_cpu/cpu.h @ ba46ffa6

4.104.114.84.95
Last change on this file since ba46ffa6 was ba46ffa6, checked in by Joel Sherrill <joel.sherrill@…>, on 06/14/99 at 16:51:13

This is a large patch from Eric Valette <valette@…> that was
described in the message following this paragraph. This patch also includes
a mcp750 BSP.

From valette@… Mon Jun 14 10:03:08 1999
Date: Tue, 18 May 1999 01:30:14 +0200 (CEST)
From: VALETTE Eric <valette@…>
To: joel@…
Cc: raguet@…, rtems-snapshots@…, valette@…
Subject: Questions/Suggestion? regarding RTEMS PowerPC code (long)

Dear knowledgeable RTEMS powerpc users,

As some of you may know, I'm currently finalizing a port
of RTEMS on a MCP750 Motorola board. I have done most
of it but have some questions to ask before submitting
the port.

In order to understand some of the changes I have made
or would like to make, maybe it is worth describing the
MCP750 Motorola board.

the MCP750 is a COMPACT PCI powerpc board with :

1) a MPC750 233 MHz processor,
2) a raven bus bridge/PCI controller that
implement an OPENPIC compliant interrupt controller,
3) a VIA 82C586 PCI/ISA bridge that offers a PC
compliant IO for keyboard, serial line, IDE, and
the well known PC 8259 cascaded PIC interrupt
architecture model,
4) a DEC 21140 Ethernet controller,
5) the PPCBUG Motorola firmware in flash,
6) A DEC PCI bridge,

This architecture is common to most Motorola 60x/7xx
board except that :

1) on VME board, the DEC PCI bridge is replaced by
a VME chipset,
2) the VIA 82C586 PCI/ISA bridge is replaced by
another bridge that is almost fully compatible
with the via bridge...

So the port should be a rather close basis for many
60x/7xx motorola board...

On this board, I already have ported Linux 2.2.3 and
use it both as a development and target board.

Now the questions/suggestions I have :

1) EXCEPTION CODE


As far as I know exceptions on PPC are handled like
interrupts. I dislike this very much as :

a) Except for the decrementer exception (and
maybe some other on mpc8xx), exceptions are
not recoverable and the handler just need to print
the full context and go to the firmware or debugger...
b) The interrupt switch is only necessary for the
decrementer and external interrupt (at least on
6xx,7xx).
c) The full context for exception is never saved and
thus cannot be used by debugger... I do understand
the most important for interrupts low level code
is to save the minimal context enabling to call C
code for performance reasons. On non recoverable
exception on the other hand, the most important is
to save the maximum information concerning proc status
in order to analyze the reason of the fault. At
least we will need this in order to implement the
port of RGDB on PPC

==> I wrote an API for connecting raw exceptions (and thus
raw interrupts) for mpc750. It should be valid for most
powerpc processors... I hope to find a way to make this coexist
with actual code layout. The code is actually located
in lib/libcpu/powerpc/mpc750 and is thus optional
(provided I write my own version of exec/score/cpu/powerpc/cpu.c ...)

See remark about files/directory layout organization in 4)

2) Current Implementation of ISR low level code


I do not understand why the MSR EE flags is cleared
again in exec/score/cpu/powerpc/irq_stubs.S

#if (PPC_USE_SPRG)

mfmsr r5
mfspr r6, sprg2

#else

lwz r6,msr_initial(r11)
lis r5,~PPC_MSR_DISABLE_MASK@ha
ori r5,r5,~PPC_MSR_DISABLE_MASK@l
and r6,r6,r5
mfmsr r5

#endif

Reading the doc, when a decrementer interrupt or an
external interrupt is active, the MSR EE flag is already
cleared. BTW if exception/interrupt could occur, it would
trash SRR0 and SRR1. In fact the code may be useful to set
MSR[RI] that re-enables exception processing. BTW I will need
to set other value in MSR to handle interrupts :

a) I want the MSR[IR] and MSR[DR] to be set for
performance reasons and also because I need DBAT
support to have access to PCI memory space as the
interrupt controller is in the PCI space.

Reading the code, I see others have the same kind of request :

/* SCE 980217

*

  • We need address translation ON when we call our ISR routine

mtmsr r5

*/

This is just another prof that even the lowest level
IRQ code is fundamentally board dependent and
not simply processor dependent especially when
the processor use external interrupt controller
because it has a single interrupt request line...

Note that if you look at the PPC code high level interrupt
handling code, as the "set_vector" routine that really connects
the interrupt is in the BSP/startup/genpvec.c,
the fact that IRQ handling is BSP specific is DE-FACTO
acknowledged.

I know I have already expressed this and understand that this
would require some heavy change in the code but believe
me you will reach a point where you will not be able
to find a compatible while optimum implementation for low level
interrupt handling code...) In my case this is already true...

So please consider removing low level IRQ handling from
exec/score/cpu/* and only let there exception handling code...
Exceptions are usually only processor dependent and do
not depend on external hardware mechanism to be masked or
acknowledged or re-enabled (there are probably exception but ...)

I have already done this for pc386 bsp but need to make it again.
This time I will even propose an API.

3) R2/R13 manipulation for EABI implementation


I do not understand the handling of r2 and r13 in the
EABI case. The specification for r2 says pointer to sdata2,
sbss2 section => constant. However I do not see -ffixed-r2
passed to any compilation system in make/custom/*
(for info linux does this on PPC).

So either this is a default compiler option when choosing
powerpc-rtems and thus we do not need to do anything with
this register as all the code is compiled with this compiler
and linked together OR this register may be used by rtems code
and then we do not need any special initialization or
handling.

The specification for r13 says pointer to the small data
area. r13 argumentation is the same except that as far
as I know the usage of the small data area requires
specific compiler support so that access to variables is
compiled via loading the LSB in a register and then
using r13 to get full address... It is like a small
memory model and it was present in IBM C compilers.

=> I propose to suppress any specific code for r2 and
r13 in the EABI case.

4) Code layout organization (yes again :-))


I think there are a number of design flaws in the way
the code is for ppc organized and I will try to point them out.
I have been beaten by this again on this new port, and
was beaten last year while modifying code for pc386.

a) exec/score/cpu/* vs lib/libcpu/cpu/*.

I think that too many things are put in exec/score/cpu that
have nothing to do with RTEMS internals but are rather
related to CPU feature.

This include at least :

a) registers access routine (e.g GET_MSR_Value),
b) interrupt masking/unmasking routines,
c) cache_mngt_routine,
d) mmu_mngt_routine,
e) Routines to connect the raw_exception, raw_interrupt
handler,

b) lib/libcpu/cpu/powerpc/*

With a processor family as exuberant as the powerpc family,
and their well known subtle differences (604 vs 750) or
unfortunately majors (8xx vs 60x) the directory structure
is fine (except maybe the names that are not homogeneous)

powerpc

ppc421 mpc821 ...

I only needed to add mpc750. But the fact that libcpu.a was not
produced was a pain and the fact that this organization may
duplicates code is also problematic.

So, except if the support of automake provides a better solution
I would like to propose something like this :

powerpc

mpc421 mpc821 ... mpc750 shared wrapup

with the following rules :

a) "shared" would act as a source container for sources that may
be shared among processors. Needed files would be compiled inside
the processor specific directory using the vpath Makefile
mechanism. "shared" may also contain compilation code
for routine that are really shared and not worth to inline...
(did not found many things so far as registers access routine
ARE WORTH INLINING)... In the case something is compiled there,
it should create libcpushared.a

b) layout under processor specific directory is free provided
that

1)the result of the compilation process exports :

libcpu/powerpc/"PROC"/*.h in $(PROJECT_INCLUDE)/libcpu

2) each processor specific directory creates
a library called libcpuspecific.a

Note that this organization enables to have a file that
is nearly the same than in shared but that must differ
because of processor differences...

c) "wrapup" should create libcpu.a using libcpushared.a
libcpuspecific.a and export it $(PROJECT_INCLUDE)/libcpu

The only thing I have no ideal solution is the way to put shared
definitions in "shared" and only processor specific definition
in "proc". To give a concrete example, most MSR bit definition
are shared among PPC processors and only some differs. if we create
a single msr.h in shared it will have ifdef. If in msr.h we
include libcpu/msr_c.h we will need to have it in each prowerpc
specific directory (even empty). Opinions are welcomed ...

Note that a similar mechanism exist in libbsp/i386 that also
contains a shared directory that is used by several bsp
like pc386 and i386ex and a similar wrapup mechanism...

NB: I have done this for mpc750 and other processors could just use
similar Makefiles...

c) The exec/score/cpu/powerpc directory layout.

I think the directory layout should be the same than the
libcpu/powerpc. As it is not, there are a lot of ifdefs
inside the code... And of course low level interrupt handling
code should be removed...

Besides that I do not understand why

1) things are compiled in the wrap directory,
2) some includes are moved to rtems/score,

I think the "preinstall" mechanism enables to put
everything in the current directory (or better in a per processor
directory),

5) Interrupt handling API


Again :-). But I think that using all the features the PIC
offers is a MUST for RT system. I already explained in the
prologue of this (long and probably boring) mail that the MCP750
boards offers an OPENPIC compliant architecture and that
the VIA 82586 PCI/ISA bridge offers a PC compatible IO and
PIC mapping. Here is a logical view of the RAVEN/VIA 82586
interrupt mapping :


| OPEN | <-----|8259|
| PIC | | | 2 ------
|(RAVEN)| | | <-----|8259|
| | | | | | 11
| | | | | | <----
| | | | | |
| | | | | |


------
| VIA PCI/ISA bridge
| x
-------- PCI interrupts

OPENPIC offers interrupt priorities among PCI interrupts
and interrupt selective masking. The 8259 offers the same kind
of feature. With actual powerpc interrupt code :

1) there is no way to specify priorities among
interrupts handler. This is REALLY a bad thing.
For me it is as importnat as having priorities
for threads...
2) for my implementation, each ISR should
contain the code that acknowledge the RAVEN
and 8259 cascade, modify interrupt mask on both
chips, and reenable interrupt at processor level,
..., restore then on interrupt return,.... This code
is actually similar to code located in some
genpvec.c powerpc files,
3) I must update _ISR_Nesting_level because
irq.inl use it...
4) the libchip code connects the ISR via set_vector
but the libchip handler code does not contain any code to
manipulate external interrupt controller hardware
in order to acknoledge the interrupt or re-enable
them (except for the target hardware of course)
So this code is broken unless set_vector adds an
additionnal prologue/epilogue before calling/returning
from in order to acknoledge/mask the raven and the
8259 PICS... => Anyway already EACH BSP MUST REWRITE
PART OF INTERRUPT HANDLING CODE TO CORRECTLY IMPLEMENT
SET_VECTOR.

I would rather offer an API similar to the one provided
in libbsp/i386/shared/irq/irq.h so that :

1) Once the driver supplied methods is called the
only things the ISR has to do is to worry about the
external hardware that triggered the interrupt.
Everything on openpic/VIA/processor would have been
done by the low levels (same things as set-vector)
2) The caller will need to supply the on/off/isOn
routine that are fundamental to correctly implements
debuggers/performance monitoring is a portable way
3) A globally configurable interrupt priorities
mechanism...

I have nothing against providing a compatible
set_vector just to make libchip happy but
as I have already explained in other
mails (months ago), I really think that the ISR
connection should be handled by the BSP and that no
code containing irq connection should exist the
rtems generic layers... Thus I really dislike
libchip on this aspect because in a long term
it will force to adopt the less reach API
for interrupt handling that exists (set_vector).

Additional note : I think the _ISR_Is_in_progress()
inline routine should be :

1) Put in a processor specific section,
2) Should not rely on a global variable,

As :

a) on symmetric MP, there is one interrupt level
per CPU,
b) On processor that have an ISP (e,g 68040),
this variable is useless (MSR bit testing could
be used)
c) On PPC, instead of using the address of the
variable via CPU_IRQ_info.Nest_level a dedicated
SPR could be used.

NOTE: most of this is also true for _Thread_Dispatch_disable_level

END NOTE


Please do not take what I said in the mail as a criticism for
anyone who submitted ppc code. Any code present helped me
a lot understanding PPC behavior. I just wanted by this
mail to :

1) try to better understand the actual code,
2) propose concrete ways of enhancing current code
by providing an alternative implementation for MCP750. I
will make my best effort to try to brake nothing but this
is actually hard due to the file layout organisation.
3) make understandable some changes I will probably make
if joel let me do them :-)

Any comments/objections are welcomed as usual.

--


/ ` Eric Valette

/-- o _. Canon CRF

(_, / (_(_( Rue de la touche lambert

35517 Cesson-Sevigne Cedex
FRANCE

Tel: +33 (0)2 99 87 68 91 Fax: +33 (0)2 99 84 11 30
E-mail: valette@…

  • Property mode set to 100644
File size: 37.0 KB
Line 
1/*  cpu.h
2 *
3 *  This include file contains information pertaining to the PowerPC
4 *  processor.
5 *
6 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
7 *
8 *  COPYRIGHT (c) 1995 by i-cubed ltd.
9 *
10 *  To anyone who acknowledges that this file is provided "AS IS"
11 *  without any express or implied warranty:
12 *      permission to use, copy, modify, and distribute this file
13 *      for any purpose is hereby granted without fee, provided that
14 *      the above copyright notice and this notice appears in all
15 *      copies, and that the name of i-cubed limited not be used in
16 *      advertising or publicity pertaining to distribution of the
17 *      software without specific, written prior permission.
18 *      i-cubed limited makes no representations about the suitability
19 *      of this software for any purpose.
20 *
21 *  Derived from c/src/exec/cpu/no_cpu/cpu.h:
22 *
23 *  COPYRIGHT (c) 1989-1997.
24 *  On-Line Applications Research Corporation (OAR).
25 *  Copyright assigned to U.S. Government, 1994.
26 *
27 *  The license and distribution terms for this file may in
28 *  the file LICENSE in this distribution or at
29 *  http://www.OARcorp.com/rtems/license.html.
30 *
31 *  $Id$
32 */
33
34#ifndef __CPU_h
35#define __CPU_h
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41#include <rtems/score/ppc.h>               /* pick up machine definitions */
42#ifndef ASM
43struct CPU_Interrupt_frame;
44typedef void ( *ppc_isr_entry )( int, struct CPU_Interrupt_frame * );
45
46#include <rtems/score/ppctypes.h>
47#endif
48
49/* conditional compilation parameters */
50
51/*
52 *  Should the calls to _Thread_Enable_dispatch be inlined?
53 *
54 *  If TRUE, then they are inlined.
55 *  If FALSE, then a subroutine call is made.
56 *
57 *  Basically this is an example of the classic trade-off of size
58 *  versus speed.  Inlining the call (TRUE) typically increases the
59 *  size of RTEMS while speeding up the enabling of dispatching.
60 *  [NOTE: In general, the _Thread_Dispatch_disable_level will
61 *  only be 0 or 1 unless you are in an interrupt handler and that
62 *  interrupt handler invokes the executive.]  When not inlined
63 *  something calls _Thread_Enable_dispatch which in turns calls
64 *  _Thread_Dispatch.  If the enable dispatch is inlined, then
65 *  one subroutine call is avoided entirely.]
66 */
67
68#define CPU_INLINE_ENABLE_DISPATCH       FALSE
69
70/*
71 *  Should the body of the search loops in _Thread_queue_Enqueue_priority
72 *  be unrolled one time?  In unrolled each iteration of the loop examines
73 *  two "nodes" on the chain being searched.  Otherwise, only one node
74 *  is examined per iteration.
75 *
76 *  If TRUE, then the loops are unrolled.
77 *  If FALSE, then the loops are not unrolled.
78 *
79 *  The primary factor in making this decision is the cost of disabling
80 *  and enabling interrupts (_ISR_Flash) versus the cost of rest of the
81 *  body of the loop.  On some CPUs, the flash is more expensive than
82 *  one iteration of the loop body.  In this case, it might be desirable
83 *  to unroll the loop.  It is important to note that on some CPUs, this
84 *  code is the longest interrupt disable period in RTEMS.  So it is
85 *  necessary to strike a balance when setting this parameter.
86 */
87
88#define CPU_UNROLL_ENQUEUE_PRIORITY      FALSE
89
90/*
91 *  Does RTEMS manage a dedicated interrupt stack in software?
92 *
93 *  If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
94 *  If FALSE, nothing is done.
95 *
96 *  If the CPU supports a dedicated interrupt stack in hardware,
97 *  then it is generally the responsibility of the BSP to allocate it
98 *  and set it up.
99 *
100 *  If the CPU does not support a dedicated interrupt stack, then
101 *  the porter has two options: (1) execute interrupts on the
102 *  stack of the interrupted task, and (2) have RTEMS manage a dedicated
103 *  interrupt stack.
104 *
105 *  If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
106 *
107 *  Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
108 *  CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE.  It is
109 *  possible that both are FALSE for a particular CPU.  Although it
110 *  is unclear what that would imply about the interrupt processing
111 *  procedure on that CPU.
112 */
113
114#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
115
116/*
117 *  Does this CPU have hardware support for a dedicated interrupt stack?
118 *
119 *  If TRUE, then it must be installed during initialization.
120 *  If FALSE, then no installation is performed.
121 *
122 *  If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
123 *
124 *  Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
125 *  CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE.  It is
126 *  possible that both are FALSE for a particular CPU.  Although it
127 *  is unclear what that would imply about the interrupt processing
128 *  procedure on that CPU.
129 */
130
131/*
132 *  ACB: This is a lie, but it gets us a handle on a call to set up
133 *  a variable derived from the top of the interrupt stack.
134 */
135
136#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
137
138/*
139 *  Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
140 *
141 *  If TRUE, then the memory is allocated during initialization.
142 *  If FALSE, then the memory is allocated during initialization.
143 *
144 *  This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
145 *  or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
146 */
147
148#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
149
150/*
151 *  Does the RTEMS invoke the user's ISR with the vector number and
152 *  a pointer to the saved interrupt frame (1) or just the vector
153 *  number (0)?
154 */
155
156#define CPU_ISR_PASSES_FRAME_POINTER 1
157
158/*
159 *  Does the CPU have hardware floating point?
160 *
161 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
162 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
163 *
164 *  If there is a FP coprocessor such as the i387 or mc68881, then
165 *  the answer is TRUE.
166 *
167 *  The macro name "PPC_HAS_FPU" should be made CPU specific.
168 *  It indicates whether or not this CPU model has FP support.  For
169 *  example, it would be possible to have an i386_nofp CPU model
170 *  which set this to false to indicate that you have an i386 without
171 *  an i387 and wish to leave floating point support out of RTEMS.
172 */
173
174#if ( PPC_HAS_FPU == 1 )
175#define CPU_HARDWARE_FP     TRUE
176#else
177#define CPU_HARDWARE_FP     FALSE
178#endif
179
180/*
181 *  Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
182 *
183 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
184 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
185 *
186 *  So far, the only CPU in which this option has been used is the
187 *  HP PA-RISC.  The HP C compiler and gcc both implicitly use the
188 *  floating point registers to perform integer multiplies.  If
189 *  a function which you would not think utilize the FP unit DOES,
190 *  then one can not easily predict which tasks will use the FP hardware.
191 *  In this case, this option should be TRUE.
192 *
193 *  If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
194 */
195
196#define CPU_ALL_TASKS_ARE_FP     FALSE
197
198/*
199 *  Should the IDLE task have a floating point context?
200 *
201 *  If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
202 *  and it has a floating point context which is switched in and out.
203 *  If FALSE, then the IDLE task does not have a floating point context.
204 *
205 *  Setting this to TRUE negatively impacts the time required to preempt
206 *  the IDLE task from an interrupt because the floating point context
207 *  must be saved as part of the preemption.
208 */
209
210#define CPU_IDLE_TASK_IS_FP      FALSE
211
212/*
213 *  Should the saving of the floating point registers be deferred
214 *  until a context switch is made to another different floating point
215 *  task?
216 *
217 *  If TRUE, then the floating point context will not be stored until
218 *  necessary.  It will remain in the floating point registers and not
219 *  disturned until another floating point task is switched to.
220 *
221 *  If FALSE, then the floating point context is saved when a floating
222 *  point task is switched out and restored when the next floating point
223 *  task is restored.  The state of the floating point registers between
224 *  those two operations is not specified.
225 *
226 *  If the floating point context does NOT have to be saved as part of
227 *  interrupt dispatching, then it should be safe to set this to TRUE.
228 *
229 *  Setting this flag to TRUE results in using a different algorithm
230 *  for deciding when to save and restore the floating point context.
231 *  The deferred FP switch algorithm minimizes the number of times
232 *  the FP context is saved and restored.  The FP context is not saved
233 *  until a context switch is made to another, different FP task.
234 *  Thus in a system with only one FP task, the FP context will never
235 *  be saved or restored.
236 */
237/*
238 *  ACB Note:  This could make debugging tricky..
239 */
240
241#define CPU_USE_DEFERRED_FP_SWITCH       TRUE
242
243/*
244 *  Does this port provide a CPU dependent IDLE task implementation?
245 *
246 *  If TRUE, then the routine _CPU_Thread_Idle_body
247 *  must be provided and is the default IDLE thread body instead of
248 *  _CPU_Thread_Idle_body.
249 *
250 *  If FALSE, then use the generic IDLE thread body if the BSP does
251 *  not provide one.
252 *
253 *  This is intended to allow for supporting processors which have
254 *  a low power or idle mode.  When the IDLE thread is executed, then
255 *  the CPU can be powered down.
256 *
257 *  The order of precedence for selecting the IDLE thread body is:
258 *
259 *    1.  BSP provided
260 *    2.  CPU dependent (if provided)
261 *    3.  generic (if no BSP and no CPU dependent)
262 */
263
264#define CPU_PROVIDES_IDLE_THREAD_BODY    FALSE
265
266/*
267 *  Does the stack grow up (toward higher addresses) or down
268 *  (toward lower addresses)?
269 *
270 *  If TRUE, then the grows upward.
271 *  If FALSE, then the grows toward smaller addresses.
272 */
273
274#define CPU_STACK_GROWS_UP               FALSE
275
276/*
277 *  The following is the variable attribute used to force alignment
278 *  of critical RTEMS structures.  On some processors it may make
279 *  sense to have these aligned on tighter boundaries than
280 *  the minimum requirements of the compiler in order to have as
281 *  much of the critical data area as possible in a cache line.
282 *
283 *  The placement of this macro in the declaration of the variables
284 *  is based on the syntactically requirements of the GNU C
285 *  "__attribute__" extension.  For example with GNU C, use
286 *  the following to force a structures to a 32 byte boundary.
287 *
288 *      __attribute__ ((aligned (32)))
289 *
290 *  NOTE:  Currently only the Priority Bit Map table uses this feature.
291 *         To benefit from using this, the data must be heavily
292 *         used so it will stay in the cache and used frequently enough
293 *         in the executive to justify turning this on.
294 */
295
296#define CPU_STRUCTURE_ALIGNMENT \
297  __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
298
299/*
300 *  Define what is required to specify how the network to host conversion
301 *  routines are handled.
302 */
303
304#define CPU_CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
305#define CPU_BIG_ENDIAN                           TRUE
306#define CPU_LITTLE_ENDIAN                        FALSE
307
308/*
309 *  The following defines the number of bits actually used in the
310 *  interrupt field of the task mode.  How those bits map to the
311 *  CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
312 *
313 *  The interrupt level is bit mapped for the PowerPC family. The
314 *  bits are set to 0 to indicate that a particular exception source
315 *  enabled and 1 if it is disabled.  This keeps with RTEMS convention
316 *  that interrupt level 0 means all sources are enabled.
317 *
318 *  The bits are assigned to correspond to enable bits in the MSR.
319 */
320
321#define PPC_INTERRUPT_LEVEL_ME   0x01
322#define PPC_INTERRUPT_LEVEL_EE   0x02
323#define PPC_INTERRUPT_LEVEL_CE   0x04
324
325/* XXX should these be maskable? */
326#if 0
327#define PPC_INTERRUPT_LEVEL_DE   0x08
328#define PPC_INTERRUPT_LEVEL_BE   0x10
329#define PPC_INTERRUPT_LEVEL_SE   0x20
330#endif
331
332#define CPU_MODES_INTERRUPT_MASK   0x00000007
333
334/*
335 *  Processor defined structures
336 *
337 *  Examples structures include the descriptor tables from the i386
338 *  and the processor control structure on the i960ca.
339 */
340
341/* may need to put some structures here.  */
342
343/*
344 * Contexts
345 *
346 *  Generally there are 2 types of context to save.
347 *     1. Interrupt registers to save
348 *     2. Task level registers to save
349 *
350 *  This means we have the following 3 context items:
351 *     1. task level context stuff::  Context_Control
352 *     2. floating point task stuff:: Context_Control_fp
353 *     3. special interrupt level context :: Context_Control_interrupt
354 *
355 *  On some processors, it is cost-effective to save only the callee
356 *  preserved registers during a task context switch.  This means
357 *  that the ISR code needs to save those registers which do not
358 *  persist across function calls.  It is not mandatory to make this
359 *  distinctions between the caller/callee saves registers for the
360 *  purpose of minimizing context saved during task switch and on interrupts.
361 *  If the cost of saving extra registers is minimal, simplicity is the
362 *  choice.  Save the same context on interrupt entry as for tasks in
363 *  this case.
364 *
365 *  Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
366 *  care should be used in designing the context area.
367 *
368 *  On some CPUs with hardware floating point support, the Context_Control_fp
369 *  structure will not be used or it simply consist of an array of a
370 *  fixed number of bytes.   This is done when the floating point context
371 *  is dumped by a "FP save context" type instruction and the format
372 *  is not really defined by the CPU.  In this case, there is no need
373 *  to figure out the exact format -- only the size.  Of course, although
374 *  this is enough information for RTEMS, it is probably not enough for
375 *  a debugger such as gdb.  But that is another problem.
376 */
377
378typedef struct {
379    unsigned32 gpr1;    /* Stack pointer for all */
380    unsigned32 gpr2;    /* TOC in PowerOpen, reserved SVR4, section ptr EABI + */
381    unsigned32 gpr13;   /* First non volatile PowerOpen, section ptr SVR4/EABI */
382    unsigned32 gpr14;   /* Non volatile for all */
383    unsigned32 gpr15;   /* Non volatile for all */
384    unsigned32 gpr16;   /* Non volatile for all */
385    unsigned32 gpr17;   /* Non volatile for all */
386    unsigned32 gpr18;   /* Non volatile for all */
387    unsigned32 gpr19;   /* Non volatile for all */
388    unsigned32 gpr20;   /* Non volatile for all */
389    unsigned32 gpr21;   /* Non volatile for all */
390    unsigned32 gpr22;   /* Non volatile for all */
391    unsigned32 gpr23;   /* Non volatile for all */
392    unsigned32 gpr24;   /* Non volatile for all */
393    unsigned32 gpr25;   /* Non volatile for all */
394    unsigned32 gpr26;   /* Non volatile for all */
395    unsigned32 gpr27;   /* Non volatile for all */
396    unsigned32 gpr28;   /* Non volatile for all */
397    unsigned32 gpr29;   /* Non volatile for all */
398    unsigned32 gpr30;   /* Non volatile for all */
399    unsigned32 gpr31;   /* Non volatile for all */
400    unsigned32 cr;      /* PART of the CR is non volatile for all */
401    unsigned32 pc;      /* Program counter/Link register */
402    unsigned32 msr;     /* Initial interrupt level */
403} Context_Control;
404
405typedef struct {
406    /* The ABIs (PowerOpen/SVR4/EABI) only require saving f14-f31 over
407     * procedure calls.  However, this would mean that the interrupt
408     * frame had to hold f0-f13, and the fpscr.  And as the majority
409     * of tasks will not have an FP context, we will save the whole
410     * context here.
411     */
412#if (PPC_HAS_DOUBLE == 1)
413    double      f[32];
414    double      fpscr;
415#else
416    float       f[32];
417    float       fpscr;
418#endif
419} Context_Control_fp;
420
421typedef struct CPU_Interrupt_frame {
422    unsigned32 stacklink;       /* Ensure this is a real frame (also reg1 save) */
423#if (PPC_ABI == PPC_ABI_POWEROPEN || PPC_ABI == PPC_ABI_GCC27)
424    unsigned32 dummy[13];       /* Used by callees: PowerOpen ABI */
425#else
426    unsigned32 dummy[1];        /* Used by callees: SVR4/EABI */
427#endif
428    /* This is what is left out of the primary contexts */
429    unsigned32 gpr0;
430    unsigned32 gpr2;            /* play safe */
431    unsigned32 gpr3;
432    unsigned32 gpr4;
433    unsigned32 gpr5;
434    unsigned32 gpr6;
435    unsigned32 gpr7;
436    unsigned32 gpr8;
437    unsigned32 gpr9;
438    unsigned32 gpr10;
439    unsigned32 gpr11;
440    unsigned32 gpr12;
441    unsigned32 gpr13;   /* Play safe */
442    unsigned32 gpr28;   /* For internal use by the IRQ handler */
443    unsigned32 gpr29;   /* For internal use by the IRQ handler */
444    unsigned32 gpr30;   /* For internal use by the IRQ handler */
445    unsigned32 gpr31;   /* For internal use by the IRQ handler */
446    unsigned32 cr;      /* Bits of this are volatile, so no-one may save */
447    unsigned32 ctr;
448    unsigned32 xer;
449    unsigned32 lr;
450    unsigned32 pc;
451    unsigned32 msr;
452    unsigned32 pad[3];
453} CPU_Interrupt_frame;
454
455
456/*
457 *  The following table contains the information required to configure
458 *  the PowerPC processor specific parameters.
459 */
460
461typedef struct {
462  void       (*pretasking_hook)( void );
463  void       (*predriver_hook)( void );
464  void       (*postdriver_hook)( void );
465  void       (*idle_task)( void );
466  boolean      do_zero_of_workspace;
467  unsigned32   idle_task_stack_size;
468  unsigned32   interrupt_stack_size;
469  unsigned32   extra_mpci_receive_server_stack;
470  void *     (*stack_allocate_hook)( unsigned32 );
471  void       (*stack_free_hook)( void* );
472  /* end of fields required on all CPUs */
473
474  unsigned32   clicks_per_usec;        /* Timer clicks per microsecond */
475  void       (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
476  boolean      exceptions_in_RAM;     /* TRUE if in RAM */
477
478#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
479  unsigned32   serial_per_sec;         /* Serial clocks per second */
480  boolean      serial_external_clock;
481  boolean      serial_xon_xoff;
482  boolean      serial_cts_rts;
483  unsigned32   serial_rate;
484  unsigned32   timer_average_overhead; /* Average overhead of timer in ticks */
485  unsigned32   timer_least_valid;      /* Least valid number from timer      */
486  boolean      timer_internal_clock;   /* TRUE, when timer runs with CPU clk */
487#endif
488
489#if (defined(mpc860) || defined(mpc821))
490  unsigned32   clock_speed;            /* Speed of CPU in Hz */
491#endif
492}   rtems_cpu_table;
493
494/*
495 *  The following type defines an entry in the PPC's trap table.
496 *
497 *  NOTE: The instructions chosen are RTEMS dependent although one is
498 *        obligated to use two of the four instructions to perform a
499 *        long jump.  The other instructions load one register with the
500 *        trap type (a.k.a. vector) and another with the psr.
501 */
502 
503typedef struct {
504  unsigned32   stwu_r1;                       /* stwu  %r1, -(??+IP_END)(%1)*/
505  unsigned32   stw_r0;                        /* stw   %r0, IP_0(%r1)       */
506  unsigned32   li_r0_IRQ;                     /* li    %r0, _IRQ            */
507  unsigned32   b_Handler;                     /* b     PROC (_ISR_Handler)  */
508} CPU_Trap_table_entry;
509
510/*
511 *  This variable is optional.  It is used on CPUs on which it is difficult
512 *  to generate an "uninitialized" FP context.  It is filled in by
513 *  _CPU_Initialize and copied into the task's FP context area during
514 *  _CPU_Context_Initialize.
515 */
516
517/* EXTERN Context_Control_fp  _CPU_Null_fp_context; */
518
519/*
520 *  On some CPUs, RTEMS supports a software managed interrupt stack.
521 *  This stack is allocated by the Interrupt Manager and the switch
522 *  is performed in _ISR_Handler.  These variables contain pointers
523 *  to the lowest and highest addresses in the chunk of memory allocated
524 *  for the interrupt stack.  Since it is unknown whether the stack
525 *  grows up or down (in general), this give the CPU dependent
526 *  code the option of picking the version it wants to use.
527 *
528 *  NOTE: These two variables are required if the macro
529 *        CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
530 */
531
532SCORE_EXTERN void               *_CPU_Interrupt_stack_low;
533SCORE_EXTERN void               *_CPU_Interrupt_stack_high;
534
535/*
536 *  With some compilation systems, it is difficult if not impossible to
537 *  call a high-level language routine from assembly language.  This
538 *  is especially true of commercial Ada compilers and name mangling
539 *  C++ ones.  This variable can be optionally defined by the CPU porter
540 *  and contains the address of the routine _Thread_Dispatch.  This
541 *  can make it easier to invoke that routine at the end of the interrupt
542 *  sequence (if a dispatch is necessary).
543 */
544
545/* EXTERN void           (*_CPU_Thread_dispatch_pointer)(); */
546
547/*
548 *  Nothing prevents the porter from declaring more CPU specific variables.
549 */
550
551
552SCORE_EXTERN struct {
553  unsigned32 *Nest_level;
554  unsigned32 *Disable_level;
555  void *Vector_table;
556  void *Stack;
557#if (PPC_ABI == PPC_ABI_POWEROPEN)
558  unsigned32 Dispatch_r2;
559#else
560  unsigned32 Default_r2;
561#if (PPC_ABI != PPC_ABI_GCC27)
562  unsigned32 Default_r13;
563#endif
564#endif
565  volatile boolean *Switch_necessary;
566  boolean *Signal;
567
568  unsigned32 msr_initial;
569} _CPU_IRQ_info CPU_STRUCTURE_ALIGNMENT;
570
571/*
572 *  The size of the floating point context area.  On some CPUs this
573 *  will not be a "sizeof" because the format of the floating point
574 *  area is not defined -- only the size is.  This is usually on
575 *  CPUs with a "floating point save context" instruction.
576 */
577
578#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
579
580/*
581 * (Optional) # of bytes for libmisc/stackchk to check
582 * If not specifed, then it defaults to something reasonable
583 * for most architectures.
584 */
585
586#define CPU_STACK_CHECK_SIZE    (128)
587
588/*
589 *  Amount of extra stack (above minimum stack size) required by
590 *  MPCI receive server thread.  Remember that in a multiprocessor
591 *  system this thread must exist and be able to process all directives.
592 */
593
594#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
595
596/*
597 *  This defines the number of entries in the ISR_Vector_table managed
598 *  by RTEMS.
599 */
600
601#define CPU_INTERRUPT_NUMBER_OF_VECTORS     (PPC_INTERRUPT_MAX)
602#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (PPC_INTERRUPT_MAX - 1)
603
604/*
605 *  Should be large enough to run all RTEMS tests.  This insures
606 *  that a "reasonable" small application should not have any problems.
607 */
608
609#define CPU_STACK_MINIMUM_SIZE          (1024*3)
610
611/*
612 *  CPU's worst alignment requirement for data types on a byte boundary.  This
613 *  alignment does not take into account the requirements for the stack.
614 */
615
616#define CPU_ALIGNMENT              (PPC_ALIGNMENT)
617
618/*
619 *  This number corresponds to the byte alignment requirement for the
620 *  heap handler.  This alignment requirement may be stricter than that
621 *  for the data types alignment specified by CPU_ALIGNMENT.  It is
622 *  common for the heap to follow the same alignment requirement as
623 *  CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
624 *  then this should be set to CPU_ALIGNMENT.
625 *
626 *  NOTE:  This does not have to be a power of 2.  It does have to
627 *         be greater or equal to than CPU_ALIGNMENT.
628 */
629
630#define CPU_HEAP_ALIGNMENT         (PPC_ALIGNMENT)
631
632/*
633 *  This number corresponds to the byte alignment requirement for memory
634 *  buffers allocated by the partition manager.  This alignment requirement
635 *  may be stricter than that for the data types alignment specified by
636 *  CPU_ALIGNMENT.  It is common for the partition to follow the same
637 *  alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
638 *  enough for the partition, then this should be set to CPU_ALIGNMENT.
639 *
640 *  NOTE:  This does not have to be a power of 2.  It does have to
641 *         be greater or equal to than CPU_ALIGNMENT.
642 */
643
644#define CPU_PARTITION_ALIGNMENT    (PPC_ALIGNMENT)
645
646/*
647 *  This number corresponds to the byte alignment requirement for the
648 *  stack.  This alignment requirement may be stricter than that for the
649 *  data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
650 *  is strict enough for the stack, then this should be set to 0.
651 *
652 *  NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
653 */
654
655#define CPU_STACK_ALIGNMENT        (PPC_STACK_ALIGNMENT)
656
657/* ISR handler macros */
658
659/*
660 *  Disable all interrupts for an RTEMS critical section.  The previous
661 *  level is returned in _isr_cookie.
662 */
663
664#define loc_string(a,b) a " (" #b ")\n"
665
666#define _CPU_MSR_Value( _msr_value ) \
667  do { \
668    _msr_value = 0; \
669    asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
670  } while (0)
671
672#define _CPU_MSR_SET( _msr_value ) \
673{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
674
675#if 0
676#define _CPU_ISR_Disable( _isr_cookie ) \
677  { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
678    _isr_cookie = 0; \
679    asm volatile (
680        "mfmsr %0" : \
681        "=r" ((_isr_cookie)) : \
682        "0" ((_isr_cookie)) \
683    ); \
684    asm volatile (
685        "andc %1,%0,%1" : \
686        "=r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
687        "0" ((_isr_cookie)), "1" ((_disable_mask)) \
688    ); \
689    asm volatile (
690        "mtmsr %1" : \
691        "=r" ((_disable_mask)) : \
692        "0" ((_disable_mask)) \
693    ); \
694  }
695#endif
696
697#define _CPU_ISR_Disable( _isr_cookie ) \
698  { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
699    _isr_cookie = 0; \
700    asm volatile ( \
701        "mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
702        "=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
703        "0" ((_isr_cookie)), "1" ((_disable_mask)) \
704        ); \
705  }
706
707
708#define _CPU_Data_Cache_Block_Flush( _address ) \
709  do { register void *__address = (_address); \
710       register unsigned32 _zero = 0; \
711       asm volatile ( "dcbf %0,%1" : \
712                      "=r" (_zero), "=r" (__address) : \
713                      "0" (_zero), "1" (__address) \
714       ); \
715  } while (0)
716
717
718/*
719 *  Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
720 *  This indicates the end of an RTEMS critical section.  The parameter
721 *  _isr_cookie is not modified.
722 */
723
724#define _CPU_ISR_Enable( _isr_cookie )  \
725  { \
726     asm volatile ( "mtmsr %0" : \
727                   "=r" ((_isr_cookie)) : \
728                   "0" ((_isr_cookie))); \
729  }
730
731/*
732 *  This temporarily restores the interrupt to _isr_cookie before immediately
733 *  disabling them again.  This is used to divide long RTEMS critical
734 *  sections into two or more parts.  The parameter _isr_cookie is not
735 *  modified.
736 *
737 *  NOTE:  The version being used is not very optimized but it does
738 *         not trip a problem in gcc where the disable mask does not
739 *         get loaded.  Check this for future (post 10/97 gcc versions.
740 */
741
742#define _CPU_ISR_Flash( _isr_cookie ) \
743  { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
744    asm volatile ( \
745      "mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
746      "=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
747      "0" ((_isr_cookie)), "1" ((_disable_mask)) \
748    ); \
749  }
750
751/*
752 *  Map interrupt level in task mode onto the hardware that the CPU
753 *  actually provides.  Currently, interrupt levels which do not
754 *  map onto the CPU in a generic fashion are undefined.  Someday,
755 *  it would be nice if these were "mapped" by the application
756 *  via a callout.  For example, m68k has 8 levels 0 - 7, levels
757 *  8 - 255 would be available for bsp/application specific meaning.
758 *  This could be used to manage a programmable interrupt controller
759 *  via the rtems_task_mode directive.
760 */
761
762unsigned32 _CPU_ISR_Calculate_level(
763  unsigned32 new_level
764);
765
766void _CPU_ISR_Set_level(
767  unsigned32 new_level
768);
769 
770unsigned32 _CPU_ISR_Get_level( void );
771
772void _CPU_ISR_install_raw_handler(
773  unsigned32  vector,
774  proc_ptr    new_handler,
775  proc_ptr   *old_handler
776);
777
778/* end of ISR handler macros */
779
780/*
781 *  Simple spin delay in microsecond units for device drivers.
782 *  This is very dependent on the clock speed of the target.
783 */
784
785#define CPU_Get_timebase_low( _value ) \
786    asm volatile( "mftb  %0" : "=r" (_value) )
787
788#define delay( _microseconds ) \
789  do { \
790    unsigned32 start, ticks, now; \
791    CPU_Get_timebase_low( start ) ; \
792    ticks = (_microseconds) * Cpu_table.clicks_per_usec; \
793    do \
794      CPU_Get_timebase_low( now ) ; \
795    while (now - start < ticks); \
796  } while (0)
797
798#define delay_in_bus_cycles( _cycles ) \
799  do { \
800    unsigned32 start, now; \
801    CPU_Get_timebase_low( start ); \
802    do \
803      CPU_Get_timebase_low( now ); \
804    while (now - start < (_cycles)); \
805  } while (0)
806
807
808
809/* Context handler macros */
810
811/*
812 *  Initialize the context to a state suitable for starting a
813 *  task after a context restore operation.  Generally, this
814 *  involves:
815 *
816 *     - setting a starting address
817 *     - preparing the stack
818 *     - preparing the stack and frame pointers
819 *     - setting the proper interrupt level in the context
820 *     - initializing the floating point context
821 *
822 *  This routine generally does not set any unnecessary register
823 *  in the context.  The state of the "general data" registers is
824 *  undefined at task start time.
825 *
826 *  NOTE:  Implemented as a subroutine for the SPARC port.
827 */
828
829void _CPU_Context_Initialize(
830  Context_Control  *the_context,
831  unsigned32       *stack_base,
832  unsigned32        size,
833  unsigned32        new_level,
834  void             *entry_point,
835  boolean           is_fp
836);
837
838/*
839 *  This routine is responsible for somehow restarting the currently
840 *  executing task.  If you are lucky, then all that is necessary
841 *  is restoring the context.  Otherwise, there will need to be
842 *  a special assembly routine which does something special in this
843 *  case.  Context_Restore should work most of the time.  It will
844 *  not work if restarting self conflicts with the stack frame
845 *  assumptions of restoring a context.
846 */
847
848#define _CPU_Context_Restart_self( _the_context ) \
849   _CPU_Context_restore( (_the_context) );
850
851/*
852 *  The purpose of this macro is to allow the initial pointer into
853 *  a floating point context area (used to save the floating point
854 *  context) to be at an arbitrary place in the floating point
855 *  context area.
856 *
857 *  This is necessary because some FP units are designed to have
858 *  their context saved as a stack which grows into lower addresses.
859 *  Other FP units can be saved by simply moving registers into offsets
860 *  from the base of the context area.  Finally some FP units provide
861 *  a "dump context" instruction which could fill in from high to low
862 *  or low to high based on the whim of the CPU designers.
863 */
864
865#define _CPU_Context_Fp_start( _base, _offset ) \
866   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
867
868/*
869 *  This routine initializes the FP context area passed to it to.
870 *  There are a few standard ways in which to initialize the
871 *  floating point context.  The code included for this macro assumes
872 *  that this is a CPU in which a "initial" FP context was saved into
873 *  _CPU_Null_fp_context and it simply copies it to the destination
874 *  context passed to it.
875 *
876 *  Other models include (1) not doing anything, and (2) putting
877 *  a "null FP status word" in the correct place in the FP context.
878 */
879
880#define _CPU_Context_Initialize_fp( _destination ) \
881  { \
882   ((Context_Control_fp *) *((void **) _destination))->fpscr = PPC_INIT_FPSCR; \
883  }
884
885/* end of Context handler macros */
886
887/* Fatal Error manager macros */
888
889/*
890 *  This routine copies _error into a known place -- typically a stack
891 *  location or a register, optionally disables interrupts, and
892 *  halts/stops the CPU.
893 */
894
895#define _CPU_Fatal_halt( _error ) \
896  _CPU_Fatal_error(_error)
897
898/* end of Fatal Error manager macros */
899
900/* Bitfield handler macros */
901
902/*
903 *  This routine sets _output to the bit number of the first bit
904 *  set in _value.  _value is of CPU dependent type Priority_Bit_map_control.
905 *  This type may be either 16 or 32 bits wide although only the 16
906 *  least significant bits will be used.
907 *
908 *  There are a number of variables in using a "find first bit" type
909 *  instruction.
910 *
911 *    (1) What happens when run on a value of zero?
912 *    (2) Bits may be numbered from MSB to LSB or vice-versa.
913 *    (3) The numbering may be zero or one based.
914 *    (4) The "find first bit" instruction may search from MSB or LSB.
915 *
916 *  RTEMS guarantees that (1) will never happen so it is not a concern.
917 *  (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
918 *  _CPU_Priority_Bits_index().  These three form a set of routines
919 *  which must logically operate together.  Bits in the _value are
920 *  set and cleared based on masks built by _CPU_Priority_mask().
921 *  The basic major and minor values calculated by _Priority_Major()
922 *  and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
923 *  to properly range between the values returned by the "find first bit"
924 *  instruction.  This makes it possible for _Priority_Get_highest() to
925 *  calculate the major and directly index into the minor table.
926 *  This mapping is necessary to ensure that 0 (a high priority major/minor)
927 *  is the first bit found.
928 *
929 *  This entire "find first bit" and mapping process depends heavily
930 *  on the manner in which a priority is broken into a major and minor
931 *  components with the major being the 4 MSB of a priority and minor
932 *  the 4 LSB.  Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
933 *  priority.  And (15 << 4) + 14 corresponds to priority 254 -- the next
934 *  to the lowest priority.
935 *
936 *  If your CPU does not have a "find first bit" instruction, then
937 *  there are ways to make do without it.  Here are a handful of ways
938 *  to implement this in software:
939 *
940 *    - a series of 16 bit test instructions
941 *    - a "binary search using if's"
942 *    - _number = 0
943 *      if _value > 0x00ff
944 *        _value >>=8
945 *        _number = 8;
946 *
947 *      if _value > 0x0000f
948 *        _value >=8
949 *        _number += 4
950 *
951 *      _number += bit_set_table[ _value ]
952 *
953 *    where bit_set_table[ 16 ] has values which indicate the first
954 *      bit set
955 */
956
957#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
958  { \
959    asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \
960                  "1" ((_value))); \
961  }
962
963/* end of Bitfield handler macros */
964
965/*
966 *  This routine builds the mask which corresponds to the bit fields
967 *  as searched by _CPU_Bitfield_Find_first_bit().  See the discussion
968 *  for that routine.
969 */
970
971#define _CPU_Priority_Mask( _bit_number ) \
972  ( 0x80000000 >> (_bit_number) )
973
974/*
975 *  This routine translates the bit numbers returned by
976 *  _CPU_Bitfield_Find_first_bit() into something suitable for use as
977 *  a major or minor component of a priority.  See the discussion
978 *  for that routine.
979 */
980
981#define _CPU_Priority_bits_index( _priority ) \
982  (_priority)
983
984/* end of Priority handler macros */
985
986/* variables */
987
988extern const unsigned32 _CPU_msrs[4];
989
990/* functions */
991
992/*
993 *  _CPU_Initialize
994 *
995 *  This routine performs CPU dependent initialization.
996 */
997
998void _CPU_Initialize(
999  rtems_cpu_table  *cpu_table,
1000  void            (*thread_dispatch)
1001);
1002
1003/*
1004 *  _CPU_ISR_install_vector
1005 *
1006 *  This routine installs an interrupt vector.
1007 */
1008
1009void _CPU_ISR_install_vector(
1010  unsigned32  vector,
1011  proc_ptr    new_handler,
1012  proc_ptr   *old_handler
1013);
1014
1015/*
1016 *  _CPU_Install_interrupt_stack
1017 *
1018 *  This routine installs the hardware interrupt stack pointer.
1019 *
1020 *  NOTE:  It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
1021 *         is TRUE.
1022 */
1023
1024void _CPU_Install_interrupt_stack( void );
1025
1026/*
1027 *  _CPU_Context_switch
1028 *
1029 *  This routine switches from the run context to the heir context.
1030 */
1031
1032void _CPU_Context_switch(
1033  Context_Control  *run,
1034  Context_Control  *heir
1035);
1036
1037/*
1038 *  _CPU_Context_restore
1039 *
1040 *  This routine is generallu used only to restart self in an
1041 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
1042 *
1043 *  NOTE: May be unnecessary to reload some registers.
1044 */
1045
1046void _CPU_Context_restore(
1047  Context_Control *new_context
1048);
1049
1050/*
1051 *  _CPU_Context_save_fp
1052 *
1053 *  This routine saves the floating point context passed to it.
1054 */
1055
1056void _CPU_Context_save_fp(
1057  void **fp_context_ptr
1058);
1059
1060/*
1061 *  _CPU_Context_restore_fp
1062 *
1063 *  This routine restores the floating point context passed to it.
1064 */
1065
1066void _CPU_Context_restore_fp(
1067  void **fp_context_ptr
1068);
1069
1070void _CPU_Fatal_error(
1071  unsigned32 _error
1072);
1073
1074/*  The following routine swaps the endian format of an unsigned int.
1075 *  It must be static because it is referenced indirectly.
1076 *
1077 *  This version will work on any processor, but if there is a better
1078 *  way for your CPU PLEASE use it.  The most common way to do this is to:
1079 *
1080 *     swap least significant two bytes with 16-bit rotate
1081 *     swap upper and lower 16-bits
1082 *     swap most significant two bytes with 16-bit rotate
1083 *
1084 *  Some CPUs have special instructions which swap a 32-bit quantity in
1085 *  a single instruction (e.g. i486).  It is probably best to avoid
1086 *  an "endian swapping control bit" in the CPU.  One good reason is
1087 *  that interrupts would probably have to be disabled to insure that
1088 *  an interrupt does not try to access the same "chunk" with the wrong
1089 *  endian.  Another good reason is that on some CPUs, the endian bit
1090 *  endianness for ALL fetches -- both code and data -- so the code
1091 *  will be fetched incorrectly.
1092 */
1093 
1094static inline unsigned int CPU_swap_u32(
1095  unsigned int value
1096)
1097{
1098  unsigned32 swapped;
1099 
1100  asm volatile("rlwimi %0,%1,8,24,31;"
1101               "rlwimi %0,%1,24,16,23;"
1102               "rlwimi %0,%1,8,8,15;"
1103               "rlwimi %0,%1,24,0,7;" :
1104               "=&r" ((swapped)) : "r" ((value)));
1105
1106  return( swapped );
1107}
1108
1109#define CPU_swap_u16( value ) \
1110  (((value&0xff) << 8) | ((value >> 8)&0xff))
1111
1112/*
1113 *  Routines to access the decrementer register
1114 */
1115
1116#define PPC_Set_decrementer( _clicks ) \
1117  do { \
1118    asm volatile( "mtdec %0" : "=r" ((_clicks)) : "r" ((_clicks)) ); \
1119  } while (0)
1120
1121/*
1122 *  Routines to access the time base register
1123 */
1124
1125static inline unsigned64 PPC_Get_timebase_register( void )
1126{
1127  unsigned32 tbr_low;
1128  unsigned32 tbr_high;
1129  unsigned32 tbr_high_old;
1130  unsigned64 tbr;
1131
1132  do {
1133    asm volatile( "mftbu %0" : "=r" (tbr_high_old));
1134    asm volatile( "mftb  %0" : "=r" (tbr_low));
1135    asm volatile( "mftbu %0" : "=r" (tbr_high));
1136  } while ( tbr_high_old != tbr_high );
1137
1138  tbr = tbr_high;
1139  tbr <<= 32;
1140  tbr |= tbr_low;
1141  return tbr;
1142}
1143
1144#ifdef __cplusplus
1145}
1146#endif
1147
1148#endif
Note: See TracBrowser for help on using the repository browser.