source: rtems/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S @ a77cd066

4.104.114.84.95
Last change on this file since a77cd066 was e831de8, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/03 at 18:52:38

2003-09-04 Joel Sherrill <joel@…>

  • bootloader/bootldr.h, bootloader/em86.c, bootloader/em86real.S, bootloader/exception.S, bootloader/head.S, bootloader/lib.c, bootloader/misc.c, bootloader/mm.c, bootloader/pci.c, clock/p_clock.c, console/console.c, console/consoleIo.h, console/inch.c, console/keyboard.h, console/polled_io.c, include/bsp.h, irq/i8259.c, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, motorola/motorola.c, motorola/motorola.h, openpic/openpic.c, openpic/openpic.h, pci/pci.c, residual/residual.c, start/start.S, startup/bspstart.c, vectors/vectors.h, vectors/vectors_init.c: URL for license changed.
  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  This file contains the assembly code for the PowerPC
3 *  IRQ veneers for RTEMS.
4 *
5 *  The license and distribution terms for this file may be
6 *  found in found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  Modified to support the MCP750.
10 *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
11 *
12 *  Till Straumann <strauman@slac.stanford.edu>, 2003/7:
13 *    - store isr nesting level in _ISR_Nest_level rather than
14 *      SPRG0 - RTEMS relies on that variable.
15 *
16 * $Id$
17 */
18       
19#include <asm.h>
20#include <rtems/score/cpu.h>
21#include <bsp/vectors.h>
22#include <libcpu/raw_exception.h>
23       
24
25#define SYNC \
26        sync; \
27        isync
28       
29        .text
30        .p2align 5     
31               
32        PUBLIC_VAR(decrementer_exception_vector_prolog_code)
33       
34SYM (decrementer_exception_vector_prolog_code):
35        /*
36         * let room for exception frame
37         */
38        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
39        stw     r4, GPR4_OFFSET(r1)
40        li      r4, ASM_DEC_VECTOR
41        ba      shared_raw_irq_code_entry
42
43        PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
44       
45        decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
46
47        PUBLIC_VAR(external_exception_vector_prolog_code)
48       
49SYM (external_exception_vector_prolog_code):
50        /*
51         * let room for exception frame
52         */
53        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
54        stw     r4, GPR4_OFFSET(r1)
55        li      r4, ASM_EXT_VECTOR
56        ba      shared_raw_irq_code_entry
57
58        PUBLIC_VAR (external_exception_vector_prolog_code_size)
59       
60        external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
61
62        PUBLIC_VAR(shared_raw_irq_code_entry)
63        PUBLIC_VAR(C_dispatch_irq_handler)
64       
65        .p2align 5
66SYM (shared_raw_irq_code_entry):
67        /*
68         * Entry conditions :
69         *      Registers already saved : R1, R4
70         *      R1  :   points to a location with enough room for the
71         *              interrupt frame
72         *      R4  :   vector number
73         */
74        /*
75         * Save SRR0/SRR1 As soon As possible as it is the minimal needed
76         * to reenable exception processing
77         */
78        stw     r0, GPR0_OFFSET(r1)
79        /* PPC EABI: R2 is reserved (pointer to short data .sdata2) - we won't touch it
80         * but we still save/restore it, just in case...
81         */
82        stw     r2, GPR2_OFFSET(r1)
83        stw     r3, GPR3_OFFSET(r1)
84       
85        mfsrr0  r0
86        mfsrr1  r3
87       
88        stw     r0, SRR0_FRAME_OFFSET(r1)
89        stw     r3, SRR1_FRAME_OFFSET(r1)
90
91        mfmsr   r3
92        /*
93         * Enable data and instruction address translation, exception recovery
94     *
95     * also, on CPUs with FP, enable FP so that FP context can be
96     * saved and restored (using FP instructions)
97         */
98#if (PPC_HAS_FPU == 0)
99        ori     r3, r3, MSR_RI | MSR_IR | MSR_DR
100#else
101        ori     r3, r3, MSR_RI | MSR_IR | MSR_DR | MSR_FP
102#endif
103        mtmsr   r3
104        SYNC
105        /*
106         * Push C scratch registers on the current stack. It may
107         * actually be the thread stack or the interrupt stack.
108         * Anyway we have to make it in order to be able to call C/C++
109         * functions. Depending on the nesting interrupt level, we will
110         * switch to the right stack later.
111         */
112        stw     r5, GPR5_OFFSET(r1)
113        stw     r6, GPR6_OFFSET(r1)
114        stw     r7, GPR7_OFFSET(r1)
115        stw     r8, GPR8_OFFSET(r1)
116        stw     r9, GPR9_OFFSET(r1)
117        stw     r10, GPR10_OFFSET(r1)
118        stw     r11, GPR11_OFFSET(r1)
119        stw     r12, GPR12_OFFSET(r1)
120        stw     r13, GPR13_OFFSET(r1)
121
122        mfcr    r5
123        mfctr   r6
124        mfxer   r7
125        mflr    r8
126       
127        stw     r5,  EXC_CR_OFFSET(r1)
128        stw     r6,  EXC_CTR_OFFSET(r1)
129        stw     r7,  EXC_XER_OFFSET(r1)
130        stw     r8,  EXC_LR_OFFSET(r1)
131
132        /*
133         * Add some non volatile registers to store information
134         * that will be used when returning from C handler
135         */
136        stw     r14, GPR14_OFFSET(r1)
137        stw     r15, GPR15_OFFSET(r1)
138        /*
139         * save current stack pointer location in R14
140         */
141        addi    r14, r1, 0
142        /*
143         * store part of _Thread_Dispatch_disable_level address in R15
144         */
145        addis r15,0, _Thread_Dispatch_disable_level@ha
146#if BROKEN_ISR_NEST_LEVEL
147        /*
148         * Get current nesting level in R3
149         */
150        mfspr   r3, SPRG0
151#else
152        /*
153         * Retrieve current nesting level from _ISR_Nest_level
154         */
155        lis             r7, _ISR_Nest_level@ha
156        lwz             r3, _ISR_Nest_level@l(r7)
157#endif
158        /*
159         * Check if stack switch is necessary
160         */
161        cmpwi   r3,0
162        bne     nested
163        mfspr   r1, SPRG1
164       
165nested:
166        /*
167         * Start Incrementing nesting level in R3
168         */
169        addi    r3,r3,1
170        /*
171         * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
172         */
173        lwz     r6,_Thread_Dispatch_disable_level@l(r15)
174#if BROKEN_ISR_NEST_LEVEL
175        /*
176         * Store new nesting level in SPRG0
177         */
178        mtspr   SPRG0, r3
179#else
180        /* store new nesting level in _ISR_Nest_level */
181        stw             r3, _ISR_Nest_level@l(r7)
182#endif
183       
184        addi    r6, r6, 1
185        mfmsr   r5
186        /*
187         * store new _Thread_Dispatch_disable_level value
188         */
189        stw     r6, _Thread_Dispatch_disable_level@l(r15)
190        /*
191         * We are now running on the interrupt stack. External and decrementer
192         * exceptions are still disabled. I see no purpose trying to optimize
193         * further assembler code.
194         */
195        /*
196         * Call C exception handler for decrementer Interrupt frame is passed just
197         * in case...
198         */
199        addi    r3, r14, 0x8
200        bl      C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
201        /*
202         * start decrementing nesting level. Note : do not test result against 0
203         * value as an easy exit condition because if interrupt nesting level > 1
204         * then _Thread_Dispatch_disable_level > 1
205         */
206#if BROKEN_ISR_NEST_LEVEL
207        mfspr   r4, SPRG0
208#else
209        lis             r7, _ISR_Nest_level@ha
210        lwz             r4, _ISR_Nest_level@l(r7)
211#endif
212        /*
213         * start decrementing _Thread_Dispatch_disable_level
214         */
215        lwz     r3,_Thread_Dispatch_disable_level@l(r15)
216        addi    r4, r4, -1      /* Continue decrementing nesting level */
217        addi    r3, r3, -1      /* Continue decrementing _Thread_Dispatch_disable_level */
218#if BROKEN_ISR_NEST_LEVEL
219        mtspr   SPRG0, r4       /* End decrementing nesting level */
220#else
221        stw             r4, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
222#endif
223        stw     r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
224        cmpwi   r3, 0
225        /*
226         * switch back to original stack (done here just optimize registers
227         * contention. Could have been done before...)
228         */
229        addi    r1, r14, 0
230        bne     easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
231        /*
232         * Here we are running again on the thread system stack.
233         * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
234         * Interrupt are still disabled. Time to check if scheduler request to
235         * do something with the current thread...
236         */
237        addis   r4, 0, _Context_Switch_necessary@ha
238        lwz     r5, _Context_Switch_necessary@l(r4)
239        cmpwi   r5, 0
240        bne     switch
241       
242        addis   r6, 0, _ISR_Signals_to_thread_executing@ha
243        lwz     r7, _ISR_Signals_to_thread_executing@l(r6)
244        cmpwi   r7, 0
245        li      r8, 0
246        beq     easy_exit
247        stw     r8, _ISR_Signals_to_thread_executing@l(r6)
248        /*
249         * going to call _ThreadProcessSignalsFromIrq
250         * Push a complete exception like frame...
251         */
252        stmw    r16, GPR16_OFFSET(r1)
253        addi    r3, r1, 0x8
254        /*
255         * compute SP at exception entry
256         */
257        addi    r4, r1, EXCEPTION_FRAME_END
258        /*
259         * store it at the right place
260         */
261        stw     r4, GPR1_OFFSET(r1)
262        /*
263         * Call High Level signal handling code
264         */
265        bl      _ThreadProcessSignalsFromIrq
266        /*
267         * start restoring exception like frame
268         */
269        lwz     r31,  EXC_CTR_OFFSET(r1)
270        lwz     r30,  EXC_XER_OFFSET(r1)
271        lwz     r29,  EXC_CR_OFFSET(r1)
272        lwz     r28,  EXC_LR_OFFSET(r1)
273       
274        mtctr   r31
275        mtxer   r30
276        mtcr    r29
277        mtlr    r28
278       
279        lmw     r4, GPR4_OFFSET(r1)
280        lwz     r2, GPR2_OFFSET(r1)
281        lwz     r0, GPR0_OFFSET(r1)
282
283        /*
284         * Disable data and instruction translation. Make path non recoverable...
285         */
286        mfmsr   r3
287        xori    r3, r3, MSR_RI | MSR_IR | MSR_DR
288        mtmsr   r3
289        SYNC
290        /*
291         * Restore rfi related settings
292         */
293                 
294        lwz     r3, SRR1_FRAME_OFFSET(r1)
295        mtsrr1  r3
296        lwz     r3, SRR0_FRAME_OFFSET(r1)
297        mtsrr0  r3
298       
299        lwz     r3, GPR3_OFFSET(r1)
300        addi    r1,r1, EXCEPTION_FRAME_END
301        SYNC
302        rfi
303       
304switch:
305        bl      SYM (_Thread_Dispatch)
306       
307easy_exit:     
308        /*
309         * start restoring interrupt frame
310         */
311        lwz     r3,  EXC_CTR_OFFSET(r1)
312        lwz     r4,  EXC_XER_OFFSET(r1)
313        lwz     r5,  EXC_CR_OFFSET(r1)
314        lwz     r6,  EXC_LR_OFFSET(r1)
315       
316        mtctr   r3
317        mtxer   r4
318        mtcr    r5
319        mtlr    r6
320
321        lwz     r15, GPR15_OFFSET(r1)
322        lwz     r14, GPR14_OFFSET(r1)
323        lwz     r13, GPR13_OFFSET(r1)
324        lwz     r12, GPR12_OFFSET(r1)
325        lwz     r11, GPR11_OFFSET(r1)
326        lwz     r10, GPR10_OFFSET(r1)
327        lwz     r9, GPR9_OFFSET(r1)
328        lwz     r8, GPR8_OFFSET(r1)
329        lwz     r7, GPR7_OFFSET(r1)
330        lwz     r6, GPR6_OFFSET(r1)
331        lwz     r5, GPR5_OFFSET(r1)
332
333        /*
334         * Disable nested exception processing, data and instruction
335         * translation.
336         */
337        mfmsr   r3
338        xori    r3, r3, MSR_RI | MSR_IR | MSR_DR
339        mtmsr   r3
340        SYNC
341        /*
342         * Restore rfi related settings
343         */
344                 
345        lwz     r4, SRR1_FRAME_OFFSET(r1)
346        lwz     r3, SRR0_FRAME_OFFSET(r1)
347        lwz     r2, GPR2_OFFSET(r1)
348        lwz     r0, GPR0_OFFSET(r1)
349
350        mtsrr1  r4
351        mtsrr0  r3
352        lwz     r4, GPR4_OFFSET(r1)
353        lwz     r3, GPR3_OFFSET(r1)
354        addi    r1,r1, EXCEPTION_FRAME_END
355        SYNC
356        rfi
357
Note: See TracBrowser for help on using the repository browser.