source: rtems/cpukit/score/cpu/arm/rtems/score/cpu.h @ 53e008b

4.11
Last change on this file since 53e008b was 53e008b, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 10, 2014 at 1:48:05 PM

score: SMP initialization changes

Add and use _CPU_SMP_Start_processor(). Add and use
_CPU_SMP_Finalize_initialization(). This makes most
_CPU_SMP_Initialize() functions a bit simpler since we can calculate the
minimum value of the count of processors requested by the application
configuration and the count of physically or virtually available
processors in the high-level code.

The CPU port has now the ability to signal a processor start failure.
With the support for clustered/partitioned scheduling the presence of
particular processors can be configured to be optional or mandatory.
There will be a fatal error only in case mandatory processors are not
present.

The CPU port may use a timeout to monitor the start of a processor.

  • Property mode set to 100644
File size: 15.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief ARM Architecture Support API
5 */
6
7/*
8 *  This include file contains information pertaining to the ARM
9 *  processor.
10 *
11 *  Copyright (c) 2009-2013 embedded brains GmbH.
12 *
13 *  Copyright (c) 2007 Ray Xu <Rayx.cn@gmail.com>
14 *
15 *  Copyright (c) 2006 OAR Corporation
16 *
17 *  Copyright (c) 2002 Advent Networks, Inc.
18 *        Jay Monkman <jmonkman@adventnetworks.com>
19 *
20 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
21 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
22 *
23 *  The license and distribution terms for this file may be
24 *  found in the file LICENSE in this distribution or at
25 *  http://www.rtems.org/license/LICENSE.
26 *
27 */
28
29#ifndef _RTEMS_SCORE_CPU_H
30#define _RTEMS_SCORE_CPU_H
31
32#include <rtems/score/types.h>
33#include <rtems/score/arm.h>
34
35#if defined(ARM_MULTILIB_ARCH_V4)
36
37/**
38 * @defgroup ScoreCPUARM ARM Specific Support
39 *
40 * @ingroup ScoreCPU
41 *
42 * @brief ARM specific support.
43 */
44/**@{**/
45
46#if defined(__thumb__) && !defined(__thumb2__)
47  #define ARM_SWITCH_REGISTERS uint32_t arm_switch_reg
48  #define ARM_SWITCH_TO_ARM ".align 2\nbx pc\n.arm\n"
49  #define ARM_SWITCH_BACK "add %[arm_switch_reg], pc, #1\nbx %[arm_switch_reg]\n.thumb\n"
50  #define ARM_SWITCH_OUTPUT [arm_switch_reg] "=&r" (arm_switch_reg)
51  #define ARM_SWITCH_ADDITIONAL_OUTPUT , ARM_SWITCH_OUTPUT
52#else
53  #define ARM_SWITCH_REGISTERS
54  #define ARM_SWITCH_TO_ARM
55  #define ARM_SWITCH_BACK
56  #define ARM_SWITCH_OUTPUT
57  #define ARM_SWITCH_ADDITIONAL_OUTPUT
58#endif
59
60/**
61 * @name Program Status Register
62 */
63/**@{**/
64
65#define ARM_PSR_N (1 << 31)
66#define ARM_PSR_Z (1 << 30)
67#define ARM_PSR_C (1 << 29)
68#define ARM_PSR_V (1 << 28)
69#define ARM_PSR_Q (1 << 27)
70#define ARM_PSR_J (1 << 24)
71#define ARM_PSR_GE_SHIFT 16
72#define ARM_PSR_GE_MASK (0xf << ARM_PSR_GE_SHIFT)
73#define ARM_PSR_E (1 << 9)
74#define ARM_PSR_A (1 << 8)
75#define ARM_PSR_I (1 << 7)
76#define ARM_PSR_F (1 << 6)
77#define ARM_PSR_T (1 << 5)
78#define ARM_PSR_M_SHIFT 0
79#define ARM_PSR_M_MASK (0x1f << ARM_PSR_M_SHIFT)
80#define ARM_PSR_M_USR 0x10
81#define ARM_PSR_M_FIQ 0x11
82#define ARM_PSR_M_IRQ 0x12
83#define ARM_PSR_M_SVC 0x13
84#define ARM_PSR_M_ABT 0x17
85#define ARM_PSR_M_UND 0x1b
86#define ARM_PSR_M_SYS 0x1f
87
88/** @} */
89
90/** @} */
91
92#endif /* defined(ARM_MULTILIB_ARCH_V4) */
93
94/**
95 * @addtogroup ScoreCPU
96 */
97/**@{**/
98
99/* If someone uses THUMB we assume she wants minimal code size */
100#ifdef __thumb__
101  #define CPU_INLINE_ENABLE_DISPATCH FALSE
102#else
103  #define CPU_INLINE_ENABLE_DISPATCH TRUE
104#endif
105
106#if defined(__ARMEL__)
107  #define CPU_BIG_ENDIAN FALSE
108  #define CPU_LITTLE_ENDIAN TRUE
109#elif defined(__ARMEB__)
110  #define CPU_BIG_ENDIAN TRUE
111  #define CPU_LITTLE_ENDIAN FALSE
112#else
113  #error "unknown endianness"
114#endif
115
116#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
117
118/*
119 *  The ARM uses the PIC interrupt model.
120 */
121#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
122
123#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
124
125#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
126
127#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
128
129#define CPU_ISR_PASSES_FRAME_POINTER 0
130
131#define CPU_HARDWARE_FP FALSE
132
133#define CPU_SOFTWARE_FP FALSE
134
135#define CPU_ALL_TASKS_ARE_FP FALSE
136
137#define CPU_IDLE_TASK_IS_FP FALSE
138
139#define CPU_USE_DEFERRED_FP_SWITCH FALSE
140
141#if defined(ARM_MULTILIB_HAS_WFI)
142  #define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
143#else
144  #define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
145#endif
146
147#define CPU_STACK_GROWS_UP FALSE
148
149/* XXX Why 32? */
150#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))
151
152#define CPU_TIMESTAMP_USE_INT64_INLINE TRUE
153
154/*
155 * The interrupt mask disables only normal interrupts (IRQ).
156 *
157 * In order to support fast interrupts (FIQ) such that they can do something
158 * useful, we have to disable the operating system support for FIQs.  Having
159 * operating system support for them would require that FIQs are disabled
160 * during critical sections of the operating system and application.  At this
161 * level IRQs and FIQs would be equal.  It is true that FIQs could interrupt
162 * the non critical sections of IRQs, so here they would have a small
163 * advantage.  Without operating system support, the FIQs can execute at any
164 * time (of course not during the service of another FIQ). If someone needs
165 * operating system support for a FIQ, she can trigger a software interrupt and
166 * service the request in a two-step process.
167 */
168#define CPU_MODES_INTERRUPT_MASK 0x1
169
170#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
171
172#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
173
174#define CPU_INTERRUPT_NUMBER_OF_VECTORS 8
175
176#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
177
178#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
179
180#define CPU_STACK_MINIMUM_SIZE (1024 * 4)
181
182/* AAPCS, section 4.1, Fundamental Data Types */
183#define CPU_SIZEOF_POINTER 4
184
185/* AAPCS, section 4.1, Fundamental Data Types */
186#define CPU_ALIGNMENT 8
187
188#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
189
190/* AAPCS, section 4.3.1, Aggregates */
191#define CPU_PARTITION_ALIGNMENT 4
192
193/* AAPCS, section 5.2.1.2, Stack constraints at a public interface */
194#define CPU_STACK_ALIGNMENT 8
195
196/*
197 * Bitfield handler macros.
198 *
199 * If we had a particularly fast function for finding the first
200 * bit set in a word, it would go here. Since we don't (*), we'll
201 * just use the universal macros.
202 *
203 * (*) On ARM V5 and later, there's a CLZ function which could be
204 *     used to implement much quicker than the default macro.
205 */
206
207#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
208
209#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
210
211#define CPU_PER_CPU_CONTROL_SIZE 0
212
213/** @} */
214
215#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
216  #define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
217#endif
218
219#ifdef ARM_MULTILIB_VFP_D32
220  #define ARM_CONTEXT_CONTROL_D8_OFFSET 48
221#endif
222
223#define ARM_EXCEPTION_FRAME_SIZE 76
224
225#define ARM_EXCEPTION_FRAME_REGISTER_SP_OFFSET 52
226
227#define ARM_EXCEPTION_FRAME_VFP_CONTEXT_OFFSET 72
228
229#define ARM_VFP_CONTEXT_SIZE 264
230
231#ifndef ASM
232
233#ifdef __cplusplus
234extern "C" {
235#endif
236
237/**
238 * @addtogroup ScoreCPU
239 */
240/**@{**/
241
242typedef struct {
243  /* There is no CPU specific per-CPU state */
244} CPU_Per_CPU_control;
245
246typedef struct {
247#if defined(ARM_MULTILIB_ARCH_V4)
248  uint32_t register_cpsr;
249  uint32_t register_r4;
250  uint32_t register_r5;
251  uint32_t register_r6;
252  uint32_t register_r7;
253  uint32_t register_r8;
254  uint32_t register_r9;
255  uint32_t register_r10;
256  uint32_t register_fp;
257  uint32_t register_sp;
258  uint32_t register_lr;
259#elif defined(ARM_MULTILIB_ARCH_V7M)
260  uint32_t register_r4;
261  uint32_t register_r5;
262  uint32_t register_r6;
263  uint32_t register_r7;
264  uint32_t register_r8;
265  uint32_t register_r9;
266  uint32_t register_r10;
267  uint32_t register_r11;
268  void *register_lr;
269  void *register_sp;
270  uint32_t isr_nest_level;
271#else
272  void *register_sp;
273#endif
274#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
275  uint32_t thread_id;
276#endif
277#ifdef ARM_MULTILIB_VFP_D32
278  uint64_t register_d8;
279  uint64_t register_d9;
280  uint64_t register_d10;
281  uint64_t register_d11;
282  uint64_t register_d12;
283  uint64_t register_d13;
284  uint64_t register_d14;
285  uint64_t register_d15;
286#endif
287} Context_Control;
288
289typedef struct {
290  /* Not supported */
291} Context_Control_fp;
292
293extern uint32_t arm_cpu_mode;
294
295static inline void _ARM_Data_memory_barrier( void )
296{
297  __asm__ volatile ( "dmb" : : : "memory" );
298}
299
300static inline void _ARM_Data_synchronization_barrier( void )
301{
302  __asm__ volatile ( "dsb" : : : "memory" );
303}
304
305static inline void _ARM_Instruction_synchronization_barrier( void )
306{
307  __asm__ volatile ( "isb" : : : "memory" );
308}
309
310static inline uint32_t arm_interrupt_disable( void )
311{
312  uint32_t level;
313
314#if defined(ARM_MULTILIB_ARCH_V4)
315  uint32_t arm_switch_reg;
316
317  __asm__ volatile (
318    ARM_SWITCH_TO_ARM
319    "mrs %[level], cpsr\n"
320    "orr %[arm_switch_reg], %[level], #0x80\n"
321    "msr cpsr, %[arm_switch_reg]\n"
322    ARM_SWITCH_BACK
323    : [arm_switch_reg] "=&r" (arm_switch_reg), [level] "=&r" (level)
324  );
325#elif defined(ARM_MULTILIB_ARCH_V7M)
326  uint32_t basepri = 0x80;
327
328  __asm__ volatile (
329    "mrs %[level], basepri\n"
330    "msr basepri_max, %[basepri]\n"
331    : [level] "=&r" (level)
332    : [basepri] "r" (basepri)
333  );
334#else
335  level = 0;
336#endif
337
338  return level;
339}
340
341static inline void arm_interrupt_enable( uint32_t level )
342{
343#if defined(ARM_MULTILIB_ARCH_V4)
344  ARM_SWITCH_REGISTERS;
345
346  __asm__ volatile (
347    ARM_SWITCH_TO_ARM
348    "msr cpsr, %[level]\n"
349    ARM_SWITCH_BACK
350    : ARM_SWITCH_OUTPUT
351    : [level] "r" (level)
352  );
353#elif defined(ARM_MULTILIB_ARCH_V7M)
354  __asm__ volatile (
355    "msr basepri, %[level]\n"
356    :
357    : [level] "r" (level)
358  );
359#endif
360}
361
362static inline void arm_interrupt_flash( uint32_t level )
363{
364#if defined(ARM_MULTILIB_ARCH_V4)
365  uint32_t arm_switch_reg;
366
367  __asm__ volatile (
368    ARM_SWITCH_TO_ARM
369    "mrs %[arm_switch_reg], cpsr\n"
370    "msr cpsr, %[level]\n"
371    "msr cpsr, %[arm_switch_reg]\n"
372    ARM_SWITCH_BACK
373    : [arm_switch_reg] "=&r" (arm_switch_reg)
374    : [level] "r" (level)
375  );
376#elif defined(ARM_MULTILIB_ARCH_V7M)
377  uint32_t basepri;
378
379  __asm__ volatile (
380    "mrs %[basepri], basepri\n"
381    "msr basepri, %[level]\n"
382    "msr basepri, %[basepri]\n"
383    : [basepri] "=&r" (basepri)
384    : [level] "r" (level)
385  );
386#endif
387}
388
389#define _CPU_ISR_Disable( _isr_cookie ) \
390  do { \
391    _isr_cookie = arm_interrupt_disable(); \
392  } while (0)
393
394#define _CPU_ISR_Enable( _isr_cookie )  \
395  arm_interrupt_enable( _isr_cookie )
396
397#define _CPU_ISR_Flash( _isr_cookie ) \
398  arm_interrupt_flash( _isr_cookie )
399
400void _CPU_ISR_Set_level( uint32_t level );
401
402uint32_t _CPU_ISR_Get_level( void );
403
404void _CPU_Context_Initialize(
405  Context_Control *the_context,
406  void *stack_area_begin,
407  size_t stack_area_size,
408  uint32_t new_level,
409  void (*entry_point)( void ),
410  bool is_fp,
411  void *tls_area
412);
413
414#define _CPU_Context_Get_SP( _context ) \
415  (_context)->register_sp
416
417#define _CPU_Context_Restart_self( _the_context ) \
418   _CPU_Context_restore( (_the_context) );
419
420#define _CPU_Context_Fp_start( _base, _offset ) \
421   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
422
423#define _CPU_Context_Initialize_fp( _destination ) \
424  do { \
425    *(*(_destination)) = _CPU_Null_fp_context; \
426  } while (0)
427
428#define _CPU_Fatal_halt( _err )             \
429   do {                                     \
430     uint32_t _level;                       \
431     uint32_t _error = _err;                \
432     _CPU_ISR_Disable( _level );            \
433     (void) _level;                         \
434     __asm__ volatile ("mov r0, %0\n"       \
435                   : "=r" (_error)          \
436                   : "0" (_error)           \
437                   : "r0" );                \
438     while (1);                             \
439   } while (0);
440
441/**
442 * @brief CPU initialization.
443 */
444void _CPU_Initialize( void );
445
446void _CPU_ISR_install_vector(
447  uint32_t vector,
448  proc_ptr new_handler,
449  proc_ptr *old_handler
450);
451
452/**
453 * @brief CPU switch context.
454 */
455void _CPU_Context_switch( Context_Control *run, Context_Control *heir );
456
457void _CPU_Context_restore( Context_Control *new_context )
458  RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
459
460#if defined(ARM_MULTILIB_ARCH_V7M)
461  void _ARMV7M_Start_multitasking( Context_Control *heir );
462  #define _CPU_Start_multitasking _ARMV7M_Start_multitasking
463#endif
464
465void _CPU_Context_volatile_clobber( uintptr_t pattern );
466
467void _CPU_Context_validate( uintptr_t pattern );
468
469#ifdef RTEMS_SMP
470  uint32_t _CPU_SMP_Initialize( void );
471
472  bool _CPU_SMP_Start_processor( uint32_t cpu_index );
473
474  void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
475
476  static inline uint32_t _CPU_SMP_Get_current_processor( void )
477  {
478    uint32_t mpidr;
479
480    /* Use ARMv7 Multiprocessor Affinity Register (MPIDR) */
481    __asm__ volatile (
482      "mrc p15, 0, %[mpidr], c0, c0, 5\n"
483      : [mpidr] "=&r" (mpidr)
484    );
485
486    return mpidr & 0xffU;
487  }
488
489  void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
490
491  static inline void _ARM_Send_event( void )
492  {
493    __asm__ volatile ( "sev" : : : "memory" );
494  }
495
496  static inline void _ARM_Wait_for_event( void )
497  {
498    __asm__ volatile ( "wfe" : : : "memory" );
499  }
500
501  static inline void _CPU_SMP_Processor_event_broadcast( void )
502  {
503    _ARM_Data_synchronization_barrier();
504    _ARM_Send_event();
505  }
506
507  static inline void _CPU_SMP_Processor_event_receive( void )
508  {
509    _ARM_Wait_for_event();
510    _ARM_Data_memory_barrier();
511  }
512#endif
513
514
515static inline uint32_t CPU_swap_u32( uint32_t value )
516{
517#if defined(__thumb2__)
518  __asm__ volatile (
519    "rev %0, %0"
520    : "=r" (value)
521    : "0" (value)
522  );
523  return value;
524#elif defined(__thumb__)
525  uint32_t byte1, byte2, byte3, byte4, swapped;
526
527  byte4 = (value >> 24) & 0xff;
528  byte3 = (value >> 16) & 0xff;
529  byte2 = (value >> 8)  & 0xff;
530  byte1 =  value & 0xff;
531
532  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
533  return swapped;
534#else
535  uint32_t tmp = value; /* make compiler warnings go away */
536  __asm__ volatile ("EOR %1, %0, %0, ROR #16\n"
537                "BIC %1, %1, #0xff0000\n"
538                "MOV %0, %0, ROR #8\n"
539                "EOR %0, %0, %1, LSR #8\n"
540                : "=r" (value), "=r" (tmp)
541                : "0" (value), "1" (tmp));
542  return value;
543#endif
544}
545
546static inline uint16_t CPU_swap_u16( uint16_t value )
547{
548#if defined(__thumb2__)
549  __asm__ volatile (
550    "rev16 %0, %0"
551    : "=r" (value)
552    : "0" (value)
553  );
554  return value;
555#else
556  return (uint16_t) (((value & 0xffU) << 8) | ((value >> 8) & 0xffU));
557#endif
558}
559
560typedef uint32_t CPU_Counter_ticks;
561
562CPU_Counter_ticks _CPU_Counter_read( void );
563
564CPU_Counter_ticks _CPU_Counter_difference(
565  CPU_Counter_ticks second,
566  CPU_Counter_ticks first
567);
568
569#if CPU_PROVIDES_IDLE_THREAD_BODY == TRUE
570  void *_CPU_Thread_Idle_body( uintptr_t ignored );
571#endif
572
573/** @} */
574
575/**
576 * @addtogroup ScoreCPUARM
577 */
578/**@{**/
579
580#if defined(ARM_MULTILIB_ARCH_V4)
581
582typedef enum {
583  ARM_EXCEPTION_RESET = 0,
584  ARM_EXCEPTION_UNDEF = 1,
585  ARM_EXCEPTION_SWI = 2,
586  ARM_EXCEPTION_PREF_ABORT = 3,
587  ARM_EXCEPTION_DATA_ABORT = 4,
588  ARM_EXCEPTION_RESERVED = 5,
589  ARM_EXCEPTION_IRQ = 6,
590  ARM_EXCEPTION_FIQ = 7,
591  MAX_EXCEPTIONS = 8,
592  ARM_EXCEPTION_MAKE_ENUM_32_BIT = 0xffffffff
593} Arm_symbolic_exception_name;
594
595#endif /* defined(ARM_MULTILIB_ARCH_V4) */
596
597typedef struct {
598  uint32_t register_fpexc;
599  uint32_t register_fpscr;
600  uint64_t register_d0;
601  uint64_t register_d1;
602  uint64_t register_d2;
603  uint64_t register_d3;
604  uint64_t register_d4;
605  uint64_t register_d5;
606  uint64_t register_d6;
607  uint64_t register_d7;
608  uint64_t register_d8;
609  uint64_t register_d9;
610  uint64_t register_d10;
611  uint64_t register_d11;
612  uint64_t register_d12;
613  uint64_t register_d13;
614  uint64_t register_d14;
615  uint64_t register_d15;
616  uint64_t register_d16;
617  uint64_t register_d17;
618  uint64_t register_d18;
619  uint64_t register_d19;
620  uint64_t register_d20;
621  uint64_t register_d21;
622  uint64_t register_d22;
623  uint64_t register_d23;
624  uint64_t register_d24;
625  uint64_t register_d25;
626  uint64_t register_d26;
627  uint64_t register_d27;
628  uint64_t register_d28;
629  uint64_t register_d29;
630  uint64_t register_d30;
631  uint64_t register_d31;
632} ARM_VFP_context;
633
634typedef struct {
635  uint32_t register_r0;
636  uint32_t register_r1;
637  uint32_t register_r2;
638  uint32_t register_r3;
639  uint32_t register_r4;
640  uint32_t register_r5;
641  uint32_t register_r6;
642  uint32_t register_r7;
643  uint32_t register_r8;
644  uint32_t register_r9;
645  uint32_t register_r10;
646  uint32_t register_r11;
647  uint32_t register_r12;
648  uint32_t register_sp;
649  void *register_lr;
650  void *register_pc;
651#if defined(ARM_MULTILIB_ARCH_V4)
652  uint32_t register_cpsr;
653  Arm_symbolic_exception_name vector;
654#elif defined(ARM_MULTILIB_ARCH_V7M)
655  uint32_t register_xpsr;
656  uint32_t vector;
657#endif
658  const ARM_VFP_context *vfp_context;
659} CPU_Exception_frame;
660
661typedef CPU_Exception_frame CPU_Interrupt_frame;
662
663void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
664
665void _ARM_Exception_default( CPU_Exception_frame *frame );
666
667/** @} */
668
669#ifdef __cplusplus
670}
671#endif
672
673#endif /* ASM */
674
675#endif /* _RTEMS_SCORE_CPU_H */
Note: See TracBrowser for help on using the repository browser.