source: rtems/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S @ bc98089

4.104.11
Last change on this file since bc98089 was 1ba9d1bb, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 12, 2009 at 2:18:28 PM

2009-03-12 Joel Sherrill <joel.sherrill@…>

PR 1385/cpukit

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