source: rtems/cpukit/score/cpu/arm/cpu_asm.S @ 32b4a0c

5
Last change on this file since 32b4a0c was 32b4a0c, checked in by Sebastian Huber <sebastian.huber@…>, on 06/09/17 at 05:25:02

Simplify TLS support in context switch

There is no need to save the thread pointer in _CPU_Context_switch()
since it is a thread invariant. It is initialized once in
_CPU_Context_Initialize().

  • Property mode set to 100644
File size: 3.8 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, 2017 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        GET_SELF_CPU_CONTROL    r2
59        ldr     r3, [r2, #PER_CPU_ISR_DISPATCH_DISABLE]
60        stm     r0, {r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
61
62#ifdef ARM_MULTILIB_VFP
63        add     r5, r0, #ARM_CONTEXT_CONTROL_D8_OFFSET
64        vstm    r5, {d8-d15}
65#endif
66
67        str     r3, [r0, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
68
69#ifdef RTEMS_SMP
70        /*
71         * The executing thread no longer executes on this processor.  Switch
72         * the stack to the temporary interrupt stack of this processor.  Mark
73         * the context of the executing thread as not executing.
74         */
75        dmb
76        add     sp, r2, #(PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE)
77        mov     r3, #0
78        strb    r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
79
80.L_check_is_executing:
81
82        /* Check the is executing indicator of the heir context */
83        add     r3, r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
84        ldrexb  r4, [r3]
85        cmp     r4, #0
86        bne     .L_get_potential_new_heir
87
88        /* Try to update the is executing indicator of the heir context */
89        mov     r4, #1
90        strexb  r5, r4, [r3]
91        cmp     r5, #0
92        bne     .L_get_potential_new_heir
93        dmb
94#endif
95
96/* Start restoring context */
97.L_restore:
98#if !defined(RTEMS_SMP) && defined(ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE)
99        clrex
100#endif
101
102#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
103        ldr     r3, [r1, #ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET]
104#endif
105
106        ldr     r4, [r1, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
107
108#ifdef ARM_MULTILIB_VFP
109        add     r5, r1, #ARM_CONTEXT_CONTROL_D8_OFFSET
110        vldm    r5, {d8-d15}
111#endif
112
113#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
114        mcr     p15, 0, r3, c13, c0, 3
115#endif
116
117        str     r4, [r2, #PER_CPU_ISR_DISPATCH_DISABLE]
118
119        /* In ARMv5T and above the load of PC is an interworking branch */
120#if __ARM_ARCH >= 5
121        ldm     r1, {r4, r5, r6, r7, r8, r9, r10, r11, r13, pc}
122#else
123        ldm     r1, {r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
124        bx      lr
125#endif
126
127/*
128 *  void _CPU_Context_restore( new_context )
129 *
130 *  This function copies the restores the registers from where r0 points.
131 *  It must match _CPU_Context_switch()
132 *
133 */
134DEFINE_FUNCTION_ARM(_CPU_Context_restore)
135        mov     r1, r0
136        GET_SELF_CPU_CONTROL    r2
137        b       .L_restore
138
139#ifdef RTEMS_SMP
140.L_get_potential_new_heir:
141
142        /* We may have a new heir */
143
144        /* Read the executing and heir */
145        ldr     r4, [r2, #PER_CPU_OFFSET_EXECUTING]
146        ldr     r5, [r2, #PER_CPU_OFFSET_HEIR]
147
148        /*
149         * Update the executing only if necessary to avoid cache line
150         * monopolization.
151         */
152        cmp     r4, r5
153        beq     .L_check_is_executing
154
155        /* Calculate the heir context pointer */
156        sub     r4, r1, r4
157        add     r1, r5, r4
158
159        /* Update the executing */
160        str     r5, [r2, #PER_CPU_OFFSET_EXECUTING]
161
162        b       .L_check_is_executing
163#endif
164
165#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.