RTEMS 6.1-rc7
Loading...
Searching...
No Matches
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
63#define AARCH64_PSTATE_N (1LL << 31)
64#define AARCH64_PSTATE_Z (1LL << 30)
65#define AARCH64_PSTATE_C (1LL << 29)
66#define AARCH64_PSTATE_V (1LL << 28)
67#define AARCH64_PSTATE_D (1LL << 9)
68#define AARCH64_PSTATE_A (1LL << 8)
69#define AARCH64_PSTATE_I (1LL << 7)
70#define AARCH64_PSTATE_F (1LL << 6)
71
74/*
75 * AArch64 uses the PIC interrupt model.
76 */
77#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
78
79#define CPU_ISR_PASSES_FRAME_POINTER FALSE
80
81#define CPU_HARDWARE_FP FALSE
82
83#define CPU_SOFTWARE_FP FALSE
84
85#define CPU_ALL_TASKS_ARE_FP FALSE
86
87#define CPU_IDLE_TASK_IS_FP FALSE
88
89#define CPU_USE_DEFERRED_FP_SWITCH FALSE
90
91#define CPU_ENABLE_ROBUST_THREAD_DISPATCH TRUE
92
93#define CPU_STACK_GROWS_UP FALSE
94
95#if defined(AARCH64_MULTILIB_CACHE_LINE_MAX_64)
96 #define CPU_CACHE_LINE_BYTES 64
97#else
98 #define CPU_CACHE_LINE_BYTES 32
99#endif
100
101#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
102
103#define CPU_MODES_INTERRUPT_MASK 0x1
104
105#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
106
107#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
108
109#define CPU_STACK_MINIMUM_SIZE (1024 * 8)
110
111/* This could be either 4 or 8, depending on the ABI in use.
112 * Could also use __LP64__ or __ILP32__ */
113/* AAPCS64, section 5.1, Fundamental Data Types */
114#define CPU_SIZEOF_POINTER __SIZEOF_POINTER__
115
116/* AAPCS64, section 5.1, Fundamental Data Types */
117#define CPU_ALIGNMENT 16
118
119#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
120
121/* AAPCS64, section 6.2.2, Stack constraints at a public interface */
122#define CPU_STACK_ALIGNMENT 16
123
124#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
125
126#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
127
128#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE
129
130#define CPU_MAXIMUM_PROCESSORS 32
131
132#define AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET 0x70
133
134#ifdef AARCH64_MULTILIB_VFP
135 #define AARCH64_CONTEXT_CONTROL_D8_OFFSET 0x78
136#endif
137
138#define AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE 0x68
139
140#ifdef RTEMS_SMP
141 #if defined(AARCH64_MULTILIB_VFP)
142 #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 0xb8
143 #else
144 #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 0x78
145 #endif
146#endif
147
148#define AARCH64_EXCEPTION_FRAME_SIZE 0x350
149
150#define AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET 0xF8
151#define AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET 0xF0
152#define AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET 0x108
153#define AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET 0x118
154#define AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET 0x128
155#define AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET 0x138
156#define AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET 0x150
157
158#ifndef ASM
159
160#ifdef __cplusplus
161extern "C" {
162#endif
163
164/*
165 This is to fix the following warning
166 ISO C does not support 'uint128_t' types
167*/
168#pragma GCC diagnostic push
169#pragma GCC diagnostic ignored "-Wpedantic"
170typedef unsigned __int128 uint128_t;
171#pragma GCC diagnostic pop
172
173typedef struct {
174 uint64_t register_x19;
175 uint64_t register_x20;
176 uint64_t register_x21;
177 uint64_t register_x22;
178 uint64_t register_x23;
179 uint64_t register_x24;
180 uint64_t register_x25;
181 uint64_t register_x26;
182 uint64_t register_x27;
183 uint64_t register_x28;
184 uint64_t register_fp;
185 uint64_t register_lr;
186 uint64_t register_sp;
188 uint64_t thread_id;
189#ifdef AARCH64_MULTILIB_VFP
190 uint64_t register_d8;
191 uint64_t register_d9;
192 uint64_t register_d10;
193 uint64_t register_d11;
194 uint64_t register_d12;
195 uint64_t register_d13;
196 uint64_t register_d14;
197 uint64_t register_d15;
198#endif
199#ifdef RTEMS_SMP
200 volatile bool is_executing;
201#endif
203
204static inline void _AARCH64_Data_memory_barrier( void )
205{
206 __asm__ volatile ( "dmb SY" : : : "memory" );
207}
208
209static inline void _AARCH64_Data_synchronization_barrier( void )
210{
211 __asm__ volatile ( "dsb SY" : : : "memory" );
212}
213
214static inline void _AARCH64_Instruction_synchronization_barrier( void )
215{
216 __asm__ volatile ( "isb" : : : "memory" );
217}
218
219void _CPU_ISR_Set_level( uint32_t level );
220
221uint32_t _CPU_ISR_Get_level( void );
222
223#if defined(AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE)
224uint64_t AArch64_interrupt_disable( void );
225void AArch64_interrupt_enable( uint64_t isr_cookie );
226void AArch64_interrupt_flash( uint64_t isr_cookie );
227#else
228static inline uint64_t AArch64_interrupt_disable( void )
229{
230 uint64_t isr_cookie;
231
232 __asm__ volatile (
233 "mrs %[isr_cookie], DAIF\n"
234 "msr DAIFSet, #0x2\n"
235 : [isr_cookie] "=&r" (isr_cookie)
236 );
237
238 return isr_cookie;
239}
240
241static inline void AArch64_interrupt_enable( uint64_t isr_cookie )
242{
243 __asm__ volatile (
244 "msr DAIF, %[isr_cookie]\n"
245 : : [isr_cookie] "r" (isr_cookie)
246 );
247}
248
249static inline void AArch64_interrupt_flash( uint64_t isr_cookie )
250{
251 AArch64_interrupt_enable(isr_cookie);
252 AArch64_interrupt_disable();
253}
254#endif /* !AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE */
255
256#define _CPU_ISR_Disable( _isr_cookie ) \
257 do { \
258 _isr_cookie = AArch64_interrupt_disable(); \
259 } while (0)
260
261#define _CPU_ISR_Enable( _isr_cookie ) \
262 AArch64_interrupt_enable( _isr_cookie )
263
264#define _CPU_ISR_Flash( _isr_cookie ) \
265 AArch64_interrupt_flash( _isr_cookie )
266
267static inline bool _CPU_ISR_Is_enabled( uint64_t isr_cookie )
268{
269 return ( isr_cookie & AARCH64_PSTATE_I ) == 0;
270}
271
272void _CPU_Context_Initialize(
273 Context_Control *the_context,
274 void *stack_area_begin,
275 size_t stack_area_size,
276 uint64_t new_level,
277 void (*entry_point)( void ),
278 bool is_fp,
279 void *tls_area
280);
281
282#define _CPU_Context_Get_SP( _context ) \
283 (_context)->register_sp
284
285#ifdef RTEMS_SMP
286 static inline bool _CPU_Context_Get_is_executing(
288 )
289 {
290 return context->is_executing;
291 }
292
293 static inline void _CPU_Context_Set_is_executing(
295 bool is_executing
296 )
297 {
298 context->is_executing = is_executing;
299 }
300
301 RTEMS_NO_RETURN void _AArch64_Start_multitasking( Context_Control *heir );
302
303 #define _CPU_Start_multitasking( _heir ) _AArch64_Start_multitasking( _heir )
304#endif
305
306#define _CPU_Context_Restart_self( _the_context ) \
307 _CPU_Context_restore( (_the_context) );
308
309#define _CPU_Context_Initialize_fp( _destination ) \
310 do { \
311 *(*(_destination)) = _CPU_Null_fp_context; \
312 } while (0)
313
317void _CPU_Initialize( void );
318
319typedef void ( *CPU_ISR_handler )( void );
320
325
326RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
327 Context_Control *executing,
328 Context_Control *heir
329);
330
331RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
332
333#ifdef RTEMS_SMP
334 uint32_t _CPU_SMP_Initialize( void );
335
336 bool _CPU_SMP_Start_processor( uint32_t cpu_index );
337
338 void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
339
340 void _CPU_SMP_Prepare_start_multitasking( void );
341
348 uint32_t _CPU_SMP_Get_current_processor( void );
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
387RTEMS_NO_RETURN void *_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
uint32_t _CPU_ISR_Get_level(void)
Returns the interrupt level of the executing thread.
Definition: cpu.c:166
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)
Prints the exception frame via printk().
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
#define CPU_swap_u16(value)
Definition: cpu.h:597
#define _CPU_ISR_Set_level(_new_level)
Definition: cpu.h:378
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:173
uint64_t isr_dispatch_disable
This member is used for the external interrupt controller (EIC) support.
Definition: cpu.h:187