source: rtems/cpukit/score/cpu/arm/cpu_asm.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: 3.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPU
5 *
6 * @brief ARM architecture support implementation.
7 */
8
9/*
10 *  This file contains all assembly code for the ARM implementation
11 *  of RTEMS.
12 *
13 *  Copyright (c) 2007 by Ray Xu, <Rayx.cn@gmail.com>
14 *          Thumb support added.
15 *
16 *  Copyright (c) 2002 by Advent Networks, Inc.
17 *          Jay Monkman <jmonkman@adventnetworks.com>
18 *
19 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
20 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
21 *
22 *  Copyright (c) 2013-2014 embedded brains GmbH
23 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.rtems.org/license/LICENSE.
27 *
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <rtems/asm.h>
35
36#ifdef ARM_MULTILIB_ARCH_V4
37
38        .text
39
40/*
41 *  void _CPU_Context_switch( run_context, heir_context )
42 *  void _CPU_Context_restore( run_context, heir_context )
43 *
44 *  This routine performs a normal non-FP context.
45 *
46 *  R0 = run_context    R1 = heir_context
47 *
48 *  This function copies the current registers to where r0 points, then
49 *  restores the ones from where r1 points.
50 *
51 *  Using the ldm/stm opcodes save 2-3 us on 100 MHz ARM9TDMI with
52 *  a 16 bit data bus.
53 *
54 */
55
56DEFINE_FUNCTION_ARM(_CPU_Context_switch)
57/* Start saving context */
58        mrs     r2, CPSR
59        stmia   r0,  {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
60
61#ifdef ARM_MULTILIB_VFP_D32
62        add     r3, r0, #ARM_CONTEXT_CONTROL_D8_OFFSET
63        vstm    r3, {d8-d15}
64#endif
65
66#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
67        mrc     p15, 0, r3, c13, c0, 3
68        str     r3, [r0, #ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET]
69#endif
70
71#ifdef RTEMS_SMP
72        /* The executing context no longer executes on this processor */
73        dmb
74        mov     r3, #0
75        strb    r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
76
77.L_check_is_executing:
78
79        /* Check the is executing indicator of the heir context */
80        add     r3, r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
81        ldrexb  r4, [r3]
82        cmp     r4, #0
83        bne     .L_check_thread_dispatch_necessary
84
85        /* Try to update the is executing indicator of the heir context */
86        mov     r4, #1
87        strexb  r5, r4, [r3]
88        cmp     r5, #0
89        bne     .L_check_thread_dispatch_necessary
90        dmb
91#endif
92
93/* Start restoring context */
94.L_restore:
95#if !defined(RTEMS_SMP) && defined(ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE)
96        clrex
97#endif
98
99#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
100        ldr     r3, [r1, #ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET]
101        mcr     p15, 0, r3, c13, c0, 3
102#endif
103
104#ifdef ARM_MULTILIB_VFP_D32
105        add     r3, r1, #ARM_CONTEXT_CONTROL_D8_OFFSET
106        vldm    r3, {d8-d15}
107#endif
108
109        ldmia   r1,  {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
110        msr     CPSR_fsxc, r2
111#ifdef __thumb__
112        bx      lr
113        nop
114#else
115        mov     pc, lr
116#endif
117/*
118 *  void _CPU_Context_restore( new_context )
119 *
120 *  This function copies the restores the registers from where r0 points.
121 *  It must match _CPU_Context_switch()
122 *
123 */
124DEFINE_FUNCTION_ARM(_CPU_Context_restore)
125        mov     r1, r0
126        b       .L_restore
127
128#ifdef RTEMS_SMP
129.L_check_thread_dispatch_necessary:
130
131        GET_SELF_CPU_CONTROL    r2, r3
132
133        /* Check if a thread dispatch is necessary */
134        ldrb    r4, [r2, #PER_CPU_DISPATCH_NEEDED]
135        cmp     r4, #0
136        beq     .L_check_is_executing
137
138        /* We have a new heir */
139
140        /* Clear the thread dispatch necessary flag */
141        mov     r4, #0
142        strb    r4, [r2, #PER_CPU_DISPATCH_NEEDED]
143        dmb
144
145        /* Read the executing and heir */
146        ldr     r4, [r2, #PER_CPU_OFFSET_EXECUTING]
147        ldr     r5, [r2, #PER_CPU_OFFSET_HEIR]
148
149        /* Calculate the heir context pointer */
150        sub     r4, r1, r4
151        add     r1, r5, r4
152
153        /* Update the executing */
154        str     r5, [r2, #PER_CPU_OFFSET_EXECUTING]
155
156        b       .L_check_is_executing
157#endif
158
159#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.