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

4.115
Last change on this file since 5048a0a was 5048a0a, checked in by Joel Sherrill <joel.sherrill@…>, on 06/29/10 at 00:39:39

2010-06-28 Joel Sherrill <joel.sherrill@…>

PR 1573/cpukit

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