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

5
Last change on this file since d50124d was d50124d, checked in by Sebastian Huber <sebastian.huber@…>, on 08/01/17 at 09:54:25

bsps/powerpc: Rename ppc_exc_wrap_async_normal_end

Rename ppc_exc_wrap_async_normal_end to ppc_exc_interrupt_end to avoid a
bit of obfuscation.

Update #3082.

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