source: rtems/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_asm.S @ e626c60

4.11
Last change on this file since e626c60 was e626c60, checked in by Chirayu Desai <cdesai@…>, on Dec 6, 2013 at 5:14:57 PM

libcpu/powerpc/mpc5xx: use THREAD_DISABLE_DISPATCH_LEVEL in asm

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * irq_asm.S
3 *
4 *  This file contains the assembly code for the PowerPC
5 *  IRQ veneers for RTEMS.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *
12 *  MPC5xx port sponsored by Defence Research and Development Canada - Suffield
13 *  Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
14 *
15 *  Derived from libbsp/powerpc/mbx8xx/irq/irq_asm.S:
16 *
17 *  Modified to support the MCP750.
18 *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
19 *
20 *  Till Straumann <strauman@slac.stanford.edu>, 2003/7:
21 *    - store isr nesting level in _ISR_Nest_level rather than
22 *      SPRG0 - RTEMS relies on that variable.
23 */
24
25#include <rtems/asm.h>
26#include <rtems/score/cpu.h>
27#include <rtems/score/percpu.h>
28#include <libcpu/vectors.h>
29#include <libcpu/raw_exception.h>
30
31
32#define SYNC \
33        sync; \
34        isync
35
36/*
37 * Common handler for interrupt exceptions.
38 *
39 * The function CPU_rtems_irq_mng_init() initializes the decrementer and
40 * external interrupt entries in the exception handler table with pointers
41 * to this routine, which saves the remainder of the interrupted code's
42 * state, then calls C_dispatch_irq_handler().
43 *
44 * On entry, R1 points to a new exception stack frame in which R3, R4, and
45 * LR have been saved.  R4 holds the exception number.
46 */
47        PUBLIC_VAR(C_dispatch_irq_handler)
48
49        PUBLIC_VAR(dispatch_irq_handler)
50SYM (dispatch_irq_handler):
51        /*
52         * Save SRR0/SRR1 As soon As possible as it is the minimal needed
53         * to re-enable exception processing.
54         *
55         * Note that R2 should never change (it's the EABI pointer to
56         * .sdata2), but we save it just in case.
57         */
58        stw     r0, GPR0_OFFSET(r1)
59        stw     r2, GPR2_OFFSET(r1)
60
61        mfsrr0  r0
62        mfsrr1  r3
63
64        stw     r0, SRR0_FRAME_OFFSET(r1)
65        stw     r3, SRR1_FRAME_OFFSET(r1)
66
67        /*
68         * Enable exception recovery.  Also enable FP so that FP context
69         * can be saved and restored (using FP instructions).
70         */
71        mfmsr   r3
72        ori     r3, r3, MSR_RI | MSR_FP
73        mtmsr   r3
74        SYNC
75
76        /*
77         * Push C scratch registers on the current stack. It may actually be
78         * the thread stack or the interrupt stack.  Anyway we have to make
79         * it in order to be able to call C/C++ functions. Depending on the
80         * nesting interrupt level, we will switch to the right stack later.
81         */
82        stw     r5, GPR5_OFFSET(r1)
83        stw     r6, GPR6_OFFSET(r1)
84        stw     r7, GPR7_OFFSET(r1)
85        stw     r8, GPR8_OFFSET(r1)
86        stw     r9, GPR9_OFFSET(r1)
87        stw     r10, GPR10_OFFSET(r1)
88        stw     r11, GPR11_OFFSET(r1)
89        stw     r12, GPR12_OFFSET(r1)
90        stw     r13, GPR13_OFFSET(r1)
91
92        mfcr    r5
93        mfctr   r6
94        mfxer   r7
95
96        stw     r5,  EXC_CR_OFFSET(r1)
97        stw     r6,  EXC_CTR_OFFSET(r1)
98        stw     r7,  EXC_XER_OFFSET(r1)
99
100        /*
101         * Add some non volatile registers to store information that will be
102         * used when returning from C handler.
103         */
104        stw     r14, GPR14_OFFSET(r1)
105        stw     r15, GPR15_OFFSET(r1)
106
107        /*
108         * Save current stack pointer location in R14.
109         */
110        addi    r14, r1, 0
111
112        /*
113         * store part of THREAD_DISPATCH_DISABLE_LEVEL address in R15
114         */
115        addis r15, 0, THREAD_DISPATCH_DISABLE_LEVEL@ha
116
117        /*
118         * Retrieve current nesting level from _ISR_Nest_level
119         */
120        lis             r7, ISR_NEST_LEVEL@ha
121        lwz             r3, ISR_NEST_LEVEL@l(r7)
122
123        /*
124         * Check if stack switch is necessary
125         */
126        cmpwi   r3, 0
127        bne     nested
128
129        mfspr   r1, SPRG1               /* switch to interrupt stack */
130nested:
131
132        /*
133         * Start Incrementing nesting level in R3
134         */
135        addi    r3, r3, 1
136
137        /*
138         * Start Incrementing THREAD_DISPATCH_DISABLE_LEVEL R4 = THREAD_DISPATCH_DISABLE_LEVEL
139         */
140        lwz     r6, THREAD_DISPATCH_DISABLE_LEVEL@l(r15)
141
142        /* store new nesting level in _ISR_Nest_level */
143        stw     r3, ISR_NEST_LEVEL@l(r7)
144
145        addi    r6, r6, 1
146
147        /*
148         * store new THREAD_DISPATCH_DISABLE_LEVEL value
149         */
150        stw     r6, THREAD_DISPATCH_DISABLE_LEVEL@l(r15)
151
152        /*
153         * We are now running on the interrupt stack. External and decrementer
154         * exceptions are still disabled. I see no purpose trying to optimize
155         * further assembler code.
156         */
157
158        /*
159         * Call C exception handler for decrementer or external interrupt.
160         * Pass frame along just in case..
161         *
162         * C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4)
163         */
164        addi    r3, r14, 0x8
165        bl      C_dispatch_irq_handler
166
167        /*
168         * start decrementing nesting level. Note : do not test result against 0
169         * value as an easy exit condition because if interrupt nesting level > 1
170         * then THREAD_DISPATCH_DISABLE_LEVEL > 1
171         */
172        lis             r7, ISR_NEST_LEVEL@ha
173        lwz             r4, ISR_NEST_LEVEL@l(r7)
174
175        /*
176         * start decrementing THREAD_DISPATCH_DISABLE_LEVEL
177         */
178        lwz     r3,THREAD_DISPATCH_DISABLE_LEVEL@l(r15)
179
180        addi    r4, r4, -1      /* Continue decrementing nesting level */
181        addi    r3, r3, -1      /* Continue decrementing THREAD_DISPATCH_DISABLE_LEVEL */
182
183        stw     r4, ISR_NEST_LEVEL@l(r7) /* End decrementing nesting level */
184        stw     r3,THREAD_DISPATCH_DISABLE_LEVEL@l(r15) /* End decrementing THREAD_DISPATCH_DISABLE_LEVEL */
185
186        cmpwi   r3, 0
187
188        /*
189         * switch back to original stack (done here just optimize registers
190         * contention. Could have been done before...)
191         */
192        addi    r1, r14, 0
193        bne     easy_exit /* if (THREAD_DISPATCH_DISABLE_LEVEL != 0) goto easy_exit */
194
195        /*
196         * Here we are running again on the thread system stack.
197         * We have interrupt nesting level = THREAD_DISPATCH_DISABLE_LEVEL = 0.
198         * Interrupt are still disabled. Time to check if scheduler request to
199         * do something with the current thread...
200         */
201        addis   r4, 0, DISPATCH_NEEDED@ha
202        lbz     r5, DISPATCH_NEEDED@l(r4)
203        cmpwi   r5, 0
204        beq     easy_exit
205
206        /*
207         * going to call _Thread_Dispatch
208         * Push a complete exception like frame...
209         */
210        stmw    r16, GPR16_OFFSET(r1)
211        addi    r3, r1, 0x8
212
213        /*
214         * compute SP at exception entry
215         */
216        addi    r4, r1, EXCEPTION_FRAME_END
217
218        /*
219         * store it at the right place
220         */
221        stw     r4, GPR1_OFFSET(r1)
222
223        /*
224         * Call High Level signal handling code
225         */
226        bl      _Thread_Dispatch
227
228        /*
229         * start restoring exception like frame
230         */
231        lwz     r31,  EXC_CTR_OFFSET(r1)
232        lwz     r30,  EXC_XER_OFFSET(r1)
233        lwz     r29,  EXC_CR_OFFSET(r1)
234        lwz     r28,  EXC_LR_OFFSET(r1)
235
236        mtctr   r31
237        mtxer   r30
238        mtcr    r29
239        mtlr    r28
240
241        lmw     r4, GPR4_OFFSET(r1)
242        lwz     r2, GPR2_OFFSET(r1)
243        lwz     r0, GPR0_OFFSET(r1)
244
245        /*
246         * Make path non recoverable...
247         */
248        mtspr   nri, r0
249        SYNC
250
251        /*
252         * Restore rfi related settings
253         */
254
255        lwz     r3, SRR1_FRAME_OFFSET(r1)
256        mtsrr1  r3
257        lwz     r3, SRR0_FRAME_OFFSET(r1)
258        mtsrr0  r3
259
260        lwz     r3, GPR3_OFFSET(r1)
261        addi    r1,r1, EXCEPTION_FRAME_END
262        SYNC
263        rfi
264
265
266easy_exit:
267        /*
268         * start restoring interrupt frame
269         */
270        lwz     r3,  EXC_CTR_OFFSET(r1)
271        lwz     r4,  EXC_XER_OFFSET(r1)
272        lwz     r5,  EXC_CR_OFFSET(r1)
273        lwz     r6,  EXC_LR_OFFSET(r1)
274
275        mtctr   r3
276        mtxer   r4
277        mtcr    r5
278        mtlr    r6
279
280        lwz     r15, GPR15_OFFSET(r1)
281        lwz     r14, GPR14_OFFSET(r1)
282        lwz     r13, GPR13_OFFSET(r1)
283        lwz     r12, GPR12_OFFSET(r1)
284        lwz     r11, GPR11_OFFSET(r1)
285        lwz     r10, GPR10_OFFSET(r1)
286        lwz     r9, GPR9_OFFSET(r1)
287        lwz     r8, GPR8_OFFSET(r1)
288        lwz     r7, GPR7_OFFSET(r1)
289        lwz     r6, GPR6_OFFSET(r1)
290        lwz     r5, GPR5_OFFSET(r1)
291
292        /*
293         * Disable nested exception processing.
294         */
295        mtspr   nri, r0
296        SYNC
297
298        /*
299         * Restore rfi related settings
300         */
301        lwz     r4, SRR1_FRAME_OFFSET(r1)
302        lwz     r3, SRR0_FRAME_OFFSET(r1)
303        lwz     r2, GPR2_OFFSET(r1)
304        lwz     r0, GPR0_OFFSET(r1)
305
306        mtsrr1  r4
307        mtsrr0  r3
308        lwz     r4, GPR4_OFFSET(r1)
309        lwz     r3, GPR3_OFFSET(r1)
310        addi    r1,r1, EXCEPTION_FRAME_END
311        SYNC
312        rfi
Note: See TracBrowser for help on using the repository browser.