RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cpu.h
Go to the documentation of this file.
1
6/*
7 * Copyright (c) 2018 embedded brains GmbH
8 *
9 * Copyright (c) 2015 University of York.
10 * Hesham Almatary <hesham@alumni.york.ac.uk>
11 *
12 * COPYRIGHT (c) 1989-1999.
13 * On-Line Applications Research Corporation (OAR).
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef _RISCV_CPU_H
38#define _RISCV_CPU_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
45#include <rtems/score/riscv.h>
46
47#define RISCV_MSTATUS_MIE 0x8
48
49#define CPU_ISR_PASSES_FRAME_POINTER FALSE
50
51#define CPU_HARDWARE_FP FALSE
52#define CPU_SOFTWARE_FP FALSE
53#define CPU_ALL_TASKS_ARE_FP FALSE
54#define CPU_IDLE_TASK_IS_FP FALSE
55#define CPU_USE_DEFERRED_FP_SWITCH FALSE
56
57#define CPU_ENABLE_ROBUST_THREAD_DISPATCH TRUE
58
59#define CPU_STACK_GROWS_UP FALSE
60
61#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (64)))
62#define CPU_BIG_ENDIAN FALSE
63#define CPU_LITTLE_ENDIAN TRUE
64#define CPU_MODES_INTERRUPT_MASK 0x0000000000000001
65
66#define CPU_CACHE_LINE_BYTES 64
67
68#if __riscv_xlen == 32
69
70#define CPU_SIZEOF_POINTER 4
71
72#define CPU_STACK_MINIMUM_SIZE 4096
73
74#elif __riscv_xlen == 64
75
76#define CPU_SIZEOF_POINTER 8
77
78#define CPU_STACK_MINIMUM_SIZE 8192
79
80#endif /* __riscv_xlen */
81
82/* RISC-V ELF psABI specification */
83#define CPU_ALIGNMENT 16
84
85#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
86
87/* RISC-V ELF psABI specification */
88#define CPU_STACK_ALIGNMENT 16
89
90#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
91
92/*
93 * Processor defined structures required for cpukit/score.
94 */
95
96#ifndef ASM
97
98#if __riscv_flen == 32
99typedef float RISCV_Float;
100#elif __riscv_flen == 64
101typedef double RISCV_Float;
102#endif
103
104typedef struct {
105#ifdef RTEMS_SMP
106 volatile uint32_t is_executing;
107#else
108 uint32_t reserved;
109#endif
110 uint32_t isr_dispatch_disable;
111 uintptr_t ra;
112 uintptr_t sp;
113 uintptr_t tp;
114 uintptr_t s0;
115 uintptr_t s1;
116 uintptr_t s2;
117 uintptr_t s3;
118 uintptr_t s4;
119 uintptr_t s5;
120 uintptr_t s6;
121 uintptr_t s7;
122 uintptr_t s8;
123 uintptr_t s9;
124 uintptr_t s10;
125 uintptr_t s11;
126#if __riscv_flen > 0
127 uint32_t fcsr;
128 RISCV_Float fs0;
129 RISCV_Float fs1;
130 RISCV_Float fs2;
131 RISCV_Float fs3;
132 RISCV_Float fs4;
133 RISCV_Float fs5;
134 RISCV_Float fs6;
135 RISCV_Float fs7;
136 RISCV_Float fs8;
137 RISCV_Float fs9;
138 RISCV_Float fs10;
139 RISCV_Float fs11;
140#endif
142
143#define _CPU_Context_Get_SP( _context ) \
144 (_context)->sp
145
146#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
147
148#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
149
150#define _CPU_Initialize_vectors()
151
152static inline uint32_t riscv_interrupt_disable( void )
153{
154 unsigned long mstatus;
155
156 __asm__ volatile (
157 "csrrc %0, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) :
158 "=&r" ( mstatus )
159 );
160
161 return mstatus & RISCV_MSTATUS_MIE;
162}
163
164static inline void riscv_interrupt_enable( uint32_t level )
165{
166 __asm__ volatile ( "csrrs zero, mstatus, %0" : : "r" ( level ) );
167}
168
169#define _CPU_ISR_Disable( _level ) \
170 _level = riscv_interrupt_disable()
171
172#define _CPU_ISR_Enable( _level ) \
173 riscv_interrupt_enable( _level )
174
175#define _CPU_ISR_Flash( _level ) \
176 do{ \
177 _CPU_ISR_Enable( _level ); \
178 riscv_interrupt_disable(); \
179 } while(0)
180
181RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( unsigned long level )
182{
183 return ( level & RISCV_MSTATUS_MIE ) != 0;
184}
185
187{
188 if ( ( level & CPU_MODES_INTERRUPT_MASK) == 0 ) {
189 __asm__ volatile (
190 "csrrs zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
191 );
192 } else {
193 __asm__ volatile (
194 "csrrc zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
195 );
196 }
197}
198
199uint32_t _CPU_ISR_Get_level( void );
200
201/* end of ISR handler macros */
202
205 void *stack_area_begin,
206 size_t stack_area_size,
207 uint32_t new_level,
208 void ( *entry_point )( void ),
209 bool is_fp,
210 void *tls_area
211);
212
213#define _CPU_Context_Restart_self( _the_context ) \
214 _CPU_Context_restore( (_the_context) )
215
216extern void _CPU_Fatal_halt(uint32_t source, uint32_t error) RTEMS_NO_RETURN;
217
218#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
219
220#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
221
222#define CPU_MAXIMUM_PROCESSORS 32
223
224typedef uint16_t Priority_bit_map_Word;
225
226/*
227 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
228 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
229 * trap.
230 */
231typedef enum {
232 RISCV_INTERRUPT_SOFTWARE_USER = 0,
233 RISCV_INTERRUPT_SOFTWARE_SUPERVISOR = 1,
234 RISCV_INTERRUPT_SOFTWARE_MACHINE = 3,
235 RISCV_INTERRUPT_TIMER_USER = 4,
236 RISCV_INTERRUPT_TIMER_SUPERVISOR = 5,
237 RISCV_INTERRUPT_TIMER_MACHINE = 7,
238 RISCV_INTERRUPT_EXTERNAL_USER = 8,
239 RISCV_INTERRUPT_EXTERNAL_SUPERVISOR = 9,
240 RISCV_INTERRUPT_EXTERNAL_MACHINE = 11
241} RISCV_Interrupt_code;
242
243/*
244 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
245 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
246 * trap.
247 */
248typedef enum {
249 RISCV_EXCEPTION_INSTRUCTION_ADDRESS_MISALIGNED = 0,
250 RISCV_EXCEPTION_INSTRUCTION_ACCESS_FAULT = 1,
251 RISCV_EXCEPTION_ILLEGAL_INSTRUCTION = 2,
252 RISCV_EXCEPTION_BREAKPOINT = 3,
253 RISCV_EXCEPTION_LOAD_ADDRESS_MISALIGNED = 4,
254 RISCV_EXCEPTION_LOAD_ACCESS_FAULT = 5,
255 RISCV_EXCEPTION_STORE_OR_AMO_ADDRESS_MISALIGNED = 6,
256 RISCV_EXCEPTION_STORE_OR_AMO_ACCESS_FAULT = 7,
257 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_U_MODE = 8,
258 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_S_MODE = 9,
259 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_M_MODE = 11,
260 RISCV_EXCEPTION_INSTRUCTION_PAGE_FAULT = 12,
261 RISCV_EXCEPTION_LOAD_PAGE_FAULT = 13,
262 RISCV_EXCEPTION_STORE_OR_AMO_PAGE_FAULT = 15
263} RISCV_Exception_code;
264
265typedef struct {
266 uintptr_t mstatus;
267 uintptr_t mepc;
268 uintptr_t a2;
269 uintptr_t s0;
270 uintptr_t s1;
271 uintptr_t ra;
272 uintptr_t a3;
273 uintptr_t a4;
274 uintptr_t a5;
275 uintptr_t a6;
276 uintptr_t a7;
277 uintptr_t t0;
278 uintptr_t t1;
279 uintptr_t t2;
280 uintptr_t t3;
281 uintptr_t t4;
282 uintptr_t t5;
283 uintptr_t t6;
284#if __riscv_flen > 0
285 uint32_t fcsr;
286 RISCV_Float ft0;
287 RISCV_Float ft1;
288 RISCV_Float ft2;
289 RISCV_Float ft3;
290 RISCV_Float ft4;
291 RISCV_Float ft5;
292 RISCV_Float ft6;
293 RISCV_Float ft7;
294 RISCV_Float ft8;
295 RISCV_Float ft9;
296 RISCV_Float ft10;
297 RISCV_Float ft11;
298 RISCV_Float fa0;
299 RISCV_Float fa1;
300 RISCV_Float fa2;
301 RISCV_Float fa3;
302 RISCV_Float fa4;
303 RISCV_Float fa5;
304 RISCV_Float fa6;
305 RISCV_Float fa7;
306#endif
307 uintptr_t a0;
308 uintptr_t a1;
310
311typedef struct {
312 CPU_Interrupt_frame Interrupt_frame;
313 uintptr_t mcause;
314 uintptr_t sp;
315 uintptr_t gp;
316 uintptr_t tp;
317 uintptr_t s2;
318 uintptr_t s3;
319 uintptr_t s4;
320 uintptr_t s5;
321 uintptr_t s6;
322 uintptr_t s7;
323 uintptr_t s8;
324 uintptr_t s9;
325 uintptr_t s10;
326 uintptr_t s11;
327#if __riscv_flen > 0
328 RISCV_Float fs0;
329 RISCV_Float fs1;
330 RISCV_Float fs2;
331 RISCV_Float fs3;
332 RISCV_Float fs4;
333 RISCV_Float fs5;
334 RISCV_Float fs6;
335 RISCV_Float fs7;
336 RISCV_Float fs8;
337 RISCV_Float fs9;
338 RISCV_Float fs10;
339 RISCV_Float fs11;
340#endif
342
349
350
351/* end of Priority handler macros */
352
353/* functions */
354
355/*
356 * _CPU_Initialize
357 *
358 * This routine performs CPU dependent initialization.
359 *
360 */
361
362void _CPU_Initialize(
363 void
364);
365
366void *_CPU_Thread_Idle_body( uintptr_t ignored );
367
368/*
369 * _CPU_Context_switch
370 *
371 * This routine switches from the run context to the heir context.
372 *
373 * RISCV Specific Information:
374 *
375 * Please see the comments in the .c file for a description of how
376 * this function works. There are several things to be aware of.
377 */
378
380 Context_Control *run,
381 Context_Control *heir
382);
383
384/*
385 * _CPU_Context_restore
386 *
387 * This routine is generally used only to restart self in an
388 * efficient manner. It may simply be a label in _CPU_Context_switch.
389 *
390 * NOTE: May be unnecessary to reload some registers.
391 *
392 */
393
395 Context_Control *new_context
397
398/* The following routine swaps the endian format of an unsigned int.
399 * It must be static because it is referenced indirectly.
400 *
401 * This version will work on any processor, but if there is a better
402 * way for your CPU PLEASE use it. The most common way to do this is to:
403 *
404 * swap least significant two bytes with 16-bit rotate
405 * swap upper and lower 16-bits
406 * swap most significant two bytes with 16-bit rotate
407 *
408 * Some CPUs have special instructions which swap a 32-bit quantity in
409 * a single instruction (e.g. i486). It is probably best to avoid
410 * an "endian swapping control bit" in the CPU. One good reason is
411 * that interrupts would probably have to be disabled to insure that
412 * an interrupt does not try to access the same "chunk" with the wrong
413 * endian. Another good reason is that on some CPUs, the endian bit
414 * endianness for ALL fetches -- both code and data -- so the code
415 * will be fetched incorrectly.
416 *
417 */
418
419static inline uint32_t CPU_swap_u32(
420 uint32_t value
421)
422{
423 uint32_t byte1, byte2, byte3, byte4, swapped;
424
425 byte4 = (value >> 24) & 0xff;
426 byte3 = (value >> 16) & 0xff;
427 byte2 = (value >> 8) & 0xff;
428 byte1 = value & 0xff;
429
430 swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
431 return ( swapped );
432}
433
434#define CPU_swap_u16( value ) \
435 (((value&0xff) << 8) | ((value >> 8)&0xff))
436
437typedef uint32_t CPU_Counter_ticks;
438
439uint32_t _CPU_Counter_frequency( void );
440
441extern volatile uint32_t * const _RISCV_Counter;
442
443CPU_Counter_ticks _CPU_Counter_read( void );
444
445static inline CPU_Counter_ticks _CPU_Counter_difference(
446 CPU_Counter_ticks second,
447 CPU_Counter_ticks first
448)
449{
450 return second - first;
451}
452
453#ifdef RTEMS_SMP
454
455uint32_t _CPU_SMP_Initialize( void );
456
457bool _CPU_SMP_Start_processor( uint32_t cpu_index );
458
459void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
460
461void _CPU_SMP_Prepare_start_multitasking( void );
462
463static inline uint32_t _CPU_SMP_Get_current_processor( void )
464{
465 unsigned long mhartid;
466
467 __asm__ volatile ( "csrr %0, mhartid" : "=&r" ( mhartid ) );
468
469 return (uint32_t) mhartid;
470}
471
472void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
473
474static inline void _CPU_SMP_Processor_event_broadcast( void )
475{
476 __asm__ volatile ( "" : : : "memory" );
477}
478
479static inline void _CPU_SMP_Processor_event_receive( void )
480{
481 __asm__ volatile ( "" : : : "memory" );
482}
483
484static inline bool _CPU_Context_Get_is_executing(
486)
487{
488 return context->is_executing;
489}
490
491static inline void _CPU_Context_Set_is_executing(
493 bool is_executing
494)
495{
496 context->is_executing = is_executing;
497}
498
499#endif /* RTEMS_SMP */
500
502typedef uintptr_t CPU_Uint32ptr;
503
504#endif /* ASM */
505
506#ifdef __cplusplus
507}
508#endif
509
510#endif
Basic Definitions.
#define CPU_STACK_ALIGNMENT
Definition: cpu.h:308
#define RTEMS_ALIGNED(_alignment)
Instructs the compiler to enforce the specified alignment.
Definition: basedefs.h:216
#define RTEMS_NO_RETURN
Definition: basedefs.h:102
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:66
#define RTEMS_XSTRING(_x)
Stringifies expansion of _x.
Definition: basedefs.h:549
void _CPU_ISR_Set_level(uint32_t level)
Sets the hardware interrupt level by the level value.
Definition: cpu.c:57
bool _CPU_ISR_Is_enabled(uint32_t level)
Returns true if interrupts are enabled in the specified ISR level, otherwise returns false.
Definition: cpu.h:375
void * _CPU_Thread_Idle_body(uintptr_t ignored)
Definition: idle-mcf5272.c:20
void _CPU_Initialize(void)
CPU initialization.
Definition: cpu.c:45
uintptr_t CPU_Uint32ptr
Definition: cpu.h:662
uint32_t _CPU_Counter_frequency(void)
Returns the current CPU counter frequency in Hz.
Definition: system-clocks.c:112
void _CPU_Context_switch(Context_Control *run, Context_Control *heir)
CPU switch context.
Definition: cpu_asm.c:91
CPU_Counter_ticks _CPU_Counter_read(void)
Returns the current CPU counter value.
Definition: system-clocks.c:117
void _CPU_Context_restore(Context_Control *new_context) RTEMS_NO_RETURN
Definition: cpu_asm.c:111
uint32_t _CPU_ISR_Get_level(void)
Definition: cpu.c:88
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: epiphany-context-initialize.c:40
void _CPU_Exception_frame_print(const CPU_Exception_frame *frame)
Prints the exception frame via printk().
Definition: vectorexceptions.c:45
register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__("g6")
The pointer to the current per-CPU control is available via register g6.
void _CPU_Fatal_halt(uint32_t source, uint32_t error) RTEMS_NO_RETURN
Definition: bsp_fatal_halt.c:12
#define ra
return address *‍/
Definition: regs.h:66
#define sp
stack-pointer *‍/
Definition: regs.h:64
#define gp
global data pointer *‍/
Definition: regs.h:63
uint32_t CPU_Counter_ticks
Unsigned integer type for CPU counter values.
Definition: cpu.h:1210
#define CPU_MODES_INTERRUPT_MASK
Definition: cpu.h:161
The set of registers that specifies the complete processor state.
Definition: cpu.h:629
Interrupt stack frame (ISF).
Definition: cpu.h:191
Thread register context.
Definition: cpu.h:194
unsigned context
Definition: tlb.h:1