source: rtems/cpukit/score/cpu/riscv/include/rtems/score/cpu.h @ 8b65b574

Last change on this file since 8b65b574 was 8b65b574, checked in by Sebastian Huber <sebastian.huber@…>, on 07/28/21 at 12:41:32

score: Canonicalize _CPU_Fatal_halt()

Move _CPU_Fatal_halt() declaration to <rtems/score/cpuimpl.h> and make sure it
is a proper declaration of a function which does not return. Fix the type of
the error code. If necessary, add the implementation to cpu.c. Implementing
_CPU_Fatal_halt() as a function makes it possible to wrap this function for
example to fully test _Terminate().

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