RTEMS 6.1-rc7
Loading...
Searching...
No Matches
cpu.h
Go to the documentation of this file.
1
6/*
7 * Copyright (c) 2018 embedded brains GmbH & Co. KG
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
150static inline uint32_t riscv_interrupt_disable( void )
151{
152 unsigned long mstatus;
153
154 __asm__ volatile (
155 ".option push\n"
156 ".option arch, +zicsr\n"
157 "csrrc %0, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) "\n"
158 ".option pop" :
159 "=&r" ( mstatus )
160 );
161
162 return mstatus & RISCV_MSTATUS_MIE;
163}
164
165static inline void riscv_interrupt_enable( uint32_t level )
166{
167 __asm__ volatile (
168 ".option push\n"
169 ".option arch, +zicsr\n"
170 "csrrs zero, mstatus, %0\n"
171 ".option pop" :
172 :
173 "r" ( level )
174 );
175}
176
177#define _CPU_ISR_Disable( _level ) \
178 _level = riscv_interrupt_disable()
179
180#define _CPU_ISR_Enable( _level ) \
181 riscv_interrupt_enable( _level )
182
183#define _CPU_ISR_Flash( _level ) \
184 do{ \
185 _CPU_ISR_Enable( _level ); \
186 riscv_interrupt_disable(); \
187 } while(0)
188
189static inline bool _CPU_ISR_Is_enabled( unsigned long level )
190{
191 return ( level & RISCV_MSTATUS_MIE ) != 0;
192}
193
194static inline void _CPU_ISR_Set_level( uint32_t level )
195{
196 /*
197 * Where CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE, the only supported
198 * interrupt level allowed to set is 0 (interrupts enabled). This constraint
199 * is enforced by the API level functions which return an error status for
200 * other interrupt levels.
201 */
202 (void) level;
203 __asm__ volatile (
204 ".option push\n"
205 ".option arch, +zicsr\n"
206 "csrrs zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) "\n"
207 ".option pop"
208 );
209}
210
211uint32_t _CPU_ISR_Get_level( void );
212
213/* end of ISR handler macros */
214
215void _CPU_Context_Initialize(
217 void *stack_area_begin,
218 size_t stack_area_size,
219 uint32_t new_level,
220 void ( *entry_point )( void ),
221 bool is_fp,
222 void *tls_area
223);
224
225#define _CPU_Context_Restart_self( _the_context ) \
226 _CPU_Context_restore( (_the_context) )
227
228#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
229
230#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
231
232#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE
233
234#define CPU_MAXIMUM_PROCESSORS 32
235
236typedef uint16_t Priority_bit_map_Word;
237
238/*
239 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
240 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
241 * trap.
242 */
243typedef enum {
244 RISCV_INTERRUPT_SOFTWARE_USER = 0,
245 RISCV_INTERRUPT_SOFTWARE_SUPERVISOR = 1,
246 RISCV_INTERRUPT_SOFTWARE_MACHINE = 3,
247 RISCV_INTERRUPT_TIMER_USER = 4,
248 RISCV_INTERRUPT_TIMER_SUPERVISOR = 5,
249 RISCV_INTERRUPT_TIMER_MACHINE = 7,
250 RISCV_INTERRUPT_EXTERNAL_USER = 8,
251 RISCV_INTERRUPT_EXTERNAL_SUPERVISOR = 9,
252 RISCV_INTERRUPT_EXTERNAL_MACHINE = 11
253} RISCV_Interrupt_code;
254
255/*
256 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
257 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
258 * trap.
259 */
260typedef enum {
261 RISCV_EXCEPTION_INSTRUCTION_ADDRESS_MISALIGNED = 0,
262 RISCV_EXCEPTION_INSTRUCTION_ACCESS_FAULT = 1,
263 RISCV_EXCEPTION_ILLEGAL_INSTRUCTION = 2,
264 RISCV_EXCEPTION_BREAKPOINT = 3,
265 RISCV_EXCEPTION_LOAD_ADDRESS_MISALIGNED = 4,
266 RISCV_EXCEPTION_LOAD_ACCESS_FAULT = 5,
267 RISCV_EXCEPTION_STORE_OR_AMO_ADDRESS_MISALIGNED = 6,
268 RISCV_EXCEPTION_STORE_OR_AMO_ACCESS_FAULT = 7,
269 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_U_MODE = 8,
270 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_S_MODE = 9,
271 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_M_MODE = 11,
272 RISCV_EXCEPTION_INSTRUCTION_PAGE_FAULT = 12,
273 RISCV_EXCEPTION_LOAD_PAGE_FAULT = 13,
274 RISCV_EXCEPTION_STORE_OR_AMO_PAGE_FAULT = 15
275} RISCV_Exception_code;
276
277typedef struct {
278 uintptr_t mstatus;
279 uintptr_t mepc;
280 uintptr_t a2;
281 uintptr_t s0;
282 uintptr_t s1;
283 uintptr_t ra;
284 uintptr_t a3;
285 uintptr_t a4;
286 uintptr_t a5;
287 uintptr_t a6;
288 uintptr_t a7;
289 uintptr_t t0;
290 uintptr_t t1;
291 uintptr_t t2;
292 uintptr_t t3;
293 uintptr_t t4;
294 uintptr_t t5;
295 uintptr_t t6;
296#if __riscv_flen > 0
297 uint32_t fcsr;
298 RISCV_Float ft0;
299 RISCV_Float ft1;
300 RISCV_Float ft2;
301 RISCV_Float ft3;
302 RISCV_Float ft4;
303 RISCV_Float ft5;
304 RISCV_Float ft6;
305 RISCV_Float ft7;
306 RISCV_Float ft8;
307 RISCV_Float ft9;
308 RISCV_Float ft10;
309 RISCV_Float ft11;
310 RISCV_Float fa0;
311 RISCV_Float fa1;
312 RISCV_Float fa2;
313 RISCV_Float fa3;
314 RISCV_Float fa4;
315 RISCV_Float fa5;
316 RISCV_Float fa6;
317 RISCV_Float fa7;
318#endif
319 uintptr_t a0;
320 uintptr_t a1;
321} RTEMS_ALIGNED( CPU_STACK_ALIGNMENT ) CPU_Interrupt_frame;
322
323typedef struct {
324 CPU_Interrupt_frame Interrupt_frame;
325 uintptr_t mcause;
326 uintptr_t sp;
327 uintptr_t gp;
328 uintptr_t tp;
329 uintptr_t s2;
330 uintptr_t s3;
331 uintptr_t s4;
332 uintptr_t s5;
333 uintptr_t s6;
334 uintptr_t s7;
335 uintptr_t s8;
336 uintptr_t s9;
337 uintptr_t s10;
338 uintptr_t s11;
339#if __riscv_flen > 0
340 RISCV_Float fs0;
341 RISCV_Float fs1;
342 RISCV_Float fs2;
343 RISCV_Float fs3;
344 RISCV_Float fs4;
345 RISCV_Float fs5;
346 RISCV_Float fs6;
347 RISCV_Float fs7;
348 RISCV_Float fs8;
349 RISCV_Float fs9;
350 RISCV_Float fs10;
351 RISCV_Float fs11;
352#endif
354
361
362
363/* end of Priority handler macros */
364
365/* functions */
366
367/*
368 * _CPU_Initialize
369 *
370 * This routine performs CPU dependent initialization.
371 *
372 */
373
374void _CPU_Initialize(
375 void
376);
377
378RTEMS_NO_RETURN void *_CPU_Thread_Idle_body( uintptr_t ignored );
379
380/*
381 * _CPU_Context_switch
382 *
383 * This routine switches from the run context to the heir context.
384 *
385 * RISCV Specific Information:
386 *
387 * Please see the comments in the .c file for a description of how
388 * this function works. There are several things to be aware of.
389 */
390
392 Context_Control *run,
393 Context_Control *heir
394);
395
396RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
397 Context_Control *executing,
398 Context_Control *heir
399);
400
401/*
402 * _CPU_Context_restore
403 *
404 * This routine is generally used only to restart self in an
405 * efficient manner. It may simply be a label in _CPU_Context_switch.
406 *
407 * NOTE: May be unnecessary to reload some registers.
408 *
409 */
410
411RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
412
413/* The following routine swaps the endian format of an unsigned int.
414 * It must be static because it is referenced indirectly.
415 *
416 * This version will work on any processor, but if there is a better
417 * way for your CPU PLEASE use it. The most common way to do this is to:
418 *
419 * swap least significant two bytes with 16-bit rotate
420 * swap upper and lower 16-bits
421 * swap most significant two bytes with 16-bit rotate
422 *
423 * Some CPUs have special instructions which swap a 32-bit quantity in
424 * a single instruction (e.g. i486). It is probably best to avoid
425 * an "endian swapping control bit" in the CPU. One good reason is
426 * that interrupts would probably have to be disabled to insure that
427 * an interrupt does not try to access the same "chunk" with the wrong
428 * endian. Another good reason is that on some CPUs, the endian bit
429 * endianness for ALL fetches -- both code and data -- so the code
430 * will be fetched incorrectly.
431 *
432 */
433
434static inline uint32_t CPU_swap_u32(
435 uint32_t value
436)
437{
438 uint32_t byte1, byte2, byte3, byte4, swapped;
439
440 byte4 = (value >> 24) & 0xff;
441 byte3 = (value >> 16) & 0xff;
442 byte2 = (value >> 8) & 0xff;
443 byte1 = value & 0xff;
444
445 swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
446 return ( swapped );
447}
448
449#define CPU_swap_u16( value ) \
450 (((value&0xff) << 8) | ((value >> 8)&0xff))
451
452typedef uint32_t CPU_Counter_ticks;
453
454uint32_t _CPU_Counter_frequency( void );
455
456extern volatile uint32_t * const _RISCV_Counter;
457
458CPU_Counter_ticks _CPU_Counter_read( void );
459
460#ifdef RTEMS_SMP
461
462uint32_t _CPU_SMP_Initialize( void );
463
464bool _CPU_SMP_Start_processor( uint32_t cpu_index );
465
466void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
467
468void _CPU_SMP_Prepare_start_multitasking( void );
469
470static inline uint32_t _CPU_SMP_Get_current_processor( void )
471{
472 unsigned long mhartid;
473
474 __asm__ volatile (
475 ".option push\n"
476 ".option arch, +zicsr\n"
477 "csrr %0, mhartid\n"
478 ".option pop" :
479 "=&r" ( mhartid )
480 );
481
482 return (uint32_t) mhartid - RISCV_BOOT_HARTID;
483}
484
485void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
486
487static inline bool _CPU_Context_Get_is_executing(
489)
490{
491 return context->is_executing;
492}
493
494static inline void _CPU_Context_Set_is_executing(
496 bool is_executing
497)
498{
499 context->is_executing = is_executing;
500}
501
502RTEMS_NO_RETURN void _RISCV_Start_multitasking( Context_Control *heir );
503
504#define _CPU_Start_multitasking( _heir ) _RISCV_Start_multitasking( _heir )
505
506#endif /* RTEMS_SMP */
507
509typedef uintptr_t CPU_Uint32ptr;
510
511#endif /* ASM */
512
513#ifdef __cplusplus
514}
515#endif
516
517#endif
This header file provides basic definitions used by the API and the implementation.
#define RTEMS_XSTRING(...)
Stringifies the expansion of the arguments.
Definition: basedefs.h:987
#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_ISR_Set_level(_new_level)
Definition: cpu.h:378
#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
rtems_termios_device_context * context
Definition: console-config.c:62
The set of registers that specifies the complete processor state.
Definition: cpu.h:446
Interrupt stack frame (ISF).
Definition: cpuimpl.h:64
Thread register context.
Definition: cpu.h:173
Definition: cpu.h:277