source: rtems/cpukit/score/cpu/arm/arm_exc_interrupt.S @ fbda4a8

4.115
Last change on this file since fbda4a8 was fbda4a8, checked in by Sebastian Huber <sebastian.huber@…>, on 07/01/14 at 08:48:28

score: PR2183: Fix context switch on SMP

Fix context switch on SMP for ARM, PowerPC and SPARC.

Atomically test and set the is executing indicator of the heir context
to ensure that at most one processor uses the heir context. Break the
busy wait loop also due to heir updates.

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[9364cf66]1/**
2 * @file
3 *
[78623bce]4 * @ingroup ScoreCPU
[39c8fdb]5 *
[9364cf66]6 * @brief ARM interrupt exception prologue and epilogue.
7 */
8
9/*
[e7d3967]10 * Copyright (c) 2009-2014 embedded brains GmbH.  All rights reserved.
[cfd8d7a]11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
[9364cf66]17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
[c499856]20 * http://www.rtems.org/license/LICENSE.
[9364cf66]21 */
22
23/*
[9db18dd]24 * The upper EXCHANGE_SIZE bytes of the INT stack area are used for data
25 * exchange between INT and SVC mode.  Below of this is the actual INT stack.
26 * The exchange area is only accessed if INT is disabled.
[9364cf66]27 */
28
[0acc9af3]29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
[39c8fdb]33#include <rtems/asm.h>
34
[c5ed148]35#ifdef ARM_MULTILIB_ARCH_V4
36
[9db18dd]37#define EXCHANGE_LR r4
38#define EXCHANGE_SPSR r5
39#define EXCHANGE_CPSR r6
[0756790]40#define EXCHANGE_INT_SP r8
[9364cf66]41
[9db18dd]42#define EXCHANGE_LIST {EXCHANGE_LR, EXCHANGE_SPSR, EXCHANGE_CPSR, EXCHANGE_INT_SP}
43#define EXCHANGE_SIZE 16
[9364cf66]44
[0756790]45#define SELF_CPU_CONTROL r7
[e7d3967]46#define SP_OF_INTERRUPTED_CONTEXT r9
[0756790]47
48#define CONTEXT_LIST {r0, r1, r2, r3, EXCHANGE_LR, EXCHANGE_SPSR, SELF_CPU_CONTROL, r12}
49#define CONTEXT_SIZE 32
[9364cf66]50
[9db18dd]51.arm
[370c2c80]52.globl _ARMV4_Exception_interrupt
53_ARMV4_Exception_interrupt:
[9364cf66]54
[9db18dd]55        /* Save exchange registers to exchange area */
56        stmdb   sp, EXCHANGE_LIST
[9364cf66]57
[9db18dd]58        /* Set exchange registers */
59        mov     EXCHANGE_LR, lr
[18e1e5b]60        mrs     EXCHANGE_SPSR, SPSR
61        mrs     EXCHANGE_CPSR, CPSR
[9db18dd]62        sub     EXCHANGE_INT_SP, sp, #EXCHANGE_SIZE
[9364cf66]63
64        /* Switch to SVC mode */
[9db18dd]65        orr     EXCHANGE_CPSR, EXCHANGE_CPSR, #0x1
[18e1e5b]66        msr     CPSR_c, EXCHANGE_CPSR
[9364cf66]67
[9db18dd]68        /*
[e7d3967]69         * Save context.  We save the link register separately because it has
70         * to be restored in SVC mode.  The other registers can be restored in
71         * INT mode.  Ensure that stack remains 8 byte aligned.  Use register
72         * necessary for the stack alignment for the stack pointer of the
73         * interrupted context.
[9db18dd]74         */
75        stmdb   sp!, CONTEXT_LIST
[e7d3967]76        stmdb   sp!, {SP_OF_INTERRUPTED_CONTEXT, lr}
[9364cf66]77
[cfd8d7a]78#ifdef ARM_MULTILIB_VFP_D32
79        /* Save VFP context */
80        vmrs    r0, FPSCR
[e7d3967]81        vstmdb  sp!, {d0-d7}
82        vstmdb  sp!, {d16-d31}
83        stmdb   sp!, {r0, r1}
[cfd8d7a]84#endif
85
[0756790]86        /* Get per-CPU control of current processor */
87        GET_SELF_CPU_CONTROL    SELF_CPU_CONTROL, r1
[f2f211c5]88
[9db18dd]89        /* Remember INT stack pointer */
90        mov     r1, EXCHANGE_INT_SP
[9364cf66]91
[9db18dd]92        /* Restore exchange registers from exchange area */
93        ldmia   r1, EXCHANGE_LIST
[9364cf66]94
[9db18dd]95        /* Get interrupt nest level */
[0756790]96        ldr     r2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL]
[9364cf66]97
[9db18dd]98        /* Switch stack if necessary and save original stack pointer */
[e7d3967]99        mov     SP_OF_INTERRUPTED_CONTEXT, sp
[9db18dd]100        cmp     r2, #0
101        moveq   sp, r1
[9364cf66]102
103        /* Switch to THUMB instructions if necessary */
[e7d3967]104        SWITCH_FROM_ARM_TO_THUMB        r1
[9364cf66]105
[9db18dd]106        /* Increment interrupt nest and thread dispatch disable level */
[0756790]107        ldr     r3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
[9db18dd]108        add     r2, #1
109        add     r3, #1
[0756790]110        str     r2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL]
111        str     r3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
[9364cf66]112
[148d6e9]113#ifdef RTEMS_PROFILING
114        cmp     r2, #1
115        bne     profiling_entry_done
116        bl      _CPU_Counter_read
117        push    {r0, r1}
118profiling_entry_done:
119#endif
120
[9db18dd]121        /* Call BSP dependent interrupt dispatcher */
[9364cf66]122        bl      bsp_interrupt_dispatch
123
124        /* Decrement interrupt nest and thread dispatch disable level */
[0756790]125        ldr     r2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL]
126        ldr     r3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
[9db18dd]127        sub     r2, #1
128        sub     r3, #1
[0756790]129        str     r2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL]
130        str     r3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
[9364cf66]131
[148d6e9]132#ifdef RTEMS_PROFILING
133        cmp     r2, #0
134        bne     profiling_exit_done
135        bl      _CPU_Counter_read
136        pop     {r1, r3}
137        mov     r2, r0
138        mov     r0, SELF_CPU_CONTROL
139        bl      _Profiling_Outer_most_interrupt_entry_and_exit
140        ldr     r3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL]
141profiling_exit_done:
142#endif
143
[9db18dd]144        /* Restore stack pointer */
[e7d3967]145        mov     sp, SP_OF_INTERRUPTED_CONTEXT
[9364cf66]146
[9db18dd]147        /* Check thread dispatch disable level */
[9364cf66]148        cmp     r3, #0
149        bne     thread_dispatch_done
150
[9db18dd]151        /* Check context switch necessary */
[0756790]152        ldrb    r1, [SELF_CPU_CONTROL, #PER_CPU_DISPATCH_NEEDED]
[9db18dd]153        cmp     r1, #0
154        beq     thread_dispatch_done
[9364cf66]155
[9db18dd]156        /* This aligns thread_dispatch_done on a 4 byte boundary */
157#ifdef __thumb__
158        nop
159#endif /* __thumb__ */
[9364cf66]160
[9db18dd]161        /* Thread dispatch */
162        bl      _Thread_Dispatch
[9364cf66]163
[9db18dd]164thread_dispatch_done:
[9364cf66]165
[9db18dd]166        /* Switch to ARM instructions if necessary */
167        SWITCH_FROM_THUMB_TO_ARM
[9364cf66]168
[cfd8d7a]169#ifdef ARM_MULTILIB_VFP_D32
170        /* Restore VFP context */
[e7d3967]171        ldmia   sp!, {r0, r1}
172        vldmia  sp!, {d16-d31}
173        vldmia  sp!, {d0-d7}
[cfd8d7a]174        vmsr    FPSCR, r0
175#endif
176
[e7d3967]177        /* Restore SP_OF_INTERRUPTED_CONTEXT register and link register */
178        ldmia   sp!, {SP_OF_INTERRUPTED_CONTEXT, lr}
[9364cf66]179
[9db18dd]180        /*
181         * XXX: Remember and restore stack pointer.  The data on the stack is
182         * still in use.  So the stack is now in an inconsistent state.  The
183         * FIQ handler implementation must not use this area.
184         */
185        mov     r0, sp
186        add     sp, #CONTEXT_SIZE
[9364cf66]187
[9db18dd]188        /* Get INT mode program status register */
[18e1e5b]189        mrs     r1, CPSR
[9db18dd]190        bic     r1, r1, #0x1
[9364cf66]191
[9db18dd]192        /* Switch to INT mode */
[18e1e5b]193        msr     CPSR_c, r1
[9364cf66]194
[9db18dd]195        /* Save EXCHANGE_LR and EXCHANGE_SPSR registers to exchange area */
196        stmdb   sp!, {EXCHANGE_LR, EXCHANGE_SPSR}
[9364cf66]197
[9db18dd]198        /* Restore context */
199        ldmia   r0, CONTEXT_LIST
[9364cf66]200
[9db18dd]201        /* Set return address and program status */
202        mov     lr, EXCHANGE_LR
[18e1e5b]203        msr     SPSR_fsxc, EXCHANGE_SPSR
[9364cf66]204
[9db18dd]205        /* Restore EXCHANGE_LR and EXCHANGE_SPSR registers from exchange area */
206        ldmia   sp!, {EXCHANGE_LR, EXCHANGE_SPSR}
[9364cf66]207
208        /* Return from interrupt */
209        subs    pc, lr, #4
[c5ed148]210
211#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.