RTEMS 6.2-rc1
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#define RISCV_MSTATUS_MDT 0x40000000000
49#define RISCV_MSTATUSH_MDT 0x400
50
51#define CPU_ISR_PASSES_FRAME_POINTER FALSE
52
53#define CPU_HARDWARE_FP FALSE
54#define CPU_SOFTWARE_FP FALSE
55#define CPU_ALL_TASKS_ARE_FP FALSE
56#define CPU_IDLE_TASK_IS_FP FALSE
57#define CPU_USE_DEFERRED_FP_SWITCH FALSE
58
59#define CPU_ENABLE_ROBUST_THREAD_DISPATCH TRUE
60
61#define CPU_STACK_GROWS_UP FALSE
62
63#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (64)))
64#define CPU_BIG_ENDIAN FALSE
65#define CPU_LITTLE_ENDIAN TRUE
66#define CPU_MODES_INTERRUPT_MASK 0x0000000000000001
67
68#define CPU_CACHE_LINE_BYTES 64
69
70#if __riscv_xlen == 32
71
72#define CPU_SIZEOF_POINTER 4
73
74#define CPU_STACK_MINIMUM_SIZE 4096
75
76#elif __riscv_xlen == 64
77
78#define CPU_SIZEOF_POINTER 8
79
80#define CPU_STACK_MINIMUM_SIZE 8192
81
82#endif /* __riscv_xlen */
83
84/* RISC-V ELF psABI specification */
85#define CPU_ALIGNMENT 16
86
87#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
88
89/* RISC-V ELF psABI specification */
90#define CPU_STACK_ALIGNMENT 16
91
92#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
93
94/*
95 * Processor defined structures required for cpukit/score.
96 */
97
98#ifndef ASM
99
100#if __riscv_flen == 32
101typedef float RISCV_Float;
102#elif __riscv_flen == 64
103typedef double RISCV_Float;
104#endif
105
106typedef struct {
107#ifdef RTEMS_SMP
108 volatile uint32_t is_executing;
109#else
110 uint32_t reserved;
111#endif
112 uint32_t isr_dispatch_disable;
113 uintptr_t ra;
114 uintptr_t sp;
115 uintptr_t tp;
116 uintptr_t s0;
117 uintptr_t s1;
118 uintptr_t s2;
119 uintptr_t s3;
120 uintptr_t s4;
121 uintptr_t s5;
122 uintptr_t s6;
123 uintptr_t s7;
124 uintptr_t s8;
125 uintptr_t s9;
126 uintptr_t s10;
127 uintptr_t s11;
128#if __riscv_flen > 0
129 uint32_t fcsr;
130 RISCV_Float fs0;
131 RISCV_Float fs1;
132 RISCV_Float fs2;
133 RISCV_Float fs3;
134 RISCV_Float fs4;
135 RISCV_Float fs5;
136 RISCV_Float fs6;
137 RISCV_Float fs7;
138 RISCV_Float fs8;
139 RISCV_Float fs9;
140 RISCV_Float fs10;
141 RISCV_Float fs11;
142#endif
144
145#define _CPU_Context_Get_SP( _context ) \
146 (_context)->sp
147
148#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
149
150#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
151
152static inline uint32_t riscv_interrupt_disable( void )
153{
154 unsigned long mstatus;
155
156 __asm__ volatile (
157 ".option push\n"
158 ".option arch, +zicsr\n"
159 "csrrc %0, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) "\n"
160 ".option pop" :
161 "=&r" ( mstatus )
162 );
163
164 return mstatus & RISCV_MSTATUS_MIE;
165}
166
167static inline void riscv_interrupt_enable( uint32_t level )
168{
169 __asm__ volatile (
170 ".option push\n"
171 ".option arch, +zicsr\n"
172 "csrrs zero, mstatus, %0\n"
173 ".option pop" :
174 :
175 "r" ( level )
176 );
177}
178
179#define _CPU_ISR_Disable( _level ) \
180 _level = riscv_interrupt_disable()
181
182#define _CPU_ISR_Enable( _level ) \
183 riscv_interrupt_enable( _level )
184
185#define _CPU_ISR_Flash( _level ) \
186 do{ \
187 _CPU_ISR_Enable( _level ); \
188 riscv_interrupt_disable(); \
189 } while(0)
190
191static inline bool _CPU_ISR_Is_enabled( unsigned long level )
192{
193 return ( level & RISCV_MSTATUS_MIE ) != 0;
194}
195
196static inline void _CPU_ISR_Set_level( uint32_t level )
197{
198 /*
199 * Where CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE, the only supported
200 * interrupt level allowed to set is 0 (interrupts enabled). This constraint
201 * is enforced by the API level functions which return an error status for
202 * other interrupt levels.
203 */
204 (void) level;
205 __asm__ volatile (
206 ".option push\n"
207 ".option arch, +zicsr\n"
208 "csrrs zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) "\n"
209 ".option pop"
210 );
211}
212
213uint32_t _CPU_ISR_Get_level( void );
214
215/* end of ISR handler macros */
216
217void _CPU_Context_Initialize(
219 void *stack_area_begin,
220 size_t stack_area_size,
221 uint32_t new_level,
222 void ( *entry_point )( void ),
223 bool is_fp,
224 void *tls_area
225);
226
227#define _CPU_Context_Restart_self( _the_context ) \
228 _CPU_Context_restore( (_the_context) )
229
230#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
231
232#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
233
234#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE
235
236#define CPU_MAXIMUM_PROCESSORS 32
237
238typedef uint16_t Priority_bit_map_Word;
239
240/*
241 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
242 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
243 * trap.
244 */
245typedef enum {
246 RISCV_INTERRUPT_SOFTWARE_USER = 0,
247 RISCV_INTERRUPT_SOFTWARE_SUPERVISOR = 1,
248 RISCV_INTERRUPT_SOFTWARE_MACHINE = 3,
249 RISCV_INTERRUPT_TIMER_USER = 4,
250 RISCV_INTERRUPT_TIMER_SUPERVISOR = 5,
251 RISCV_INTERRUPT_TIMER_MACHINE = 7,
252 RISCV_INTERRUPT_EXTERNAL_USER = 8,
253 RISCV_INTERRUPT_EXTERNAL_SUPERVISOR = 9,
254 RISCV_INTERRUPT_EXTERNAL_MACHINE = 11
255} RISCV_Interrupt_code;
256
257/*
258 * See The RISC-V Instruction Set Manual, Volume II: RISC-V Privileged
259 * Architectures V1.10, Table 3.6: Machine cause register (mcause) values after
260 * trap.
261 */
262typedef enum {
263 RISCV_EXCEPTION_INSTRUCTION_ADDRESS_MISALIGNED = 0,
264 RISCV_EXCEPTION_INSTRUCTION_ACCESS_FAULT = 1,
265 RISCV_EXCEPTION_ILLEGAL_INSTRUCTION = 2,
266 RISCV_EXCEPTION_BREAKPOINT = 3,
267 RISCV_EXCEPTION_LOAD_ADDRESS_MISALIGNED = 4,
268 RISCV_EXCEPTION_LOAD_ACCESS_FAULT = 5,
269 RISCV_EXCEPTION_STORE_OR_AMO_ADDRESS_MISALIGNED = 6,
270 RISCV_EXCEPTION_STORE_OR_AMO_ACCESS_FAULT = 7,
271 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_U_MODE = 8,
272 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_S_MODE = 9,
273 RISCV_EXCEPTION_ENVIRONMENT_CALL_FROM_M_MODE = 11,
274 RISCV_EXCEPTION_INSTRUCTION_PAGE_FAULT = 12,
275 RISCV_EXCEPTION_LOAD_PAGE_FAULT = 13,
276 RISCV_EXCEPTION_STORE_OR_AMO_PAGE_FAULT = 15
277} RISCV_Exception_code;
278
279typedef struct {
280 uintptr_t mstatus;
281 uintptr_t mepc;
282 uintptr_t a2;
283 uintptr_t s0;
284 uintptr_t s1;
285 uintptr_t ra;
286 uintptr_t a3;
287 uintptr_t a4;
288 uintptr_t a5;
289 uintptr_t a6;
290 uintptr_t a7;
291 uintptr_t t0;
292 uintptr_t t1;
293 uintptr_t t2;
294 uintptr_t t3;
295 uintptr_t t4;
296 uintptr_t t5;
297 uintptr_t t6;
298#if __riscv_flen > 0
299 uint32_t fcsr;
300 RISCV_Float ft0;
301 RISCV_Float ft1;
302 RISCV_Float ft2;
303 RISCV_Float ft3;
304 RISCV_Float ft4;
305 RISCV_Float ft5;
306 RISCV_Float ft6;
307 RISCV_Float ft7;
308 RISCV_Float ft8;
309 RISCV_Float ft9;
310 RISCV_Float ft10;
311 RISCV_Float ft11;
312 RISCV_Float fa0;
313 RISCV_Float fa1;
314 RISCV_Float fa2;
315 RISCV_Float fa3;
316 RISCV_Float fa4;
317 RISCV_Float fa5;
318 RISCV_Float fa6;
319 RISCV_Float fa7;
320#endif
321 uintptr_t a0;
322 uintptr_t a1;
323} RTEMS_ALIGNED( CPU_STACK_ALIGNMENT ) CPU_Interrupt_frame;
324
325typedef struct {
326 CPU_Interrupt_frame Interrupt_frame;
327 uintptr_t mcause;
328 uintptr_t sp;
329 uintptr_t gp;
330 uintptr_t tp;
331 uintptr_t s2;
332 uintptr_t s3;
333 uintptr_t s4;
334 uintptr_t s5;
335 uintptr_t s6;
336 uintptr_t s7;
337 uintptr_t s8;
338 uintptr_t s9;
339 uintptr_t s10;
340 uintptr_t s11;
341#if __riscv_flen > 0
342 RISCV_Float fs0;
343 RISCV_Float fs1;
344 RISCV_Float fs2;
345 RISCV_Float fs3;
346 RISCV_Float fs4;
347 RISCV_Float fs5;
348 RISCV_Float fs6;
349 RISCV_Float fs7;
350 RISCV_Float fs8;
351 RISCV_Float fs9;
352 RISCV_Float fs10;
353 RISCV_Float fs11;
354#endif
356
363
364
365/* end of Priority handler macros */
366
367/* functions */
368
369/*
370 * _CPU_Initialize
371 *
372 * This routine performs CPU dependent initialization.
373 *
374 */
375
376void _CPU_Initialize(
377 void
378);
379
380RTEMS_NO_RETURN void *_CPU_Thread_Idle_body( uintptr_t ignored );
381
382/*
383 * _CPU_Context_switch
384 *
385 * This routine switches from the run context to the heir context.
386 *
387 * RISCV Specific Information:
388 *
389 * Please see the comments in the .c file for a description of how
390 * this function works. There are several things to be aware of.
391 */
392
394 Context_Control *run,
395 Context_Control *heir
396);
397
398RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
399 Context_Control *executing,
400 Context_Control *heir
401);
402
403/*
404 * _CPU_Context_restore
405 *
406 * This routine is generally used only to restart self in an
407 * efficient manner. It may simply be a label in _CPU_Context_switch.
408 *
409 * NOTE: May be unnecessary to reload some registers.
410 *
411 */
412
413RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
414
415/* The following routine swaps the endian format of an unsigned int.
416 * It must be static because it is referenced indirectly.
417 *
418 * This version will work on any processor, but if there is a better
419 * way for your CPU PLEASE use it. The most common way to do this is to:
420 *
421 * swap least significant two bytes with 16-bit rotate
422 * swap upper and lower 16-bits
423 * swap most significant two bytes with 16-bit rotate
424 *
425 * Some CPUs have special instructions which swap a 32-bit quantity in
426 * a single instruction (e.g. i486). It is probably best to avoid
427 * an "endian swapping control bit" in the CPU. One good reason is
428 * that interrupts would probably have to be disabled to insure that
429 * an interrupt does not try to access the same "chunk" with the wrong
430 * endian. Another good reason is that on some CPUs, the endian bit
431 * endianness for ALL fetches -- both code and data -- so the code
432 * will be fetched incorrectly.
433 *
434 */
435
436static inline uint32_t CPU_swap_u32(
437 uint32_t value
438)
439{
440 uint32_t byte1, byte2, byte3, byte4, swapped;
441
442 byte4 = (value >> 24) & 0xff;
443 byte3 = (value >> 16) & 0xff;
444 byte2 = (value >> 8) & 0xff;
445 byte1 = value & 0xff;
446
447 swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
448 return ( swapped );
449}
450
451#define CPU_swap_u16( value ) \
452 (((value&0xff) << 8) | ((value >> 8)&0xff))
453
454typedef uint32_t CPU_Counter_ticks;
455
456uint32_t _CPU_Counter_frequency( void );
457
458extern volatile uint32_t * const _RISCV_Counter;
459
460CPU_Counter_ticks _CPU_Counter_read( void );
461
462#ifdef RTEMS_SMP
463
464uint32_t _CPU_SMP_Initialize( void );
465
466bool _CPU_SMP_Start_processor( uint32_t cpu_index );
467
468void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
469
470void _CPU_SMP_Prepare_start_multitasking( void );
471
472static inline uint32_t _CPU_SMP_Get_current_processor( void )
473{
474 unsigned long mhartid;
475
476 __asm__ volatile (
477 ".option push\n"
478 ".option arch, +zicsr\n"
479 "csrr %0, mhartid\n"
480 ".option pop" :
481 "=&r" ( mhartid )
482 );
483
484 return (uint32_t) mhartid - RISCV_BOOT_HARTID;
485}
486
487void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
488
489static inline bool _CPU_Context_Get_is_executing(
491)
492{
493 return context->is_executing;
494}
495
496static inline void _CPU_Context_Set_is_executing(
498 bool is_executing
499)
500{
501 context->is_executing = is_executing;
502}
503
504RTEMS_NO_RETURN void _RISCV_Start_multitasking( Context_Control *heir );
505
506#define _CPU_Start_multitasking( _heir ) _RISCV_Start_multitasking( _heir )
507
508#endif /* RTEMS_SMP */
509
511typedef uintptr_t CPU_Uint32ptr;
512
513#endif /* ASM */
514
515#ifdef __cplusplus
516}
517#endif
518
519#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:279