source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h @ 94e1931c

4.104.114.95
Last change on this file since 94e1931c was 94e1931c, checked in by Till Straumann <strauman@…>, on 12/08/07 at 23:43:24

2007-12-08 Till Straumann <strauman@…>

  • new-exceptions/bspsupport/, new-exceptions/bspsupport/ppc_exc.S, new-exceptions/bspsupport/ppc_exc_test.c, new-exceptions/bspsupport/vectors.h, new-exceptions/bspsupport/vectors_init.c, new-exceptions/bspsupport/irq.c, new-exceptions/bspsupport/ppc_exc_bspsupp.h, new-exceptions/bspsupport/ppc_exc_hdl.c, new-exceptions/bspsupport/ppc_exc_asm_macros.h, new-exceptions/bspsupport/nested_irq_test.c: New files. Added 'middleware' code for helping BSPs implement exception and interrupt handling and implementing the 'new' RTEMS IRQ API (which I personally dislike).
  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * (c) 1999, Eric Valette valette@crf.canon.fr
3 *
4 * Modified and partially rewritten by Till Straumann, 2007
5 *
6 * Low-level assembly code for PPC exceptions (macros).
7 *
8 * This file was written with the goal to eliminate
9 * ALL #ifdef <cpu_flavor> conditionals -- please do not
10 * reintroduce such statements.
11 */
12
13#include <rtems/score/cpu.h>
14#include <bsp/vectors.h>
15#include <libcpu/raw_exception.h>
16
17#define EXC_MIN_GPR1            0
18#define FRAME_LINK_SPACE        8
19
20#define r0      0
21#define r1      1
22#define r2      2
23#define r3      3
24#define r4      4
25#define r5      5
26#define r6      6
27#define r7      7
28#define r8      8
29#define r9      9
30#define r10     10
31#define r11     11
32#define r12     12
33#define r13     13
34#define r14     14
35#define r15     15
36#define r16     16
37#define r17     17
38#define r18     18
39#define r19     19
40#define r20     20
41#define r21     21
42#define r22     22
43#define r23     23
44#define r24     24
45#define r25     25
46#define r26     26
47#define r27     27
48#define r28     28
49#define r29     29
50#define r30     30
51#define r31     31
52
53#define cr0 0
54#define cr1 1
55#define cr4 4
56
57#define LT(cr)  ((cr)*4+0)
58#define GT(cr)  ((cr)*4+1)
59#define EQ(cr)  ((cr)*4+2)
60
61#define NOFRAME 0xffff8000
62
63/* Switch r1 to interrupt stack if not already there.
64 *
65 * USES:    RA, RB
66 * ON EXIT: RA, RB available, r1 points into interrupt
67 *          stack.
68 *
69 * NOTES:
70 *   - NEVER store stuff in a frame before
71 *     reserving it (stwu r1) - otherwise
72 *     higher-priority exception may overwrite.
73 *   - algorithm should allow nesting of higher
74 *     priority exceptions (HPE) (by disabling
75 *     them while the stack is switched).
76 */
77#if 0
78        .macro  SWITCH_STACK RA RB FLVR
79        mfspr   \RB, SPRG1
80        cmplw   cr0, r1, \RB
81        bgt             do_r1_reload_\FLVR
82        lwz     \RA, ppc_exc_intr_stack_size@sdarel(r13)
83        subf    \RB, \RB, \RA
84        cmplw   cr0, r1, \RB
85        bge             no_r1_reload_\FLVR
86do_r1_reload_\FLVR:
87        mfspr   r1, SPRG1
88no_r1_reload_\FLVR:
89        .endm
90#else
91        .macro  SWITCH_STACK RA RB FLVR
92        /* disable interrupts */
93        lwz             \RA, ppc_exc_msr_irq_mask@sdarel(r13)
94        mfmsr   \RB
95        and             \RA, \RB, \RA
96        mtmsr   \RA
97        /* increment nest level */
98        lwz             \RA, _ISR_Nest_level@sdarel(r13)
99        cmplwi  cr0, \RA, 0
100        bne     no_r1_reload_\FLVR
101        /* reload r1            */
102        mfspr   r1, SPRG1
103no_r1_reload_\FLVR:
104        addi    \RA, \RA, 1
105        stw             \RA, _ISR_Nest_level@sdarel(r13)
106        /* restore IRQ mask     */
107        mtmsr   \RB
108        .endm
109#endif
110
111        /*
112         * Minimal prologue snippets:
113         *
114         * Rationale: on some PPCs the vector offsets are spaced
115         * as closely as 16 bytes.
116         *
117         * If we deal with asynchronous exceptions ('interrupts')
118         * then we can use 4 instructions to
119         *   1. atomically write lock to indicate ISR is in progress
120         *      (we cannot atomically increase the Thread_Dispatch_disable_level,
121         *      see README)
122         *   2. save a register in special area
123         *   3. load register with vector info
124         *   4. branch
125         *
126         * If we deal with a synchronous exception (no stack switch
127         * nor dispatch-disabling necessary) then it's easier:
128         *   1. push stack frame
129         *   2. save register on stack
130         *   3. load register with vector info
131         *   4. branch
132         *
133         */
134        .macro  PPC_EXC_MIN_PROLOG_ASYNC _NAME _VEC _PRI _FLVR
135        .global ppc_exc_min_prolog_async_\_NAME
136ppc_exc_min_prolog_async_\_NAME:
137        /* Atomically write lock variable in 1st instruction with non-zero value
138         * (r1 is always nonzero; r13 could also be used)
139         */
140        stw             r1, ppc_exc_lock_\_PRI@sdarel(r13)
141        /* We have no stack frame yet; store r3 in special area;
142         * a higher-priority (critical) interrupt uses a different area
143         * (hence the different prologue snippets) (\PRI)
144         */
145        stw             r3, ppc_exc_gpr3_\_PRI@sdarel(r13)
146        /* Load vector.
147         */
148        li              r3, ( \_VEC | 0xffff8000 )
149        /* Branch (must be within 32MB)
150         */
151        ba              wrap_\_FLVR
152        .endm
153
154        .macro PPC_EXC_MIN_PROLOG_SYNC _NAME _VEC _PRI _FLVR
155        .global ppc_exc_min_prolog_sync_\_NAME
156ppc_exc_min_prolog_sync_\_NAME:
157        stwu    r1, -EXCEPTION_FRAME_END(r1)
158        stw             r3, GPR3_OFFSET(r1)
159        li              r3, \_VEC
160        ba              wrap_nopush_\_FLVR
161        .endm
162               
163        .macro TEST_LOCK_std
164        /* 'std' is lowest level, i.e., can not be locked -> EQ(cr4) = 1 */
165        creqv EQ(cr4), EQ(cr4), EQ(cr4)
166        .endm
167
168        /* critical-exception wrapper has to check 'std' lock: */
169        .macro TEST_LOCK_crit
170        lwz r5, ppc_exc_lock_std@sdarel(r13)
171        cmpli   cr4, r5, 0
172        .endm
173
174        /* machine-check wrapper has to check 'std' and 'crit' locks */
175        .macro TEST_LOCK_mchk
176        lwz r5, ppc_exc_lock_std@sdarel(r13)
177        cmpli   cr4, r5, 0
178        lwz r5, ppc_exc_lock_crit@sdarel(r13)
179        cmpli   cr0, r5, 0
180        cror    EQ(cr4), EQ(cr4), EQ(cr0)
181        .endm
182
183        /* Minimal prologue snippets jump into WRAP
184         * which prepares calling code common to all
185         * flavors of exceptions.
186         * We must have this macro instantiated for
187         * each possible flavor of exception so that
188         * we use the proper lock variable, SRR register pair and
189         * RFI instruction.
190         */
191        .macro  WRAP _FLVR _PRI _SRR0 _SRR1 _RFI
192wrap_\_FLVR:
193        stwu    r1,  -EXCEPTION_FRAME_END(r1)
194wrap_nopush_\_FLVR:
195        stw             r14, GPR14_OFFSET(r1)
196wrap_no_save_r14_\_FLVR:
197
198        /* Save r4 r5 and CR; we want CR soon */
199        mfcr    r14
200        stw             r4,  GPR4_OFFSET(r1)
201        stw             r5,  GPR5_OFFSET(r1)
202        stw             r14, EXC_CR_OFFSET(r1)
203
204        /* Check if this is an 'interrupt-type' exception
205         * (MSB vector is set).
206         * 'interrupt-type' exceptions disable thread dispatching
207         * and switch to a private stack.
208         * The type of exception is kept in (non-volatile) cr2
209         *  < 0 -> interrupt-type
210         *  > 0 -> 'normal' exception; always on task stack,
211         *         may switch context at any time.
212         */
213        cmpwi   cr2, r3, 0
214
215        /*
216         * Save frame address in r14
217         */
218        mr      r14, r1
219
220        bge     cr2, no_thread_dispatch_disable_\_FLVR
221
222        /* first thing we need to
223         * increment the thread-dispatch disable level
224         * in case a higher priority exception occurs
225         * we don't want it to run the scheduler.
226         */
227        lwz             r5,  _Thread_Dispatch_disable_level@sdarel(r13)
228        addi    r5,  r5, 1
229        stw             r5,  _Thread_Dispatch_disable_level@sdarel(r13)
230
231        /* clear lock; no higher-priority interrupt occurring after
232         * this point can cause a context switch.
233         */
234        li              r5,  0
235        stw             r5,  ppc_exc_lock_\_PRI@sdarel(r13)
236
237        /* test lower-priority locks; result in (non-volatile) cr4 */
238        TEST_LOCK_\_PRI
239
240        /* Peform stack switch if necessary */
241        SWITCH_STACK RA=r4 RB=r5 FLVR=\_FLVR
242
243        /* save r3, in exception frame */
244        lwz             r5,  ppc_exc_gpr3_\_PRI@sdarel(r13)
245        stw             r5,  GPR3_OFFSET(r14)
246
247no_thread_dispatch_disable_\_FLVR:
248
249        /* save lr into exception frame */
250        mflr    r4
251        stw     r4,  EXC_LR_OFFSET(r14)
252
253        /* we now have r4,r5,lr,cr available;
254         * r3  still holds the vector,
255         * r14 a pointer to the exception frame (always on
256         *     task stack)
257         * r1  is the stack pointer, either on the task stack
258         *     or on the IRQ stack
259         */
260
261        /* retrieve SRR0/SRR1 */
262        mf\_SRR0        r4
263        mf\_SRR1        r5
264
265        /* branch to common routine */
266        bl              wrap_common
267
268        /* restore SRR, r4, r5, r1 (stack pointer) and lr */
269        mt\_SRR0        r4
270        mt\_SRR1        r5
271        /* restore lr */
272        lwz             r5,  EXC_LR_OFFSET(r1)
273        lwz             r4,  GPR4_OFFSET(r1)
274        mtlr    r5
275        lwz             r5,  GPR5_OFFSET(r1)
276        lwz             r1,  EXC_MIN_GPR1(r1)
277        \_RFI
278        .endm
Note: See TracBrowser for help on using the repository browser.