source: rtems/cpukit/score/cpu/arm/cpu.c @ a6c5a7e0

4.11
Last change on this file since a6c5a7e0 was a6c5a7e0, checked in by Daniel Krueger <daniel.krueger@…>, on Mar 17, 2015 at 2:02:59 PM

arm: Align ARM exception frame to 8 bytes

The stack pointer must be aligned on 8 byte boundary on ARM, so the size of
the exception frame must be a multiple of 8 bytes. Otherwise we might/will
get an alignment fault, when executing code in the data abort handler for
example.

Close #2318.

Signed-off-by: Daniel Krueger <daniel.krueger@…>

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPU
5 *
6 * @brief ARM architecture support implementation.
7 */
8
9/*
10 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
11 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
12 *
13 *  Copyright (c) 2002 Advent Networks, Inc
14 *      Jay Monkman <jmonkman@adventnetworks.com>
15 *
16 *  Copyright (c) 2007 Ray xu <rayx.cn@gmail.com>
17 *
18 *  Copyright (c) 2009-2011 embedded brains GmbH
19 *
20 *  The license and distribution terms for this file may be
21 *  found in the file LICENSE in this distribution or at
22 *  http://www.rtems.org/license/LICENSE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <rtems/system.h>
30#include <rtems.h>
31#include <rtems/bspIo.h>
32#include <rtems/score/isr.h>
33#include <rtems/score/wkspace.h>
34#include <rtems/score/thread.h>
35#include <rtems/score/tls.h>
36#include <rtems/score/cpu.h>
37
38#ifdef ARM_MULTILIB_VFP
39  RTEMS_STATIC_ASSERT(
40    offsetof( Context_Control, register_d8 ) == ARM_CONTEXT_CONTROL_D8_OFFSET,
41    ARM_CONTEXT_CONTROL_D8_OFFSET
42  );
43#endif
44
45#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
46  RTEMS_STATIC_ASSERT(
47    offsetof( Context_Control, thread_id )
48      == ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET,
49    ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET
50  );
51#endif
52
53#ifdef RTEMS_SMP
54  RTEMS_STATIC_ASSERT(
55    offsetof( Context_Control, is_executing )
56      == ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET,
57    ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
58  );
59#endif
60
61RTEMS_STATIC_ASSERT(
62  sizeof( CPU_Exception_frame ) == ARM_EXCEPTION_FRAME_SIZE,
63  ARM_EXCEPTION_FRAME_SIZE
64);
65
66RTEMS_STATIC_ASSERT(
67  sizeof( CPU_Exception_frame ) % CPU_STACK_ALIGNMENT == 0,
68  CPU_Exception_frame_alignment
69);
70
71RTEMS_STATIC_ASSERT(
72  offsetof( CPU_Exception_frame, register_sp )
73    == ARM_EXCEPTION_FRAME_REGISTER_SP_OFFSET,
74  ARM_EXCEPTION_FRAME_REGISTER_SP_OFFSET
75);
76
77RTEMS_STATIC_ASSERT(
78  sizeof( ARM_VFP_context ) == ARM_VFP_CONTEXT_SIZE,
79  ARM_VFP_CONTEXT_SIZE
80);
81
82#ifdef ARM_MULTILIB_ARCH_V4
83
84/*
85 * This variable can be used to change the running mode of the execution
86 * contexts.
87 */
88uint32_t arm_cpu_mode = 0x13;
89
90void _CPU_Context_Initialize(
91  Context_Control *the_context,
92  void *stack_area_begin,
93  size_t stack_area_size,
94  uint32_t new_level,
95  void (*entry_point)( void ),
96  bool is_fp,
97  void *tls_area
98)
99{
100  the_context->register_sp = (uint32_t) stack_area_begin + stack_area_size;
101  the_context->register_lr = (uint32_t) entry_point;
102  the_context->register_cpsr = ( ( new_level != 0 ) ? ARM_PSR_I : 0 )
103    | arm_cpu_mode;
104
105#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
106  the_context->thread_id = (uint32_t) tls_area;
107#endif
108
109  if ( tls_area != NULL ) {
110    _TLS_TCB_at_area_begin_initialize( tls_area );
111  }
112}
113
114/* Preprocessor magic for stringification of x */
115#define _CPU_ISR_LEVEL_DO_STRINGOF( x) #x
116#define _CPU_ISR_LEVEL_STRINGOF( x) _CPU_ISR_LEVEL_DO_STRINGOF( x)
117
118void _CPU_ISR_Set_level( uint32_t level )
119{
120  uint32_t arm_switch_reg;
121
122  level = ( level != 0 ) ? ARM_PSR_I : 0;
123
124  __asm__ volatile (
125    ARM_SWITCH_TO_ARM
126    "mrs %[arm_switch_reg], cpsr\n"
127    "bic %[arm_switch_reg], #" _CPU_ISR_LEVEL_STRINGOF( ARM_PSR_I ) "\n"
128    "orr %[arm_switch_reg], %[level]\n"
129    "msr cpsr, %0\n"
130    ARM_SWITCH_BACK
131    : [arm_switch_reg] "=&r" (arm_switch_reg)
132    : [level] "r" (level)
133  );
134}
135
136uint32_t _CPU_ISR_Get_level( void )
137{
138  ARM_SWITCH_REGISTERS;
139  uint32_t level;
140
141  __asm__ volatile (
142    ARM_SWITCH_TO_ARM
143    "mrs %[level], cpsr\n"
144    "and %[level], #" _CPU_ISR_LEVEL_STRINGOF( ARM_PSR_I ) "\n"
145    ARM_SWITCH_BACK
146    : [level] "=&r" (level) ARM_SWITCH_ADDITIONAL_OUTPUT
147  );
148
149  return ( level & ARM_PSR_I ) != 0;
150}
151
152void _CPU_ISR_install_vector(
153  uint32_t vector,
154  proc_ptr new_handler,
155  proc_ptr *old_handler
156)
157{
158  /* Redirection table starts at the end of the vector table */
159  volatile uint32_t *table = (volatile uint32_t *) (MAX_EXCEPTIONS * 4);
160
161  uint32_t current_handler = table [vector];
162
163  /* The current handler is now the old one */
164  if (old_handler != NULL) {
165    *old_handler = (proc_ptr) current_handler;
166  }
167
168  /* Write only if necessary to avoid writes to a maybe read-only memory */
169  if (current_handler != (uint32_t) new_handler) {
170    table [vector] = (uint32_t) new_handler;
171  }
172}
173
174void _CPU_Initialize( void )
175{
176  /* Do nothing */
177}
178
179#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.