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
12/*
13 * COPYRIGHT (c) 1989-2011.
14 * On-Line Applications Research Corporation (OAR).
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _RTEMS_SCORE_CPU_H
39#define _RTEMS_SCORE_CPU_H
40
41#ifndef ASM
42#include <string.h> /* for memcpy */
43#endif
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
50#if defined(RTEMS_PARAVIRT)
51#include <rtems/score/paravirt.h>
52#endif
53#include <rtems/score/i386.h>
54
64/* conditional compilation parameters */
65
66/*
67 * Does the CPU follow the simple vectored interrupt model?
68 *
69 * If TRUE, then RTEMS allocates the vector table it internally manages.
70 * If FALSE, then the BSP is assumed to allocate and manage the vector
71 * table
72 *
73 * PowerPC Specific Information:
74 *
75 * The PowerPC and x86 were the first to use the PIC interrupt model.
76 * They do not use the simple vectored interrupt model.
77 */
78#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
79
80/*
81 * Does the RTEMS invoke the user's ISR with the vector number and
82 * a pointer to the saved interrupt frame (1) or just the vector
83 * number (0)?
84 */
85
86#define CPU_ISR_PASSES_FRAME_POINTER FALSE
87
88/*
89 * Some family members have no FP, some have an FPU such as the i387
90 * for the i386, others have it built in (i486DX, Pentium).
91 */
92
93#ifdef __SSE__
94#define CPU_HARDWARE_FP TRUE
95#define CPU_SOFTWARE_FP FALSE
96
97#define CPU_ALL_TASKS_ARE_FP TRUE
98#define CPU_IDLE_TASK_IS_FP TRUE
99#define CPU_USE_DEFERRED_FP_SWITCH FALSE
100#else /* __SSE__ */
101
102#if ( I386_HAS_FPU == 1 )
103#define CPU_HARDWARE_FP TRUE /* i387 for i386 */
104#else
105#define CPU_HARDWARE_FP FALSE
106#endif
107#define CPU_SOFTWARE_FP FALSE
108
109#define CPU_ALL_TASKS_ARE_FP FALSE
110#define CPU_IDLE_TASK_IS_FP FALSE
111#if defined(RTEMS_SMP)
112 #define CPU_USE_DEFERRED_FP_SWITCH FALSE
113#else
114 #define CPU_USE_DEFERRED_FP_SWITCH TRUE
115#endif
116#endif /* __SSE__ */
117
118#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
119
120#define CPU_STACK_GROWS_UP FALSE
121
122/* FIXME: The Pentium 4 used 128 bytes, it this processor still relevant? */
123#define CPU_CACHE_LINE_BYTES 64
124
125#define CPU_STRUCTURE_ALIGNMENT
126
127#define CPU_MAXIMUM_PROCESSORS 32
128
129#define I386_CONTEXT_CONTROL_EFLAGS_OFFSET 0
130#define I386_CONTEXT_CONTROL_ESP_OFFSET 4
131#define I386_CONTEXT_CONTROL_EBP_OFFSET 8
132#define I386_CONTEXT_CONTROL_EBX_OFFSET 12
133#define I386_CONTEXT_CONTROL_ESI_OFFSET 16
134#define I386_CONTEXT_CONTROL_EDI_OFFSET 20
135#define I386_CONTEXT_CONTROL_GS_0_OFFSET 24
136#define I386_CONTEXT_CONTROL_GS_1_OFFSET 28
137#define I386_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE 32
138
139#ifdef RTEMS_SMP
140 #define I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 36
141#endif
142
143/* structures */
144
145#ifndef ASM
146
147/*
148 * Basic integer context for the i386 family.
149 */
150
151typedef struct {
152 uint32_t eflags; /* extended flags register */
153 void *esp; /* extended stack pointer register */
154 void *ebp; /* extended base pointer register */
155 uint32_t ebx; /* extended bx register */
156 uint32_t esi; /* extended source index register */
157 uint32_t edi; /* extended destination index flags register */
158 segment_descriptors gs; /* gs segment descriptor */
160#ifdef RTEMS_SMP
161 volatile bool is_executing;
162#endif
164
165#define _CPU_Context_Get_SP( _context ) \
166 (uintptr_t) (_context)->esp
167
168#ifdef RTEMS_SMP
169 static inline bool _CPU_Context_Get_is_executing(
171 )
172 {
173 return context->is_executing;
174 }
175
176 static inline void _CPU_Context_Set_is_executing(
178 bool is_executing
179 )
180 {
181 context->is_executing = is_executing;
182 }
183#endif
184
185/*
186 * FP context save area for the i387 numeric coprocessors.
187 */
188#ifdef __SSE__
189/* All FPU and SSE registers are volatile; hence, as long
190 * as we are within normally executing C code (including
191 * a task switch) there is no need for saving/restoring
192 * any of those registers.
193 * We must save/restore the full FPU/SSE context across
194 * interrupts and exceptions, however:
195 * - after ISR execution a _Thread_Dispatch() may happen
196 * and it is therefore necessary to save the FPU/SSE
197 * registers to be restored when control is returned
198 * to the interrupted task.
199 * - gcc may implicitly use FPU/SSE instructions in
200 * an ISR.
201 *
202 * Even though there is no explicit mentioning of the FPU
203 * control word in the SYSV ABI (i386) being non-volatile
204 * we maintain MXCSR and the FPU control-word for each task.
205 */
206typedef struct {
207 uint32_t mxcsr;
208 uint16_t fpucw;
210
211#else
212
213typedef struct {
214 uint8_t fp_save_area[108]; /* context size area for I80387 */
215 /* 28 bytes for environment */
217
218#endif
219
220
221/*
222 * The following structure defines the set of information saved
223 * on the current stack by RTEMS upon receipt of execptions.
224 *
225 * idtIndex is either the interrupt number or the trap/exception number.
226 * faultCode is the code pushed by the processor on some exceptions.
227 *
228 * Since the first registers are directly pushed by the CPU they
229 * may not respect 16-byte stack alignment, which is, however,
230 * mandatory for the SSE register area.
231 * Therefore, these registers are stored at an aligned address
232 * and a pointer is stored in the CPU_Exception_frame.
233 * If the executive was compiled without SSE support then
234 * this pointer is NULL.
235 */
236
238
239typedef struct {
240 struct Context_Control_sse *fp_ctxt;
241 uint32_t edi;
242 uint32_t esi;
243 uint32_t ebp;
244 uint32_t esp0;
245 uint32_t ebx;
246 uint32_t edx;
247 uint32_t ecx;
248 uint32_t eax;
249 uint32_t idtIndex;
250 uint32_t faultCode;
251 uint32_t eip;
252 uint32_t cs;
253 uint32_t eflags;
255
256#ifdef __SSE__
257typedef struct Context_Control_sse {
258 uint16_t fcw;
259 uint16_t fsw;
260 uint8_t ftw;
261 uint8_t res_1;
262 uint16_t fop;
263 uint32_t fpu_ip;
264 uint16_t cs;
265 uint16_t res_2;
266 uint32_t fpu_dp;
267 uint16_t ds;
268 uint16_t res_3;
269 uint32_t mxcsr;
270 uint32_t mxcsr_mask;
271 struct {
272 uint8_t fpreg[10];
273 uint8_t res_4[ 6];
274 } fp_mmregs[8];
275 uint8_t xmmregs[8][16];
276 uint8_t res_5[224];
278__attribute__((aligned(16)))
279;
280#endif
281
282typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
283extern cpuExcHandlerType _currentExcHandler;
284extern void rtems_exception_init_mngt(void);
285
286/*
287 * This port does not pass any frame info to the
288 * interrupt handler.
289 */
290
291typedef struct {
292/* allow for 16B alignment (worst case 12 Bytes more) and isr right after pushfl */
293 uint32_t reserved[3];
294/* registers saved by _ISR_Handler */
295 uint32_t isr_vector;
296 uint32_t ebx;
297 uint32_t ebp;
298 uint32_t esp;
299/* registers saved by rtems_irq_prologue_##_vector */
300 uint32_t edx;
301 uint32_t ecx;
302 uint32_t eax;
303/* registers saved by CPU */
304 uint32_t eip;
305 uint32_t cs;
306 uint32_t eflags;
308
309typedef enum {
310 I386_EXCEPTION_DIVIDE_BY_ZERO = 0,
311 I386_EXCEPTION_DEBUG = 1,
312 I386_EXCEPTION_NMI = 2,
313 I386_EXCEPTION_BREAKPOINT = 3,
314 I386_EXCEPTION_OVERFLOW = 4,
315 I386_EXCEPTION_BOUND = 5,
316 I386_EXCEPTION_ILLEGAL_INSTR = 6,
317 I386_EXCEPTION_MATH_COPROC_UNAVAIL = 7,
318 I386_EXCEPTION_DOUBLE_FAULT = 8,
319 I386_EXCEPTION_I386_COPROC_SEG_ERR = 9,
320 I386_EXCEPTION_INVALID_TSS = 10,
321 I386_EXCEPTION_SEGMENT_NOT_PRESENT = 11,
322 I386_EXCEPTION_STACK_SEGMENT_FAULT = 12,
323 I386_EXCEPTION_GENERAL_PROT_ERR = 13,
324 I386_EXCEPTION_PAGE_FAULT = 14,
325 I386_EXCEPTION_INTEL_RES15 = 15,
326 I386_EXCEPTION_FLOAT_ERROR = 16,
327 I386_EXCEPTION_ALIGN_CHECK = 17,
328 I386_EXCEPTION_MACHINE_CHECK = 18,
329 I386_EXCEPTION_ENTER_RDBG = 50 /* to enter manually RDBG */
330
331} Intel_symbolic_exception_name;
332
333
334/*
335 * context size area for floating point
336 *
337 * NOTE: This is out of place on the i386 to avoid a forward reference.
338 */
339
340#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
341
342/* variables */
343
344extern Context_Control_fp _CPU_Null_fp_context;
345
346#endif /* ASM */
347
348/* constants */
349
350/*
351 * This defines the number of levels and the mask used to pick those
352 * bits out of a thread mode.
353 */
354
355#define CPU_MODES_INTERRUPT_MASK 0x00000001 /* interrupt level in mode */
356
357/*
358 * extra stack required by the MPCI receive server thread
359 */
360
361#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
362
363/*
364 * This is defined if the port has a special way to report the ISR nesting
365 * level. Most ports maintain the variable _ISR_Nest_level.
366 */
367
368#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
369
370/*
371 * Minimum size of a thread's stack.
372 */
373
374#define CPU_STACK_MINIMUM_SIZE 4096
375
376#define CPU_SIZEOF_POINTER 4
377
378/*
379 * i386 is pretty tolerant of alignment. Just put things on 4 byte boundaries.
380 */
381
382#define CPU_ALIGNMENT 4
383#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
384
385/*
386 * On i386 thread stacks require no further alignment after allocation
387 * from the Workspace. However, since gcc maintains 16-byte alignment
388 * we try to respect that. If you find an option to let gcc squeeze
389 * the stack more tightly then setting CPU_STACK_ALIGNMENT to 16 still
390 * doesn't waste much space since this only determines the *initial*
391 * alignment.
392 */
393
394#define CPU_STACK_ALIGNMENT 16
395
396#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
397
398/* macros */
399
400#ifndef ASM
401/*
402 * ISR handler macros
403 *
404 * These macros perform the following functions:
405 * + initialize the RTEMS vector table
406 * + disable all maskable CPU interrupts
407 * + restore previous interrupt level (enable)
408 * + temporarily restore interrupts (flash)
409 * + set a particular level
410 */
411
412#if !defined(I386_DISABLE_INLINE_ISR_DISABLE_ENABLE)
413#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
414
415#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
416
417#define _CPU_ISR_Flash( _level ) i386_flash_interrupts( _level )
418
419#define _CPU_ISR_Set_level( _new_level ) \
420 { \
421 if ( _new_level ) __asm__ volatile ( "cli" ); \
422 else __asm__ volatile ( "sti" ); \
423 }
424#else
425#define _CPU_ISR_Disable( _level ) _level = i386_disable_interrupts()
426#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
427#define _CPU_ISR_Flash( _level ) i386_flash_interrupts( _level )
428#define _CPU_ISR_Set_level( _new_level ) i386_set_interrupt_level(_new_level)
429#endif
430
431static inline bool _CPU_ISR_Is_enabled( uint32_t level )
432{
433 return ( level & EFLAGS_INTR_ENABLE ) != 0;
434}
435
436uint32_t _CPU_ISR_Get_level( void );
437
438/* Make sure interrupt stack has space for ISR
439 * 'vector' arg at the top and that it is aligned
440 * properly.
441 */
442
443#define _CPU_Interrupt_stack_setup( _lo, _hi ) \
444 do { \
445 _hi = (void*)(((uintptr_t)(_hi) - 4) & ~ (CPU_STACK_ALIGNMENT - 1)); \
446 } while (0)
447
448#endif /* ASM */
449
450/* end of ISR handler macros */
451
452/*
453 * Context handler macros
454 *
455 * These macros perform the following functions:
456 * + initialize a context area
457 * + restart the current thread
458 * + calculate the initial pointer into a FP context area
459 * + initialize an FP context area
460 */
461
462#define CPU_EFLAGS_INTERRUPTS_ON 0x00003202
463#define CPU_EFLAGS_INTERRUPTS_OFF 0x00003002
464
465#ifndef ASM
466
467void _CPU_Context_Initialize(
468 Context_Control *the_context,
469 void *stack_area_begin,
470 size_t stack_area_size,
471 uint32_t new_level,
472 void (*entry_point)( void ),
473 bool is_fp,
474 void *tls_area
475);
476
477#define _CPU_Context_Restart_self( _the_context ) \
478 _CPU_Context_restore( (_the_context) );
479
480#if defined(RTEMS_SMP)
481 uint32_t _CPU_SMP_Initialize( void );
482
483 bool _CPU_SMP_Start_processor( uint32_t cpu_index );
484
485 void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
486
487 void _CPU_SMP_Prepare_start_multitasking( void );
488
489 uint32_t _CPU_SMP_Get_current_processor( void );
490
491 void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
492#endif
493
494#define _CPU_Context_Initialize_fp( _fp_area ) \
495 { \
496 memcpy( *_fp_area, &_CPU_Null_fp_context, CPU_CONTEXT_FP_SIZE ); \
497 }
498
499/* end of Context handler macros */
500
501#endif /* ASM */
502
503#define CPU_USE_LIBC_INIT_FINI_ARRAY FALSE
504
505/*
506 * Bitfield handler macros
507 *
508 * These macros perform the following functions:
509 * + scan for the highest numbered (MSB) set in a 16 bit bitfield
510 */
511
512#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
513
514#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
515 { \
516 uint16_t __value_in_register = ( _value ); \
517 uint16_t __output = 0; \
518 __asm__ volatile ( "bsfw %0,%1 " \
519 : "=r" ( __value_in_register ), "=r" ( __output ) \
520 : "0" ( __value_in_register ), "1" ( __output ) \
521 ); \
522 ( _output ) = __output; \
523 }
524
525/* end of Bitfield handler macros */
526
527/*
528 * Priority handler macros
529 *
530 * These macros perform the following functions:
531 * + return a mask with the bit for this major/minor portion of
532 * of thread priority set.
533 * + translate the bit number returned by "Bitfield_find_first_bit"
534 * into an index into the thread ready chain bit maps
535 */
536
537#define _CPU_Priority_Mask( _bit_number ) \
538 ( 1 << (_bit_number) )
539
540#define _CPU_Priority_bits_index( _priority ) \
541 (_priority)
542
543/* functions */
544
545#ifndef ASM
546/*
547 * _CPU_Initialize
548 *
549 * This routine performs CPU dependent initialization.
550 */
551
552void _CPU_Initialize(void);
553
554typedef void ( *CPU_ISR_handler )( void );
555
557 uint32_t vector,
558 CPU_ISR_handler new_handler,
559 CPU_ISR_handler *old_handler
560);
561
562RTEMS_NO_RETURN void *_CPU_Thread_Idle_body( uintptr_t ignored );
563
564/*
565 * _CPU_Context_switch
566 *
567 * This routine switches from the run context to the heir context.
568 */
569
571 Context_Control *run,
572 Context_Control *heir
573);
574
575RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
576 Context_Control *executing,
577 Context_Control *heir
578);
579
580/*
581 * _CPU_Context_restore
582 *
583 * This routine is generally used only to restart self in an
584 * efficient manner and avoid stack conflicts.
585 */
586
587RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
588
589/*
590 * _CPU_Context_save_fp
591 *
592 * This routine saves the floating point context passed to it.
593 */
594
595#ifdef __SSE__
596#define _CPU_Context_save_fp(fp_context_pp) \
597 do { \
598 __asm__ __volatile__( \
599 "fstcw %0" \
600 :"=m"((*(fp_context_pp))->fpucw) \
601 ); \
602 __asm__ __volatile__( \
603 "stmxcsr %0" \
604 :"=m"((*(fp_context_pp))->mxcsr) \
605 ); \
606 } while (0)
607#else
609 Context_Control_fp **fp_context_ptr
610);
611#endif
612
613/*
614 * _CPU_Context_restore_fp
615 *
616 * This routine restores the floating point context passed to it.
617 */
618#ifdef __SSE__
619#define _CPU_Context_restore_fp(fp_context_pp) \
620 do { \
621 __asm__ __volatile__( \
622 "fldcw %0" \
623 ::"m"((*(fp_context_pp))->fpucw) \
624 :"memory" \
625 ); \
626 __builtin_ia32_ldmxcsr(_Thread_Executing->fp_context->mxcsr); \
627 } while (0)
628#else
630 Context_Control_fp **fp_context_ptr
631);
632#endif
633
634#ifdef __SSE__
635#define _CPU_Context_Initialization_at_thread_begin() \
636 do { \
637 __asm__ __volatile__( \
638 "finit" \
639 : \
640 : \
641 :"st","st(1)","st(2)","st(3)", \
642 "st(4)","st(5)","st(6)","st(7)", \
643 "fpsr","memory" \
644 ); \
645 if ( _Thread_Executing->fp_context ) { \
646 _CPU_Context_restore_fp(&_Thread_Executing->fp_context); \
647 } \
648 } while (0)
649#endif
650
652
653typedef uint32_t CPU_Counter_ticks;
654
655uint32_t _CPU_Counter_frequency( void );
656
657CPU_Counter_ticks _CPU_Counter_read( void );
658
662typedef uintptr_t CPU_Uint32ptr;
663
664#endif /* ASM */
665
666#ifdef __cplusplus
667}
668#endif
669
670#endif
This header file provides basic definitions used by the API and the implementation.
lpc176x_can_isr_vector isr_vector
Vector of isr for the can_driver .
Definition: can.c:37
#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
void _CPU_ISR_install_vector(uint32_t vector, CPU_ISR_handler hdl, CPU_ISR_handler *oldHdl)
SPARC specific RTEMS ISR installer.
Definition: idt.c:106
Intel I386 CPU Dependent Source.
rtems_termios_device_context * context
Definition: console-config.c:62
#define _CPU_Context_restore_fp(_fp_context_ptr)
Nothing to do due to the synchronous or lazy floating point switch.
Definition: cpu.h:901
#define _CPU_Context_save_fp(_fp_context_ptr)
Nothing to do due to the synchronous or lazy floating point switch.
Definition: cpu.h:895
The set of registers that specifies the complete processor state.
Definition: cpu.h:446
Interrupt stack frame (ISF).
Definition: cpuimpl.h:64
SPARC basic context.
Definition: cpu.h:213
Definition: sse_test.c:126
Thread register context.
Definition: cpu.h:173
uint32_t isr_dispatch_disable
This member is used for the external interrupt controller (EIC) support.
Definition: cpu.h:159
Definition: xnandpsu_onfi.h:185