source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S @ d7ed684

5
Last change on this file since d7ed684 was d7ed684, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 20, 2017 at 5:18:53 AM

bsps/powerpc: Fix PPC_EXC_CONFIG_USE_FIXED_HANDLER

Fix link-time error on BSPs not using PPC_EXC_CONFIG_USE_FIXED_HANDLER.

Update #3085.

  • Property mode set to 100644
File size: 15.2 KB
Line 
1/*
2 * Copyright (c) 2011, 2017 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <bspopts.h>
16#include <rtems/score/percpu.h>
17#include <bsp/vectors.h>
18
19#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
20
21#define SCRATCH_0_REGISTER r0
22#define SCRATCH_1_REGISTER r3
23#define SCRATCH_2_REGISTER r4
24#define SCRATCH_3_REGISTER r5
25#define SCRATCH_4_REGISTER r6
26#define SCRATCH_5_REGISTER r7
27#define SCRATCH_6_REGISTER r8
28#define SCRATCH_7_REGISTER r9
29#define SCRATCH_8_REGISTER r10
30#define SCRATCH_9_REGISTER r11
31#define SCRATCH_10_REGISTER r12
32#define FRAME_REGISTER r14
33
34#define SCRATCH_0_OFFSET GPR0_OFFSET
35#define SCRATCH_1_OFFSET GPR3_OFFSET
36#define SCRATCH_2_OFFSET GPR4_OFFSET
37#define SCRATCH_3_OFFSET GPR5_OFFSET
38#define SCRATCH_4_OFFSET GPR6_OFFSET
39#define SCRATCH_5_OFFSET GPR7_OFFSET
40#define SCRATCH_6_OFFSET GPR8_OFFSET
41#define SCRATCH_7_OFFSET GPR9_OFFSET
42#define SCRATCH_8_OFFSET GPR10_OFFSET
43#define SCRATCH_9_OFFSET GPR11_OFFSET
44#define SCRATCH_10_OFFSET GPR12_OFFSET
45#define FRAME_OFFSET PPC_EXC_INTERRUPT_FRAME_OFFSET
46
47#ifdef RTEMS_PROFILING
48.macro GET_TIME_BASE REG
49#if defined(__PPC_CPU_E6500__)
50        mfspr \REG, FSL_EIS_ATBL
51#elif defined(ppc8540)
52        mfspr   \REG, TBRL
53#else /* ppc8540 */
54        mftb    \REG
55#endif /* ppc8540 */
56.endm
57#endif /* RTEMS_PROFILING */
58
59        .global ppc_exc_min_prolog_async_tmpl_normal
60        .global ppc_exc_interrupt
61
62ppc_exc_min_prolog_async_tmpl_normal:
63
64        stwu    r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1)
65        PPC_REG_STORE   SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
66        li      SCRATCH_1_REGISTER, 0xffff8000
67
68        /*
69         * We store the absolute branch target address here.  It will be used
70         * to generate the branch operation in ppc_exc_make_prologue().
71         */
72        .int    ppc_exc_interrupt
73
74ppc_exc_interrupt:
75
76        /* Save non-volatile FRAME_REGISTER */
77        PPC_REG_STORE   FRAME_REGISTER, FRAME_OFFSET(r1)
78
79#ifdef RTEMS_PROFILING
80        /* Get entry instant */
81        GET_TIME_BASE   FRAME_REGISTER
82        stw     FRAME_REGISTER, PPC_EXC_INTERRUPT_ENTRY_INSTANT_OFFSET(r1)
83#endif /* RTEMS_PROFILING */
84
85#ifdef __SPE__
86        /* Enable SPE */
87        mfmsr   FRAME_REGISTER
88        oris    FRAME_REGISTER, FRAME_REGISTER, MSR_SPE >> 16
89        mtmsr   FRAME_REGISTER
90        isync
91#endif
92
93#if defined(PPC_MULTILIB_FPU) || defined(PPC_MULTILIB_ALTIVEC)
94        /* Enable FPU and/or AltiVec */
95        mfmsr   FRAME_REGISTER
96#ifdef PPC_MULTILIB_FPU
97        ori     FRAME_REGISTER, FRAME_REGISTER, MSR_FP
98#endif
99#ifdef PPC_MULTILIB_ALTIVEC
100        oris    FRAME_REGISTER, FRAME_REGISTER, MSR_VE >> 16
101#endif
102        mtmsr   FRAME_REGISTER
103        isync
104#endif
105
106        /* Move frame pointer to non-volatile FRAME_REGISTER */
107        mr      FRAME_REGISTER, r1
108
109        /*
110         * Save volatile registers.  The SCRATCH_1_REGISTER has been saved in
111         * minimum prologue.
112         */
113        PPC_GPR_STORE   SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
114#ifdef __powerpc64__
115        PPC_GPR_STORE   r2, GPR2_OFFSET(r1)
116        LA32    r2, .TOC.
117#endif
118        PPC_GPR_STORE   SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
119        GET_SELF_CPU_CONTROL    SCRATCH_2_REGISTER
120        PPC_GPR_STORE   SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
121        PPC_GPR_STORE   SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
122        PPC_GPR_STORE   SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
123        PPC_GPR_STORE   SCRATCH_6_REGISTER, SCRATCH_6_OFFSET(r1)
124        PPC_GPR_STORE   SCRATCH_7_REGISTER, SCRATCH_7_OFFSET(r1)
125        PPC_GPR_STORE   SCRATCH_8_REGISTER, SCRATCH_8_OFFSET(r1)
126        PPC_GPR_STORE   SCRATCH_9_REGISTER, SCRATCH_9_OFFSET(r1)
127        PPC_GPR_STORE   SCRATCH_10_REGISTER, SCRATCH_10_OFFSET(r1)
128
129        /* Load ISR nest level and thread dispatch disable level */
130        lwz     SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_2_REGISTER)
131        lwz     SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_2_REGISTER)
132
133        /* Save SRR0, SRR1, CR, XER, CTR, and LR */
134        mfsrr0  SCRATCH_0_REGISTER
135        mfsrr1  SCRATCH_5_REGISTER
136        mfcr    SCRATCH_6_REGISTER
137        mfxer   SCRATCH_7_REGISTER
138        mfctr   SCRATCH_8_REGISTER
139        mflr    SCRATCH_9_REGISTER
140        PPC_REG_STORE   SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
141        PPC_REG_STORE   SCRATCH_5_REGISTER, SRR1_FRAME_OFFSET(r1)
142        stw     SCRATCH_6_REGISTER, EXC_CR_OFFSET(r1)
143        stw     SCRATCH_7_REGISTER, EXC_XER_OFFSET(r1)
144        PPC_REG_STORE   SCRATCH_8_REGISTER, EXC_CTR_OFFSET(r1)
145        PPC_REG_STORE   SCRATCH_9_REGISTER, EXC_LR_OFFSET(r1)
146
147#ifdef __SPE__
148        /* Save SPEFSCR and ACC */
149        mfspr   SCRATCH_0_REGISTER, FSL_EIS_SPEFSCR
150        evxor   SCRATCH_5_REGISTER, SCRATCH_5_REGISTER, SCRATCH_5_REGISTER
151        evmwumiaa       SCRATCH_5_REGISTER, SCRATCH_5_REGISTER, SCRATCH_5_REGISTER
152        stw     SCRATCH_0_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
153        evstdd  SCRATCH_5_REGISTER, PPC_EXC_ACC_OFFSET(r1)
154#endif
155
156#ifdef PPC_MULTILIB_ALTIVEC
157        /* Save volatile AltiVec context */
158        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
159        stvx    v0, r1, SCRATCH_0_REGISTER
160        mfvscr  v0
161        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
162        stvx    v1, r1, SCRATCH_0_REGISTER
163        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
164        stvx    v2, r1, SCRATCH_0_REGISTER
165        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
166        stvx    v3, r1, SCRATCH_0_REGISTER
167        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
168        stvx    v4, r1, SCRATCH_0_REGISTER
169        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
170        stvx    v5, r1, SCRATCH_0_REGISTER
171        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
172        stvx    v6, r1, SCRATCH_0_REGISTER
173        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
174        stvx    v7, r1, SCRATCH_0_REGISTER
175        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
176        stvx    v8, r1, SCRATCH_0_REGISTER
177        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
178        stvx    v9, r1, SCRATCH_0_REGISTER
179        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
180        stvx    v10, r1, SCRATCH_0_REGISTER
181        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
182        stvx    v11, r1, SCRATCH_0_REGISTER
183        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
184        stvx    v12, r1, SCRATCH_0_REGISTER
185        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
186        stvx    v13, r1, SCRATCH_0_REGISTER
187        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
188        stvx    v14, r1, SCRATCH_0_REGISTER
189        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
190        stvx    v15, r1, SCRATCH_0_REGISTER
191        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
192        stvx    v16, r1, SCRATCH_0_REGISTER
193        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
194        stvx    v17, r1, SCRATCH_0_REGISTER
195        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
196        stvx    v18, r1, SCRATCH_0_REGISTER
197        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
198        stvx    v19, r1, SCRATCH_0_REGISTER
199        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
200        stvewx  v0, r1, SCRATCH_0_REGISTER
201#endif
202
203#ifdef PPC_MULTILIB_FPU
204        /* Save volatile FPU context */
205        stfd    f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
206        mffs    f0
207        stfd    f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
208        stfd    f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
209        stfd    f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
210        stfd    f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
211        stfd    f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
212        stfd    f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
213        stfd    f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
214        stfd    f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
215        stfd    f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
216        stfd    f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
217        stfd    f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
218        stfd    f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
219        stfd    f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
220        stfd    f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
221#endif
222
223        /* Increment ISR nest level and thread dispatch disable level */
224        cmpwi   SCRATCH_3_REGISTER, 0
225#ifdef RTEMS_PROFILING
226        cmpwi   cr2, SCRATCH_3_REGISTER, 0
227#endif
228        addi    SCRATCH_3_REGISTER, SCRATCH_3_REGISTER, 1
229        addi    SCRATCH_4_REGISTER, SCRATCH_4_REGISTER, 1
230        stw     SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_2_REGISTER)
231        stw     SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_2_REGISTER)
232
233        /* Switch stack if necessary */
234        mfspr   SCRATCH_0_REGISTER, SPRG1
235        iselgt  r1, r1, SCRATCH_0_REGISTER
236
237        /* Call fixed high level handler */
238        bl      bsp_interrupt_dispatch
239        PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
240
241#ifdef RTEMS_PROFILING
242        /* Update profiling data if necessary */
243        bne     cr2, .Lprofiling_done
244        GET_SELF_CPU_CONTROL    r3
245        lwz     r4, PPC_EXC_INTERRUPT_ENTRY_INSTANT_OFFSET(FRAME_REGISTER)
246        GET_TIME_BASE   r5
247        bl      _Profiling_Outer_most_interrupt_entry_and_exit
248        PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
249.Lprofiling_done:
250#endif /* RTEMS_PROFILING */
251
252        /* Load some per-CPU variables */
253        GET_SELF_CPU_CONTROL    SCRATCH_1_REGISTER
254        lbz     SCRATCH_0_REGISTER, PER_CPU_DISPATCH_NEEDED(SCRATCH_1_REGISTER)
255        lwz     SCRATCH_5_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
256        lwz     SCRATCH_6_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
257        lwz     SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_1_REGISTER)
258
259        /*
260         * Switch back to original stack (FRAME_REGISTER == r1 if we are still
261         * on the IRQ stack) and restore FRAME_REGISTER.
262         */
263        mr      r1, FRAME_REGISTER
264        PPC_REG_LOAD    FRAME_REGISTER, FRAME_OFFSET(r1)
265
266        /* Decrement levels and determine thread dispatch state */
267        xori    SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, 1
268        or      SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, SCRATCH_5_REGISTER
269        subi    SCRATCH_4_REGISTER, SCRATCH_6_REGISTER, 1
270        or.     SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, SCRATCH_4_REGISTER
271        subi    SCRATCH_3_REGISTER, SCRATCH_3_REGISTER, 1
272
273        /* Store thread dispatch disable and ISR nest levels */
274        stw     SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
275        stw     SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_1_REGISTER)
276
277        /*
278         * Check thread dispatch necessary, ISR dispatch disable and thread
279         * dispatch disable level.
280         */
281        bne     .Lthread_dispatch_done
282
283        /* Thread dispatch */
284.Ldo_thread_dispatch:
285
286        /* Set ISR dispatch disable and thread dispatch disable level to one */
287        li      SCRATCH_0_REGISTER, 1
288        stw     SCRATCH_0_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
289        stw     SCRATCH_0_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
290
291        /*
292         * Call _Thread_Do_dispatch(), this function will enable interrupts.
293         * The r3 is SCRATCH_1_REGISTER.
294         */
295        mfmsr   r4
296        ori     r4, r4, MSR_EE
297        bl      _Thread_Do_dispatch
298        PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
299
300        /* Disable interrupts */
301        wrteei  0
302
303        /* SCRATCH_1_REGISTER is volatile, we must set it again */
304        GET_SELF_CPU_CONTROL    SCRATCH_1_REGISTER
305
306        /* Check if we have to do the thread dispatch again */
307        lbz     SCRATCH_0_REGISTER, PER_CPU_DISPATCH_NEEDED(SCRATCH_1_REGISTER)
308        cmpwi   SCRATCH_0_REGISTER, 0
309        bne     .Ldo_thread_dispatch
310
311        /* We are done with thread dispatching */
312        li      SCRATCH_0_REGISTER, 0
313        stw     SCRATCH_0_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
314
315.Lthread_dispatch_done:
316
317#ifdef PPC_MULTILIB_ALTIVEC
318        /* Restore volatile AltiVec context */
319        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
320        lvewx   v0, r1, SCRATCH_0_REGISTER
321        mtvscr  v0
322        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
323        lvx     v0, r1, SCRATCH_0_REGISTER
324        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
325        lvx     v1, r1, SCRATCH_0_REGISTER
326        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
327        lvx     v2, r1, SCRATCH_0_REGISTER
328        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
329        lvx     v3, r1, SCRATCH_0_REGISTER
330        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
331        lvx     v4, r1, SCRATCH_0_REGISTER
332        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
333        lvx     v5, r1, SCRATCH_0_REGISTER
334        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
335        lvx     v6, r1, SCRATCH_0_REGISTER
336        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
337        lvx     v7, r1, SCRATCH_0_REGISTER
338        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
339        lvx     v8, r1, SCRATCH_0_REGISTER
340        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
341        lvx     v9, r1, SCRATCH_0_REGISTER
342        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
343        lvx     v10, r1, SCRATCH_0_REGISTER
344        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
345        lvx     v11, r1, SCRATCH_0_REGISTER
346        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
347        lvx     v12, r1, SCRATCH_0_REGISTER
348        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
349        lvx     v13, r1, SCRATCH_0_REGISTER
350        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
351        lvx     v14, r1, SCRATCH_0_REGISTER
352        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
353        lvx     v15, r1, SCRATCH_0_REGISTER
354        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
355        lvx     v16, r1, SCRATCH_0_REGISTER
356        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
357        lvx     v17, r1, SCRATCH_0_REGISTER
358        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
359        lvx     v18, r1, SCRATCH_0_REGISTER
360        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
361        lvx     v19, r1, SCRATCH_0_REGISTER
362#endif
363
364#ifdef PPC_MULTILIB_FPU
365        /* Restore volatile FPU context */
366        lfd     f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
367        mtfsf   0xff, f0
368        lfd     f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
369        lfd     f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
370        lfd     f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
371        lfd     f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
372        lfd     f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
373        lfd     f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
374        lfd     f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
375        lfd     f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
376        lfd     f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
377        lfd     f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
378        lfd     f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
379        lfd     f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
380        lfd     f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
381        lfd     f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
382#endif
383
384#ifdef __SPE__
385        /* Load SPEFSCR and ACC */
386        lwz     SCRATCH_3_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
387        evldd   SCRATCH_4_REGISTER, PPC_EXC_ACC_OFFSET(r1)
388#endif
389
390        /*
391         * We must clear reservations here, since otherwise compare-and-swap
392         * atomic operations with interrupts enabled may yield wrong results.
393         * A compare-and-swap atomic operation is generated by the compiler
394         * like this:
395         *
396         *   .L1:
397         *     lwarx  r9, r0, r3
398         *     cmpw   r9, r4
399         *     bne-   .L2
400         *     stwcx. r5, r0, r3
401         *     bne-   .L1
402         *   .L2:
403         *
404         * Consider the following scenario.  A thread is interrupted right
405         * before the stwcx.  The interrupt updates the value using a
406         * compare-and-swap sequence.  Everything is fine up to this point.
407         * The interrupt performs now a compare-and-swap sequence which fails
408         * with a branch to .L2.  The current processor has now a reservation.
409         * The interrupt returns without further stwcx.  The thread updates the
410         * value using the unrelated reservation of the interrupt.
411         */
412        li      SCRATCH_0_REGISTER, FRAME_OFFSET
413        stwcx.  SCRATCH_0_REGISTER, r1, SCRATCH_0_REGISTER
414
415        /* Load SRR0, SRR1, CR, XER, CTR, and LR */
416        PPC_REG_LOAD    SCRATCH_5_REGISTER, SRR0_FRAME_OFFSET(r1)
417        PPC_REG_LOAD    SCRATCH_6_REGISTER, SRR1_FRAME_OFFSET(r1)
418        lwz     SCRATCH_7_REGISTER, EXC_CR_OFFSET(r1)
419        lwz     SCRATCH_8_REGISTER, EXC_XER_OFFSET(r1)
420        PPC_REG_LOAD    SCRATCH_9_REGISTER, EXC_CTR_OFFSET(r1)
421        PPC_REG_LOAD    SCRATCH_10_REGISTER, EXC_LR_OFFSET(r1)
422
423        /* Restore volatile registers */
424        PPC_GPR_LOAD    SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
425#ifdef __powerpc64__
426        PPC_GPR_LOAD    r2, GPR2_OFFSET(r1)
427#endif
428        PPC_GPR_LOAD    SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
429        PPC_GPR_LOAD    SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
430
431#ifdef __SPE__
432        /* Restore SPEFSCR and ACC */
433        mtspr   FSL_EIS_SPEFSCR, SCRATCH_3_REGISTER
434        evmra   SCRATCH_4_REGISTER, SCRATCH_4_REGISTER
435#endif
436
437        /* Restore volatile registers */
438        PPC_GPR_LOAD    SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
439        PPC_GPR_LOAD    SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
440
441        /* Restore SRR0, SRR1, CR, CTR, XER, and LR plus volatile registers */
442        mtsrr0  SCRATCH_5_REGISTER
443        PPC_GPR_LOAD    SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
444        mtsrr1  SCRATCH_6_REGISTER
445        PPC_GPR_LOAD    SCRATCH_6_REGISTER, SCRATCH_6_OFFSET(r1)
446        mtcr    SCRATCH_7_REGISTER
447        PPC_GPR_LOAD    SCRATCH_7_REGISTER, SCRATCH_7_OFFSET(r1)
448        mtxer   SCRATCH_8_REGISTER
449        PPC_GPR_LOAD    SCRATCH_8_REGISTER, SCRATCH_8_OFFSET(r1)
450        mtctr   SCRATCH_9_REGISTER
451        PPC_GPR_LOAD    SCRATCH_9_REGISTER, SCRATCH_9_OFFSET(r1)
452        mtlr    SCRATCH_10_REGISTER
453        PPC_GPR_LOAD    SCRATCH_10_REGISTER, SCRATCH_10_OFFSET(r1)
454
455        /* Pop stack */
456        addi    r1, r1, PPC_EXC_INTERRUPT_FRAME_SIZE
457
458        /* Return */
459        rfi
460
461/* Symbol provided for debugging and tracing */
462ppc_exc_interrupt_end:
463
464#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
Note: See TracBrowser for help on using the repository browser.