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

4.104.114.84.9
Last change on this file since 98afe31 was 8c9fffd, checked in by Till Straumann <strauman@…>, on Nov 4, 2005 at 1:39:45 AM

2005-11-03 <strauman@…>

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