RTEMS 6.1-rc1
cpu.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
11/*
12 * Copyright (C) 2020 On-Line Applications Research Corporation (OAR)
13 * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _RTEMS_SCORE_CPU_H
38#define _RTEMS_SCORE_CPU_H
39
41#if defined(RTEMS_PARAVIRT)
42#include <rtems/score/paravirt.h>
43#endif
44#include <rtems/score/aarch64.h>
45#include <libcpu/vectors.h>
46#include <limits.h>
47
59#define AARCH64_PSTATE_N (1LL << 31)
60#define AARCH64_PSTATE_Z (1LL << 30)
61#define AARCH64_PSTATE_C (1LL << 29)
62#define AARCH64_PSTATE_V (1LL << 28)
63#define AARCH64_PSTATE_D (1LL << 9)
64#define AARCH64_PSTATE_A (1LL << 8)
65#define AARCH64_PSTATE_I (1LL << 7)
66#define AARCH64_PSTATE_F (1LL << 6)
67
70/*
71 * AArch64 uses the PIC interrupt model.
72 */
73#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
74
75#define CPU_ISR_PASSES_FRAME_POINTER FALSE
76
77#define CPU_HARDWARE_FP FALSE
78
79#define CPU_SOFTWARE_FP FALSE
80
81#define CPU_ALL_TASKS_ARE_FP FALSE
82
83#define CPU_IDLE_TASK_IS_FP FALSE
84
85#define CPU_USE_DEFERRED_FP_SWITCH FALSE
86
87#define CPU_ENABLE_ROBUST_THREAD_DISPATCH TRUE
88
89#define CPU_STACK_GROWS_UP FALSE
90
91#if defined(AARCH64_MULTILIB_CACHE_LINE_MAX_64)
92 #define CPU_CACHE_LINE_BYTES 64
93#else
94 #define CPU_CACHE_LINE_BYTES 32
95#endif
96
97#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
98
99#define CPU_MODES_INTERRUPT_MASK 0x1
100
101#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
102
103#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
104
105#define CPU_STACK_MINIMUM_SIZE (1024 * 8)
106
107/* This could be either 4 or 8, depending on the ABI in use.
108 * Could also use __LP64__ or __ILP32__ */
109/* AAPCS64, section 5.1, Fundamental Data Types */
110#define CPU_SIZEOF_POINTER __SIZEOF_POINTER__
111
112/* AAPCS64, section 5.1, Fundamental Data Types */
113#define CPU_ALIGNMENT 16
114
115#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
116
117/* AAPCS64, section 6.2.2, Stack constraints at a public interface */
118#define CPU_STACK_ALIGNMENT 16
119
120#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
121
122#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
123
124#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE
125
126#define CPU_MAXIMUM_PROCESSORS 32
127
128#define AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET 0x70
129
130#ifdef AARCH64_MULTILIB_VFP
131 #define AARCH64_CONTEXT_CONTROL_D8_OFFSET 0x78
132#endif
133
134#define AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE 0x68
135
136#ifdef RTEMS_SMP
137 #if defined(AARCH64_MULTILIB_VFP)
138 #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 0xb8
139 #else
140 #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 0x78
141 #endif
142#endif
143
144#define AARCH64_EXCEPTION_FRAME_SIZE 0x350
145
146#define AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET 0xF8
147#define AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET 0xF0
148#define AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET 0x108
149#define AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET 0x118
150#define AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET 0x128
151#define AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET 0x138
152#define AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET 0x150
153
154#ifndef ASM
155
156#ifdef __cplusplus
157extern "C" {
158#endif
159
160/*
161 This is to fix the following warning
162 ISO C does not support 'uint128_t' types
163*/
164#pragma GCC diagnostic push
165#pragma GCC diagnostic ignored "-Wpedantic"
166typedef unsigned __int128 uint128_t;
167#pragma GCC diagnostic pop
168
169typedef struct {
170 uint64_t register_x19;
171 uint64_t register_x20;
172 uint64_t register_x21;
173 uint64_t register_x22;
174 uint64_t register_x23;
175 uint64_t register_x24;
176 uint64_t register_x25;
177 uint64_t register_x26;
178 uint64_t register_x27;
179 uint64_t register_x28;
180 uint64_t register_fp;
181 uint64_t register_lr;
182 uint64_t register_sp;
184 uint64_t thread_id;
185#ifdef AARCH64_MULTILIB_VFP
186 uint64_t register_d8;
187 uint64_t register_d9;
188 uint64_t register_d10;
189 uint64_t register_d11;
190 uint64_t register_d12;
191 uint64_t register_d13;
192 uint64_t register_d14;
193 uint64_t register_d15;
194#endif
195#ifdef RTEMS_SMP
196 volatile bool is_executing;
197#endif
199
200static inline void _AARCH64_Data_memory_barrier( void )
201{
202 __asm__ volatile ( "dmb SY" : : : "memory" );
203}
204
205static inline void _AARCH64_Data_synchronization_barrier( void )
206{
207 __asm__ volatile ( "dsb SY" : : : "memory" );
208}
209
210static inline void _AARCH64_Instruction_synchronization_barrier( void )
211{
212 __asm__ volatile ( "isb" : : : "memory" );
213}
214
215void _CPU_ISR_Set_level( uint32_t level );
216
217uint32_t _CPU_ISR_Get_level( void );
218
219#if defined(AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE)
220uint64_t AArch64_interrupt_disable( void );
221void AArch64_interrupt_enable( uint64_t isr_cookie );
222void AArch64_interrupt_flash( uint64_t isr_cookie );
223#else
224static inline uint64_t AArch64_interrupt_disable( void )
225{
226 uint64_t isr_cookie;
227
228 __asm__ volatile (
229 "mrs %[isr_cookie], DAIF\n"
230 "msr DAIFSet, #0x2\n"
231 : [isr_cookie] "=&r" (isr_cookie)
232 );
233
234 return isr_cookie;
235}
236
237static inline void AArch64_interrupt_enable( uint64_t isr_cookie )
238{
239 __asm__ volatile (
240 "msr DAIF, %[isr_cookie]\n"
241 : : [isr_cookie] "r" (isr_cookie)
242 );
243}
244
245static inline void AArch64_interrupt_flash( uint64_t isr_cookie )
246{
247 AArch64_interrupt_enable(isr_cookie);
248 AArch64_interrupt_disable();
249}
250#endif /* !AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE */
251
252#define _CPU_ISR_Disable( _isr_cookie ) \
253 do { \
254 _isr_cookie = AArch64_interrupt_disable(); \
255 } while (0)
256
257#define _CPU_ISR_Enable( _isr_cookie ) \
258 AArch64_interrupt_enable( _isr_cookie )
259
260#define _CPU_ISR_Flash( _isr_cookie ) \
261 AArch64_interrupt_flash( _isr_cookie )
262
263static inline bool _CPU_ISR_Is_enabled( uint64_t isr_cookie )
264{
265 return ( isr_cookie & AARCH64_PSTATE_I ) == 0;
266}
267
269 Context_Control *the_context,
270 void *stack_area_begin,
271 size_t stack_area_size,
272 uint64_t new_level,
273 void (*entry_point)( void ),
274 bool is_fp,
275 void *tls_area
276);
277
278#define _CPU_Context_Get_SP( _context ) \
279 (_context)->register_sp
280
281#ifdef RTEMS_SMP
282 static inline bool _CPU_Context_Get_is_executing(
284 )
285 {
286 return context->is_executing;
287 }
288
289 static inline void _CPU_Context_Set_is_executing(
291 bool is_executing
292 )
293 {
294 context->is_executing = is_executing;
295 }
296
297 RTEMS_NO_RETURN void _AArch64_Start_multitasking( Context_Control *heir );
298
299 #define _CPU_Start_multitasking( _heir ) _AArch64_Start_multitasking( _heir )
300#endif
301
302#define _CPU_Context_Restart_self( _the_context ) \
303 _CPU_Context_restore( (_the_context) );
304
305#define _CPU_Context_Initialize_fp( _destination ) \
306 do { \
307 *(*(_destination)) = _CPU_Null_fp_context; \
308 } while (0)
309
313void _CPU_Initialize( void );
314
315typedef void ( *CPU_ISR_handler )( void );
316
321
322RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
323 Context_Control *executing,
324 Context_Control *heir
325);
326
328
329#ifdef RTEMS_SMP
330 uint32_t _CPU_SMP_Initialize( void );
331
332 bool _CPU_SMP_Start_processor( uint32_t cpu_index );
333
334 void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
335
336 void _CPU_SMP_Prepare_start_multitasking( void );
337
338 static inline uint32_t _CPU_SMP_Get_current_processor( void )
339 {
340 uint32_t mpidr;
341
342 __asm__ volatile (
343 "mrs %[mpidr], mpidr_el1\n"
344 : [mpidr] "=&r" (mpidr)
345 );
346
347 return mpidr & 0xffU;
348 }
349
350 void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
351
352 static inline void _AARCH64_Send_event( void )
353 {
354 __asm__ volatile ( "sev" : : : "memory" );
355 }
356
357 static inline void _AARCH64_Wait_for_event( void )
358 {
359 __asm__ volatile ( "wfe" : : : "memory" );
360 }
361#endif
362
363
364static inline uint32_t CPU_swap_u32( uint32_t value )
365{
366 uint32_t tmp = value; /* make compiler warnings go away */
367 __asm__ volatile ("EOR %1, %0, %0, ROR #16\n"
368 "BIC %1, %1, #0xff0000\n"
369 "MOV %0, %0, ROR #8\n"
370 "EOR %0, %0, %1, LSR #8\n"
371 : "=r" (value), "=r" (tmp)
372 : "0" (value), "1" (tmp));
373 return value;
374}
375
376static inline uint16_t CPU_swap_u16( uint16_t value )
377{
378 return (uint16_t) (((value & 0xffU) << 8) | ((value >> 8) & 0xffU));
379}
380
381typedef uint32_t CPU_Counter_ticks;
382
383uint32_t _CPU_Counter_frequency( void );
384
385CPU_Counter_ticks _CPU_Counter_read( void );
386
387void *_CPU_Thread_Idle_body( uintptr_t ignored );
388
389typedef enum {
390 AARCH64_EXCEPTION_SP0_SYNCHRONOUS = 0,
391 AARCH64_EXCEPTION_SP0_IRQ = 1,
392 AARCH64_EXCEPTION_SP0_FIQ = 2,
393 AARCH64_EXCEPTION_SP0_SERROR = 3,
394 AARCH64_EXCEPTION_SPx_SYNCHRONOUS = 4,
395 AARCH64_EXCEPTION_SPx_IRQ = 5,
396 AARCH64_EXCEPTION_SPx_FIQ = 6,
397 AARCH64_EXCEPTION_SPx_SERROR = 7,
398 AARCH64_EXCEPTION_LEL64_SYNCHRONOUS = 8,
399 AARCH64_EXCEPTION_LEL64_IRQ = 9,
400 AARCH64_EXCEPTION_LEL64_FIQ = 10,
401 AARCH64_EXCEPTION_LEL64_SERROR = 11,
402 AARCH64_EXCEPTION_LEL32_SYNCHRONOUS = 12,
403 AARCH64_EXCEPTION_LEL32_IRQ = 13,
404 AARCH64_EXCEPTION_LEL32_FIQ = 14,
405 AARCH64_EXCEPTION_LEL32_SERROR = 15,
406 MAX_EXCEPTIONS = 16,
407 AARCH64_EXCEPTION_MAKE_ENUM_64_BIT = INT_MAX
408} AArch64_symbolic_exception_name;
409
410#define VECTOR_POINTER_OFFSET 0x78
411#define VECTOR_ENTRY_SIZE 0x80
412void _AArch64_Exception_interrupt_no_nest( void );
413void _AArch64_Exception_interrupt_nest( void );
414static inline void* AArch64_set_exception_handler(
415 AArch64_symbolic_exception_name exception,
416 void (*handler)(void)
417)
418{
419 /* get current table address */
420 char *vbar = (char*)AArch64_get_vector_base_address();
421
422 /* calculate address of vector to be replaced */
423 char *cvector_address = vbar + VECTOR_ENTRY_SIZE * exception
424 + VECTOR_POINTER_OFFSET;
425
426 /* get current vector pointer */
427 void (**vector_address)(void) = (void(**)(void))cvector_address;
428 void (*current_vector_pointer)(void);
429 current_vector_pointer = *vector_address;
430
431 /* replace vector pointer */
432 *vector_address = handler;
433
434 /* return now-previous vector pointer */
435
436/*
437 * This was put in to fix the following warning:
438 * warning: ISO C forbids conversion of function pointer to object pointer type.
439 */
440#pragma GCC diagnostic push
441#pragma GCC diagnostic ignored "-Wpedantic"
442 return (void*)current_vector_pointer;
443#pragma GCC diagnostic pop
444}
445
446typedef struct {
447 uint64_t register_x0;
448 uint64_t register_x1;
449 uint64_t register_x2;
450 uint64_t register_x3;
451 uint64_t register_x4;
452 uint64_t register_x5;
453 uint64_t register_x6;
454 uint64_t register_x7;
455 uint64_t register_x8;
456 uint64_t register_x9;
457 uint64_t register_x10;
458 uint64_t register_x11;
459 uint64_t register_x12;
460 uint64_t register_x13;
461 uint64_t register_x14;
462 uint64_t register_x15;
463 uint64_t register_x16;
464 uint64_t register_x17;
465 uint64_t register_x18;
466 uint64_t register_x19;
467 uint64_t register_x20;
468 uint64_t register_x21;
469 uint64_t register_x22;
470 uint64_t register_x23;
471 uint64_t register_x24;
472 uint64_t register_x25;
473 uint64_t register_x26;
474 uint64_t register_x27;
475 uint64_t register_x28;
476 uint64_t register_fp;
477 void *register_lr;
478#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
479 uint32_t _register_lr_top;
480#endif
481 uintptr_t register_sp;
482#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
483 uint32_t _register_sp_top;
484#endif
485 void *register_pc;
486#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
487 uint32_t _register_pc_top;
488#endif
489 uint64_t register_daif;
490 uint64_t register_cpsr;
491 uint64_t register_syndrome;
492 uint64_t register_fault_address;
493 AArch64_symbolic_exception_name vector;
494 uint64_t reserved_for_stack_alignment;
495 uint64_t register_fpsr;
496 uint64_t register_fpcr;
497 uint128_t register_q0;
498 uint128_t register_q1;
499 uint128_t register_q2;
500 uint128_t register_q3;
501 uint128_t register_q4;
502 uint128_t register_q5;
503 uint128_t register_q6;
504 uint128_t register_q7;
505 uint128_t register_q8;
506 uint128_t register_q9;
507 uint128_t register_q10;
508 uint128_t register_q11;
509 uint128_t register_q12;
510 uint128_t register_q13;
511 uint128_t register_q14;
512 uint128_t register_q15;
513 uint128_t register_q16;
514 uint128_t register_q17;
515 uint128_t register_q18;
516 uint128_t register_q19;
517 uint128_t register_q20;
518 uint128_t register_q21;
519 uint128_t register_q22;
520 uint128_t register_q23;
521 uint128_t register_q24;
522 uint128_t register_q25;
523 uint128_t register_q26;
524 uint128_t register_q27;
525 uint128_t register_q28;
526 uint128_t register_q29;
527 uint128_t register_q30;
528 uint128_t register_q31;
530
532
533RTEMS_NO_RETURN void _CPU_Exception_resume( CPU_Exception_frame *frame );
534
536_CPU_Exception_dispatch_and_resume( CPU_Exception_frame *frame );
537
538void _CPU_Exception_disable_thread_dispatch( void );
539
540int _CPU_Exception_frame_get_signal( CPU_Exception_frame *frame );
541
542void _CPU_Exception_frame_set_resume( CPU_Exception_frame *frame,
543 void *address );
544
545void _CPU_Exception_frame_make_resume_next_instruction(
547);
548
549void _AArch64_Exception_frame_copy(
550 CPU_Exception_frame *new_ef,
551 CPU_Exception_frame *old_ef
552);
553
554void _AArch64_Exception_default( CPU_Exception_frame *frame );
555
557typedef uintptr_t CPU_Uint32ptr;
558
559#ifdef __cplusplus
560}
561#endif
562
563#endif /* ASM */
564
567#endif /* _RTEMS_SCORE_CPU_H */
ARM AArch64 Assembler Support API.
This header file provides basic definitions used by the API and the implementation.
#define RTEMS_NO_RETURN
Tells the compiler in a function declaration that this function does not return.
Definition: basedefs.h:386
void _CPU_ISR_Set_level(uint32_t level)
Sets the hardware interrupt level by the level value.
Definition: cpu.c:149
void * _CPU_Thread_Idle_body(uintptr_t ignored)
Definition: idle-mcf5272.c:39
void _CPU_Initialize(void)
CPU initialization.
Definition: cpu.c:45
uintptr_t CPU_Uint32ptr
Definition: cpu.h:557
void _CPU_Exception_frame_print(const CPU_Exception_frame *frame)
Definition: vectorexceptions.c:64
uint32_t _CPU_Counter_frequency(void)
Gets the current CPU counter frequency in Hz.
Definition: system-clocks.c:125
void _CPU_Context_switch(Context_Control *run, Context_Control *heir)
CPU switch context.
Definition: cpu_asm.c:110
CPU_Counter_ticks _CPU_Counter_read(void)
Gets the current CPU counter value.
Definition: system-clocks.c:130
void _CPU_Context_Initialize(Context_Control *context, void *stack_area_begin, size_t stack_area_size, uint32_t new_level, void(*entry_point)(void), bool is_fp, void *tls_area)
Initializes the CPU context.
Definition: cpu.c:167
RTEMS_NO_RETURN void _CPU_Context_restore(Context_Control *new_context)
Definition: cpu_asm.c:130
#define CPU_swap_u16(value)
Definition: cpu.h:597
uint32_t _CPU_ISR_Get_level(void)
Definition: cpu.c:165
register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__("g6")
The pointer to the current per-CPU control is available via register g6.
uint32_t CPU_Counter_ticks
Unsigned integer type for CPU counter values.
Definition: cpu.h:1294
rtems_termios_device_context * context
Definition: console-config.c:62
The set of registers that specifies the complete processor state.
Definition: cpu.h:446
Thread register context.
Definition: cpu.h:169
uint64_t isr_dispatch_disable
This member is used for the external interrupt controller (EIC) support.
Definition: cpu.h:183